Auto sort tabs (real-time)
-
Hello, @maxitrol-mat and All,
Ah… OK. I understand your needs. And, seemingly, your are looking for an alphabetic tab’s names sort ! I think that is, typically, the kind of task that could be achieved with a Python script. But, as my Python skills are near zero, I just hope that one of our Python’s gurus , of our Community, could find out a nice solution !
Basically, you can call a Python function when events occur in
Notepad++
orScintilla
. In a Python script, you may register a function, named, for instance,SortTabs
, doing the actions that I described, in my previous post, to be called whenever a specific event occurs ( i.e. when you open a file ), using the notification :notepad.callback(SortTabs, [NOTIFICATION.FILEOPENED])
Not really sure about this notification : it could be
NOTIFICATION.BUFFERACTIVATED
or evenNOTIFICATION.FILEBEFOREOPEN
. As I told you, Python language isn’t my cup of tea, yet ;-))So, every time, you open a file, it would re-sort, automatically, all your tabs
So, thank you to be patient for a more enlightened and constructive help.!
BR
guy038
-
Theoretically yes, the problem is that there is no public API for the tab container, so it is not that simple.
The simulation of what npp internal does is crucial here, because otherwise npp has a different view on how the buffer list is sorted. -
https://github.com/notepad-plus-plus/notepad-plus-plus/issues/8147 << there is even a bug
-
@ArkadiuszMichalski said in Auto sort tabs (real-time):
there is even a bug
No bug. A feature request, yes.
-
@Ekopalypse said in Auto sort tabs (real-time):
Theoretically yes, the problem is that there is no public API for the tab container, so it is not that simple.
The simulation of what npp internal does is crucial here, because otherwise npp has a different view on how the buffer list is sorted.Thank you very much for great answers to all of you! Feature request doesn’t help because I requested it years ago. The author is just not interested to add this - too bad because for him is probably 10 min task and would be extremely useful. I found two editors that does this but are otherwise not good to use.
I guess there is nothing we can do.
p.s. Who put sort tabs as manual option in menu where you have to click 4 times before tabs get sorted - crazy! LOL
Thanks again!
-
@Maxitrol-Mat said in Auto sort tabs (real-time):
Feature request doesn’t help because I requested it years ago. The author is just not interested to add this
Here’s your true answer.
It’s the author’s product that he lets you use for no cost.
As such, he can make such decisions.
Be glad for the features that do exist.is probably 10 min task
If the author happened to see a comment like that (he won’t BTW), it would totally seal the coffin from such a feature ever happening.
How long would it take YOU to add this feature?
And while you investigate that, just do it and contribute your change. :-)
I can hear the response: “I’m not a programmer”.
Well, if that’s the case, then how do you know it takes 10 minutes??Who put sort tabs as manual option in menu where you have to click 4 times before tabs get sorted - crazy
Apparently it is something so few people want to do, buried as a subfunction seems an appropriate place.
-
@Maxitrol-Mat said in Auto sort tabs (real-time):
p.s. Who put sort tabs as manual option in menu where you have to click 4 times before tabs get sorted - crazy! LOL
How about just using the shortcut:
Alt+W, W, T
That is, press and hold the
Alt
key while then pressing in succession (while still holding theAlt
key through all key presses)W
,W
,T
Cheers.
-
@Michael-Vincent said in Auto sort tabs (real-time):
…press and hold the Alt key while then pressing in succession (while still holding the Alt key through all key presses) W, W, T
I might be tempted to buy-a-vowel and put an O (the letter “Oh”, not a zero) at the end of that sequence. It closes the extra window that has appeared (from the first W press).
-
@Alan-Kilborn said in Auto sort tabs (real-time):
It closes the extra window that has appeared
Indeed it does! I wonder can that be setup as a macro so just need one keypress by shortcutting the Macro? That’s about as close as the OP can get to a plugin that does this automatically - one “keystroke”.
Cheers.
-
(from the first W press).
Nitpick: the window opens on the second
W
. ;-)I wonder can that be setup as a macro
You cannot record it with the macros.
Usingtype=2 wParam="11001"
, you can open the Windows dialog with a macro.
Hmm,english.xml
showsSort tabs
button as 7004… but running7004
alone as the wParam doesn’t sort the tabs, and if you try a 7004 after the 11001, the 7004 (and anything subsequent) doesn’t try to run until after the Windows dialog is closed.However, knowing that the “Sort tabs” button ID for that dialog is 7004 (and OK is 2), @Ekopalypse could probably figure out the necessary PythonScript to launch the dialog, push “sort tabs”, and push “ok”.
-
@Michael-Vincent, All:
Beware that those shortcuts are language-dependant, for example,
Alt-W
won’t work in my configuration, instead I need to pressAlt-V
to open that window. -
that, of course, could be a solution but to be honest,
it would drive me nuts to see this blinking window all the time.@Maxitrol-Mat
are you interested in such a solution? -
@Ekopalypse said in Auto sort tabs (real-time):
it would drive me nuts to see this blinking window all the time.
Me too. But would it really need to be “all the time”? The only time you would need to re-sort tabs would be when a new tab is added (if you close/remove a tab, the rest are still sorted properly), so wouldn’t you just hook onto the file-opened notification (which I believe triggers for both opening an existing file and for creating a new file tab)?
But yes, no need to do further work if @Maxitrol-Mat isn’t willing to use PythonScript for the solution. ;-)
-
@Maxitrol-Mat and all
Instead of using the built-in dialog, tab sorting can be done very easily using the Move Tab Forward / Backward commands from the
View -> Tab
menu.In the following I provide a solution in NppExec plugin script language. It uses a slightly optimized version of the Bubble Sort algorithm and sorts the tabs case-insensitive per view. The active tabs of the views are restored after sorting.
::SortTabs npp_console keep // Retrieve values of some constants set local $(PrimaryViewId) ~ MAIN_VIEW set local $(SecondViewId) ~ SUB_VIEW set local $(PrimaryView) ~ PRIMARY_VIEW set local $(SecondView) ~ SECOND_VIEW // Get id of active buffer's view npp_sendmsg NPPM_GETCURRENTVIEW set local $(CurViewId) = $(MSG_RESULT) // Init variables for view switching if $(CurViewId) == $(PrimaryViewId) then set local $(ActiveView) = $(PrimaryView) set local $(ActiveViewId) = $(PrimaryViewId) set local $(InactiveView) = $(SecondView) set local $(InactiveViewId) = $(SecondViewId) else if $(CurViewId) == $(SecondViewId) then set local $(ActiveView) = $(SecondView) set local $(ActiveViewId) = $(SecondViewId) set local $(InactiveView) = $(PrimaryView) set local $(InactiveViewId) = $(PrimaryViewId) else exit endif // Remember buffer id of active tab in active view npp_sendmsg NPPM_GETCURRENTDOCINDEX 0 $(ActiveViewId) npp_sendmsg NPPM_GETBUFFERIDFROMPOS $(MSG_RESULT) $(ActiveViewId) set local $(ActiveViewCurBufferId) = $(MSG_RESULT) // Remember buffer id of active tab in inactive view if this view is visible npp_sendmsg NPPM_GETCURRENTDOCINDEX 0 $(InactiveViewId) if $(MSG_RESULT) == -1 then set local $(ProcessInactiveView) = 0 else npp_sendmsg NPPM_GETBUFFERIDFROMPOS $(MSG_RESULT) $(InactiveViewId) set local $(InactiveViewCurBufferId) = $(MSG_RESULT) set local $(ProcessInactiveView) = 1 endif // Start tab sorting in active view set local $(CurView) = $(ActiveView) :IterateAllViews // Retrieve number of open tabs in current view npp_sendmsg NPPM_GETNBOPENFILES 0 $(CurView) set local $(MaxTabIdx) ~ $(MSG_RESULT) - 1 set local $(MinTabIdx) = 0 // Sort tabs using optimized version of Bubble Sort // and "Move Tab xxx" commands from menu "View -> Tab" :DoLoopStart set local $(Swapped) = 0 set local $(CurTabIdx) = $(MaxTabIdx) npp_sendmsg NPPM_ACTIVATEDOC $(CurViewId) $(CurTabIdx) set local $(LeftFileName) ~ strupper $(FILE_NAME) :ForLoopStart if $(CurTabIdx) <= $(MinTabIdx) goto :ForLoopEnd set local $(RightFileName) = $(LeftFileName) set local $(NextTabIdx) ~ $(CurTabIdx) - 1 npp_sendmsg NPPM_ACTIVATEDOC $(CurViewId) $(NextTabIdx) set local $(LeftFileName) ~ strupper $(FILE_NAME) if "$(LeftFileName)" > "$(RightFileName)" then npp_sendmsg WM_COMMAND IDM_VIEW_TAB_MOVEFORWARD set local $(LeftFileName) = $(RightFileName) set local $(Swapped) = 1 endif set local $(CurTabIdx) ~ $(CurTabIdx) - 1 goto :ForLoopStart :ForLoopEnd set local $(MinTabIdx) ~ $(MinTabIdx) + 1 if $(Swapped) == 1 goto :DoLoopStart // As long as the inactive view is visible ... if $(ProcessInactiveView) == 1 then // ... and we didn't process all views ... if $(CurView) != $(InactiveView) then // ... advance to next view and repeat tab sorting set local $(CurView) = $(InactiveView) set local $(CurViewId) = $(InactiveViewId) goto :IterateAllViews endif endif // If inactive view is visible restore its active tab if $(ProcessInactiveView) == 1 then npp_sendmsg NPPM_GETPOSFROMBUFFERID $(InactiveViewCurBufferId) $(InactiveViewId) set local $(InactiveViewActiveTabIdx) ~ $(MSG_RESULT) & 0x3FFFFFFF npp_sendmsg NPPM_ACTIVATEDOC $(InactiveViewId) $(InactiveViewActiveTabIdx) endif // Restore active tab of active view npp_sendmsg NPPM_GETPOSFROMBUFFERID $(ActiveViewCurBufferId) $(ActiveViewId) set local $(ActiveViewActiveTabIdx) ~ $(MSG_RESULT) & 0x3FFFFFFF npp_sendmsg NPPM_ACTIVATEDOC $(ActiveViewId) $(ActiveViewActiveTabIdx)
I have to admit that it produces lots of screen flickering (depending on the number of open tabs), but as tab sorting normally is not a frequently executed task it should be OK.
-
@dinkumoil said in Auto sort tabs (real-time):
f screen flickering (depending on the number of open tabs), but as tab sorting normally is not a frequently executed task it should be
I don’t mind flickering if it will auto-sort each time I add a new file.
If the author happened to see a comment like that (he won’t BTW), it would totally seal the coffin from such a feature ever happening.
That would make such an author an idiot. Have you done any business, ever?
-
Have you done any business, ever?
Notepad++ is not a business, it’s a completely free product. Thus, business rules don’t fit for Npp project.
I don’t mind flickering if it will auto-sort each time I add a new file.
My script will not auto-sort. The script has to be assigned to a keyboard shortcut. Another way would be to install the NppEventExec plugin as well. This plugin is intended to work together with NppExec and can call NppExec scripts when an event is fired.
That would make such an author an idiot.
Because you were insulting, go figure out the solution which is perfect for you by yourself.
-
Same poster, same topic, DIFFERENT thread.
-
So not that I find this idea useful, but I needed some mental exercise while waiting for something to happen today, so I gave it a go with scripting, specifically Pythonscripting.
The result is below; it is a bit of a visual treat when a new file is opened into a view with already a lot of tabs. It is probably too annoying to really be practical, but…
I call the script
SortFileTabsByFilename.py
and here we go:# -*- coding: utf-8 -*- from Npp import editor, notepad, NOTIFICATION import os class SFTBF(object): def __init__(self): self.installed = False def install(self): if not self.installed: notepad.callback(self.file_opened_callback, [NOTIFICATION.FILEOPENED]) self.installed = True def uninstall(self): if self.installed: notepad.clearCallbacks(self.file_opened_callback) self.installed = False def is_installed(self): return self.installed def file_opened_callback(self, args): current_view = notepad.getCurrentView() other_view = 1 if current_view == 0 else 0 if notepad.getCurrentDocIndex(other_view) == 4294967295L: other_view = None curr_view_paths_list = []; curr_view_sorted_paths_list = [] other_view_paths_list = []; other_view_sorted_paths_list = [] for (filename, _, index_in_view, view) in notepad.getFiles(): if view == current_view: curr_view_paths_list.append(filename) curr_view_sorted_paths_list.append(filename) else: other_view_paths_list.append(filename) other_view_sorted_paths_list.append(filename) curr_view_sorted_paths_list.sort(key=lambda x: x.rsplit(os.sep, 1)[-1].upper()) curr_view_already_sorted = True if curr_view_paths_list == curr_view_sorted_paths_list else False other_view_sorted_paths_list.sort(key=lambda x: x.rsplit(os.sep, 1)[-1].upper()) other_view_already_sorted = True if other_view_paths_list == other_view_sorted_paths_list else False if curr_view_already_sorted and other_view_already_sorted: return # nothing to do processed_other_view = False if other_view != None and not other_view_already_sorted: self.rearrange_tabs_in_view(other_view, other_view_sorted_paths_list) processed_other_view = True processed_current_view = False if not curr_view_already_sorted: self.rearrange_tabs_in_view(current_view, curr_view_sorted_paths_list) processed_current_view = True if processed_other_view and not processed_current_view: # leave the view we started in as the active one: notepad.activateIndex(current_view, notepad.getCurrentDocIndex(current_view)) def rearrange_tabs_in_view(self, view, sorted_name_list): notepad.activateIndex(view, notepad.getCurrentDocIndex(view)) # get switched into the correct view remembered_active_filename = notepad.getCurrentFilename() destination_index = 0 num_of_tabs = len(sorted_name_list) while destination_index < num_of_tabs: current_order_list = [] for (filename, _, index_in_view, v) in notepad.getFiles(): if v == view: current_order_list.append(filename) curr_location_index = current_order_list.index(sorted_name_list[destination_index]) move_left_count = curr_location_index - destination_index if move_left_count > 0: notepad.activateFile(current_order_list[curr_location_index]) for _ in range(move_left_count): notepad.menuCommand(MENUCOMMAND.VIEW_TAB_MOVEBACKWARD) destination_index += 1 notepad.activateFile(remembered_active_filename) if __name__ == '__main__': if 'sftbf' not in globals(): sftbf = SFTBF() # each running of the script toggles install/uninstall: sftbf.uninstall() if sftbf.is_installed() else sftbf.install() notepad.messageBox('SortFileTabsByFilename {}INSTALLED!'.format('' if sftbf.is_installed() else 'UN'), '')
-
Nice.
However, when I previously said,
which I believe triggers for both opening an existing file and for creating a new file tab
… I was apparently wrong. Because File > New doesn’t trigger the script’s sorting function for me, whereas Open does. I don’t see a message that does seem to be triggered for New, either. Hmm…
-
I assume because, technically, new, does not open a file.