TildeCompact:
PROCEDURE [dir: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
RopeIsPrefix:
PROCEDURE [prefix: Rope.
ROPE, subject: Rope.
ROPE, case:
BOOL ←
TRUE]
RETURNS [
BOOL] = {
RETURN [subject.Substr[len: prefix.Length[]].Index[s2: prefix, case: case] = 0];
};
FileNamesIsAbsolutePath:
PROCEDURE [name: Rope.
ROPE]
RETURNS [
BOOL] = {
RETURN [ name.Fetch[0] = '/ OR name.Fetch[0] = '[ ];
};
home: Rope.ROPE = FileNames.HomeDirectory[];
dir ← FileNames.ResolveRelativePath[FileNames.ConvertToSlashFormat[dir]];
IF dir.Length[] # 0
AND
NOT FileNamesIsAbsolutePath[dir]
THEN
dir ← Rope.Concat[FileNames.CurrentWorkingDirectory[], dir];
IF RopeIsPrefix[prefix: home, subject: dir]
THEN
dir ← Rope.Concat[GetHomeDirectoryAbbreviation[], Rope.Substr[dir, home.Length[]]];
RETURN [dir];
};
ChangeWorkingDirectory: Commander.CommandProc = {
[cmd: REF CommandObject] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL]
CommandObject = [
in, out, err: STREAM, commandLine, command: Rope.ROPE,
propertyList: List.AList, procData: CommandProcHandle]
wDir: Rope.ROPE;
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd,
TRUE
! CommandTool.Failed => {msg ← errorMsg; GO TO oops}];
list: LIST OF Rope.ROPE ← NARROW[CommandTool.GetProp[cmd, $WorkingDirectoryStack]];
SELECT cmd.procData.clientData
FROM
$PushWorkingDirectory, $Push, $PushR =>
list ← CONS[FileNames.CurrentWorkingDirectory[], list];
ENDCASE;
SELECT cmd.procData.clientData
FROM
$ChangeWorkingDirectory, $CD, $CDR, $PushWorkingDirectory, $Push, $PushR => {
root: BOOL ← (cmd.procData.clientData = $CDR OR cmd.procData.clientData = $PushR);
SELECT argv.argc
FROM
1 => wDir ← IF root THEN "///" ELSE FileNames.HomeDirectory[];
2 => {
wDir ← argv[1];
IF root
THEN {
wDir ← FileNames.ConvertToSlashFormat[
FS.ExpandName[wDir, "///"
!
FS.Error => {
msg ← FSErrorMsg[error];
GO TO oops
};
].fullFName];
};
};
ENDCASE => {
msg ← "Usage: ChangeWorkingDirectory directoryName";
GO TO oops
};
};
$PopWorkingDirectory, $Pop => {
IF list =
NIL
THEN wDir ← FileNames.CurrentWorkingDirectory[]
ELSE {
wDir ← list.first;
list ← list.rest;
};
};
$RollDirectoryStack, $RollDS => {
count: CARDINAL;
ListOfRopeAppend1:
PROCEDURE [list:
LIST
OF Rope.
ROPE, element: Rope.
ROPE]
RETURNS [
LIST
OF Rope.
ROPE] = {
Note that this procedure only knows it is dealing with lists of Rope.ROPE in the declaration of the arguments and return value. Given a type T, this could take lists of T and a T and return a list of T.
IF list =
NIL
THEN
RETURN [CONS[element, NIL]]
ELSE
RETURN [CONS[list.first, ListOfRopeAppend1[list.rest, element]]];
};
SELECT argv.argc
FROM
1 => {
no arguments means roll the directory stack once.
count ← 1;
};
2 => {
one argument means roll the directory stack argv[1] times
count ← Convert.CardFromRope[argv[1]
! Convert.Error => GO TO rollUsage
];
};
ENDCASE => GO TO rollUsage;
cons the current directory onto the list, roll the list, and extract the first element.
list ← CONS[FileNames.CurrentWorkingDirectory[], list];
FOR rolls:
CARDINAL
IN [1..count]
DO
list ← ListOfRopeAppend1[list.rest, list.first];
ENDLOOP;
wDir ← list.first;
list ← list.rest;
EXITS
rollUsage => {
msg ← "Usage: RollDirectoryStack [count: CARDINAL ← 1]";
GO TO oops;
};
};
ENDCASE => GO TO huh;
[result, msg] ← SetWD[wDir];
IF result # $Failure
THEN {
cmd.propertyList ← List.PutAssoc[$WorkingDirectoryStack, list, cmd.propertyList];
SetCommandToolHerald[cmd, msg];
};
SELECT cmd.procData.clientData
FROM
$CD, $Push, $Pop, $RollDS => msg ← TildeCompact[msg];
ENDCASE;
EXITS
oops => result ← $Failure;
huh => {
result ← $Failure;
msg ← "bad clientData"
};
};
SetWD:
PROCEDURE [wDir: Rope.
ROPE]
RETURNS [result:
REF
ANY ←
NIL, msg: Rope.
ROPE ←
NIL] = {
wDir ← FileNames.ResolveRelativePath[FileNames.ConvertToSlashFormat[wDir]];
Do a bit of checking!
IF wDir.Length[] = 0 THEN RETURN[$Failure, "empty working directory"];
IF wDir.Fetch[0] # '/
THEN
wDir ← Rope.Concat[FileNames.CurrentWorkingDirectory[], wDir];
IF wDir.Fetch[wDir.Length[] - 1] # '/ THEN wDir ← Rope.Concat[wDir, "/"];
IF wDir.Length[] < 3 THEN RETURN[NIL];
msg ← wDir;
[] ← List.PutAssoc[key: $WorkingDirectory, val: wDir, aList: ProcessProps.GetPropList[]];
};
PrintWorkingDirectory: Commander.CommandProc = {
[cmd: REF CommandObject] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL]
CommandObject = [
in, out, err: STREAM, commandLine, command: ROPE,
propertyList: List.AList, procData: CommandProcHandle]
IF cmd.procData.clientData = $PWD
THEN
RETURN[NIL, TildeCompact[FileNames.CurrentWorkingDirectory[]]]
ELSE
RETURN[NIL, FileNames.CurrentWorkingDirectory[]];
};
PrintDirectoryStack: Commander.CommandProc = {
[cmd: REF CommandObject] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL]
CommandObject = [
in, out, err: STREAM, commandLine, command: ROPE,
propertyList: List.AList, procData: CommandProcHandle]
IF cmd.procData.clientData = $PDS
THEN msg ← TildeCompact[FileNames.CurrentWorkingDirectory[]]
ELSE msg ← FileNames.CurrentWorkingDirectory[];
FOR list:
LIST
OF Rope.
ROPE ←
NARROW[CommandTool.GetProp[cmd, $WorkingDirectoryStack]], list.rest
UNTIL list =
NIL
DO
IF cmd.procData.clientData = $PDS
THEN msg ← Rope.Cat[msg, " ", TildeCompact[list.first]]
ELSE msg ← Rope.Cat[msg, " ", list.first];
ENDLOOP;
RETURN[NIL, msg];
};
WorkingDirectory: Commander.CommandProc = {
[cmd: REF CommandObject] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL]
CommandObject = [
in, out, err: STREAM, commandLine, command: ROPE,
propertyList: List.AList, procData: CommandProcHandle]
SetCommandToolHerald[cmd: cmd, wDir: FileNames.CurrentWorkingDirectory[]];
};
Init:
PROCEDURE = {
Commander.Register[
key: "PrintWorkingDirectory",
proc: PrintWorkingDirectory,
doc: "Print working directory",
clientData: $PrintWorkingDirectory];
Commander.Register[
key: "PWD",
proc: PrintWorkingDirectory,
doc: "Print working directory",
clientData: $PWD];
Commander.Register[
key: "PrintDirectoryStack",
proc: PrintDirectoryStack,
doc: "Print directory stack",
clientData: $PrintDirectoryStack];
Commander.Register[
key: "PDS",
proc: PrintDirectoryStack,
doc: "Print working directory",
clientData: $PDS];
Commander.Register[
key: "ChangeWorkingDirectory",
proc: ChangeWorkingDirectory,
doc: "Change working directory",
clientData: $ChangeWorkingDirectory];
Commander.Register[
key: "CD",
proc: ChangeWorkingDirectory,
doc: "Change working directory",
clientData: $CD];
Commander.Register[
key: "CDR",
proc: ChangeWorkingDirectory,
doc: "Change working directory (root relative)",
clientData: $CDR];
Commander.Register[
key: "PushWorkingDirectory",
proc: ChangeWorkingDirectory,
doc: "Push working directory",
clientData: $PushWorkingDirectory];
Commander.Register[
key: "Push",
proc: ChangeWorkingDirectory,
doc: "Push working directory",
clientData: $Push];
Commander.Register[
key: "PushR",
proc: ChangeWorkingDirectory,
doc: "Push working directory (root relative)",
clientData: $PushR];
Commander.Register[
key: "PopWorkingDirectory",
proc: ChangeWorkingDirectory,
doc: "Pop working directory",
clientData: $PopWorkingDirectory];
Commander.Register[
key: "Pop",
proc: ChangeWorkingDirectory,
doc: "Pop working directory",
clientData: $Pop];
Commander.Register[
key: "RollDirectoryStack",
proc: ChangeWorkingDirectory,
doc: "Roll the directory stack n times",
clientData: $RollDirectoryStack];
Commander.Register[
key: "RollDS",
proc: ChangeWorkingDirectory,
doc: "Roll the directory stack n times",
clientData: $RollDS];
Commander.Register[
key: "WorkingDirectory",
proc: WorkingDirectory,
doc: "Initialize the CommandTool herald",
clientData: NIL];
};
}.