Community
    • Login

    Macro Complex instructions.

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    9 Posts 4 Posters 4.0k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Annas TaherA
      Annas Taher
      last edited by

      Well. I don’t know how to explain it so I will give the example right away:
      I have 2 Files
      File1 is a list:
      aaa
      bbb
      ccc
      ddd
      etc…
      And File2: all X are the same value
      Blue Box xxx
      It contains grapes and xxx
      Red Box xxx
      It contains tomatoes and xxx
      Green Box xxx
      It contains oranges and xxx
      Yellow Box xxx
      It contains lemons and xxx
      etc.

      I want is so macro can take from File1 and replace the first two xxx with aaa the 2nd two xxx with bbb and so on .

      How do I do that?

      Claudia FrankC 2 Replies Last reply Reply Quote 0
      • PeterJonesP
        PeterJones
        last edited by PeterJones

        You could use a scripting language, like PythonScript. The general procedure would be akin to

        1. Open both File1 and File2.

        2. RClick on the File2 tab, and Move to Other View

        3. Run a PythonScript that does something like the following (not valid PythonScript… this just gives an outline in pseudocode.)

           // editor1 is the PythonScript object instance for the first (left or top) document window in NPP
           // editor2 is the instance for the second (right or bottom) document window
           for( lineNumber = 1 to editor1.getLineCount() )
               // grab the nth line from File1
               editor1.gotoLine(lineNumber)
               newValue = editor1.getCurLine()
               for ( time = 1 to 2 )
                   // look for the first occurrence of 'xxx'
                   position = editor2.findText( flags, 0, end, "xxx")      // Look in the PythonScript documentation
                   //      for Editor Object > Scintilla Methods:
                   //      I would need to study .findText() and the associated SCI_FINDTEXT more
                   //      to figure out the right values for flags, and then search thru to find
                   //      the right command for finding the end-location of editor2
                   editor2.????(position, position+3)                      // select the text from "position" to "position+3" or whatever length of "xxx" is
                   editor2.replaceSel(newValue)                            // replace the selected "xxx" with the newValue
          

        Sorry, I’m not a Python/PythonScript expert, and didn’t have much time this morning, otherwise I could have researched a bit more and tried to get valid/running code. Hopefully, this outline will spark a PythonScript guru (@Claudia-Frank , hint, hint) could turn this pseudocode into a valid PythonScript in a few minutes.

        (edit: added the for time=1 to 2 loop, because I forgot you wanted to replace two instances of each “xxx” with a given newValue)

        1 Reply Last reply Reply Quote 1
        • Claudia FrankC
          Claudia Frank @Annas Taher
          last edited by

          @Annas-Taher

          Thx to Peter :-), I already have the logic to follow - should be straightforward.
          When back home I will build something but in the meantime you need to install
          the python script plugin (preferable use the msi) to make it work. And you have to use the 32bit version of notepad++
          as there is no python script plugin for 64 bit available yet.

          Cheers
          Claudia

          1 Reply Last reply Reply Quote 0
          • PeterJonesP
            PeterJones
            last edited by

            Actually, it was pestering me so much I couldn’t think about anything else…

            This appears to do what @Annas-Taher described:

            # editor1 is the PythonScript object instance for the first (left or top) document window in NPP
            # editor2 is the instance for the second (right or bottom) document window
            
            for lineNumber in range(0, editor1.getLineCount() ):
                # grab the nth line from File1 (exclude newline)
                editor1.gotoLine(lineNumber)
                newValue = editor1.getCurLine().rstrip()
                console.write("editor1: #" + str(lineNumber) + " = \"" + newValue + "\"\n")
            
                editor2.documentEnd()               # go to the last position
                end2 = editor2.getCurrentPos()      # record the position
                console.write("editor2.end = " + str(end2)+"\n")
                editor2.documentStart()             # back to the beginning
                start2 = editor2.getCurrentPos()    # record the position
                console.write("editor2.start = " + str(start2)+"\n")
            
                # want to replace two "xxx" entries in File2 with each line from File1
                for time in range(1, 2):
            
                    # look for the first occurrence of 'xxx', starting at start2 and ending at end2
                    #  position is a tuple with the start and end locations of the match
                    position = editor2.findText( FINDOPTION.MATCHCASE, start2, end2, "xxx")
                    console.write("editor2: findText @ " + str(position[0]) + ":" + str(position[1]) + "\n")
            
                    # select the "xxx"
                    editor2.setSelectionStart(position[0])
                    editor2.setSelectionEnd(position[1])
            
                    # replace the selection with newValue
                    editor2.replaceSel(newValue)
            
                    # the cursor is now at the end of the replaced value, and we want to
                    start2 = editor2.getCurrentPos()
                    console.write("Start2: " + str(start2)+"\n")
            
            Claudia FrankC 1 Reply Last reply Reply Quote 1
            • Claudia FrankC
              Claudia Frank @PeterJones
              last edited by

              @PeterJones

              So you gave me a job and fired me instantly :-D
              To quote Meat Loaf: “Is this the way to treat an employee (well he said “an expensive guitar”)” :-D

              Cheers
              Claudia

              1 Reply Last reply Reply Quote 1
              • PeterJonesP
                PeterJones
                last edited by

                Well, there is a bug in the code: The nested loop isn’t working, and it’s just replacing one of each, rather than two xxx with each line from File1. So whichever of us finds the Round Tuit to debug the code first will get credit for final solution. :-)

                1 Reply Last reply Reply Quote 1
                • Claudia FrankC
                  Claudia Frank @Annas Taher
                  last edited by

                  @Annas-Taher
                  @PeterJones

                  from your description I would solve it like this

                  editor1_list = editor1.getText().split()
                  string_to_be_replaced = 'xxx'
                  line_counter_editor2 = 0
                  
                  editor.beginUndoAction()
                  for i in editor1_list:
                      editor2.replaceLine(line_counter_editor2, editor2.getLine(line_counter_editor2).replace(string_to_be_replaced, i).rstrip())
                      editor2.replaceLine(line_counter_editor2+1, editor2.getLine(line_counter_editor2+1).replace(string_to_be_replaced, i).rstrip())
                      line_counter_editor2 += 2
                  editor.endUndoAction()
                  

                  If the code doesn’t explain itself, let me know.

                  Cheers
                  Claudia

                  1 Reply Last reply Reply Quote 2
                  • guy038G
                    guy038
                    last edited by guy038

                    Hello @annas-taher, and All,

                    Surely, Claudia and Peter, your Python scripts should give nice results. I just imagined … a regex S/R equivalent method :-))

                    Annas, my method, below, will work, assuming two facts :

                    • The expression xxx ends all the lines of File2

                    • The number of lines of the list, in File1, is, exactly, half the number of lines of File2


                    If so, first, merge the File1 contents, right after the File2 contents, as below, and save these contents as File3 :

                    Blue Box xxx
                    It contains grapes and xxx
                    Red Box xxx
                    It contains tomatoes and xxx
                    Green Box xxx
                    It contains oranges and xxx
                    Yellow Box xxx
                    It contains lemons and xxx
                    aaa
                    bbb
                    ccc
                    ddd
                    

                    Then, in File3, with a first regex S/R, we join two consecutive lines, ending with the xxx expression

                    SEARCH (?-s)^(.+xxx)\R(.+xxx)

                    REPLACE \1\2

                    OPTIONS Wrap Around and Regular expression checked

                    ACTION Click on the Replace All button

                    You should obtain the text, below :

                    Blue Box xxxIt contains grapes and xxx
                    Red Box xxxIt contains tomatoes and xxx
                    Green Box xxxIt contains oranges and xxx
                    Yellow Box xxxIt contains lemons and xxx
                    aaa
                    bbb
                    ccc
                    ddd
                    

                    Notes :

                    • As usual, the (?-s) modifier, ensures that the dot special character will match standard characters, only

                    • The ^ assertion represents the position beginning of line, which must be verified

                    • The two syntaxes (.+xxx) catch the contents of two consecutive lines, ending with xxx, and stored, successively, in group1 and group 2, due to each pair of parentheses

                    • The \R form represents the line-break characters between these two lines

                    • In replacement, we rewrite the contents of the two lines, \1\2, except for the line break


                    Well. now, note that after the first line, you have to cross 3 complete lines to get the aaa first line of your list

                    Therefore, we’ll use the second and last regex S/R, below :

                    SEARCH (?-s)^(.+)xxx(.+)xxx\R(?=(?:.+\R){3}(.+\R))

                    REPLACE \1\3\2\3

                    OPTIONS Wrap Around and Regular expression checked

                    ACTION Click on the Replace All button

                    => Your File3 contents should be as below :

                    Blue Box aaa
                    It contains grapes and aaa
                    Red Box bbb
                    It contains tomatoes and bbb
                    Green Box ccc
                    It contains oranges and ccc
                    Yellow Box ddd
                    It contains lemons and ddd
                    aaa
                    bbb
                    ccc
                    ddd
                    

                    Notes :

                    • This time, group 1 and group 2, (.+), contain the totality of the two consecutive lines, apart from the xxx expression

                    • So, the part ^(.+)xxx(.+)xxx\R matches each complete line, with its line-break

                    • But, ONLY IF, further on, the positive look-ahead (?=(?:.+\R){3}(.+\R)), ( where it looks for 3 complete lines, with its line-break character(s), in a non-capturing group, (?:.+\R){3}, followed with an other complete line (.+\R) ) , is verified

                    • Note that this condition is always true, but, thanks to this syntax, we can store any line of the list aaa, bbb,… as group 3

                    • In replacement, we simply, rewrite groups 1 and 2, replacing the old expression xxx by \3 which represents any value of the list aaa, bbb and so on…, with its line breaks, to get the initial form of the text


                    Finally, just get rid of the list aaa......ddd, at the end of File3 ( Ctrl + Shift + End and Del ! )

                    Of course, for n lines, between the first one and the aaa line, simply change the search regex as :

                    (?-s)^(.+?)xxx(.+?)xxx\R(?=(?:.+\R){n}(.+\R)) , with the appropriate integer n

                    Best Regards,

                    guy038

                    1 Reply Last reply Reply Quote 2
                    • PeterJonesP
                      PeterJones
                      last edited by

                      For completeness, I eventually found the bug in mine: I was misusing range(start, end) – I thought it included end when iterating over the range, but it only uses the values less than end.

                      The following is my code, with the bug fixed (and some of my debug prints left in) that I think now does what was requested… though @Claudia-Frank did it much more succinctly… and the magic of @guy038 regex ability is virtually limitless. :-)

                      # editor1 is the PythonScript object instance for the first (left or top) document window in NPP
                      # editor2 is the instance for the second (right or bottom) document window
                      
                      # Python's range(start, stop) operator will keep going while the index variable is LESS THAN stop, so it will never use stop: https://docs.python.org/2/library/functions.html#range
                      for lineNumber in range(0, editor1.getLineCount() ):
                          # grab the nth line from File1 (exclude newline)
                          editor1.gotoLine(lineNumber)
                          newValue = editor1.getCurLine().rstrip()
                          console.write("editor1: #" + str(lineNumber) + " = \"" + newValue + "\"\n")
                      
                          editor2.documentEnd()               # go to the last position
                          end2 = editor2.getCurrentPos()      # record the position
                          console.write("editor2.end = " + str(end2)+"\n")
                          editor2.documentStart()             # back to the beginning
                          start2 = editor2.getCurrentPos()    # record the position
                          console.write("editor2.start = " + str(start2)+"\n")
                      
                          # want to replace two "xxx" entries in File2 with each line from File1
                          for time in range(0, 2):
                              console.write("time# " + str(time) + "!!!\n")
                      
                              # look for the first occurrence of 'xxx', starting at start2 and ending at end2
                              #  position is a tuple with the start and end locations of the match
                              position = editor2.findText( FINDOPTION.MATCHCASE, start2, end2, "xxx")
                              if position is None:
                                  console.write("editor2.position is NONE, so skipping...\n")
                                  break                   # don't try to replace
                      
                              console.write("editor2: findText @ " + str(position[0]) + ":" + str(position[1]) + "\n")
                      
                              # select the "xxx"
                              editor2.setSelectionStart(position[0])
                              editor2.setSelectionEnd(position[1])
                      
                              # replace the selection with newValue
                              editor2.replaceSel(newValue)
                      
                              # the cursor is now at the end of the replaced value, and we want to
                              start2 = editor2.getCurrentPos()
                              console.write("Start2: " + str(start2)+"\n")
                      
                          console.write("next source line...\n")
                      
                      1 Reply Last reply Reply Quote 1
                      • First post
                        Last post
                      The Community of users of the Notepad++ text editor.
                      Powered by NodeBB | Contributors