Backspace Unindents
-
Yeah, this is one of the oddities in Npp. To users, the program pretends most of its settings are global to all documents. But internally every document/text buffer has its own set of preferences. I’m fighting with this in all my plugins.
I ended up with writing a buffer management, that remembers if a certain setting has been adopted by a text buffer. When a buffer is activated the first time, I do all configuration for this new buffer and store its id in a list. When a buffer is activated the next time, I will find it in the list and avoid doing any configuration. I do that mostly because of keeping Npp performant.
During development of the text buffer management I discovered some Npp quirks that I had to deal with. For example when a user moves a buffer from one view to the other it may get another buffer id.
You can have a look to the code of e.g. my AutoCodpage plugin to get some insights. The relevant code is in file Main.pas.
-
@dinkumoil said in Backspace Unindents:
I ended up with writing a buffer management … I discovered some Npp quirks…
In such a case we could also add a property to the document, can’t we?
Should resolve these kind of quirks. Might be a bit slower but maybe
more reliable. -
@Ekopalypse said in Backspace Unindents:
In such a case we could also add a property to the document, can’t we?
I’ve never tried this technique but it seems that a property is global for a certain Scintilla window, but one Scintilla windows hosts many text buffers (the document tabs). Thus I’m not sure if this feature can be used for a text buffer management.
-
as I understand it is a document property. Let me give it a quick try.
-
@dinkumoil
Yes, should work as it is bind to the document.
Script used to test:from Npp import editor editor.setProperty('secret_text','blablabla') print(editor.getProperty('secret_text'))
-
I don’t know the Python API for Npp. The editor object represents a single text buffer? Or an instance of Scintilla?
-
editor is an scintilla instance but the property is set on document level.
-
Hmm, which document? The active one?
-
yes if editor is used. And in case editor1 or 2 is used, then the
current viewable document. -
OK, then it’s worth to try using Scintilla’s properties for a text buffer management. But as I have a working system I will not change it. But I’m interested in knowing how that approach works.
-
Never change a running system!!! :-D
-
just a quick test
from Npp import editor1, notepad def loop_files(): for file in notepad.getFiles(): notepad.activateFile(file[0]) print(f'file: {file}') print(f' secret_text:{editor1.getProperty("secret_text")}') loop_files() notepad.activateFile('new 3') editor1.setProperty('secret_text', 'blablabla') loop_files()
returned
file: ('new 1', 44120304, 0, 0) secret_text: file: ('new 2', 112914256, 1, 0) secret_text: file: ('new 3', 112915984, 2, 0) secret_text: file: ('new 4', 112916416, 3, 0) secret_text: file: ('new 5', 112915552, 4, 0) secret_text: file: ('new 6', 112916848, 0, 1) secret_text: file: ('new 1', 44120304, 0, 0) secret_text: file: ('new 2', 112914256, 1, 0) secret_text: file: ('new 3', 112915984, 2, 0) secret_text:blablabla file: ('new 4', 112916416, 3, 0) secret_text: file: ('new 5', 112915552, 4, 0) secret_text: file: ('new 6', 112916848, 0, 1) secret_text:
Btw. setting and reading the value takes about ~20 microseconds each for python.
-
FYI, SCI_GETPROPERTY and SCI_SETPROPERTY are put to good use by @Claudia-Frank in the File Specific word wrap (vs. global enable) discussion thread, specifically, THIS POSTING.
-
@Michael-Vincent said in Backspace Unindents:
In a previous thread I mentioned I started using backspace unindents
THIS POSTING must be that reference to a previous thread.
-
So for anybody interested, I turned the addition of the backspace-unindent capability into a PythonScript.
I put it in a
BackspaceUnindents.py
file:from Npp import editor, notepad, NOTIFICATION class BackspaceUnindents(object): def __init__(self): self.activated = True notepad.callback(self.callback_for_bufferactivated, [NOTIFICATION.BUFFERACTIVATED]) self.callback_for_bufferactivated(None) # set it for the currently active document def callback_for_bufferactivated(self, args): # this document property won't automatically be applied to newly created tabs; adjust for that: editor.setBackSpaceUnIndents(self.activated) def is_activated(self): return self.activated def set_activated(self, b): self.activated = b self.callback_for_bufferactivated(None) if __name__ == '__main__': try: backspace_unindents except NameError: backspace_unindents = BackspaceUnindents() notepad.messageBox('BackspaceUnindents installed and activated') else: if backspace_unindents.is_activated(): backspace_unindents.set_activated(False) notepad.messageBox('BackspaceUnindents deactivated') else: backspace_unindents.set_activated(True) notepad.messageBox('BackspaceUnindents activated')
I set mine to run from
startup.py
as follows:import BackspaceUnindents backspace_unindents = BackspaceUnindents.BackspaceUnindents()
but it can be run manually with or without that. Run it once to turn it on, run again to turn off.
-
Hi, @alan-kilborn, @ekopalypse, @michael-vincent and All,
Alan, Just tried your
BackspaceUnindents.py
with no difference seen between the two states, although the script seems to work nice ?!Did I clearly understand what’s for ? I mean, from the link below :
https://www.scintilla.org/ScintillaDoc.html#SCI_SETBACKSPACEUNINDENTS
I supposed that the Python script alternatively change the behaviour of the Backspace key :
-
By default or when the
BackspaceUnindents
process is deactivated, a hit on theBackspace
key deletes the previous indentation -
When the
BackspaceUnindents
process is activated, a hit on theBackspace
key simply moves the caret to the previous indentation location
Am I right about it ? What I miss, there ?
Best Regards
guy038
-
-
Hmmm, not sure.
For me, without the script or with it deactivated, on a line that contains only lots of space characters and the caret right before the line ending, pressing Backspace repeatedly will remove one space at a time.
With the script active, in the same situation, the Backspace key will remove 4 spaces with each press (I have my tabs setting to insert 4 spaces per tab), assuming I started with a number of spaces evenly divisible by 4.
I suppose, if one has tab set to insert tab characters, backspacing those out of existence will work the same either with the script of without it.
-
@Alan-Kilborn, @guy038 and All
Haven’t read all this thread, but in case you want to make a comparation, the
Extended Settings plugin
provides a similar feature. Works fine, by the way.Cheers.
-
the Extended Settings plugin provides a similar feature
Sure; I’m actually quite surprised no one earlier in the thread mentioned that.
If I used Extended Settings plugin, I’d like to think I would have mentioned it.
At the time the plugin came out, I already had most of its functionality, thru scripts.I even had a backspace-unindenter script (different from the one above); not realizing that Scintilla provided the function, my script did it manually and was tied to the Backspace key binding.
(In some ways I liked my earlier script better than Scintilla’s function!) -
Hello @alan-kilborn and All,
OK ! When doing tests, the
TAB
key was set to write a four positionsTAB
character and I principally did tests with leadingtab
chars ! But never mind, now, I understood the whole thing :First, from the Scintilla documentation, I saw that there a similar message to
BackspaceUnindents
, which isTabIndents
. Note that, by default Notepad++ starts with theTabIndents
message activated and with theBackspaceUnindents
message deactivated !So, I created an other python script, called
TabIndents.py
, in order to activate/deactivate theTabIndents
message. I get absolutely no credit because it’s just a copy/paste of the Alan’s script !from Npp import editor, notepad, NOTIFICATION class TabIndents(object): def __init__(self): self.activated = True notepad.callback(self.callback_for_bufferactivated, [NOTIFICATION.BUFFERACTIVATED]) self.callback_for_bufferactivated(None) # set it for the currently active document def callback_for_bufferactivated(self, args): # this document property won't automatically be applied to newly created tabs; adjust for that: editor.setTabIndents(self.activated) def is_activated(self): return self.activated def set_activated(self, b): self.activated = b self.callback_for_bufferactivated(None) if __name__ == '__main__': try: tab_indents except NameError: tab_indents = TabIndents() notepad.messageBox('TabIndents installed and activated') else: if tab_indents.is_activated(): tab_indents.set_activated(False) notepad.messageBox('TabIndents deactivated') else: tab_indents.set_activated(True) notepad.messageBox('TabIndents activated')
Then I played around, with a sample line of mixed
TAB
andSPACE
chars, both, in the leading part and further on, between usual characters :-
Activating / deactivating the
TabIndents.py
and/or theBaskspaceUnindents.py
messages -
Choosing, either,
1 TAB
char of4
positions long OR4 SPACE
chars, when you hit theTAB
key, for language normal, inPreferences... > Language > Tab Settings > normal
-
Moving caret within the leading blank chars OR in subsequents blanks ranges, further on, in current line
And, here is, below, a summary of my observations :
Regarding the
BACKSPACE
key behaviour :-
If caret within the
leading blank
range of chars ANDBackspaceUnindents
message activated [ NEW backspace behaviour ] :-
If setting TAB to
4 SPACE
chars, a hit on theBACKSPACE
key :- Deletes previous char(s) to get the previous indentation level
- Normalizes all preceding blank chars, till beginning of line, to
SPACE
chars - Moves the caret after the last leading
SPACE
char
-
If setting TAB to
1 TAB
char of4
positions long, a hit on theBACKSPACE
key :- Deletes previous char(s) to get the previous indentation level
- Normalizes all preceding blank chars, till beginning of line, to
TAB
chars - Moves the caret after the last leading
TAB
char
-
-
If caret outside the
leading blank
range of chars ORBackspaceUnindents
message deactivated OR by DEFAULT, a hit on theBACKSPACE
key :- Deletes previous char to get the correct or previous indentation level
- Leave the caret at current position
Regarding the
TAB
key behaviour :-
If caret outside the
leading blank
range of chars, whatever the status of theTabIndents
message :-
When setting TAB to
4 SPACE
chars, a hit on theTAB
key :- Adds up to
4 SPACE
char(s) to get the next indentation level - Leave the caret right after these added
SPACE
char(s)
- Adds up to
-
When setting TAB to a
1 TAB
of4
positions long , a hit on theTAB
key :- Adds a
TAB
char to get the next indentation level - Leave the caret right after the added
TAB
char
- Adds a
-
-
If caret within the
leading blank
range of chars :-
If the
TabIndents
message is activated OR by DEFAULT :-
When setting TAB to
4 SPACE
chars, a hit on theTAB
key :- Adds up to
4 SPACE
char(s) to get the next indentation level - Normalizes all preceding blank chars, till beginning of line, to
SPACE
chars - Moves the caret after the last leading
SPACE
char
- Adds up to
-
When setting TAB to a
1 TAB
of4
positions long , a hit on theTAB
key :- Adds a
TAB
char to get the next indentation level - Normalizes all preceding blank chars, till beginning of line, to
TAB
chars - Moves the caret after the last leading
TAB
char
- Adds a
-
-
If the
TabIndents
message is deactivated [ NEW tab behaviour ] :-
When setting TAB to
4 SPACE
chars, a hit on theTAB
key :- Adds up to
4 SPACE
char(s) to get the next indentation level - Leave the caret right after these added
SPACE
char(s)
- Adds up to
-
When setting TAB to a
1 TAB
of4
positions long , a hit on theTAB
key :- Adds a
TAB
char to get the next indentation level - Leave the caret right after the added
TAB
char
- Adds a
-
-
Best Regards,
guy038
-