Sublime Forum

Sort Open Files

#2

I don’t see why you’d need this when there’s the GoToAnything…

0 Likes

#3

… because it would be easier on the eyes and some people, like myself, prefer to have things well ordered.

0 Likes

#4

I think this would be a quick helpful thing to have available with many open files.

+1 for my interest.

0 Likes

#5

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

0 Likes

#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