<> <> <> <> <<>> DIRECTORY Atom, Commander, CommandTool, CommandToolLookup, PopUpSelection, Process, ProcessProps, Rope, ViewerClasses; PopUpCommandImpl: CEDAR PROGRAM IMPORTS Atom, Commander, CommandTool, CommandToolLookup, PopUpSelection, Process, ProcessProps, Rope ~ BEGIN ROPE: TYPE ~ Rope.ROPE; usageMessage: ROPE ~ "\n Usage: PopUpCommand [-title] \"cmd1\" \"cmd2\" ..."; PopUp: Commander.CommandProc = { options: LIST OF ROPE _ CommandTool.ParseToList[cmd: cmd].list; IF options#NIL THEN { header: ROPE _ NIL; IF Rope.Fetch[options.first]='- THEN { header _ Rope.Substr[base: options.first, start: 1]; options _ options.rest; IF options=NIL THEN RETURN [msg: usageMessage, result: $Failure]; IF Rope.Length[header]=0 THEN { header _ options.first; options _ options.rest; IF options=NIL THEN RETURN [msg: usageMessage, result: $Failure]; }; }; TRUSTED {Process.Detach[FORK SelectAndExecute[header: header, options: options, processProps: ProcessProps.GetPropList[], viewer: CommandTool.GetViewer[cmd: cmd]]]}; } ELSE RETURN [msg: usageMessage, result: $Failure]; }; FirstNonBlank: PROC [r: ROPE] RETURNS [ROPE] = INLINE { n: INT ~ Rope.SkipTo[s: r, skip: " "]; RETURN [Rope.Substr[base: r, len: n]] }; Doc: PROC [for: ROPE, rules: REF_NIL] RETURNS [ROPE_NIL] = { procData: Commander.CommandProcHandle _ CommandToolLookup.FindMatchingCommands[FirstNonBlank[for], TRUE, rules].data; IF procData#NIL THEN RETURN [procData.doc]; }; SelectAndExecute: PROC [header: ROPE, options: LIST OF ROPE, processProps: ProcessProps.AList, viewer: ViewerClasses.Viewer] ~ { Inner: PROC ~ { selection: INT; rules: REF _ NIL; docs, doctail: LIST OF ROPE _ NIL; WITH Atom.GetPropFromList[processProps, $CommanderHandle] SELECT FROM h: Commander.Handle => rules _ Atom.GetPropFromList[h.propertyList, $SearchRules]; ENDCASE => NULL; FOR list: LIST OF ROPE _ options, list.rest WHILE list#NIL DO doc: ROPE _ Doc[list.first, rules]; IF doctail#NIL THEN { doctail.rest _ LIST[doc]; doctail _ doctail.rest; } ELSE doctail _ docs _ LIST[doc]; ENDLOOP; selection _ PopUpSelection.Request[header: header, choice: options, choiceDoc: docs, default: 1]; IF selection>0 THEN { THROUGH [1..selection) DO options _ options.rest; ENDLOOP; viewer.class.notify[viewer, LIST[Rope.Concat[options.first, "\n"]]]; }; }; ProcessProps.AddPropList[propList: processProps, inner: Inner]; }; Commander.Register[key: "///Commands/PopUpCommand", proc: PopUp, doc: "Pops up menu for selection of next command.", interpreted: FALSE]; END.