I have a custom plugin below to provide this functionality:
import sublime
import sublime_plugin
from os import path
from difflib import unified_diff
def get_view(active_view, **kwargs):
view = active_view
if 'group' in kwargs and 'index' in kwargs:
view = view.window().views_in_group(kwargs['group'])[kwargs['index']]
return view
class CopyFilePathCommand(sublime_plugin.TextCommand):
def run(self, edit, **kwargs):
get_view(self.view, **kwargs).run_command('copy_path')
def is_enabled(self, **kwargs):
file_path = get_view(self.view, **kwargs).file_name()
return isinstance(file_path, str)
def is_visible(self, **kwargs):
return True
class OpenContainingFolderFromTabCommand(sublime_plugin.TextCommand):
def run(self, edit, **kwargs):
view = get_view(self.view, **kwargs)
self.view.window().focus_view(view)
file_path = view.file_name()
folder = path.dirname(file_path)
args = { 'dir': '$file_path', 'file': '$file_name' }
if not path.isfile(file_path):
del args['file']
self.view.window().run_command('open_dir', args)
self.view.window().focus_view(self.view)
def is_enabled(self, **kwargs):
file_path = get_view(self.view, **kwargs).file_name()
if file_path is None:
return False
folder = path.dirname(file_path)
return file_path is not None and path.isdir(folder)
def is_visible(self, **kwargs):
return True
class DiffViewsCommand(sublime_plugin.TextCommand):
def get_lines_for_view(self, view):
for line in view.lines(sublime.Region(0, view.size())):
yield view.substr(line) + '\n'
def run(self, edit, **kwargs):
view = get_view(self.view, **kwargs)
views = None
#if view.id() == self.view.id():
# views = self.view.window().views()[-2:]
#else:
views = [view, self.view]
view = self.view.window().new_file()
for line in unified_diff(list(self.get_lines_for_view(views[0])), list(self.get_lines_for_view(views[1])), fromfile=views[0].file_name() or views[0].name() or 'fromfile', tofile=views[1].file_name() or views[1].name() or 'tofile'):
view.run_command('append', { 'characters': line })
view.assign_syntax('Packages/Diff/Diff.sublime-syntax')
def is_enabled(self, **kwargs):
return self.is_visible(**kwargs)
def is_visible(self, **kwargs):
view = get_view(self.view, **kwargs)
return view.id() != self.view.id()
and the following override for Packages/Default/Tab Context.sublime-menu
:
[
{ "command": "close_by_index", "args": { "group": -1, "index": -1 }, "caption": "Close" },
{ "command": "close_others_by_index", "args": { "group": -1, "index": -1 }, "caption": "Close Other Tabs" },
{ "command": "close_to_right_by_index", "args": { "group": -1, "index": -1 }, "caption": "Close Tabs to the Right" },
{ "caption": "-" },
{ "command": "new_file", "caption": "New File" },
{ "command": "prompt_open_file", "caption": "Open File" },
{ "caption": "-" },
{ "command": "open_containing_folder_from_tab", "args": { "group": -1, "index": -1 }, "caption": "Open Containing Folder…" },
{ "command": "copy_file_path", "args": { "group": -1, "index": -1 }, "caption": "Copy File Path" },
//{ "command": "reveal_in_side_bar_from_tab", "args": { "group": -1, "index": -1 }, "caption": "Reveal in Side Bar" }
{ "command": "diff_views", "args": { "group": -1, "index": -1 }, "caption": "Diff With Current View" },
]
The idea is that, if you specify the group
and index
args, these will be automatically populated with the correct values corresponding to the tab for which the context menu was opened. Then, one can use custom commands to execute the real underlying functionality on the correct tab/view instance. In some cases, the underlying functionality makes use of window level commands, so I temporarily switch the active view.