Macro Complex instructions.
-
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?
-
You could use a scripting language, like PythonScript. The general procedure would be akin to
-
Open both
File1
andFile2
. -
RClick on the
File2
tab, andMove to Other View
-
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 givennewValue
) -
-
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 -
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")
-
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”)” :-DCheers
Claudia -
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. :-)
-
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 -
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 ofFile2
If so, first, merge the
File1
contents, right after theFile2
contents, as below, and save these contents asFile3
: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 expressionSEARCH
(?-s)^(.+xxx)\R(.+xxx)
REPLACE
\1\2
OPTIONS
Wrap Around
andRegular expression
checkedACTION Click on the
Replace All
buttonYou 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 theaaa
first line of your listTherefore, 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
andRegular expression
checkedACTION 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 for3
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 listaaa
,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 ofFile3
(Ctrl + Shift + End
andDel
! )Of course, for
n
lines, between the first one and theaaa
line, simply change the search regex as :(?-s)^(.+?)xxx(.+?)xxx\R(?=(?:.+\R){n}(.+\R))
, with the appropriate integern
Best Regards,
guy038
-
-
For completeness, I eventually found the bug in mine: I was misusing
range(start, end)
– I thought it includedend
when iterating over the range, but it only uses the values less thanend
.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")