Script to integrate / include / embed referenced files again and again

Script to integrate / include / embed referenced files again and again

1581
Power UserPower User
1581

    Feb 06, 2018#1

    Just a basic question, not that important at the moment.

    In many other software (Word, CAD, ..) you can "reference" external files to a "main document". Are there some ideas or ways to do something like this in UE?

    Example:

    I have partA.txt and partB.txt and main.txt.

    In main.txt there should be a code like this:

    Code: Select all

    Code bla bla
    Code bla bla
    ; command: remove following section until ENDFLAG and insert partA.txt 
    ...
    old content of old partA.txt
    ...
    ; ENDFLAG for referenced file above
    Code bla
    Code bla bla
    
    ; command: remove following section until ENDFLAG and insert partB.txt 
    ...
    old content of old partB.txt
    ...
    ; ENDFLAG for referenced file above
    
    Then I press the "red button" and sections are searched and replaced - every time I press the button ...

    Is there already something like this?
    Could be a JavaScript thing, isn't it?
    Or a new feature?
    UE 26.20.0.74 German / Win 10 x 64 Pro

    6,603547
    Grand MasterGrand Master
    6,603547

      Feb 07, 2018#2

      There is the command Insert File to insert content of a file at current position of the caret or replace the current selection by content of file to insert which is unfortunately not available as scripting command.

      However, it is possible to use an UltraEdit script for this task.

      Code: Select all

      function ResolveRelativePath (sFullNameOfFile)
      {
         var bUncPath = (sFullNameOfFile.search(/^\\\\/) == 0) ? true : false;
      
         // Replace each series of backslashes by a single backslash.
         var sFullPathName = sFullNameOfFile.replace(/\\+/g,"\\");
      
         // But do not remove the two backslashes at beginning of a UNC path.
         if (bUncPath) sFullPathName = "\\" + sFullPathName;
      
         // Replace all occurrences of ..\ by << for easier removing next all
         // occurrences of .\ in path. << is used as being invalid in a path and
         // just < as well as << are interpreted literal in a regular expression.
         sFullPathName = sFullPathName.replace(/\.\.\\/g,"<<");
      
         // Remove all .\ from path.
         sFullPathName = sFullPathName.replace(/(?:\.\\)+/g,"");
      
         // Resolve ..\ in file path being replaced before by << by removing each
         // occurrence of ..\ respectively <<  with the directory before as long
         // as this is possible. Return unmodified file name string as passed to
         // this function if that is not possible, e.g. too many ..\ in path.
         while (sFullPathName.search(/<</) >= 0)
         {
            var sTempFullPathName = sFullPathName;
            sFullPathName = sFullPathName.replace(/\\[^\\]+\\<</,"\\");
            if (sFullPathName == sTempFullPathName)
            {
               return sFullNameOfFile;
            }
         }
      
         // Return file name string as passed to the function if
         // the resolved file name string is an empty string now.
         if (!sFullPathName.length)
         {
            return sFullNameOfFile;
         }
      
         return sFullPathName;
      }
      
      
      if (UltraEdit.document.length > 0)  // Is any file opened?
      {
         // Define environment for this script.
         UltraEdit.insertMode();
         UltraEdit.columnModeOff();
      
         // Move caret to top of the active file.
         UltraEdit.activeDocument.top();
      
         // Get file path, document index and line termination of active file.
         var sFilePath = GetFilePath();
         var nActiveFile = GetFileIndex();
         var sLineTerm;
         if(UltraEdit.activeDocument.lineTerminator < 1) sLineTerm = "\r\n";
         else if(UltraEdit.activeDocument.lineTerminator == 1) sLineTerm = "\n";
         else sLineTerm = "\r";
      
         UltraEdit.perlReOn();
         UltraEdit.activeDocument.findReplace.mode=0;
         UltraEdit.activeDocument.findReplace.matchCase=true;
         UltraEdit.activeDocument.findReplace.matchWord=false;
         UltraEdit.activeDocument.findReplace.regExp=true;
         UltraEdit.activeDocument.findReplace.searchDown=true;
         if (typeof(UltraEdit.activeDocument.findReplace.searchInColumn) == "boolean")
         {
            UltraEdit.activeDocument.findReplace.searchInColumn=false;
         }
         UltraEdit.selectClipboard(9);
         var bShowOutputWindow = false;
      
         while(UltraEdit.activeDocument.findReplace.find("; command: remove following section until ENDFLAG and insert +\\K.\\S.*$"))
         {
            // Get selected file name without trailing spaces.
            var sFileName = UltraEdit.activeDocument.selection.replace(/[\t ]+$/,"");
      
            // Replace all forward slashes by backslashes in file name string.
            // Note: This replace should not be done if the script should
            //       be used for files opened using FTP, FTPS or SFTP.
            var sFileName = sFileName.replace(/[\/]/g,"\\");
      
            // Does the file name not start with a drive letter and a colon
            // or with two backslashes as a UNC path starts with, prepend
            // the file name with path of current file.
            if(sFileName.search(/^[A-Za-z]:|\\\\/) < 0)
            {
               sFileName = sFilePath+sFileName;
            }
      
            // Resolve quickly file name with a relative path to a file name
            // with full path. This quick and simple relative path resolve is
            // not completely according to Windows standard, but should work in
            // general. For details see Windows kernel function GetFullPathName
            // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963.aspx
            // and MSDN article "Naming Files, Paths and Namespaces (Windows)"
            // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx
            sFileName = ResolveRelativePath(sFileName);
      
            // Get index of file to insert in list of already opened files?
            var nInsertFile = GetFileIndex(sFileName);
      
            // Is the file to insert not already opened?
            if (nInsertFile < 0)
            {
               nFileCount = UltraEdit.document.length;
               UltraEdit.open(sFileName);
               // Has the number of opened files changed?
               if (nFileCount != UltraEdit.document.length)
               {
                  // The file could be opened. Select everything in this file.
                  UltraEdit.activeDocument.selectAll();
      
                  // Is the file not empty which means there is a selection?
                  if(UltraEdit.activeDocument.isSel())
                  {
                     UltraEdit.activeDocument.copy();
                  }
                  else  // The file is empty.
                  {
                     UltraEdit.outputWindow.write("Empty file: "+sFileName);
                     UltraEdit.clearClipboard();
                     bShowOutputWindow = true;
                  }
                  UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
                  UltraEdit.document[nActiveFile].setActive();
               }
               else  // The file to insert could not be opened.
               {
                  UltraEdit.outputWindow.write("Failed to open file: "+sFileName);
                  UltraEdit.clearClipboard();
                  bShowOutputWindow = true;
               }
            }
            else     // The file to insert is opened already in UltraEdit.
            {
               // Get position of caret in this file.
               var nLineNumber = UltraEdit.document[nInsertFile].currentLineNum;
               var nColumnNumber = UltraEdit.document[nInsertFile].currentColumnNum;
      
               // Select everything in this file.
               UltraEdit.document[nInsertFile].selectAll();
      
               // Is the file not empty which means there is a selection?
               if(UltraEdit.document[nInsertFile].isSel())
               {
                  UltraEdit.document[nInsertFile].copy();
                  UltraEdit.document[nInsertFile].gotoLine(nLineNumber,nColumnNumber)
               }
               else  // The file is empty.
               {
                  UltraEdit.outputWindow.write("Empty file: "+UltraEdit.document[nInsertFile].path);
                  UltraEdit.clearClipboard();
                  bShowOutputWindow = true;
               }
            }
      
            // Set caret to start of next line.
            UltraEdit.activeDocument.gotoLine(UltraEdit.activeDocument.currentLineNum+1,1);
      
            // Get text on this line to check if it starts with end marker string.
            var nActiveLineNumber = UltraEdit.activeDocument.currentLineNum;
            UltraEdit.activeDocument.selectLine()
            var sActiveLine = UltraEdit.activeDocument.selection;
            UltraEdit.activeDocument.gotoLine(nActiveLineNumber,1);
      
            if (sActiveLine.search(/^; ENDFLAG/) != 0)
            {
               // Select everything from this position to next ; ENDFLAG
               if(!UltraEdit.activeDocument.findReplace.find("^(?=; ENDFLAG)"))
               {
                  UltraEdit.outputWindow.write("There is no ; ENDFLAG after line: " + nActiveLineNumber);
                  bShowOutputWindow = true;
                  break;
               }
               UltraEdit.activeDocument.gotoLineSelect(nActiveLineNumber,1);
            }
      
            // Is there text from file to insert or to replace an existing text?
            if (UltraEdit.clipboardContent.length)
            {
               // Replace the selection by just copied text from other file.
               UltraEdit.activeDocument.paste();
      
               // Insert a line termination if the inserted content of
               // other file has no line termination at end of file.
               if (UltraEdit.activeDocument.isColNumGt(1))
               {
                  UltraEdit.activeDocument.write(sLineTerm);
                  if (UltraEdit.activeDocument.isColNumGt(1))
                  {
                     UltraEdit.activeDocument.deleteToStartOfLine();
                  }
               }
            }
            else  // There is nothing to insert. So just delete the
            {     // selected text if something is select all all.
               if (UltraEdit.activeDocument.isSel())
               {
                  UltraEdit.activeDocument.deleteText();
               }
            }
         }
      
         // Clear user clipboard 9, select clipboard of operating
         // system and move caret in active file to top.
         UltraEdit.clearClipboard();
         UltraEdit.selectClipboard(0);
         UltraEdit.activeDocument.top();
      
         // Show output window at least for a short time if something
         // was written to output window during execution of the script.
         if (bShowOutputWindow)
         {
            UltraEdit.outputWindow.showWindow(true);
         }
      }
      
      There must be copied into the script file additionally the functions GetFilePath and GetFileIndex for completeness.
      Best regards from an UC/UE/UES for Windows user from Austria

      1581
      Power UserPower User
      1581

        Feb 09, 2018#3

        Many thanks to Vienna! 🇦🇹
        UE 26.20.0.74 German / Win 10 x 64 Pro

        6,603547
        Grand MasterGrand Master
        6,603547

          Mar 28, 2018#4

          Peter, I improved the script above further. The updated version has following improvements:
          1. Function ResolveRelativePath() added which resolves a file name with relative path to a file name with full path for better checking if a file to insert/replace is opened already in UltraEdit. This function is no real replacement for Windows kernel function GetFullPathName which handles all variations of relative paths according to Microsoft article Naming Files, Paths and Namespaces (Windows). But it should work well for typical relative paths.
          2. The script handles now also correct a file with following content:

            Code: Select all

            Code bla bla
            Code bla bla
            ; command: remove following section until ENDFLAG and insert partA.txt 
            ; ENDFLAG for referenced file above
            Code bla
            Code bla bla
            
            ; command: remove following section until ENDFLAG and insert partB.txt 
            ; ENDFLAG for referenced file above
            The first posted version of the script failed to handle the use case of no text between begin and end marker line.
          3. The updated script detects and reports in output window if a file to insert could not be opened at all and just deletes the text between the marker lines in this case.
          4. The updated script detects, reports to output window, and handles correct the use case of opened file is completely empty.
          5. And there is an additional error check added in case of no ; ENDFLAG found anymore to end of file although there should be one more.
          Best regards from an UC/UE/UES for Windows user from Austria

          1581
          Power UserPower User
          1581

            Apr 20, 2018#5

            Hi Mofi,

            thanks for the improvements. I just found time to start testing, and a quick first test shows me.

            a) It works,
            b) but it still needs the external(?) functions "GetFilePath" and "GetFileIndex".
            c) (It does not work when you try to integrate PRJ files, because it starts to work with this file.)

              Oct 08, 2018#6

              Update / Refresh after half a year:

              1) It works great and quick!!

              2) Interesting:
              a) Define c:\data\test.txt to import
              b) Open the file in UE. It gets the current "state / content", e.g. from 09:48
              c) Another software modifies the file c:\data\test.txt, e.g. to state 09:55
              d) Run the script: It will import the old data from opened file and not the current data from hard disk.
              e) Close the import file and run the script again - now it takes the current data from hard disk.

              Regards

              Peter
              UE 26.20.0.74 German / Win 10 x 64 Pro

              6,603547
              Grand MasterGrand Master
              6,603547

                Oct 08, 2018#7

                Well, the script contains:

                Code: Select all

                      // Is the file to insert not already opened?
                      if (nInsertFile < 0)
                      {
                          // Script code to open the file, load the content and close it.
                      }
                      else     // The file to insert is opened already in UltraEdit.
                      {
                          // Script code to use unmodified or modified content of already opened file.
                      }
                
                So it depends on customizable file change detection as well as customizable file polling or the script code which file content is copied for an opened file modified in background by another application. It is also possible to configure that no application can modify a file while being opened in UltraEdit. Most applications open files with read/write lock (deny shared file access) while UltraEdit does not by default because of usage of a temporary file for each opened file.

                I assumed on writing the script that on an already opened file the unmodified or modified content even on not yet being saved should be copied into the other file making it possible to work on several files in same instance of UltraEdit and run the script at any time to update the main file even on unsaved changes on other files. But if the other files are mainly updated by another application in background, the code can be modified to always close an already opened file and re-open it to get newest content of this file. That is not really difficult to code with taking into account that the document index of the main file on which to insert the other files can change in this case during script execution.
                Best regards from an UC/UE/UES for Windows user from Austria