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 =
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.