DIRECTORY Feedback, FileNames, FS, GGBasicTypes, GGContainer, GGEvent, GGFileIn, GGFileOps, GGFont, GGInterfaceTypes, GGUserInput, GGModelTypes, GGScene, GGSegmentTypes, GGWindow, GList, Imager, IO, Match, MatchGrep, MatchTurtle, MatchViewer, Rope, SlackProcess, ViewerClasses, ViewerOps; MatchGrepImpl: CEDAR PROGRAM IMPORTS Feedback, FileNames, FS, GGEvent, GGFileIn, GGFileOps, GList, GGScene, GGWindow, IO, Match, MatchViewer, Rope, ViewerOps EXPORTS MatchGrep = BEGIN GGData: TYPE = GGInterfaceTypes.GGData; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGModelTypes.Scene; fileList: LIST OF Rope.ROPE _ NIL; Grep: PUBLIC GGUserInput.UserInputProc = { FillFileList: FS.NameProc = { fileList _ CONS[fullFName, fileList]; RETURN[TRUE];}; grepData: GGData _ MatchViewer.GetGrepData[]; pattern: Rope.ROPE _ NARROW[event.rest.first]; IF pattern = NIL OR pattern = "" THEN MatchViewer.ErrorFeedback["Must select a filename pattern"] ELSE { fileList _ NIL; IF Rope.Index[pattern, 0, "!"] >= Rope.Length[pattern] THEN pattern _ Rope.Concat[pattern, "!H"]; -- if they don't specify a version, only enumerate the last FS.EnumerateForNames[pattern, FillFileList ! FS.Error => { mesg: Rope.ROPE _ IO.PutFR["Invalid filename pattern: %g", IO.rope[pattern]]; MatchViewer.ErrorFeedback[mesg]; GOTO Abort; };]; IF fileList = NIL THEN MatchViewer.ErrorFeedback["No files match the pattern."] ELSE { fileList _ NARROW[GList.DReverse[fileList]]; -- back in order of enumeration FOR files: LIST OF Rope.ROPE _ fileList, files.rest UNTIL files = NIL DO fileList _ files.rest; IF GrepFile[files.first, TRUE] THEN { SpawnViewer[grepData, files.first]; RETURN; }; ENDLOOP; MatchViewer.ErrorFeedback["No matches."]; }; }; EXITS Abort => Feedback.Blink[MatchViewer.GetToData[].feedback]; }; GrepListOnly: PUBLIC GGUserInput.UserInputProc = { FillFileList: FS.NameProc = { fileList _ CONS[fullFName, fileList]; RETURN[TRUE];}; matchData: MatchViewer.MatchData _ MatchViewer.GetMatchData[]; grepData: GGData _ MatchViewer.GetGrepData[]; pattern: Rope.ROPE _ NARROW[event.rest.first]; IF pattern = NIL OR pattern = "" THEN MatchViewer.ErrorFeedback["Must select a filename pattern"] ELSE { fileList _ NIL; IF Rope.Index[pattern, 0, "!"] >= Rope.Length[pattern] THEN pattern _ Rope.Concat[pattern, "!H"]; -- if they don't specify a version, only enumerate the last FS.EnumerateForNames[pattern, FillFileList ! FS.Error => { mesg: Rope.ROPE _ IO.PutFR["Invalid filename pattern: %g", IO.rope[pattern]]; MatchViewer.ErrorFeedback[mesg]; GOTO Abort; };]; IF fileList = NIL THEN MatchViewer.ErrorFeedback["No files match the pattern."] ELSE { fileList _ NARROW[GList.DReverse[fileList]]; -- back in order of enumeration FOR files: LIST OF Rope.ROPE _ fileList, files.rest UNTIL files = NIL DO IF GrepFile[files.first, TRUE] THEN IO.PutF[matchData.commander.out, "\n%g matched.", IO.rope[files.first]]; ENDLOOP; MatchViewer.ErrorFeedback["No matches."]; }; }; EXITS Abort => Feedback.Blink[MatchViewer.GetToData[].feedback]; }; GrepFile: PROC [fullFName: Rope.ROPE, verbose: BOOL _ TRUE] RETURNS [found: BOOL] = { grepData: GGData _ MatchViewer.GetGrepData[]; fullName: Rope.ROPE; success, versionSpecified: BOOL; [fullName, success, versionSpecified] _ GGFileOps.GetGargoyleFileName[fullFName, NIL, grepData.feedback, FALSE]; IF NOT success THEN { mesg: Rope.ROPE _ IO.PutFR["Couldn't load %g.\n", IO.rope[fullName]]; IF verbose THEN MatchViewer.ErrorFeedback[mesg]; RETURN[FALSE]; } ELSE { matchData: MatchViewer.MatchData _ MatchViewer.GetMatchData[]; f: FS.STREAM; IF verbose THEN Feedback.PutFHerald[grepData.feedback, oneLiner, "Loading %g.", IO.rope[fullName]]; f _ FS.StreamOpen[fullName, $read ! FS.Error, IO.Error => { msgRope: Rope.ROPE _ IO.PutFR["Could not find: %g", [rope[fullName]]]; Feedback.Append[grepData.feedback, msgRope, oneLiner]; GOTO Abort; };]; grepData.scene _ GGScene.CreateScene[]; -- give GGData a new clean slate/scene [] _ GGFileIn.FileinSceneOnly[f, grepData.scene]; f.Close[]; IF verbose THEN Feedback.PutFHerald[grepData.feedback, oneLiner, "Searching %g.", IO.rope[fullName]]; matchData.theirData _ NIL; -- force a reset of search lists success _ Match.Search[grepData, LIST[$MatchSearch, $SearchFromTop], FALSE]; IF success THEN { IF verbose THEN MatchViewer.ErrorFeedback["It matched!!!"]; RETURN [TRUE]; }; RETURN[FALSE]; }; EXITS Abort => { Feedback.Blink[MatchViewer.GetToData[].feedback]; RETURN[FALSE]; }; }; NextFile: PUBLIC GGUserInput.UserInputProc = { grepData: GGData _ MatchViewer.GetGrepData[]; IF fileList = NIL THEN MatchViewer.ErrorFeedback["No more file matches."] ELSE { FOR files: LIST OF Rope.ROPE _ fileList, files.rest UNTIL files = NIL DO fileList _ files.rest; IF GrepFile[files.first, TRUE] THEN { SpawnViewer[grepData, files.first]; RETURN; }; ENDLOOP; MatchViewer.ErrorFeedback["No more file matches."]; }; }; lastSpawned: GGData _ NIL; SpawnViewer: PROC [ggData: GGData, fileName: Rope.ROPE] = { f: FS.STREAM _ FS.StreamOpen[fileName, $read ! FS.Error, IO.Error => { msgRope: Rope.ROPE _ IO.PutFR["Could not find: %g", [rope[fileName]]]; Feedback.Append[ggData.feedback, msgRope, oneLiner]; GOTO Abort; };]; IF lastSpawned = NIL OR lastSpawned.outer.newVersion THEN { -- we create a gargoyle viewer lastSpawned _ GGWindow.CreateWindow[ggData.scene, TRUE, FALSE, fileName]; [] _ GGFileIn.FileinSceneAndOptions[f, lastSpawned, $OptionsOnly]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, ggData: lastSpawned, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: FALSE]; ViewerOps.OpenIcon[lastSpawned.outer]; MatchViewer.CenterSel[NIL, lastSpawned]; -- this may not happen, since OpenIcon is async. } ELSE { -- we use the old unedited viewer lastSpawned.scene _ ggData.scene; [] _ GGFileIn.FileinSceneAndOptions[f, lastSpawned, $OptionsOnly]; MatchViewer.CenterSel[NIL, lastSpawned]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, ggData: lastSpawned, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: FALSE]; }; lastSpawned.outer.file _ FileNames.StripVersionNumber[fileName]; lastSpawned.outer.label _ FileNames.GetShortName[path: fileName]; lastSpawned.outer.name _ fileName; GGEvent.ChangeIcon[lastSpawned, $clean]; -- will also repaint the label EXITS Abort => ERROR; -- we've already opened fileName prior to this, so something's screwy }; END. ψMatchGrep.mesa Last edited by: David Kurlander - September 6, 1987 5:18:03 pm PDT BitVector: TYPE = GGBasicTypes.BitVector; BoundBox: TYPE = GGModelTypes.BoundBox; Caret: TYPE = REF CaretObj; CaretObj: TYPE = GGInterfaceTypes.CaretObj; ChoiceData: TYPE = MatchViewer.ChoiceData; FontData: TYPE = GGFont.FontData; GGDataObj: TYPE = GGInterfaceTypes.GGDataObj; ItemMatch: TYPE = Match.ItemMatch; LooksInfo: TYPE = Match.LooksInfo; MatchData: TYPE = MatchViewer.MatchData; MatchDescriptor: TYPE = Match.MatchDescriptor; SearchInfo: TYPE = Match.SearchInfo; SearchState: TYPE = Match.SearchState; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; SequenceOfReal: TYPE = GGModelTypes.SequenceOfReal; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceDescriptorObj: TYPE = GGModelTypes.SliceDescriptorObj; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceParts: TYPE = REF ANY; Traj: TYPE = GGModelTypes.Traj; TrajGenerator: TYPE = GGModelTypes.TrajGenerator; TurtleHeader: TYPE = MatchTurtle.TurtleHeader; TurtleInfo: TYPE = MatchTurtle.TurtleInfo; The interactive grep (compared to GrepListOnly). Invokes a gargoyle viewer on the matched scene file. Greps for graphical matches, only printing out their names in the invoker commander when there's a hit. Returns true if there is a match between the MatchTool From viewer and the gargoyle scene file described by fullFName. Now do search Creates a gargoyle viewer, stuffs the scene from ggData into that Gargoyle viewer, and loads the various scene state info (from fileName) Now change the viewer file, label, and name ΚΎ˜J™JšœC™CIcode˜šΟk ˜ Kšœœ’œ[˜–K˜šΟn œœ˜Kšœœ:œ%˜€Kšœ ˜—K˜Kšœ œ™)Kšœ œ™'Kšœœœ ™Kšœ œ™+Kšœ œ™*Kšœ œ™!Kšœ œ™-Kšœœ˜'Kšœ œ™"Kšœ œ™"Kšœ œ™(Kšœœ™.Kšœœ˜!Kšœ œ™$Kšœ œ™&Kšœ œ™'Kšœœ!™7Kšœ œ™'Kšœœ™3Kšœœ˜!Kšœœ™!Kšœœ ™5Kšœœ)™GKšœœ#™;Kšœœ™3Kšœ œœœ™Kšœœ™Kšœœ™1Kšœœ™.Kšœ œ™*—J™Jš œ œœœœ˜"J˜šžœœ˜*J™fJš ž œœœœœ˜SJ˜-Jšœœœ˜.Jšœ œœœ<˜ašœ˜Jšœ œ˜Jšœ5œ'Οc;˜šœ+œ ˜:Jšœ œœ'œ˜MJšœ ˜ Jšœ˜ Jšœ˜—Jšœ œœ9˜Ošœ˜Jšœ œŸ˜Lš œœœœœ œ˜HJ˜šœœœ˜%Jšœ#˜#Jšœ˜J˜—Jšœ˜J˜)—J˜—J˜—š˜J˜:—J˜J˜—šž œœ˜2J™gJš ž œœœœœ˜SJšœ>˜>J˜-Jšœœœ˜.Jšœ œœœ<˜ašœ˜Jšœ œ˜Jšœ5œ'Ÿ;˜šœ+œ ˜:Jšœ œœ'œ˜MJšœ ˜ Jšœ˜ Jšœ˜—Jšœ œœ9˜Ošœ˜Jšœ œŸ˜Lš œœœœœ œ˜HJš œœœœ0œ˜lJšœ˜—J˜)J˜—J˜—š˜J˜:—J˜J˜—šžœœœ œœœ œ˜UJ™vJ˜-Jšœœ˜Jšœœ˜ JšœQœœ˜pšœœ œ˜Jšœ œœœ˜EJšœ œ!˜0Jšœœ˜J˜—šœ˜Jšœ>˜>Jšœœœ˜ Jšœ œAœ˜cšœœœœ ˜;Kšœœœ/˜FKšœ6˜6Kšœ˜ Kšœ˜—Jšœ(Ÿ&˜NJ˜1J˜ Jšœ œCœ˜eJ™ JšœœŸ ˜;Jšœ!œ œ˜Lšœ œ˜Jšœ œ,˜;Jšœœ˜J˜—Jšœœ˜J˜—š˜˜ J˜1Jšœœ˜J˜——J˜J˜—šžœœ˜.J˜-Jšœ œœ3˜Išœ˜š œœœœœ œ˜HJšœ˜šœœœ˜%Jšœ#˜#Jšœ˜J˜—Jšœ˜—Jšœ3˜3Jšœ˜—J˜—J˜Jšœœ˜šž œœ!œ˜;J™‰š œœœœœœ ˜FKšœœœ/˜FKšœ4˜4Kšœ˜ Kšœ˜—š œœœœŸ˜ZJšœ2œœ ˜IJ˜BKšœxœ œœ˜¨J˜&JšœœŸ0˜YJ˜—šœŸ!˜(J˜!J˜BJšœœ˜(Kšœxœ œœ˜¨J˜—J™+J˜@JšœA˜AKšœ"˜"Jšœ)Ÿ˜Gš˜Jšœ œŸE˜U—J˜J™—Jšœ˜—…—μ'’