Sublime Forum

Sort Open Files

#6

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(?).

0 Likes

#7

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.

0 Likes

#8

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?

0 Likes

#9

And finally :smiley: :sunglasses:

[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]
0 Likes

#10

You can sort the tabs every time a new tab is opened or finish loading. That way the list will stay sorted always.

0 Likes

#11

How do we sort tabs? Presumably there’s a Command for that :smiley:. Although, this won’t stop me finishing my work :smiley:

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 :laughing:

[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.

0 Likes

#12

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]

sublimetext.com/docs/2/api_reference.html

0 Likes

#13

Thank you tito. This could be an additional feature to the one I’ve built. Andy.

0 Likes

#14

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.

0 Likes

#15

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]

0 Likes

#16

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.

0 Likes

#17

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]
0 Likes

#18

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 :sunglasses: )

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 :question:. 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 :smile:. Andy.

0 Likes

#19

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?

0 Likes

#20

Go to Preferences > Browse Packages. Then save it in the User folder.

0 Likes

#21

The file doesn’t have to be named ‘OrderedFiles.py’, although it seems sensible to do so.

0 Likes

#22

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.

0 Likes

#23

@skube. Every key-binding must be separated by a comma, except the last one.

{ "keys": "ctrl+alt+x"], "command": "ordered_files", "args": { "index": 0 } }, { "keys": "ctrl+alt+c"], "command": "ordered_files", "args": { "index": 2 } } << bet you need to add a comma!

Otherwise, press the key-combination and then Ctrl-apostrophe to open the Console and see if there is an error message.

0 Likes

#24

I managed to get this running. However, this opens a new list/dopdown with all the open files. Would it be possible to use this to re-order the “open files” list on the left?

0 Likes

#25

That is beyond the scope of my little utility. I think there may be a package/plug-in that does what you are after: check here. Maybe SidebarEnhancements(?) but I don’t really know.

I suppose you could use my SortTabs.py:

[code]import sublime_plugin
from os import path
from operator import itemgetter

A simple command to sort current tabs alphabetically (returning focus to the

original tab).

Does not work with different groups or windows. Not catered for unsaved views

(although it seems to work okay if there are any). It could be modified to

work in these circumstances.

{ “keys”: “ctrl+alt+b”], “command”: “sort_tabs” },

class SortTabsCommand(sublime_plugin.WindowCommand):
def run(self):
file_views = ]
win = self.window
curr_view = win.active_view()
for vw in win.views():
, tail = path.split(vw.file_name() or path.sep)
group, _ = win.get_view_index(vw)
file_views.append((tail.lower(), vw, group))
file_views.sort(key = itemgetter(2, 0))
moving_index = 0
for index, (
, vw, group) in enumerate(file_views):
if index == 0 or 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]
Sorting the tabs will also sort the list in the sidebar. It works within the current group - not across all groups.

# suggested key binding { "keys": "ctrl+alt+b"], "command": "sort_tabs" }

0 Likes