<> <> <> 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] -- = { <> 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 ] = { <> 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 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 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