… because it would be easier on the eyes and some people, like myself, prefer to have things well ordered.
Sort Open Files
I think this would be a quick helpful thing to have available with many open files.
+1 for my interest.
+1 … I want this too. I always end up working on 20+ files no matter how hard I try to keep closing them and at that point the tabs become unreadable and locating an open file would be simple if it was alpha sorted.
I suppose it wouldn’t be impossible to create a TextCommand that closes all open files, re-opens them in a specific sorted order, and returns to the previous cursor position.
Easier, and perhaps more convenient, is to create a command that shows a quick panel listing the currently open files in a particular order, and allows you to switch to a selected file. This way, the SideBar will continue to list files in the order they were opened.
I quite like this idea… might give it a bash. Added: However, Ctrl-P and other menu options seem to almost cover this anyway(?).
Here’s a rough and ready version (for Windows):
[code]import sublime, sublime_plugin, os
open_files = ]
full_files = ]
class OrderedFilesCommand(sublime_plugin.TextCommand):
def run(self, edit):
global open_files
global full_files
open_files = ]
full_files = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
open_files.append(tail)
full_files.append((tail, head))
open_files.sort()
full_files.sort()
self.view.window().show_quick_panel(open_files, self.on_done_choosing)
def on_done_choosing(self, index):
if index != -1:
win = self.view.window()
win.open_file(full_files[index][1] + '\\' + full_files[index][0])[/code]
Assign it a shortcut key and it will open a quick panel listing files in alphabetical order. Select the file to activate it.
Amending ‘\’ to ‘/’ should get it to work with other os’s, but I’m sure there’s a property like ‘file_separator’ that will make it work in both.
It’s not as neat as I would like, but not bad for a first attempt. It will be possible to amend it so that a different shortcut would show the list in, for example, last modified order. Andy.
This is much neater and doesn’t require the file separator character:
[code]import sublime, sublime_plugin, os
open_files = ]
their_view = ]
class OrderedFilesCommand(sublime_plugin.TextCommand):
def run(self, edit):
global open_files
global their_view
open_files = ]
their_view = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
open_files.append(tail)
their_view.append((tail, vw))
open_files.sort()
their_view.sort()
self.view.window().show_quick_panel(open_files, self.on_done_choosing)
def on_done_choosing(self, index):
if index != -1:
win = self.view.window()
win.focus_view(their_view[index][1])[/code]
I would prefer to only use one list. But if I have a list of tuples, how can I pass this as an array of strings - using only the first of the 2 tuple-elements?
And finally
[code]import sublime, sublime_plugin, os
file_views = ]
class OrderedFilesCommand(sublime_plugin.TextCommand):
def run(self, edit):
global file_views
file_views = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
file_views.append((tail, vw))
file_views.sort()
self.view.window().show_quick_panel([x for (x, y) in file_views], self.on_chosen)
def on_chosen(self, index):
if index != -1:
win = self.view.window()
win.focus_view(file_views[index][1])[/code]
You can sort the tabs every time a new tab is opened or finish loading. That way the list will stay sorted always.
How do we sort tabs? Presumably there’s a Command for that . Although, this won’t stop me finishing my work
This last/latest(?) version will display the files in either alphabetical or modified date order. If using modified date order, the date-time also appears in the quick panel.
[code]import sublime, sublime_plugin, os, datetime
from operator import itemgetter
file_views = ]
class OrderedFilesCommand(sublime_plugin.TextCommand):
def run(self, edit, index):
global file_views
file_views = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
modified = os.path.getmtime(vw.file_name())
file_views.append((tail, vw, modified))
file_views.sort(key = itemgetter(index))
print file_views
if index == 2:
self.view.window().show_quick_panel([x + ’ ’ +
(datetime.datetime.fromtimestamp(z)).strftime("%d-%m-%y %H:%M")
for (x, y, z) in file_views], self.on_chosen)
else:
self.view.window().show_quick_panel([x for (x, y, z) in file_views],
self.on_chosen)
def on_chosen(self, index):
if index != -1:
win = self.view.window()
win.focus_view(file_views[index][1])[/code]
I’ve assigned key bindings:
{ "keys": "ctrl+alt+x"], "command": "ordered_files", "args": { "index": 0 } },
{ "keys": "ctrl+alt+c"], "command": "ordered_files", "args": { "index": 2 } }
where index == 2 sorts by modified date.
I’ve been playing with ‘rjust(50 - len(x))’ to try and align the date-times to the right, but it’s misbehaving a little. Andy.
Added: Doh! Why “piddle with padding” when I can just put the timestamp first
[code]import sublime, sublime_plugin, os, datetime
from operator import itemgetter
file_views = ]
class OrderedFilesCommand(sublime_plugin.TextCommand):
def run(self, edit, index):
global file_views
file_views = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
modified = os.path.getmtime(vw.file_name())
file_views.append((tail, vw, modified))
file_views.sort(key = itemgetter(index))
print file_views
if index == 2:
self.view.window().show_quick_panel(
(datetime.datetime.fromtimestamp(z)).strftime("%d-%m-%y %H:%M ") + x
for (x, y, z) in file_views], self.on_chosen)
else:
self.view.window().show_quick_panel([x for (x, y, z) in file_views],
self.on_chosen)
def on_chosen(self, index):
if index != -1:
win = self.view.window()
win.focus_view(file_views[index][1])[/code]
Now perfect. Signing off.
There is an API method to set the position of a tab in the tabbar with set_view_index. Example to move the current view to group 0 in position 0
You can check current view_index with
[quote]
group, index = sublime.active_window().get_view_index(sublime.active_window().active_view())
print group
print index[/quote]
Thank you tito. This could be an additional feature to the one I’ve built. Andy.
Inspired/ encouraged by tito, the following will sort tabs alphabetically. My previous code was case-sensitive, whereas this is not. It should also sort within each existing group - although I haven’t tried this.
[code]import sublime, sublime_plugin, os
class SortTabsCommand(sublime_plugin.TextCommand):
def run(self, edit):
file_views = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
file_views.append((tail, vw))
file_views.sort(key = lambda (tail, ): tail.lower())
win = self.view.window()
for index, (, vw) in enumerate(file_views):
group, _ = win.get_view_index(vw)
win.set_view_index(vw, group, index)[/code]
Added: Careful! It doesn’t work with more than one group as yet.
Now we can work with more than one group (if you use such things…)
[code]import sublime, sublime_plugin, os
from operator import itemgetter
class SortTabsCommand(sublime_plugin.TextCommand):
def run(self, edit):
file_views = ]
win = self.view.window()
curr_view = win.active_view()
for vw in win.views():
head, tail = os.path.split(vw.file_name())
group, _ = win.get_view_index(vw)
file_views.append((tail.lower(), vw, group))
file_views.sort(key = itemgetter(2, 0))
for index, (_, vw, group) in enumerate(file_views):
if not index:
prev_group = group
moving_index = 0
elif group > prev_group:
moving_index = 0
prev_group = group
else:
moving_index += 1
win.set_view_index(vw, group, moving_index)
win.focus_view(curr_view)[/code]
I’m interested into having a “sort tabs” package. In rare occasions is useful, please add it to github. if you can add it to the sublime organization better.
I’ve put it on Gist for the moment. Oops, try this https://gist.github.com/1995067
This final (again) version of OrderedFiles.py is now case-insensitive:
[code]import sublime, sublime_plugin, os, datetime
from operator import itemgetter
file_views = ]
class OrderedFilesCommand(sublime_plugin.TextCommand):
def run(self, edit, index):
global file_views
file_views = ]
for vw in self.view.window().views():
head, tail = os.path.split(vw.file_name())
modified = os.path.getmtime(vw.file_name())
file_views.append((tail, vw, modified))
if index == 0:
file_views.sort(key = lambda (tail, Doh, Dur): tail.lower())
else:
file_views.sort(key = itemgetter(2))
if index == 2:
self.view.window().show_quick_panel(
(datetime.datetime.fromtimestamp(z)).strftime("%d-%m-%y %H:%M ") + x
for (x, y, z) in file_views], self.on_chosen)
else:
self.view.window().show_quick_panel([x for (x, y, z) in file_views],
self.on_chosen)
def on_chosen(self, index):
if index != -1:
win = self.view.window()
win.focus_view(file_views[index][1])[/code]
OrderedFiles.py is more sensible as a WindowCommand, and I’ve *tidied *the code a little.
[code]import sublime_plugin
from os import path
from operator import itemgetter
from datetime import datetime
class OrderedFilesCommand(sublime_plugin.WindowCommand):
def run(self, index):
OF = OrderedFilesCommand
OF.file_views = ]
win = self.window
for vw in win.views():
head, tail = path.split(vw.file_name())
modified = path.getmtime(vw.file_name())
OF.file_views.append((tail, vw, modified))
if index == 0: # sort by file name (case-insensitive)
OF.file_views.sort(key = lambda (tail, _, Doh): tail.lower())
win.show_quick_panel([x for (x, y, z) in OF.file_views], self.on_chosen)
else: # sort by modified date (index == 2)
OF.file_views.sort(key = itemgetter(2))
win.show_quick_panel(
(datetime.fromtimestamp(z)).strftime("%d-%m-%y %H:%M ") + x
for (x, y, z) in OF.file_views], self.on_chosen)
def on_chosen(self, index):
if index != -1:
self.window.focus_view(OrderedFilesCommand.file_views[index][1])[/code]
No previous poster has come back about this, so I’ve no idea if anyone is finding it useful (I am )
I was thinking it’s (probably) possible to expand it such that typing a single number will jump to that (numbered) file: ‘(1) somefile.ext’. But having more than 10 files open might make it a little cumbersome… But still, you could just type a second number . A more complex solution would be to have a ‘key’ letter(s) highlighted (I believe? this is possible in the quick panel…) to cause the file to be focused.
But I won’t bother unless someone expresses an interest . Andy.
How does one use this? Do you copy and save to a file call OrderedFiles.py? Does it have to go in any particular folder in the packages directory?
The file doesn’t have to be named ‘OrderedFiles.py’, although it seems sensible to do so.
Great thanks. But how do I actually sort? I’ve tried adding the key bindings:
{ "keys": "ctrl+alt+x"], "command": "ordered_files", "args": { "index": 0 } },
{ "keys": "ctrl+alt+c"], "command": "ordered_files", "args": { "index": 2 } }
But nothing happens.