CommanderImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Larry Stewart, January 14, 1984 3:40 pm
Russ Atkinson (RRA) March 6, 1985 12:50:20 pm PST
DIRECTORY
Commander,
List USING [AList, Assoc, PutAssoc],
ProcessProps USING [GetProp],
Rope USING [Concat, Equal, Fetch, FromRefText, IsEmpty, ROPE],
SymTab USING [Create, Delete, EachPairAction, Fetch, Pairs, Ref, Store];
CommanderImpl:
CEDAR
MONITOR
IMPORTS List, Rope, ProcessProps, SymTab
EXPORTS Commander = BEGIN
ROPE: TYPE = Rope.ROPE;
registry: SymTab.Ref;
Register:
PUBLIC
ENTRY
PROC[key:
ROPE, proc: Commander.CommandProc, doc:
ROPE, clientData:
REF
ANY ←
NIL, interpreted:
BOOL ←
TRUE] = {
key ← PrependWorkingDir[key];
IF proc = NIL THEN {[] ← SymTab.Delete[x: registry, key: key]; RETURN};
[] ← SymTab.Store[
x: registry, key: key,
val:
NEW[Commander.CommandProcObject
← [proc: proc, doc: doc, clientData: clientData, interpreted: interpreted]]];
};
Enumerate:
PUBLIC
ENTRY
PROC [matchProc:
PROC[key:
ROPE, procData: Commander.CommandProcHandle]
RETURNS [stop:
BOOL]]
RETURNS [key:
ROPE, procData: Commander.CommandProcHandle] = {
outerKey: ROPE;
outerProcData: Commander.CommandProcHandle;
EachPairProc: SymTab.EachPairAction = {
outerProcData ← NARROW[val, Commander.CommandProcHandle];
outerKey ← key;
RETURN[matchProc[key: outerKey, procData: outerProcData]];
};
IF
NOT SymTab.Pairs[x: registry, action: EachPairProc]
THEN {
outerKey ← NIL;
outerProcData ← NIL;
};
RETURN[key: outerKey, procData: outerProcData];
};
Lookup:
PUBLIC
PROC [key:
ROPE]
RETURNS [procData: Commander.CommandProcHandle] = {
procRef: REF ANY;
found: BOOL;
key ← PrependWorkingDir[key];
[found: found, val: procRef] ← SymTab.Fetch[x: registry, key: key];
IF found
AND procRef #
NIL
THEN procData ← NARROW[procRef, Commander.CommandProcHandle]
ELSE procData ← NIL;
};
PrependWorkingDir:
PUBLIC PROC [key:
ROPE]
RETURNS [
ROPE] = {
IF
NOT Rope.IsEmpty[key]
THEN
SELECT Rope.Fetch[key, 0]
FROM
'[, '/ => {
There is already a directory specified, so don't change it.
};
ENDCASE => {
There is no directory part, so prepend the working directory. If no working directory is found, then prepend "///Commands/".
workingDir: ROPE ← NIL;
WITH ProcessProps.GetProp[$WorkingDirectory]
SELECT
FROM
wd: ROPE => workingDir ← wd;
ENDCASE;
IF Rope.IsEmpty[workingDir] THEN workingDir ← "///Commands/";
key ← Rope.Concat[workingDir, key];
};
RETURN [key];
};
Useful procedures for property lists
This procedure is much like List.Assoc, except it works more sensibly for ROPEs
GetProperty:
PUBLIC
ENTRY
PROCEDURE [key:
REF
ANY, aList: List.AList]
RETURNS [val:
REF
ANY] = {
ropeKey: ROPE;
val ← List.Assoc[key: key, aList: aList];
IF val # NIL THEN RETURN;
handle it differently if key is a ROPE
WITH key
SELECT
FROM
r: ROPE => ropeKey ← r;
t: REF TEXT => ropeKey ← Rope.FromRefText[t];
ENDCASE;
IF ropeKey #
NIL
THEN {
FOR l: List.AList ← aList, l.rest
WHILE l #
NIL
DO
WITH l.first.key
SELECT
FROM
r: ROPE => IF Rope.Equal[s1: ropeKey, s2: r, case: TRUE] THEN RETURN[l.first.val];
t: REF TEXT => IF Rope.Equal[s1: ropeKey, s2: Rope.FromRefText[t], case: TRUE] THEN RETURN[l.first.val];
ENDCASE;
ENDLOOP;
};
RETURN[NIL];
};
This procedure is much like List.PutAssoc, except it works more sensibly for ROPEs
PutProperty:
PUBLIC
ENTRY
PROCEDURE [key:
REF
ANY, val:
REF
ANY, aList: List.AList]
RETURNS [List.AList] = {
handle it differently if key is a ROPE and already present on the list
IF
ISTYPE[key,
ROPE]
THEN {
ropeKey: ROPE ← NARROW[key];
FOR l: List.AList ← aList, l.rest
WHILE l #
NIL
DO
IF
ISTYPE[l.first.key,
ROPE]
THEN {
IF Rope.Equal[s1: ropeKey, s2:
NARROW[l.first.key,
ROPE], case:
TRUE]
THEN {
l.first.val ← val;
RETURN[aList];
};
};
ENDLOOP;
};
RETURN[List.PutAssoc[key: key, val: val, aList: aList]];
};
Init:
PROCEDURE = {
registry ← SymTab.Create[mod: 101, case: FALSE];
};
Initialization
Init[];
END.
March 28, 1983 12:26 pm, L. Stewart, created
September 9, 1983 11:04 am, L. Stewart, Cedar 5
November 3, 1983 2:10 pm, L. Stewart, add CommandExtras
January 14, 1984 3:40 pm, L. Stewart, Register uses working directory