<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[renumbering&#x2F;incremental]]></title><description><![CDATA[<p dir="auto">This was asked before but I didnt see an answer that fixed the issue.  I have CNC programs and each line looks like this (here is an example of the first 4 lines of a program)</p>
<p dir="auto">N01  O0032<br />
N02/     .44 R1;<br />
N03/  G10 P010000 X-0.   Z-1.8495<br />
N04 G92</p>
<p dir="auto">Now, the machine that reads it MUST see the N0 in numerical order as above (N01, N02, N03 etc).    I need to make some edits to the program which was suggested to me with an amazing bit of help in a previous post.  This will remove the first 3 lines (N01, N02 and N03) and replace it with 7 lines of code (N01 through N07).  However, if you see then that will make it look like this:</p>
<p dir="auto">N01;<br />
N02;<br />
N03;<br />
N04 g94 g53 g56 t0000 ;<br />
N05 g92 x0.602 z2.2 ;<br />
N06 g59 ;<br />
N04 G92</p>
<p dir="auto">Which as you see will make it go from N06 back to N07 and then cause the machine to not be able to read the program.  Is there a way, that after I make the aforementioned changes, there is something in this program that will allow me to make the Ns in numerical order without changing the code (like this)?</p>
<p dir="auto">N01;<br />
N02;<br />
N03;<br />
N04 g94 g53 g56 t0000 ;<br />
N05 g92 x0.602 z2.2 ;<br />
N06 g59 ;<br />
N07 G92</p>
]]></description><link>https://community.notepad-plus-plus.org/topic/23750/renumbering-incremental</link><generator>RSS for Node</generator><lastBuildDate>Tue, 16 Jun 2026 14:51:54 GMT</lastBuildDate><atom:link href="https://community.notepad-plus-plus.org/topic/23750.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 16 Nov 2022 12:33:59 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Sun, 14 Jan 2024 21:02:16 GMT]]></title><description><![CDATA[<p dir="auto">If you’ve used a script in this thread, you might want to double check your copy of it for a bug I’ve discovered.<br />
Look to previous postings in this topic thread where the script has been changed – find the text <code>moderator edit (2024-Jan-14)</code>.<br />
There’s a link there that describes the bug in more detail, and shows what needs to be changed in an old copy (or you can simply grab a copy of the current version).</p>
]]></description><link>https://community.notepad-plus-plus.org/post/92065</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/92065</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Sun, 14 Jan 2024 21:02:16 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Mon, 05 Dec 2022 11:12:22 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> so sorry, we were closed for a bit and Im just getting back.  I will try those both this week, thank you so much for all of your help!</p>
]]></description><link>https://community.notepad-plus-plus.org/post/82269</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/82269</guid><dc:creator><![CDATA[Scott Raskin 0]]></dc:creator><pubDate>Mon, 05 Dec 2022 11:12:22 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Wed, 23 Nov 2022 12:23:57 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin" aria-label="Profile: Scott-Raskin">@<bdi>Scott-Raskin</bdi></a></p>
<p dir="auto">Are you making a “macro” out of your second op, the standard <em>Replace in Files</em> operation?</p>
<p dir="auto">If so, then it really becomes less painful as a separate operation; you don’t have to fill in all the fields in the UI each time, you just pick the “macro” from the <em>Macro</em> menu to run it.</p>
<p dir="auto">So your workflow becomes:</p>
<ul>
<li>run the script</li>
<li>run the macro</li>
</ul>
<p dir="auto">Downside of a macro:  For a <em>Replace in Files</em> macro, the folder is “hardcoded”.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81874</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81874</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Wed, 23 Nov 2022 12:23:57 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Wed, 23 Nov 2022 12:20:27 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin-0" aria-label="Profile: Scott-Raskin-0">@<bdi>Scott-Raskin-0</bdi></a></p>
<p dir="auto">Concerning:</p>
<blockquote>
<p dir="auto">Maybe youre right and 2 ops is the best</p>
</blockquote>
<p dir="auto">I think so…especially due to your newness to the scripting world.  As you’ve found, it is very easy to screw up something to the point where a previously-running script now won’t run.  (This is often even easy for scripting veterans to do.)</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81873</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81873</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Wed, 23 Nov 2022 12:20:27 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Wed, 23 Nov 2022 12:27:35 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin" aria-label="Profile: Scott-Raskin">@<bdi>Scott-Raskin</bdi></a> said in <a href="/post/81869">renumbering/incremental</a>:</p>
<blockquote>
<p dir="auto">copy/paste made it look weird for some reason in the post</p>
</blockquote>
<p dir="auto">If you want it to appear verbatim in a posting, you have to format it correctly.</p>
<p dir="auto">Add lines with 3 backticks at the start and bottom of your “block”:</p>
<p dir="auto">```<br />
one<br />
two<br />
three<br />
```</p>
<p dir="auto">Do that and it will appear like this:</p>
<pre><code>one
two
three
</code></pre>
<p dir="auto">Alternatively, select the text to format and press the “code” button in the “toolbar” to get the same effect:</p>
<p dir="auto"><img src="/assets/uploads/files/1669206424766-3b9761d1-033d-44e5-a085-6496b5910c8b-image.png" alt="3b9761d1-033d-44e5-a085-6496b5910c8b-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">More info on <a href="https://community.notepad-plus-plus.org/topic/21925/faq-desk-formatting-forum-posts">FORMATTING</a> posts is in the FAQ entry concerning it.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81872</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81872</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Wed, 23 Nov 2022 12:27:35 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Wed, 23 Nov 2022 10:43:43 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> copy/paste made it look weird for some reason in the post but that search/replace was all one line in the script</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81869</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81869</guid><dc:creator><![CDATA[Scott Raskin]]></dc:creator><pubDate>Wed, 23 Nov 2022 10:43:43 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Wed, 23 Nov 2022 10:18:02 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> tried this<br />
self.print(‘making replacements in’, pathname)<br />
replacements_made_in_this_file = self.perform_custom_replace_in_one_file(first_time_thru)<br />
editor.rereplace(\A(?-s).<em>\R.&amp;\R.</em>\R.<em>\R.</em>\R.<em>\R.</em>\R.*\R,O0001  ;N0001 ;N0002 ;N0003 ;N0005  G94 G53 G56 T0000 ;N0010  G92 X0.6820 Z2.1505 ;<br />
)           self.print(‘{} replacements made in current file’.format(replacements_made_in_this_file))</p>
<p dir="auto">and the script wont even run now.  Maybe youre right and 2 ops is the best</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81868</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81868</guid><dc:creator><![CDATA[Scott Raskin 0]]></dc:creator><pubDate>Wed, 23 Nov 2022 10:18:02 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Tue, 22 Nov 2022 16:24:11 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin" aria-label="Profile: Scott-Raskin">@<bdi>Scott-Raskin</bdi></a> said :</p>
<blockquote>
<p dir="auto">…run your script, followed by that search/replace it seems it does all I need to do.</p>
</blockquote>
<blockquote>
<p dir="auto">Its only 2 operations if I need to do separately and it will change 10k files so its worth it either way</p>
</blockquote>
<p dir="auto">The script is rather dedicated to its renumbering/incrementing purpose, but it is just code so you could change it to go beyond that.</p>
<p dir="auto">As the search/replace op you mention is just a normal one (no special math/renumber/increment stuff), you could just include an <code>editor.rereplace(</code>search<code>,</code>replace<code>)</code> function call right after this line:</p>
<pre><code class="language-py">replacements_made_in_this_file = self.perform_custom_replace_in_one_file(first_time_thru)
</code></pre>
<p dir="auto">Note however that this would invalidate the script’s results reporting (at completion, telling you number of replacements made, etc.).  Not a big deal if you trust the script, mainly I put that stuff in to be general purpose, and to give a user a sanity check if they know about how many files should be matched via filespec/filter, about how many replaces should have been done, etc.</p>
<p dir="auto">If I were you, I’d keep it as two separate and distinct operations, running of a script, and then a follow-up <em>Replace in Files</em> op.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81839</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81839</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Tue, 22 Nov 2022 16:24:11 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Tue, 22 Nov 2022 12:37:11 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin" aria-label="Profile: Scott-Raskin">@<bdi>Scott-Raskin</bdi></a> said in <a href="/post/81836">renumbering/incremental</a>:</p>
<blockquote>
<p dir="auto">First thing I noticed was I needed to change this line: renumbering = [ 1, 1 ] to renumbering = [ 10, 1 ], as it has to start at 10</p>
</blockquote>
<p dir="auto">You <em>could</em> change it the way you state, but I’d suggest this as cleaner:</p>
<pre><code class="language-py">renumbering[CURRENT] = 10
</code></pre>
<p dir="auto">inserted above this line in the script:</p>
<pre><code class="language-py">renumbering[INCREMENT] = 10
</code></pre>
<p dir="auto">The “current” value is the starting value, and also the “running” value as the replacement moves along (that’s why I didn’t want to call it “starting”).  Expressing one’s self in code isn’t always straightforward.</p>
<p dir="auto">The “increment” value is well-named, but the fact that the <code>INCREMENT</code> tag in the code is 1 and NEVER should be changed, well, this does seem odd (it is used for a <em>different</em> purpose than one might think).  Expressing one’s self in code isn’t always straightforward.</p>
<p dir="auto">If you just think in terms of:</p>
<ul>
<li>
<p dir="auto">if I want to change the starting value, I need to set <code>renumbering[CURRENT] = </code> something</p>
</li>
<li>
<p dir="auto">if I want to change the incrementing value, I need to set <code>renumbering[INCREMENT] = </code> something</p>
</li>
</ul>
<p dir="auto">and forget about the rest…for this specific application.</p>
<hr />
<blockquote>
<p dir="auto">This is all amazing, and even with you being modest, you still put a good deal of effort into this and it is much appreciated</p>
</blockquote>
<p dir="auto">Not a problem.  Part of the goal was somewhat of a generic solution (as you’ve probably noticed), so that the <em>next</em> time a question like this comes up (and it will), there is a model of a solution for it.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81838</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81838</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Tue, 22 Nov 2022 12:37:11 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Tue, 22 Nov 2022 11:52:03 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a>  Sorry for breaking this into two messages: I also see where you have the self.search_regex and def retuen_replacement_text_func(m) I would be l;looking to make any future code modifications, so I can probably try adding that \A(?-s).\R.\R.\R.\R.\R.\R.*\R into the first part and the replacement into the second I just dont want to screw up the code.  I will be back at the factory in a few hours to see.<br />
Thanks again</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81837</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81837</guid><dc:creator><![CDATA[Scott Raskin]]></dc:creator><pubDate>Tue, 22 Nov 2022 11:52:03 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Tue, 22 Nov 2022 10:32:18 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> This looks great and I will be doing some testing on it today.  First thing I noticed was I needed to change this line: renumbering = [ 1, 1 ] to renumbering = [ 10, 1 ], as it has to start at 10 (or more, but I figured 10 was a good # to use, as if you remember from my other post, I need to edit some lines.  So I really appreciate you making it easy, as that was very simple to find and edit.  The next part I need to figure out is, where to have it  do this (or do I justdo it separately.  Its only 2 operations if I need to do separately and it will change 10k files so its worth it either way.  The other post I had done we came up with</p>
<p dir="auto">replace:  \A(?-s).<em>\R.</em>\R.<em>\R.</em>\R.<em>\R.</em>\R.*\R<br />
with : O0001  ;N01 ;N02 ;N03 ;N04  G94 G53 G56 T0000 ;N05  G92 X0.6820 Z2.1505 ;N06  G59 ;</p>
<p dir="auto">So right now, If I run your script, followed by that search/replace it seems it does all I need to do.  Just wondering if that is something python allows.</p>
<p dir="auto">This is all amazing, and even with you being modest, you still put a good deal of effort into this and it is much appreciated</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81836</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81836</guid><dc:creator><![CDATA[Scott Raskin]]></dc:creator><pubDate>Tue, 22 Nov 2022 10:32:18 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Mon, 21 Nov 2022 20:26:02 GMT]]></title><description><![CDATA[<p dir="auto">The script does what I think was what was wanted; it renumbers into order, with gaps in the numbering, all the Nx fields that occur at start-of-line, where “x” is some number of digits – and the important part: it does this across some folder hierarchy of possibly a large number of files.</p>
<p dir="auto">If someone wanted to keep the core logic, but change the specific search and replacement, here’s what someone would do:</p>
<p dir="auto">Search the code for the text <code>USER MODS</code>; you’d find some sections that look like this:</p>
<pre><code># vvvvvvvvvv---------- USER MODS REQUIRED BELOW ----------vvvvvvvvvv
# ^^^^^^^^^^---------- USER MODS REQUIRED ABOVE ----------^^^^^^^^^^
</code></pre>
<p dir="auto">In between those lines are what you’d change for customization.</p>
<p dir="auto">In the first case, you’d change what is being looked for, e.g.:</p>
<pre><code>self.search_regex = r'^N\d+'  # search for N followed by some number of digits (but must be at start-of-line)
</code></pre>
<p dir="auto">Change what is between the <code>'</code> characters for the regular expression you’ve tested independent of the script.</p>
<p dir="auto">In the second case, you’d find this:</p>
<pre><code>def return_replacement_text_func(m):
    ....
</code></pre>
<p dir="auto">and that’s where you’d put the replacement function you developed for the one file case.</p>
<p dir="auto">For our scenario under discussion in this thread, that function looks like this:</p>
<pre><code>def return_replacement_text_func(m):
    # replace with N and a minimum of 2 digits, e.g. N01, N90, N300
    repl_text = 'N{0:02}'.format(renumbering[CURRENT])      
    renumbering[CURRENT] += renumbering[INCREMENT]
    return repl_text
</code></pre>
<p dir="auto">However, for this scenario, we need to remember some things between runs of this function – e.g., what’s our current count value – so we have some code that appears just <strong>above</strong> the definition of return_replacement_text_func, to allow that “memory” to happen:</p>
<pre><code>renumbering = [ 1, 1 ]  # default to re-numbering starting with 1 and incrementing by 1; in the general case
CURRENT = 0; INCREMENT = 1  # indexes into the re-numbering list
renumbering[INCREMENT] = 10  # override our default increment-by and change it to 10, for our specific need
</code></pre>
<p dir="auto">The replacement will do the first replacement using the text <code>N01</code>, the second with <code>N11</code>, third with <code>N21</code>, and so on.</p>
<p dir="auto">Now, this all may seem very complicated if you were trying to write it from nothing, but maybe it isn’t so bad to read and follow the logic, or adapt to similar need.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81823</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81823</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Mon, 21 Nov 2022 20:26:02 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Sun, 14 Jan 2024 19:21:37 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin" aria-label="Profile: Scott-Raskin">@<bdi>Scott-Raskin</bdi></a></p>
<p dir="auto">So the script listing follows. Before you think, from the length of it, that it was (a) a lot of work for me, or (b) that it is very complicated, well, it really was/is neither. The base algorithm is minimal, and I basically recycled <a href="https://community.notepad-plus-plus.org/topic/23638/massive-list-and-massive-search-and-replace">ANOTHER SCRIPT</a> for most of the logic.</p>
<p dir="auto">Here’s the script listing for what I call <code>ReplaceInFilesUsingCustomReplacementFunction.py</code> (wow, sorry for long name!); after the listing are some details about running it:</p>
<pre><code># -*- coding: utf-8 -*-
from __future__ import print_function

# references:
#  https://community.notepad-plus-plus.org/topic/23750/renumbering-incremental
#  also https://community.notepad-plus-plus.org/topic/23638/massive-list-and-massive-search-and-replace

from Npp import *
import inspect
import os
import fnmatch

#-------------------------------------------------------------------------------

class RIFUCRF(object):

    def __init__(self):

        self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0]

        self.debug = True if 0 else False
        if self.debug:
            pass
            #console.show()
            #console.clear()

        self.run_example_from_pythonscript_docs = True if 0 else False

        if not self.debug:
            prompt = '\r\n\r\n\r\n'.join([
                'Prompt 1 (of 6):',
                'IT IS STRONGLY SUGGESTED TO MAKE A BACKUP OF ALL ORIGINAL FILES BEFORE CONTINUING !!',
                'Press Cancel to exit script and do that. After that, re-run the script.',
            ])
            if not self.mb_ok_cancel(prompt): return

        active_tab_filepath = notepad.getCurrentFilename()
        active_tab_filename = active_tab_filepath.rsplit(os.sep, 1)[-1]
        active_tab_extension = active_tab_filename.rsplit('.', 1)

        if not os.path.isfile(active_tab_filepath):
            self.mb('You must have a tab that has been saved into the file system active when running this script; exiting.')
            return

        if self.run_example_from_pythonscript_docs:
            # base example from PythonScript docs:
            self.search_regex = r'X([0-9]+)'  # search for X followed by some number of digits; remember what the digits are for use at replace time
        else:
            # vvvvvvvvvv---------- USER MODS REQUIRED BELOW ----------vvvvvvvvvv
            self.search_regex = r'^N\d+'  # search for N followed by some number of digits (but must be at start-of-line)
            # ^^^^^^^^^^---------- USER MODS REQUIRED ABOVE ----------^^^^^^^^^^

        prompt = '\r\n\r\n'.join([
            'Prompt 2 (of 6):\r\n',
            'Is this the correct search expression to use for the custom replacement?:',
            self.search_regex + '\r\n',
            'Answering No will give you a path to stopping script execution; Yes will continue.',
        ])
        yes = self.yes_no(prompt)
        if not yes:
            msg = '\r\n\r\n'.join([
                'Edit the script code and set this variable to the indended value:',
                'self.search_regex',
                '\r\n',
                'Also verify replacement functionality in this function:',
                'perform_custom_replace_in_one_file',
                '\r\n',
                'After you close this box, the script will exit so you can go off and do that stuff. After that, re-run the script.',
            ])
            self.mb(msg)
            return

        suggested_search_folder_top_level_path = active_tab_filepath.rsplit(os.sep, 1)[0] + os.sep
        self.print('(default) suggested_search_folder_top_level_path:', suggested_search_folder_top_level_path)

        user_input = suggested_search_folder_top_level_path
        while True:  # loop until valid folder input is obtained
            search_folder_top_level_paths_list = []
            prompt = '\r\n'.join([
                'Prompt 3 (of 6):',
                'Perform custom replacements in the files in this folder?',
            ])
            user_input = self.prompt(prompt, user_input)
            if user_input == None: return  # user cancel
            input_list = user_input.rstrip().split('\r\n')
            self.print('input_list:', input_list)
            all_input_is_valid = True
            for folder in input_list:
                folder = folder.strip()
                self.print('folder:|{}|'.format(folder))
                if len(folder) == 0: continue
                if folder[-1] != os.sep: folder += os.sep
                if not os.path.isdir(folder):
                    self.mb('Invalid folder name specified!:\r\n\r\n{}\r\n\r\nYou will be given a chance to correct this.'.format(folder))
                    all_input_is_valid = False
                else:
                    search_folder_top_level_paths_list.append(folder)
            if all_input_is_valid and len(search_folder_top_level_paths_list) &gt; 0:
                break  # exit the while loop
        self.print('search_folder_top_level_paths_list:', search_folder_top_level_paths_list)
        only_1_top_level_folder = True if len(search_folder_top_level_paths_list) == 1 else False

        process_subfolders = self.yes_no_cancel('\r\n\r\n'.join([
            'Prompt 4 (of 6):\r\n',
            'Do custom replacements in files in SUBFOLDERS (if any) {}also?'.format('of this folder ' if only_1_top_level_folder else ''),
            (search_folder_top_level_paths_list[0] if only_1_top_level_folder else '') + '\r\n',
            '(Cancel will exit the script.)',
            ]))
        if process_subfolders == None: return  # user cancel
        self.print('process_subfolders:', process_subfolders)

        suggested_filespec = '*.*'
        if len(active_tab_extension) == 2: suggested_filespec = '*.' + active_tab_extension[-1]
        prompt = '\r\n'.join([
            'Prompt 5 (of 6):',
            'Supply filespec filter list (ex1.:    *.html *.txt *.log            ex2.:    *.*    )',
        ])
        filter_input = self.prompt(prompt, suggested_filespec)
        if filter_input == None: return  # user cancel
        filters_list = filter_input.split(' ')
        filters_list = [ f for f in filters_list if len(f) &gt; 0 ]  # remove any empty entries in filters_list
        self.print('filters_list:', filters_list)

        pathnames_matching_filters_list = []
        total_folders_encountered = total_files_encountered = 0

        for top_level_path in search_folder_top_level_paths_list:
            for (root, __, filenames) in os.walk(top_level_path):
                total_folders_encountered += 1
                total_files_encountered += len(filenames)
                for filter_filespec in filters_list:
                    for filename in fnmatch.filter(filenames, filter_filespec):
                        pathnames_matching_filters_list.append(os.path.join(root, filename))
                if not process_subfolders: break
            self.print('pathnames_matching_filters_list:', pathnames_matching_filters_list)

        num_files_matching_filters = len(pathnames_matching_filters_list)
        if num_files_matching_filters == 0:
            self.mb('Of {tf} files examined in {td} folders, no files matched specified filter(s). Script will exit.'.format(
                tf=total_files_encountered, td=total_folders_encountered))
            return

        pathname_currently_open_in_a_tab_list = []
        for (pathname, __, __, __) in notepad.getFiles():
            if pathname not in pathname_currently_open_in_a_tab_list:
                pathname_currently_open_in_a_tab_list.append(pathname)
        self.print('pathname_currently_open_in_a_tab_list:', pathname_currently_open_in_a_tab_list)

        num_folders_below_top_levels = total_folders_encountered - len(search_folder_top_level_paths_list)

        prompt = '\r\n\r\n'.join([
            'Prompt 6 (of 6):\r\n',
            '---- FINAL CONFIRMATION !!! ----\r\n',
            'Make custom replacements in {nf} candidate files in this folder{b} ?:'.format(
                nf=num_files_matching_filters,
                b=' AND {} folders below'.format(num_folders_below_top_levels) if process_subfolders else '\r\n(but not its subfolders)'),
            (search_folder_top_level_paths_list[0] if only_1_top_level_folder else '(multiple top-level folders specified)') + '\r\n',
            'Answering Yes will make the replacements.\r\n(No will exit the script, changing nothing.)',
        ])
        confirmed = self.yes_no(prompt)
        if not confirmed: return

        total_replacements_made_in_all_files = 0
        pathnames_with_replacements_made_dict = {}
        folders_with_replacements_made_dict = {}
        first_time_thru = True

        for pathname in pathnames_matching_filters_list:

            foldername_of_pathname = pathname.rsplit(os.sep, 1)[0]

            # the 'pathname' var here could be in "poor case" if user has entered the directory in a different
            #  case than what the file system has, so compensate for that possibility:
            open_in_a_npp_tab = pathname.lower() in map(str.lower, pathname_currently_open_in_a_tab_list)

            if open_in_a_npp_tab:
                self.print('switching active tab to', pathname)
                notepad.activateFile(pathname)
                editor.beginUndoAction()
            else:
                self.print('opening', pathname)
                notepad.open(pathname)
            assert notepad.getCurrentFilename().lower() == pathname.lower()

            if editor.getReadOnly():
                self.print('file is readonly so cannot change:', pathname)
                if not open_in_a_npp_tab: notepad.close()
                continue

            self.print('making replacements in', pathname)
            replacements_made_in_this_file = self.perform_custom_replace_in_one_file(first_time_thru)
            self.print('{} replacements made in current file'.format(replacements_made_in_this_file))

            if replacements_made_in_this_file &gt; 0:
                total_replacements_made_in_all_files += replacements_made_in_this_file
                pathnames_with_replacements_made_dict[pathname] = replacements_made_in_this_file
                folders_with_replacements_made_dict[foldername_of_pathname] = 1

            if open_in_a_npp_tab:
                editor.endUndoAction()
            else:
                if editor.getModify():
                    self.print('saving', pathname)
                    notepad.save()
                self.print('closing', pathname)
                notepad.close()

            first_time_thru = False

        # restore tab that was active before we started:
        notepad.activateFile(active_tab_filepath)

        info = '\r\n\r\n'.join([
            '---- DONE !!! ----',
            '{} total replacements made'.format(total_replacements_made_in_all_files),
            'Do you want to see details of the replacements made?' if total_replacements_made_in_all_files &gt; 0 else '',
            '(Script will end after your response.)',
            ])
        if total_replacements_made_in_all_files == 0:
            self.mb(info)
        elif self.yes_no(info):
            eol = ['\r\n', '\r', '\n'][editor.getEOLMode()]
            d = pathnames_with_replacements_made_dict
            digits = len(str(max(d.values())))
            summary_line_list = []
            summary_line_list.append('{tr} replacements made in {rp} files in {md} folders'.format(
                tr=total_replacements_made_in_all_files,
                rp=len(pathnames_with_replacements_made_dict),
                md=len(folders_with_replacements_made_dict),
                ))
            summary_line_list.append('{} folders examined'.format(total_folders_encountered))
            summary_line_list.append('{mf}/{tf} files matched the filter(s) provided:  {filts}'.format(
                mf=num_files_matching_filters,
                tf=total_files_encountered,
                filts=' '.join(filters_list),
                ))
            summary_line_list.append('-' * 40)
            summary_line_list.append(eol.join([ '{v:{d}} replacements - "{k}"'.format(v=v, k=k, d=digits) for (k, v) in sorted(d.items()) ]))
            notepad.new()
            editor.setText(eol.join(summary_line_list) + eol)
            editor.scrollRange(0, 0)  # ensure line 1 is shown
            editor.setSavePoint()  # make the temporary file seem saved

    def perform_custom_replace_in_one_file(self, first_time):

        # since the editor.replace() function won't tell us how many replacements it made,
        #  count them by searching for the matches BEFORE doing the replacement:
        match_list = []
        editor.research(self.search_regex, lambda m: match_list.append(1))

        if len(match_list) &gt; 0:

            if self.run_example_from_pythonscript_docs:

                # base example from PythonScript docs:
                def return_replacement_text_func(m):
                    # replace X followed by numbers by an incremented number, e.g.  X56 X39 X999  becomes  Y57 Y40 Y1000
                    return 'Y' + str(int(m.group(1)) + 1)

            else:

                # vvvvvvvvvv---------- USER MODS REQUIRED BELOW ----------vvvvvvvvvv

                renumbering = [ 1, 1 ]  # default to re-numbering starting with 1 and incrementing by 1; this would be the general case
                CURRENT = 0; INCREMENT = 1  # indexes into the re-numbering list
                renumbering[INCREMENT] = 10  # override our default increment-by and change it to 10, for our specific need

                def return_replacement_text_func(m):
                    repl_text = 'N{0:02}'.format(renumbering[CURRENT])  # replace with N and a minimum of 2 digits, e.g. N01, N90, N300
                    renumbering[CURRENT] += renumbering[INCREMENT]
                    return repl_text

                # ^^^^^^^^^^---------- USER MODS REQUIRED ABOVE ----------^^^^^^^^^^

            editor.rereplace(self.search_regex, return_replacement_text_func)

        return len(match_list)

    def mb(self, msg, flags=0, title=''):  # a message-box function
        return notepad.messageBox(msg, title if title else self.this_script_name, flags)

    def mb_ok_cancel(self, msg, title=''):  # returns True(OK) or False(Cancel)
        okay = notepad.messageBox(msg, title if title else self.this_script_name, MESSAGEBOXFLAGS.OKCANCEL) == MESSAGEBOXFLAGS.RESULTOK
        return okay

    def yes_no(self, question_text):  # returns True(Yes), False(No)
        answer = self.mb(question_text, MESSAGEBOXFLAGS.YESNO, self.this_script_name)
        return True if answer == MESSAGEBOXFLAGS.RESULTYES else False

    def yes_no_cancel(self, question_text):  # returns True(Yes), False(No), or None(Cancel)
        retval = None
        answer = self.mb(question_text, MESSAGEBOXFLAGS.YESNOCANCEL, self.this_script_name)
        if answer == MESSAGEBOXFLAGS.RESULTYES: retval = True
        elif answer == MESSAGEBOXFLAGS.RESULTNO: retval = False
        return retval

    def prompt(self, prompt_text, default_text=''):
        if '\n' not in prompt_text: prompt_text = '\r\n' + prompt_text
        prompt_text += ':'
        return notepad.prompt(prompt_text, self.this_script_name, default_text)

    def print(self, *args):
        if self.debug:
            print(self.__class__.__name__ + ':', *args)

#-------------------------------------------------------------------------------

if __name__ == '__main__': RIFUCRF()
</code></pre>
<p dir="auto">To reiterate from an earlier post in this thread, information about setting up and running a PythonScript is in the FAQ, <a href="https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript/">HERE</a>.</p>
<p dir="auto">So how do you run it, specifically for this application?</p>
<p dir="auto">Open into Notepad++ a data file in the top-level folder where you want to do the replacements. Execute the script from the <code>PythonScript</code> menu in Notepad++. You’ll be asked some questions, and then the core replacement logic will run to make your changes.</p>
<p dir="auto">--<br />
<em>Moderator EDIT (2024-Jan-14): fixed EOL order</em></p>
]]></description><link>https://community.notepad-plus-plus.org/post/81822</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81822</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Sun, 14 Jan 2024 19:21:37 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Mon, 21 Nov 2022 19:07:51 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> nothing to be frowny-faced about.   Will appreciate it as much next Monday as I would have today</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81821</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81821</guid><dc:creator><![CDATA[Scott Raskin]]></dc:creator><pubDate>Mon, 21 Nov 2022 19:07:51 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Mon, 21 Nov 2022 19:19:17 GMT]]></title><description><![CDATA[<p dir="auto">Under construction, please come back soon. :-(</p>
<h3>Edit:</h3>
<p dir="auto">I posted the script, then I wanted to add some comments about it, so I edited it, but the site told me my post was “too long”, so I chopped off the first part (containing the script), thinking that when I submitted, what I submitted would be an additional posting.  Doh!  It just replaced the original (of course, like it is supposed to do).</p>
<p dir="auto">So please wait while I reconstruct the two postings.  I saved the second one, so no loss there; the first one I have the script listing , of course, but I lost the surrounding data there.  :-(</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81820</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81820</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Mon, 21 Nov 2022 19:19:17 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Fri, 18 Nov 2022 11:21:34 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> not a problem. You’re doing us all a favor, and thr time it will save me will be way more than the time between now and you posting it so we are all very appreciative.  Also I’m in NY so I think we are on the same time zone, and as you can see by when I  posted that. We both need to sleep more</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81708</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81708</guid><dc:creator><![CDATA[Scott Raskin 0]]></dc:creator><pubDate>Fri, 18 Nov 2022 11:21:34 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Fri, 18 Nov 2022 09:49:25 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin-0" aria-label="Profile: Scott-Raskin-0">@<bdi>Scott-Raskin-0</bdi></a> said in <a href="/post/81700">renumbering/incremental</a>:</p>
<blockquote>
<p dir="auto">so what I did was click load folder into workspace and loaded that folder.  I think there were close to 1000 files on the tree on the left.  So, if I right click on the folder and do a find/replace and then click replace in all, it will replace in all 1000 files there.</p>
</blockquote>
<p dir="auto">OK, I understand your thinking on this now.  Unfortunately, there’s no easy way to hook a script with custom-replace functionality into that action.  But never fear, what I have in mind will work, albeit a bit differently.</p>
<blockquote>
<p dir="auto">As for posting the code that would be amazing (as I’ve already seen a few people with my specific problem, and I imagine others with something similar)</p>
</blockquote>
<p dir="auto">Yes, give me a bit of time to do it and post it.  Although it is 4am where I am (and I’ve just arisen after my 5 hours of sleep), I have a few other tasks to get to as well.  Check back here periodically…</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81702</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81702</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Fri, 18 Nov 2022 09:49:25 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Fri, 18 Nov 2022 09:40:55 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> so what I did was click load folder into workspace and loaded that folder.  I think there were close to 1000 files on the tree on the left.  So, if I right click on the folder and do a find/replace and then click replace in all, it will replace in all 1000 files there.  As for posting the code that would be amazing (as I’ve already seen a few people with my specific problem, and I imagine others with something similar)</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81700</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81700</guid><dc:creator><![CDATA[Scott Raskin 0]]></dc:creator><pubDate>Fri, 18 Nov 2022 09:40:55 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Fri, 18 Nov 2022 01:07:41 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin-0" aria-label="Profile: Scott-Raskin-0">@<bdi>Scott-Raskin-0</bdi></a> said in <a href="/post/81686">renumbering/incremental</a>:</p>
<blockquote>
<p dir="auto">are either of those things possible (running the script on all of the files loaded in the workspace) and/or adding that line renumbered thing to the python code?</p>
</blockquote>
<p dir="auto">Yes and yes, both are possible.<br />
But…I think you started out talking about 1000 files…surely you aren’t going to have that many “loaded in the workspace” of Notepad++??</p>
<p dir="auto">I think you’ve put in some hard work on this solution; how about if I finish up the script for you and post it?  We sort of need such a model for the <em>next</em> time someone asks for this frequent need.  We already have a template for a similar task that I can modify…</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81690</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81690</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Fri, 18 Nov 2022 01:07:41 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Thu, 17 Nov 2022 22:05:34 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> yeah, can’t work from home unfortunately as production of a physical product is a bit difficult remotely (until we have fully automated robots to do it all)<br />
So, before I exhaust myself looking for naught, are either of those things possible (running the script on all of the files loaded in the workspace) and/or adding that line renumbered thing to the python code?  If so.  I will spend my weekend on the hunt</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81686</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81686</guid><dc:creator><![CDATA[Scott Raskin 0]]></dc:creator><pubDate>Thu, 17 Nov 2022 22:05:34 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Thu, 17 Nov 2022 20:10:41 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/scott-raskin" aria-label="Profile: Scott-Raskin">@<bdi>Scott-Raskin</bdi></a> said in <a href="/post/81666">renumbering/incremental</a>:</p>
<blockquote>
<p dir="auto">Every time I start …“task x”…, someone comes and interrupts me (and with my ADD I have to start all over again)  How do you guys do this as I am assuming you are helping dozens of people on top of your regular life?</p>
</blockquote>
<p dir="auto">Hah, well, occupational hazard I guess.<br />
Work-from-home helps. :-)<br />
But yea, sometimes I wish the “real world” would go away, so I could sit around and play with Notepad++ all day.  :-)</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81679</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81679</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Thu, 17 Nov 2022 20:10:41 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Thu, 17 Nov 2022 17:13:24 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> and then I am going to do some more research on seeing if I can combine the two things you helped me with into one script (the replacing specific line thing: \A(?-s).<em>\R.</em>\R.*\R)<br />
Every time I start looking for the ability to use the script to replace EVERY file in a folders info, someone comes and interrupts me (and with my ADD I have to start all over again)  How do you guys do this as I am assuming you are helping dozens of people on top of your regular life?</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81666</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81666</guid><dc:creator><![CDATA[Scott Raskin]]></dc:creator><pubDate>Thu, 17 Nov 2022 17:13:24 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Thu, 17 Nov 2022 10:36:40 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> Yes, that is what I was saying could be a wrinkle.  However having been up since 2am, I am realizing that having to insert lines in between is an exception to the rule, rather than the rule.</p>
<p dir="auto">That being said, I ran that script and it worked perfectly.  I am going to study (I mean its only 3 lines, but still) that script and try to understand what each part means so maybe I can go forward and make changes on my own.  Really my end goal with everything is to be able to learn, so I really appreciate all of the help youve given me to get here.</p>
<p dir="auto">The only thing I dont see, is how to run that script on ALL of the files in the workspace.  When I do a find/replace, you can run it on all files open in the workspace (which I will do when I get to the point that you previously helped me with (replacing by line # within program), but I am sure that is somewhere in the python help guides!</p>
<p dir="auto">Thank you again and I will let you know my progress and what I have learned (I know, you are waiting with bated breath)</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81618</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81618</guid><dc:creator><![CDATA[Scott Raskin]]></dc:creator><pubDate>Thu, 17 Nov 2022 10:36:40 GMT</pubDate></item><item><title><![CDATA[Reply to renumbering&#x2F;incremental on Thu, 17 Nov 2022 04:55:35 GMT]]></title><description><![CDATA[<p dir="auto">Writing here as a former N/C Systems programmer.</p>
<ol>
<li>Renumbering is usually easiest if you simply remove all the line numbers, completely, and generate a new set from scratch.</li>
</ol>
<p dir="auto">Fortunately, this is not like BASIC programs, where the numbers were <em>referenced</em> (GOTO, GOSUB) from other lines.  (Some CNC controllers did <em>allow</em> that, but I never saw it used very much in <em>actual</em> CNC programs.)</p>
<p dir="auto">If such references do exist, then you’d need to track down the references, and update them, too, to match.  This requires good recordkeeping, and is definitely a candidate for automation.</p>
<p dir="auto">If I recall correctly, some users would number only a selected few lines, e.g., those where a tool change occurred, or those beginning a subroutine or loop.  The rest would remain unnumbered.  On the other hand, if the machine found a syntax or other error, then tracking it down, <em>without</em> line numbers, became a major pain.  There were, then, sometimes, two versions of a program: one with line numbers, used for early runs, and one without, used after the fully-numbered version had been proven reliable.</p>
<p dir="auto">BASIC programs were often numbered in increments of 10, to allow for easy insertion of lines, without having to renumber the whole darn program.  If you want to number every line, then I suggest doing the same thing here.</p>
<ol start="2">
<li>Doing it for thousands of distinct program files will require <em>two distinct</em> automations: one to locate and enumerate all the CNC files to be changed, wherever they are in the file system, and another to renumber each one.</li>
</ol>
<p dir="auto">I recommend putting the new, renumbered versions in a new location entirely, to avoid accidentally overwriting the original files.  After all, programs rarely work right the first time!</p>
<p dir="auto">Under Windows 10, CMD.EXE’s batch language can probably handle this kind of work.  The advantage being that you don’t need to install it; it’s already there.  The disadvantage being that it is a <em>horrible</em> programming language for newbies.  (And just about everyone else.)</p>
<p dir="auto">Having several years of experience, now, with Python, I can confidently say that Python is a much better bet for writing programs that novices can actually read, understand, and update.  No add-on modules are required.  Moreover, for tasks like this, <em>very</em> little of the Python language needs to be understood, to do an adequate job.</p>
<p dir="auto">Python is available, free, in the Windows Store, so it is virtually painless to install.  And Notepad++ is an excellent editor for writing your Python programs.</p>
<p dir="auto">The sheer volume of work to be done makes it hard for me to recommend Notepad++ – or any manually-operated editor – in any other capacity, for this particular task.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/81613</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/81613</guid><dc:creator><![CDATA[Phil Colbert]]></dc:creator><pubDate>Thu, 17 Nov 2022 04:55:35 GMT</pubDate></item></channel></rss>