<Top>GetDWIM.DF>> <> 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; <> { 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.