DIRECTORY ACFind, Commander, FS, IO, Process, Rope, RopeEdit, RopeFile; FindKeywordsCommandsImpl: CEDAR PROGRAM IMPORTS ACFind, Commander, FS, IO, Process, Rope, RopeEdit, RopeFile = BEGIN ROPE: TYPE = Rope.ROPE; Plural: PROC [list: LIST OF ROPE] RETURNS [IO.Value] ~ { IF list = NIL OR list.rest # NIL THEN RETURN [[character['s]]] ELSE RETURN [[rope[NIL]]]; }; Count: PROC [list: LIST OF ROPE] RETURNS [n: INT _ 0] ~ { WHILE list # NIL DO n _ n+1; list _ list.rest ENDLOOP; }; FindKeywordsCommand: Commander.CommandProc -- [cmd: Commander.Handle] -- = { [result: result, msg: msg] _ FindKeywords[cmd ! FS.Error => {msg _ error.explanation; result _ $Failure; CONTINUE}]; }; GetToken: PROC [stream: IO.STREAM] RETURNS [token: ROPE _ NIL] = { token _ stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token; }; Break: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ OR char = '; THEN RETURN [break]; IF char = ' OR char = ' OR char = ', OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; FindKeywords: Commander.CommandProc -- [cmd: Commander.Handle] -- = { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; keys: LIST OF ROPE _ NIL; files: LIST OF ROPE _ LIST[NIL]; fileLast: LIST OF ROPE _ NIL; acFinder: ACFind.Ref _ NIL; nHits: INT _ 0; case: BOOL _ FALSE; anywhere: BOOL _ FALSE; token: ROPE; UNTIL (token _ GetToken[stream]) = NIL DO SELECT TRUE FROM Rope.Run[token, 0, "-c", 0, FALSE] = 2 => {case _ TRUE}; Rope.Run[token, 0, "-a", 0, FALSE] = 2 => {anywhere _ TRUE}; fileLast # NIL => { hit: BOOL _ FALSE; nameProc: PROC [fullFName: ROPE] RETURNS [continue: BOOL _ TRUE] ~ { fileLast.rest _ LIST[fullFName]; fileLast _ fileLast.rest; hit _ TRUE; }; FS.EnumerateForNames[pattern: token, proc: nameProc]; IF NOT hit THEN IO.PutF[cmd.out, "(No files matching \"%g\")\n", IO.rope[token]]; }; Rope.Equal[token, "IN", FALSE] => {fileLast _ files}; ENDCASE => { keys _ CONS[token, keys]; }; ENDLOOP; files _ files.rest; IO.PutF[cmd.out, "Searching for %g %gkeyword%g in %g file%g . . . ", IO.int[Count[keys]], IO.rope[IF case THEN "case-sensitive " ELSE ""], Plural[keys], IO.int[Count[files]], Plural[files]]; IO.PutRope[cmd.out, "\n"]; acFinder _ ACFind.Create[keys, case]; FOR p: LIST OF ROPE _ files, p.rest UNTIL p = NIL DO Process.CheckForAbort[]; nHits _ nHits + SearchFile[acFinder, p.first, cmd, anywhere ! FS.Error => { IO.PutRope[cmd.out, error.explanation]; IO.PutRope[cmd.out, "\n"]; CONTINUE; }]; ENDLOOP; IO.PutF[cmd.out, "%g match%g.\n", IO.int[nHits], IO.rope[IF nHits=1 THEN "" ELSE "es"]]; }; SearchFile: PROC [acFinder: ACFind.Ref, fileName: ROPE, cmd: Commander.Handle, anywhere: BOOL] RETURNS [nHits: INT _ 0] = { rope: ROPE ~ RopeFile.Create[name: fileName, raw: FALSE]; Alpha: PROC [pos: INT] RETURNS [BOOL] ~ { IF pos <= 0 OR pos > Rope.Size[rope] THEN RETURN [FALSE]; RETURN [RopeEdit.GetCharProp[Rope.Fetch[rope, pos]] = alphaNumeric]; }; action: PROC [position: INT, keyFound: ROPE] RETURNS [quit: BOOL _ FALSE] ~ { start: INT _ position - Rope.Size[keyFound]; IF NOT anywhere AND (Alpha[start-1] OR Alpha[position]) THEN RETURN; IO.PutF[cmd.out, " %g\t %g|%g\n", IO.rope[keyFound], IO.rope[fileName], IO.int[start]]; nHits _ nHits + 1; }; [] _ ACFind.Find[acFinder, rope, action]; }; Commander.Register[key: "FindKeywords", proc: FindKeywordsCommand, doc: "Searches for keywords in a set of files\nFindKeywords [-Case] [-Anywhere] key1 key2 ... IN filepat1 filePat2 ..."]; END. ΊFindKeywordsCommandsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, October 28, 1985 1:01:46 pm PST Dave Rumph, June 18, 1986 10:20:57 am PDT Κζ˜code– "Cedar" stylešœ™K– "Cedar" stylešœ Οmœ1™˜DKšœ˜—š œžœ žœ žœžœžœžœ˜MKšœžœ"˜,Kš žœžœ žœžœžœžœ˜DKšžœ!žœžœžœ ˜XKšœ˜Kšœ˜—Kšœ)˜)K˜—K˜KšœΌ˜ΌK˜Kšžœ˜K˜—…— r