FindKeywordsCommandsImpl.mesa
Copyright © 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
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: ROPENIL] = {
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.STREAMIO.RIS[cmd.commandLine];
keys: LIST OF ROPENIL;
files: LIST OF ROPELIST[NIL];
fileLast: LIST OF ROPENIL;
acFinder: ACFind.Ref ← NIL;
nHits: INT ← 0;
case: BOOLFALSE;
anywhere: BOOLFALSE;
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: BOOLFALSE;
nameProc: PROC [fullFName: ROPE] RETURNS [continue: BOOLTRUE] ~ {
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: BOOLFALSE] ~ {
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.