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: BOOLFALSE;
includeApostrophes: BOOLTRUE;
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: BOOLFALSE;
verbose: BOOLTRUE;
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.STREAMFS.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: CHARIO.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
ELSE
state ← oneNull;
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;
REPEAT
eof => NULL;
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 ROPENIL] = {
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