File: WordCountImpl.mesa
Last Edited by: Nix, February 6, 1984 1:32:54 pm PST
Last Edited by: Beach, September 16, 1983 9:29 am
DIRECTORY
Buttons USING [ButtonProc, Create],
Commander USING [CommandProc, Register],
FS USING [StreamOpen, Error, NameProc, EnumerateForNames],
IO USING [STREAM, PutF, rope, Close, int, GetChar, EndOfStream, RIS, PutFR],
List USING [DReverse],
MessageWindow USING [Append],
Rope USING [ROPE],
CommandTool USING [Parse, ArgumentVector],
ViewerTools USING [GetSelectionContents];
WordCountImpl:
CEDAR
MONITOR
IMPORTS Buttons, Commander, FS, IO, List, MessageWindow, CommandTool, ViewerTools =
BEGIN
ROPE: TYPE = Rope.ROPE;
countWordLengths: BOOL ← FALSE;
includeApostrophes: BOOL ← TRUE;
maxWordLength: NAT = 100;
countWordLens:
REF
ARRAY [1..maxWordLength]
OF
INT ←
NEW[ARRAY [1..maxWordLength] OF INT];
WordCount:
ENTRY Commander.CommandProc
-- [cmd: Commander.Handle] -- = {
Callable from the command interpreter. Expects a list of file names as arguments, and counts the number of words in the indicated files.
stdout: IO.STREAM ← cmd.out;
cmdLine: CommandTool.ArgumentVector ← CommandTool.Parse[cmd];
fileCount: INT ← 0;
totalWordCount: INT ← 0;
totalLineCount: INT ← 0;
headerWritten: BOOL ← FALSE;
verbose: BOOL ← TRUE;
countWordLens^ ← ALL[0];
FOR argCount:
INT
IN [1..cmdLine.argc)
DO
fileNames: LIST OF ROPE ← FileList[cmdLine.s[argCount]];
IF verbose
AND fileNames =
NIL
THEN
IO.PutF[stdout, "No files matched \"%g\"\n", IO.rope[cmdLine.s[argCount]]];
FOR fileName:
LIST
OF
ROPE ← fileNames, fileName.rest
UNTIL fileName =
NIL
DO
in: IO.STREAM ← FS.StreamOpen[fileName.first ! FS.Error => GOTO openFailed ];
charCount, wordCount, newLineCount: INT;
fileCount ← fileCount + 1;
[charCount, wordCount, newLineCount] ← CountFile[in, countWordLens];
totalWordCount ← totalWordCount + wordCount;
totalLineCount ← totalLineCount + newLineCount;
in.Close[];
IF verbose
AND ~headerWritten
THEN {
headerWritten ← TRUE;
IO.PutF[stdout, "Lines\tWords\t\tFile\n"];
};
IO.PutF[stdout, "%6d\t%6d\t\t%g\n", IO.int[newLineCount], IO.int[wordCount], IO.rope[fileName.first]];
REPEAT
openFailed =>
IO.PutF[stdout, "Could not open \"%g\"\n", IO.rope[fileName.first]];
ENDLOOP;
ENDLOOP;
IF fileCount > 1
AND verbose
THEN {
IO.PutF[stdout,"%6d\t%6d\t\t\tTotal for %g files.\n", IO.int[totalLineCount], IO.int[totalWordCount], IO.int[fileCount]];
};
IF countWordLengths
THEN
FOR i:
NAT
IN [1..100]
DO
IF countWordLens[i] > 0
THEN
IO.PutF[stdout,"Words of length %6d:\t%6d.\n", IO.int[i], IO.int[countWordLens[i]]];
ENDLOOP;
};
CountFile:
INTERNAL
PROC[file:
IO.
STREAM, countWordLens:
REF
ARRAY [1..100]
OF
INT]
RETURNS [ charCount:
INT ← 0, wordCount:
INT ← 0, newLineCount:
INT ← 0 ] = {
Counts the number of words in the indicated stream.
State: TYPE = { inWord, inJunk, oneNull };
state: State ← inJunk;
wordLen: NAT ← 0;
DO
c: CHAR ← IO.GetChar[file ! IO.EndOfStream => GOTO eof];
SELECT c
FROM
IN ['0..'9],
IN ['A..'Z],
IN ['a..'z] => {
IF state ~= inWord
THEN {
state ← inWord;
wordCount ← wordCount + 1;
wordLen ← 0;
};
wordLen ← wordLen + 1;
};
= 0C =>
IF state = oneNull
THEN
EXIT
ENDCASE => {
IF c = '\'
AND includeApostrophes
AND state = inWord
THEN {
wordLen ← wordLen + 1;
}
ELSE {
IF state = inWord
THEN
IF wordLen > maxWordLength
THEN
countWordLens[maxWordLength] ← countWordLens[maxWordLength]+1
ELSE
countWordLens[wordLen] ← countWordLens[wordLen]+1;
state ← inJunk;
IF c = '\n
THEN
newLineCount ← newLineCount + 1;
};
};
charCount ← charCount + 1;
ENDLOOP;
};
WordCountButton:
ENTRY Buttons.ButtonProc = {
chars, words, lines: INT;
countWordLens^ ← ALL[0];
[chars, words, lines] ←
CountFile[IO.RIS[ViewerTools.GetSelectionContents[]], countWordLens];
MessageWindow.Append[IO.PutFR["Selection contains %d chars, %d words, and %d lines.", IO.int[chars], IO.int[words], IO.int[lines]], TRUE];
};
FileList:
PROC [pattern:
ROPE]
RETURNS [fileNames:
LIST
OF
ROPE ←
NIL] = {
GetNames:
FS.NameProc = {
fileNames ← CONS[fullFName, fileNames];
continue ← TRUE;
};
FS.EnumerateForNames[pattern, GetNames];
TRUSTED {fileNames ← LOOPHOLE[List.DReverse[LOOPHOLE[fileNames]]]};
};
Commander.Register[
key: "WordCount", proc: WordCount, doc: "Counts the words in a group of files."];
[] ← Buttons.Create[
info: [
name: "WC",
parent: NIL],
proc: WordCountButton,
documentation: "Counts the words in the current selection."];
END.
CHANGE LOG
Created by Nix on September 8, 1983 11:17 am