plugin that support auto-numbering
-
You can do interesting things with script plugins.
-
@guy038 said in plugin that support auto-numbering:
Your version does not stop the numbering, when hitting the Enter key whereas my version stops it ( I didn’t do it on purpose ! )
I think this is probably because you added the
(?=\w)
look-ahead assertion. If there is no data on the current line after the number(s) and the “symbol(s)” then your lookahead fails and them =
regex test fails, thus the script does nothing more.Note that the “curr_line” and “prev_line” verbage that I use in the script are relative to what is “current” and “previous” AFTER the Enter key is pressed!
If I write a number of more than two digits, and hit the Enter key, at one moment, my version bugs definitively ! I couldn’t understand exactly why.
That part should be easy for you to understand as it only involves the regex! :-)
Say you type
789
at the start of a line and hit Enter right after.
The\s*
matches nothing.
The\d+
will match the7
.
The.+?
will match the8
.
The(?=\w)
will match the9
.
This is clearly not what is wanted here (we wanted the\d+
part to match the complete789
number).I thought of an small improvement : why not allow any list of symbols between the number and the first letter ?
I presented sort of a “basic” script for this type of processing, that met the OP’s specification, mainly to show how “easy” it was to implement in a short script, leveraging the Pythonscript plugin.
Note to the OP’s original desire: To implement a full-blown independent plugin for this behavior, while not difficult (probably), would be a bigger effort, and why would someone do that?
-
Hello, @alan-kilborn, @StoopidoMan, @peterjones and All
OK… So, I changed the old regex
\s*(\d+)(.+?)(?=\w)
with this new version\s*(\d+)([^\w\r\n]+)
. Indeed, as the[^\w\r\n]+
looks for a non-null range of non-word character(s), different fromEOL
chars, no need for a look-ahead ! This new regex ensures that, both :-
All the digits of a number will be matched by the
\d+
part -
Necessarily, the next character, after the symbol(s) range, will be a word character or an
EOL
character
So, my final version ( as I’m really not fluent at Python ! ) is :
# -*- coding: utf-8 -*- from Npp import editor, SCINTILLANOTIFICATION import re class NA(object): def __init__(self): self.eol = ['\r\n', '\r', '\n'][editor.getEOLMode()] editor.callback(self.callback_sci_CHARADDED, [SCINTILLANOTIFICATION.CHARADDED]) def callback_sci_CHARADDED(self, args): if chr(args['ch']) == self.eol[-1]: caret_pos = editor.getCurrentPos() curr_line_num = editor.lineFromPosition(caret_pos) if curr_line_num > 0: prev_line = editor.getLine(curr_line_num - 1) m = re.match(r'\s*(\d+)([^\w\r\n]+)', prev_line) if m: prev_number = int(m.group(1)) symbols_after = m.group(2) new_number = prev_number + 1 text_to_insert = str(new_number) + symbols_after editor.insertText(caret_pos, text_to_insert) new_caret_pos = caret_pos + len(text_to_insert) editor.setEmptySelection(new_caret_pos) if __name__ == '__main__': try: na except NameError: na = NA()
Notes :
-
First, all credits must be given to @alan-kilborn, as I haven’t modified very much the original script ;-))
-
As soon as you type in, at least, one digit followed with, at least, one symbol, including space(s), different from a word character ( digits, letters and underscore ), the script begins an auto-numbering sequence
-
A hit on the
Enter
key moves the caret so the same column of next line with the increased number, even if no additional word char(s) is added, at end of current line -
At any time, you may change the indentation, adding or deleting space and/or tab character(s) at beginning of current line
-
Delete all the symbol(s) range, and, possibly, the current number, to stop the auto numbering sequence. Of course, you may, as well, move the caret anywhere else and go on typing !
Cheers,
guy038
-
-
This post is deleted! -
@guy038 And @Alan-Kilborn
I am not that versed in NPP, how do I run a script when NPP runs?Google told me I have to install a plugin, to run python scripts, do you guys mind explaining it to me like I am 5.
And thank you guys, I appreciate it, and I hope many others who need this would appreciate it as well when they come across it.
-
We talk about scripts so much here that I’m surprised we don’t have a FAQ entry about getting up and running. [moderator update 4 years later: for the last two years, we have had that FAQ, but it didn’t exist in 2020, so I added the link so future readers can find it.]
So the first thing is to use Plugins Admin (on Plugins menu) to get the Python Script plugin.
After that, do Plugins > Python Script > New Script and give the script a name; as I said, I called my copy
NumberAutomagically.py
but you are free to name it anything you like (it is just a name so that the plugin can find the script file).Then N++ will open the (empty) script file, at which point you can copy and paste one version of the script above in and save it.
To run a script you do Plugins > Python Script > Scripts > and then click on your script.
I recommend trying it out before bothering to try to hook it into running when Notepad++ runs.
-
@Alan-Kilborn from the documentation I found out that I can paste your script to [Startup.py] to run it when NPP starts, however, is it possible to run NumberAutomagically.py located in user Folder at NPP startup, I can’t figure that out?
This way I can run several scripts in different file on NPP startup, instead of having all those scripts in side one file, it is more elegant.Also, if you have time, would you please modify the script so it would renumber the existing 5- to 10- as 6- through 11- when you enter a new line after 4-
PS: just noticed NumberAutomagically.py, cool name :) And really THANK YOU both.
Don’t read after this, it is for other StoopidoPeople who came across this, hi future people:
After installing Python Script and creating the script, you can add it to NPP toolbar with a custom icon or added to the Python script menu by going to:
[ Main Notepad++ UI>Plugins> Python Scripts>Configuration…> choose [NumberAutomagically by Alan Kilbor and Guy038.py] or [NumberAutomagically by Alan Kilbor.py] and then click Add button on the right side or left depending on your preference.Clarification:
The left Add button will add [NumberAutomagically.py] to [Plugins>Python Scripts>NumberAutomagically.py] menu
And, the right button will add the a button to run the script on NPP toolbar
Also, you can install Customize Toolbar by going to [plugins>Plugins Admin…] and searching for [Customize Toolbar ] to change the order of that buttons :) -
@Alan-Kilborn
One more thing 😬 if possible add this feature: pressing backspace would stop NumberingAutomagically, here is what I mean:1- test
2- test
3- (here if you entered backspace it would remove [3-] instead of pressing backspace 3 times to stop NumberingAutomagically )I think many would love that since that how Microsoft word Functions, And again, THANK YOU🙏
-
@StoopidoMan and anyone else still interested,
I modded the script to add 2 new functionalities:
- Bullet lists now supported (only “+” signs accepted at the moment)
- If you create a new line but have not written anything after the bullet or number (anything other than non-word chars) then the list ends, adding no new list item. This is similar to how Word handles lists (where pressing “Enter” twice ends the list).
Code below:
# -*- coding: utf-8 -*- from Npp import editor, SCINTILLANOTIFICATION import re class NA(object): def __init__(self): self.eol = ['\r\n', '\r', '\n'][editor.getEOLMode()] editor.callback(self.callback_sci_CHARADDED, [SCINTILLANOTIFICATION.CHARADDED]) def callback_sci_CHARADDED(self, args): if chr(args['ch']) == self.eol[-1]: caret_pos = editor.getCurrentPos() curr_line_num = editor.lineFromPosition(caret_pos) if curr_line_num > 0: prev_line = editor.getLine(curr_line_num - 1) m = re.match(r'\s*(\d+)([^\w\r\n]+)', prev_line) if m: full = str(m.group(1)) + str(m.group(2)) full_prev = prev_line.rstrip('\r\n') if (len(full_prev) > len(full)): # if m: prev_number = int(m.group(1)) symbols_after = m.group(2) new_number = prev_number + 1 text_to_insert = str(new_number) + symbols_after editor.insertText(caret_pos, text_to_insert) new_caret_pos = caret_pos + len(text_to_insert) editor.setEmptySelection(new_caret_pos) return m = re.match(r'\s*(\+)([^\w\r\n]+)', prev_line) if m: full = str(m.group(1)) + str(m.group(2)) full_prev = prev_line.rstrip('\r\n') if (len(full_prev) > len(full)): # if m: bullet = m.group(1) symbols_after = m.group(2) text_to_insert = bullet + symbols_after editor.insertText(caret_pos, text_to_insert) new_caret_pos = caret_pos + len(text_to_insert) editor.setEmptySelection(new_caret_pos) return if __name__ == '__main__': try: na except NameError: na = NA()
-
Tiny improvement (IMO) for bullet list: now it only copies spaces, no punctuation:
from Npp import editor, SCINTILLANOTIFICATION import re class NA(object): def __init__(self): self.eol = ['\r\n', '\r', '\n'][editor.getEOLMode()] editor.callback(self.callback_sci_CHARADDED, [SCINTILLANOTIFICATION.CHARADDED]) def callback_sci_CHARADDED(self, args): if chr(args['ch']) == self.eol[-1]: caret_pos = editor.getCurrentPos() curr_line_num = editor.lineFromPosition(caret_pos) if curr_line_num > 0: prev_line = editor.getLine(curr_line_num - 1) m = re.match(r'\s*(\d+)([^\w\r\n]+)', prev_line) if m: full = str(m.group(1)) + str(m.group(2)) full_prev = prev_line.rstrip('\r\n') if (len(full_prev) > len(full)): # if m: prev_number = int(m.group(1)) symbols_after = m.group(2) new_number = prev_number + 1 text_to_insert = str(new_number) + symbols_after editor.insertText(caret_pos, text_to_insert) new_caret_pos = caret_pos + len(text_to_insert) editor.setEmptySelection(new_caret_pos) return m = re.match(r'\s*(\+)([\s*]+)', prev_line) if m: full = str(m.group(1)) + str(m.group(2)) full_prev = prev_line.rstrip('\r\n') if (len(full_prev) > len(full)): # if m: bullet = m.group(1) symbols_after = m.group(2) text_to_insert = bullet + symbols_after editor.insertText(caret_pos, text_to_insert) new_caret_pos = caret_pos + len(text_to_insert) editor.setEmptySelection(new_caret_pos) return if __name__ == '__main__': try: na except NameError: na = NA()