// -*- ASCII:EDT -*- // purpose: add and update custom entries in existing macro files. // The existence of such entries is detected by special keys // (tagged by "@BEGIN: key" and "@END: key") // // Use %$('localTargetFile'); as *local* copy (%b) of // %$('globalTargetFile'); (*global* Path %B). Presume that // the string %$('insertBeforeKey'); (default="End;" or // "// @DEFAULT") can be found in the file (start backward // searching at the end of file) // Find more documentation at the end of this file. // // author: G.Schmitz // version: Assign("AOUversion","2005-01-27"); // remark: first template made by Denis Stancer // revision and *substantial* extensions by Robert Schlicht //---------------------------------------------- // check whether we have the correct version //---------------------------------------------- IfStr("%$('requiresAOUversion');","","<>",> "IfStr('%$(|requiresAOUversion|);','%$(|AOUversion|);','>',> 'Prompt(''The addOrUpdate.edt macro is too old!%\> You have to get the latest version from www.winedt.org.%\%\> Shall I download it for you?%\(You have to save it in the folder %\%B\Macros\macro)'',0,3,> ''ShellExecute(|open|,|http://www.winedt.org/Macros/macro/addOrUpdate.edt|,||,||,5);'');> Assign(''AOUerror'',''1'');Exit;');"); //--------------------------------- // SOME INITIALIZING //--------------------------------- Assign("AOUerror","0"); IfStr("%$('extensionKey');","","=","Assign('AOUerror','1');> Prompt('This is addOrUpdate.edt speaking:%\%\No extension key specified. I cannot continue!%\> Complain to the author of the package you are trying to install.',3,1);Exit;"); // if empty, assign default value (= "End;" or "// @DEFAULT") IfStr("%$('insertBeforeKey');","","=","Assign('insertBeforeKey','{ // nice strange feature/bug in CopyFile here (I use it as a feature!): // if the source file and the path for the target file do not exist // then the destination path will be created nevertheless, // even though no file is copied CopyFile("%$('globalTargetFile');", "%$('localTargetFile');", 0, 1);> |); //---------------------------------------------------------------------- // submacro: GenerateTargetFile //---------------------------------------------------------------------- Assign("GenerateTargetFile",!` > SetOK(1); > OpenOutput("%$(|localTargetFile|);"); > WrL("%$(|targetFileGenerationComment|);"); > CloseOutput; > IfOK(" > Relax; > ",!" > Assign(|AOUerror|,|1|); > Prompt('Generation of %\ %$(|localTargetFile|);%\by addOrUpdate.edt failed!!!'); > Exit; > ");> `); // if target file doesn't exist, a decision has to be made, if it should // be generated: // + after asking the user in a dialog, or // + automatically -> use of 'forceTargetFileGeneration' IfFileExists("%$('localTargetFile');","",!` > IfStr("%$(|forceTargetFileGeneration|);","1","=",!" > Do(""%$(|GenerateTargetFile|);""); > ",!" > // If no automatism is required, we have to ask Prompt('This is addOrUpdate.edt speaking:%\%\The target file ""%$(|localTargetFile|);"" does not exist. I cannot continue!%\%\> Shall I generate first a *blank* file for you %\(which will be updated later in this running setup)? %\> (-> say YES) %\%\> If not %\> (-> say NO), %\%\ > complain to the author of the package you are trying to install.',1,3,!' > // Yes -> Macro1 Do(""%$(|GenerateTargetFile|);""); > ',!' > // No -> Macro2 Assign(|AOUerror|,|1|);> Exit; > '); > "); > `); // read the file 'localTargetFile' and put it into reg0 ReadFile("%$('localTargetFile');", 0); GetLength(9, "%!0"); IfStr("%$('deleteExtension');","1","=","Relax;", !` > IfFileExists("%$('extensionFile');","","Assign('AOUerror','1');> Prompt('This is addOrUpdate.edt speaking:%\%\The extension file ""%$(|extensionFile|);"" does not exist. I cannot continue!%\> Complain to the author of the package you are trying to install.',3,1);Exit;"); > // read the file with extensions into reg3 (no delete job) > ReadFile("%$('extensionFile');", 3); > `); //---------------------------------------------------------------------- // submacro: searchAndCondenseDate //---------------------------------------------------------------------- // purpose: search and reformat ISO Date of the form of "2003-03-12T12:23:59" // (and similar) to abbreviated (condensed) form "20030312122359" //---------------------------------------------------------------------- // author: Robert Schlicht //---------------------------------------------------------------------- Assign("searchAndCondenseDate",!`> Release("condensedDate");> Release("uncondensedDate");> SetOK(1);> FindInString("%$('datesource');",> "{\@DATE: \(1+$Numeric+[""/:\-. +""]$\)}|{{\$}Date: \(1+$Numeric+[""/:\-.+ ""]$\)\$}",5,6,1011,%!8);> IfOK(!"GetTag(1,1);> Assign('uncondensedDate','%!1');> LetRegNum(6,0);> Loop(!'SetOK(1);FindInString(''%!1'',''^$Numeric$'',5,6,1001,%!6);> IfOK(!''ReplaceInString(""%!1"","""",%!5,%!6,0,1);'',''Stop;'');');> FormatString('%!1', 1, 'trimboth'); > Assign('condensedDate','%!1');> ");> `); //--------------------------------- // Key Searching //--------------------------------- SetOK(1); // Search for the section "marked" with 'extensionKey' FindInString("%!0", " // Save the index > Assign("beginSnipIdx", "%!7"); > // there are already entries for this mode > // find out which version (date in reg0) the code fragment contains > SetOK(1); > // extract the date Assign("datesource","%!0");> Do("%$('searchAndCondenseDate');");> // we need a normal and condensed version of the dates: > // normal version for user prompt and condensed for comparing > Assign("currentFragmentVersion","%$('uncondensedDate');");> Assign("condensedCurrentFragmentVersion","%$('condensedDate');");> // the extension (reg3) is which version? Reset reg8 (is used as resume index in searchAndCondenseDate )> LetRegNum(8,0);> Assign("datesource","%!3");> Do("%$('searchAndCondenseDate');");> Assign("newFragmentVersion","%$('uncondensedDate');");> Assign("condensedNewFragmentVersion","%$('condensedDate');");> IfStr("%$('condensedNewFragmentVersion');","%$('condensedCurrentFragmentVersion');",">=",> // THEN > "Assign('NewerOrOlder','NEWER');", > // ELSE > "Assign('NewerOrOlder','OLDER');" > ); > IfStr("%$('deleteExtension');","1","=","Assign('NewerOrOlder','NEWER');");> // ask, if it's older > IfStr("%$('NewerOrOlder');","OLDER","=",!*> Prompt("%$('localTargetFile'); already contains %\ additions (%$('currentFragmentVersion');)%\ > Do you wish to replace it by the %$('NewerOrOlder'); one (%$('newFragmentVersion');)?",0,3, > // THEN ("Relax;" means: continue macro execution)> "Relax;", > // ELSE > "Exit;");> *); > // until the end of what has to be replaced > FindInString("%!0", " // FindInString("%!0", "@END: %$('extensionKey');", 7, 8, 0); > Assign("endSnipIdx", "%!8+2"); > `,!| > // OK, then we have a virgin "TargetFile", > // with delete job, there is nothing to delete > IfStr("%$('deleteExtension');","1","=","Assign('AOUerror','1');");> // search the place where to insert the extensions (usually right before "End;") > SetOK(1); > FindInString("%!0", "%$('insertBeforeKey');", 7, 8, 111); > IfOK(!`> Assign("beginSnipIdx", "%!7"); > Assign("endSnipIdx", "%!7"); > // a second run (usually for "// @DEFAULT"), don't bother if > // this one is not found > FindInString("%!0", "%$('insertBeforeKey');", 7, 8, 1111, %!7-1); > IfOK('> Assign("beginSnipIdx", "%!7"); > Assign("endSnipIdx", "%!7"); > '); > `,!` > // this was considered as an error until version 2005-01-03, // now you have to request this behavior explicitly IfStr("%$('forceInsertBeforeKey');","1","=",!' > Assign("AOUerror","1");> Prompt("This is addOrUpdate.edt speaking:%\%\%$(*insertBeforeKey*); not found in %$(*localTargetFile*);. Cannot continue!",3,1,"Exit;"); > ',!' > // the extension should simply be pasted at the end of the file, > // so take the length of the file and assign it as index to both SnipIdx's > GetLength(7, "%!0"); > Assign("beginSnipIdx", "%!7"); > Assign("endSnipIdx", "%!7"); > '); > `); > |); SetOK(1); > //----------------------------------------------------- // INSERT THE CHUNK AND WRITE THE FILE //----------------------------------------------------- LetRegNum(7,"%$('beginSnipIdx');"); LetRegNum(8,"%$('endSnipIdx');"); ExtractByIndex(1, "%!0", 0, %!7-1); ExtractByIndex(2, "%!0", %!8, %!9); OpenOutput("%$('localTargetFile');.new"); WrS("%!1"); // Only write the fragment, if no delete command was set IfStr("%$('deleteExtension');","1","=","Relax;", !"WrS('%!3');"); WrS("%!2"); CloseOutput; CopyFile("%$('localTargetFile');", "%$('localTargetFile');.bak", 1, 0); CopyFile("%$('localTargetFile');.new", "%$('localTargetFile');", 1, 0); DeleteFile("%$('localTargetFile');.new"); Release("currentFragmentVersion"); Release("newFragmentVersion"); Release("NewerOrOlder"); Release("beginSnipIdx"); Release("endSnipIdx"); Release("localTargetFile"); Release("globalTargetFile"); Release("insertBeforeKey"); Release("forceInsertBeforeKey"); Release("extensionFile"); Release("deleteExtension"); Release("requiresAOUversion"); Release("AOUversion"); Release("targetFileGenerationComment"); Release("forceTargetFileGeneration"); End; // ====================================================================================== This macro inserts or updates tagged code fragments in any sort of macro but makes especially sense in shortcut macros and of course also in GDI settings. For the moment, the macro checks the "@BEGIN" , "@END" and the "@DATE" tag (see example below). The macro is also able to insert new code fragments before the "@DEFAULT" tag resp. End; command or to update an existing section if it is newer than the existing one ("@DATE" has to be in ISO format: YYYY-MM-DD). This behavior is essential, because a setup routine has to respect customizations made by other mode contributors (who perhaps used this macro in their setup routines too). Simply copying new versions over existing ones is not a solution! Usage Suppose you have a macro file (eg. completeWord.edt invoked by a shortcut) that looks like this: // @DEFAULT CMD("Complete Word"); End; You want to insert a custom macro fragment, that should only react in a specific mode, in this example "XML" . // @BEGIN: XML // @DATE: 2003-02-06 // @AUTHOR: Georges Schmitz // ------------------------------------------------------------- IfisMode("XML","%!m","Exe('%b\Config\XML\macros\xmlTagCompletion.edt');Exit;"); // ------------------------------------------------------------- // @END: XML or of the following form: // $Begin: XML $ // $Date: 2005/01/21 13:43:57 $ // $Author: schmitz $ // ------------------------------------------------------------- IfisMode("XML","%!m","Exe('%b\Config\XML\macros\xmlTagCompletion.edt');Exit;"); // ------------------------------------------------------------- // $End: XML $ You do not know 1. if this fragment already exists in completeWord.edt or 2. if your setup macro comes with the newest version of the fragment 3. and you don't want to edit the shortcut macro by hand (well, the running setup wouldn't be a setup anymore) Incorporating the following macro fragment into your setup will do the job. Assign('extensionKey', 'XML'); Assign('extensionFile', 'extensions\tagCompletion.edt'); Assign('localTargetFile', '%b\Menus\Tools\completeWord.edt'); Assign('globalTargetFile', '%B\Menus\Tools\completeWord.edt'); Exe('%B\Macros\macro\addOrUpdate.edt'); Used Local Variables extensionKey A key like XML that is used in the "@BEGIN" and "@END" tags. extensionKey is not released at the end of the macro, because in mode setup routines, you will probably execute this macro more than once with the same extensionKey value. deleteExtension If set to 1, instruct the macro to delete the specific extension (helpful in uninstall routines). In this case, the following parameter extensionFile needs not to be specified. extensionFile The path to the file with the specific extension globalTargetFile the path to the global copy of the macro (%B), eg. %B\Menus\Tools\completeWord.edt. A setup writer normally doesn't know, if WinEdt is running with a specific user profile at all, (located in %b), so he can specify both locations. localTargetFile the path to the local copy of the macro (%b), where your fragment should be inserted, eg. %b\Menus\Tools\completeWord.edt (if localTargetFile doesn't exist, globalTargetFile is automatically copied to localTargetFile!). insertBeforeKey presume that the content of this global variable can be found in the file (start backward searching at the end of file). If not defined, then End; or // @DEFAULT is used as default forceInsertBeforeKey the absence of the key in the target file should be considered as an error requiresAOUversion can be used to demand a specific mininmal version of addOrUpdate.edt (ISO date format) If the code could not be written for any reason, the variable %$('AOUerror'); will be "1", otherwise "0". forceTargetFileGeneration if the target file didn't exist, use this flag to force the generation of an empty one targetFileGenerationComment see previous flag: this comment is inserted at the beginning of the generated file, eg. something like: GetDate(7); Assign("targetFileGenerationComment","//Generated by XML Setup on %!7");