GetDWIM.Mesa, from [Indigo]<Cedar>Top>GetDWIM.DF
Last Edited by: Spreitzer, November 25, 1984 12:17:24 pm PST
DIRECTORY BasicTime, DFOperations, DFUtilities, FS, IO, List, ProcessProps, Rope, TEditOpsExtras, UserProfile, ViewerClasses;
GetDWIM:
CEDAR
PROGRAM
IMPORTS DFUtilities, FS, IO, Rope, TEditOpsExtras, UserProfile =
BEGIN
ROPE: TYPE = Rope.ROPE;
ROPEList: TYPE = LIST OF ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
inPlace, processDF, assocExts, followAttachments: BOOLEAN ← FALSE;
OldFNP: PROC [ROPE, Viewer] RETURNS [fileName: ROPE, search: ROPE] ← NIL;
log: IO.STREAM ← NIL;
Debug: PROC = {log ← IO.ROS[]};
DontDebug: PROC = {log ← NIL};
GetLog: PROC RETURNS [r: ROPE] = {r ← log.RopeFromROS[]};
sourceFileExtensions, implFileExtensions: ROPEList ← NIL;
DWIMit:
PROC [orgName:
ROPE, viewer: Viewer]
RETURNS [fileName:
ROPE, search:
ROPE] =
BEGIN
Try:
PROC [dir, short:
ROPE, BaseMatch,
FullMatch:
PROC [dir, file, ext:
ROPE]
RETURNS [stop:
BOOL]]
RETURNS [stop:
BOOL] = {
cp: FS.ComponentPositions;
expanded, dirPart: ROPE;
stop ← FALSE;
[expanded, cp, ] ← FS.ExpandName[dir.Concat[short], NIL];
dirPart ← expanded.Substr[start: 0, len: cp.base.start];
IF goalVersioned
THEN {
IF expanded.Substr[start: cp.base.start, len: cp.ver.start+cp.ver.length - cp.base.start].Equal[s2: goalFull, case: FALSE] THEN stop ← FullMatch[dirPart, goalFull, NIL];
}
ELSE {
testBase: ROPE ← expanded.Substr[start: cp.base.start, len: cp.base.length];
testExt: ROPE ← expanded.Substr[start: cp.ext.start, len: cp.ext.length];
IF testBase.Equal[goalBase,
FALSE]
THEN {
stop ← IF testExt.Equal[goalExt, FALSE] THEN FullMatch[dirPart, goalFull, NIL] ELSE BaseMatch[dirPart, testBase, testExt]
};
};
stop ← stop;
};
FullMatch:
PROC [dir, file, ext:
ROPE]
RETURNS [stop:
BOOL] = {
IF Exists[fileName ← dir.Cat[file]]
THEN {
search ← ext;
RETURN [found ← TRUE]};
stop ← stop;
};
BaseMatch:
PROC [dir, file, ext:
ROPE]
RETURNS [stop:
BOOL] = {
allButExt: ROPE ← dir.Cat[file];
stop ← FALSE;
IF goalExtended
THEN {
IF assocExts
AND Exists[fileName ← allButExt.Cat[".", goalExt]]
THEN {
search ← NIL;
RETURN [found ← TRUE]};
IF Member[ext, implFileExtensions]
AND Exists[fileName ← allButExt.Cat[".", ext]]
THEN {
search ← goalExt;
RETURN [found ← TRUE]};
IF assocExts
AND
NOT allButExt.Equal[lastImplAssoced,
FALSE]
THEN {
lastImplAssoced ← allButExt;
FOR ifel: ROPEList ← implFileExtensions, ifel.rest
WHILE ifel #
NIL
DO
IF Exists[fileName ← allButExt.Cat[".", ifel.first]]
THEN {
search ← goalExt;
RETURN [found ← TRUE]};
ENDLOOP;
};
};
IF
NOT goalExtended
THEN {
IF Member[ext, sourceFileExtensions]
AND Exists[fileName ← allButExt.Cat[".", ext]]
THEN {
search ← NIL;
RETURN [found ← TRUE]};
IF assocExts
AND
NOT allButExt.Equal[lastSourceAssoced,
FALSE]
THEN {
lastSourceAssoced ← allButExt;
FOR ifel: ROPEList ← sourceFileExtensions, ifel.rest
WHILE ifel #
NIL
DO
IF Exists[fileName ← allButExt.Cat[".", ifel.first]]
THEN {
search ← goalExt;
RETURN [found ← TRUE]};
ENDLOOP;
};
};
stop ← stop;
};
found: BOOL ← FALSE;
goalFull, goalExpanded, goalBase, goalExt: ROPE;
goalCP: FS.ComponentPositions;
goalExtended, goalVersioned: BOOL;
wDir: ROPE ← IF viewer # NIL THEN TEditOpsExtras.WorkingDirectoryFromViewer[viewer] ELSE NIL;
lastSourceAssoced, lastImplAssoced: ROPE ← NIL;
goalFull ← orgName;
[goalExpanded, goalCP, ] ← FS.ExpandName[orgName];
goalBase ← goalExpanded.Substr[start: goalCP.base.start, len: goalCP.base.length];
goalExt ← goalExpanded.Substr[start: goalCP.ext.start, len: goalCP.ext.length];
goalExtended ← goalCP.ext.length # 0;
goalVersioned ← goalCP.ver.length # 0;
First, look around locally.
{
Consume:
PROC [fullFName, attachedTo:
ROPE, created: BasicTime.
GMT, bytes:
INT, keep:
CARDINAL]
RETURNS [continue:
BOOLEAN]
--FS.InfoProc-- = {
IF Try[NIL, fullFName, BaseMatch, FullMatch] THEN RETURN [FALSE];
IF followAttachments AND attachedTo # NIL AND Try[NIL, attachedTo, BaseMatch, FullMatch] THEN RETURN [FALSE];
};
IF assocExts
AND followAttachments
THEN {
FS.EnumerateForInfo[pattern: goalBase.Cat["!H"], proc: Consume, wDir: wDir];
IF found THEN RETURN;
FS.EnumerateForInfo[pattern: goalBase.Cat[".*!H"], proc: Consume, wDir: wDir];
IF found THEN RETURN;
}
ELSE {
EnumerateForInfo[base: goalBase, exts: sourceFileExtensions, proc: Consume, wDir: wDir];
IF found THEN RETURN;
};
};
IF viewer #
NIL
THEN
BEGIN
IF processDF
AND IsADFFileName[viewer.file]
THEN
BEGIN
[] ← Find[viewer.file, Try, BaseMatch, FullMatch];
IF found THEN RETURN;
END;
END;
IF OldFNP # NIL THEN [fileName, search] ← OldFNP[orgName, viewer]
ELSE {fileName ← search ← NIL};
END;
EnumerateForInfo:
PROC [base:
ROPE, exts: ROPEList, proc:
FS.InfoProc, wDir:
ROPE ←
NIL] = {
FOR exts ← exts, exts.rest
WHILE exts #
NIL
DO
fullFName, attachedTo: ROPE;
keep: CARDINAL;
bytes: INT;
created: BasicTime.GMT;
[fullFName:fullFName, attachedTo:attachedTo, keep:keep, bytes:bytes, created:created] ← FS.FileInfo[name: base.Cat[".", exts.first], remoteCheck: FALSE, wDir: wDir !FS.Error => LOOP];
IF NOT proc[fullFName:fullFName, attachedTo:attachedTo, keep:keep, bytes:bytes, created:created] THEN EXIT;
ENDLOOP;
wDir ← wDir;
};
Find:
PROC
[
dfFileName: ROPE,
Try:
PROC
[
dir, short: ROPE,
BaseMatch, FullMatch: PROC [dir, file, ext: ROPE] RETURNS [stop: BOOL]]
RETURNS [stop: BOOL],
BaseMatch, FullMatch: PROC [dir, file, ext: ROPE] RETURNS [stop: BOOL]]
RETURNS [stopped: BOOL] =
BEGIN
PerItem:
PROC [item:
REF
ANY]
RETURNS [stop:
BOOL ←
FALSE]
--DFUtilities.ProcessItemProc-- =
BEGIN
WITH item
SELECT
FROM
di: REF DFUtilities.DirectoryItem => dir ← di.path1;
fi: REF DFUtilities.FileItem => IF Try[dir, fi.name, BaseMatch, FullMatch] THEN stop ← TRUE;
ii:
REF DFUtilities.ImportsItem => {
IF Try[NIL, ii.path1, BaseMatch, FullMatch] THEN stop ← TRUE
ELSE {
tryThis: BOOL ← ii.list = NIL;
RightOn:
PROC [dir, file, ext:
ROPE]
RETURNS [stop:
BOOL] = {
tryThis ← stop ← TRUE;
};
Almost:
PROC [dir, file, ext:
ROPE]
RETURNS [stop:
BOOL] = {
IF stop ← assocExts THEN tryThis ← TRUE;
};
IF
NOT tryThis
THEN
FOR i:
NAT
IN [0 .. ii.list.nEntries)
WHILE
NOT tryThis
DO
[] ← Try["[]<>", ii.list[i].name, Almost, RightOn];
ENDLOOP;
IF tryThis THEN stop ← Find[ii.path1, Try, BaseMatch, FullMatch];
};
};
ii: REF DFUtilities.IncludeItem => stop ← Find[ii.path1, Try, BaseMatch, FullMatch];
c: REF DFUtilities.CommentItem => NULL;
w: REF DFUtilities.WhiteSpaceItem => NULL;
ENDCASE => ERROR;
stopped ← stop;
END;
from: IO.STREAM ← NIL;
dir: ROPE ← NIL;
stopped ← FALSE;
from ← FS.StreamOpen[dfFileName !FS.Error => CONTINUE];
IF from = NIL THEN RETURN;
DFUtilities.ParseFromStream[in: from, proc: PerItem];
from.Close[];
END;
Member:
PROC [r:
ROPE, in: ROPEList]
RETURNS [m:
BOOL] = {
FOR in ← in, in.rest
WHILE in #
NIL
DO
IF in.first.Equal[r, FALSE] THEN RETURN [TRUE];
ENDLOOP;
m ← FALSE};
IsADFFileName:
PROC [name:
ROPE]
RETURNS [isa:
BOOLEAN] =
{isa ← name.Find[s2: ".DF!", case: FALSE] >= 0};
Exists:
PROC [fileName:
ROPE]
RETURNS [exists:
BOOLEAN] =
BEGIN
exists ← TRUE;
[] ← FS.FileInfo[name: fileName, remoteCheck: FALSE ! FS.Error => {exists ← FALSE; CONTINUE}];
exists ← exists; --wouldn't it be nice if we could really break on exit?
END;
NoticeProfileChanges:
PROC [reason: UserProfile.ProfileChangeReason]
--UserProfile.ProfileChangedProc-- =
BEGIN
processDF ← UserProfile.Boolean["GetDWIM.ProcessDF", TRUE];
assocExts ← UserProfile.Boolean["GetDWIM.AssociateExtensions", TRUE];
followAttachments ← UserProfile.Boolean["GetDWIM.FollowAttachments", TRUE];
sourceFileExtensions ← UserProfile.ListOfTokens["SourceFileExtensions", LIST["mesa", "tioga", "df", "cm", "config", "style"]];
implFileExtensions ← UserProfile.ListOfTokens["ImplFileExtensions", LIST["mesa", "cedar"]];
IF (processDF
OR assocExts)
AND
NOT inPlace
THEN
BEGIN
inPlace ← TRUE;
OldFNP ← TEditOpsExtras.ReplaceFileNameProc[DWIMit];
END;
END;
UserProfile.CallWhenProfileChanges[NoticeProfileChanges];
END.