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: BOOLEANFALSE;
OldFNP: PROC [ROPE, Viewer] RETURNS [fileName: ROPE, search: ROPE] ← NIL;
log: IO.STREAMNIL;
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: BOOLFALSE;
goalFull, goalExpanded, goalBase, goalExt: ROPE;
goalCP: FS.ComponentPositions;
goalExtended, goalVersioned: BOOL;
wDir: ROPEIF viewer # NIL THEN TEditOpsExtras.WorkingDirectoryFromViewer[viewer] ELSE NIL;
lastSourceAssoced, lastImplAssoced: ROPENIL;
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: ROPENIL] = {
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: BOOLFALSE] --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.STREAMNIL;
dir: ROPENIL;
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.