Made UltiSnipsEdit more useful and consistent.

It now by default only edits private files, add a ! if you want to edit
non private files.
This commit is contained in:
Holger Rapp 2014-03-06 09:10:48 +01:00
parent f446409230
commit 6398a598b5
6 changed files with 76 additions and 78 deletions

View File

@ -30,13 +30,17 @@ function! s:compensate_for_pum()
endif endif
endfunction endfunction
function! UltiSnips#Edit(...) function! UltiSnips#Edit(bang, ...)
if a:0 == 1 && a:1 != '' if a:0 == 1 && a:1 != ''
let type = a:1 let type = a:1
else else
exec g:_uspy "vim.command(\"let type = '%s'\" % UltiSnips_Manager._primary_filetype)" exec g:_uspy "vim.command(\"let type = '%s'\" % UltiSnips_Manager._primary_filetype)"
endif endif
exec g:_uspy "vim.command(\"let file = '%s'\" % UltiSnips_Manager._file_to_edit(vim.eval(\"type\")))" exec g:_uspy "vim.command(\"let file = '%s'\" % UltiSnips_Manager._file_to_edit(vim.eval(\"type\"), vim.eval('a:bang')))"
if !len(file)
return
endif
let mode = 'e' let mode = 'e'
if exists('g:UltiSnipsEditSplit') if exists('g:UltiSnipsEditSplit')

View File

@ -167,10 +167,10 @@ https://github.com/honza/vim-snippets
3.1 Commands *UltiSnips-commands* 3.1 Commands *UltiSnips-commands*
------------ ------------
*:UltiSnipsEdit* *:UltiSnipsEdit*
The UltiSnipsEdit command opens the private snippet definition file for the The UltiSnipsEdit command opens a private snippet definition file for the
current filetype for editing. If a definition file does not exist, a new file current filetype. If no snippet file exists, a new file is created. If used as
is opened with the appropriate name. Snippet definition files are standard UltiSnipsEdit! all public snippet files are taken into account too. If
text files and can be edited directly. UltiSnipsEdit makes it easier. multiple files match the search, the user gets to choose the file.
There are several variables associated with the UltiSnipsEdit command. There are several variables associated with the UltiSnipsEdit command.
@ -191,6 +191,7 @@ g:UltiSnipsSnippetsDir
directories named "snippets" are reserved for directories named "snippets" are reserved for
snipMate snippets and cannot be used. snipMate snippets and cannot be used.
*:UltiSnipsAddFiletypes* *:UltiSnipsAddFiletypes*
The UltiSnipsAddFiletypes command allows for explicit merging of other snippet The UltiSnipsAddFiletypes command allows for explicit merging of other snippet
filetypes for the current buffer. For example, if you edit a .rst file but filetypes for the current buffer. For example, if you edit a .rst file but

View File

@ -11,8 +11,8 @@ if exists('did_UltiSnips_plugin') || &cp || version < 700
endif endif
" The Commands we define. " The Commands we define.
command! -nargs=? -complete=customlist,UltiSnips#FileTypeComplete UltiSnipsEdit command! -bang -nargs=? -complete=customlist,UltiSnips#FileTypeComplete UltiSnipsEdit
\ :call UltiSnips#Edit(<q-args>) \ :call UltiSnips#Edit(<q-bang>, <q-args>)
command! -nargs=1 UltiSnipsAddFiletypes :call UltiSnips#AddFiletypes(<q-args>) command! -nargs=1 UltiSnipsAddFiletypes :call UltiSnips#AddFiletypes(<q-args>)

View File

@ -7,4 +7,4 @@ from UltiSnips.snippet.source._base import SnippetSource
from UltiSnips.snippet.source.added import AddedSnippetsSource from UltiSnips.snippet.source.added import AddedSnippetsSource
from UltiSnips.snippet.source.file.snipmate import SnipMateFileSource from UltiSnips.snippet.source.file.snipmate import SnipMateFileSource
from UltiSnips.snippet.source.file.ultisnips import UltiSnipsFileSource, \ from UltiSnips.snippet.source.file.ultisnips import UltiSnipsFileSource, \
base_snippet_files_for find_all_snippet_files, find_snippet_files

View File

@ -13,34 +13,26 @@ from UltiSnips.snippet.source.file._base import SnippetFileSource
from UltiSnips.snippet.source.file._common import handle_extends from UltiSnips.snippet.source.file._common import handle_extends
from UltiSnips.text import LineIterator, head_tail from UltiSnips.text import LineIterator, head_tail
def find_snippet_files(ft, directory):
"""Returns all matching snippet files for 'ft' in 'directory'."""
patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")]
ret = set()
directory = os.path.expanduser(directory)
for pattern in patterns:
for fn in glob.glob(os.path.join(directory, pattern % ft)):
ret.add(os.path.realpath(fn))
return ret
def _plugin_dir(): def find_all_snippet_files(ft):
"""Calculates the plugin directory for UltiSnips.""" """Returns all snippet files matching 'ft' in the given runtime path
directory = __file__ directory."""
for _ in range(10):
directory = os.path.dirname(directory)
if (os.path.isdir(os.path.join(directory, "plugin")) and
os.path.isdir(os.path.join(directory, "doc"))):
return directory
raise Exception("Unable to find the plugin directory.")
def base_snippet_files_for(ft, default=True):
"""Returns a list of snippet files matching the given filetype (ft).
If default is set to false, it doesn't include shipped files.
Searches through each path in 'runtimepath' in reverse order,
in each of these, it searches each directory name listed in
'g:UltiSnipsSnippetDirectories' in order, then looks for files in these
directories called 'ft.snippets' or '*_ft.snippets' replacing ft with
the filetype.
"""
if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1": if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1":
snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories") snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories")
else: else:
snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories") snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories")
base_snippets = os.path.realpath(os.path.join(_plugin_dir(), "UltiSnips")) patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")]
ret = [] ret = set()
for rtp in _vim.eval("&runtimepath").split(','): for rtp in _vim.eval("&runtimepath").split(','):
for snippet_dir in snippet_dirs: for snippet_dir in snippet_dirs:
if snippet_dir == "snippets": if snippet_dir == "snippets":
@ -50,14 +42,9 @@ def base_snippet_files_for(ft, default=True):
"directory for UltiSnips snippets.") "directory for UltiSnips snippets.")
pth = os.path.realpath(os.path.expanduser( pth = os.path.realpath(os.path.expanduser(
os.path.join(rtp, snippet_dir))) os.path.join(rtp, snippet_dir)))
patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")]
if not default and pth == base_snippets:
patterns.remove("%s.snippets")
for pattern in patterns: for pattern in patterns:
for fn in glob.glob(os.path.join(pth, pattern % ft)): for fn in glob.glob(os.path.join(pth, pattern % ft)):
if fn not in ret: ret.add(fn)
ret.append(fn)
return ret return ret
def _handle_snippet_or_global(line, lines, python_globals, priority): def _handle_snippet_or_global(line, lines, python_globals, priority):
@ -146,7 +133,7 @@ class UltiSnipsFileSource(SnippetFileSource):
"""Manages all snippets definitions found in rtp for ultisnips.""" """Manages all snippets definitions found in rtp for ultisnips."""
def _get_all_snippet_files_for(self, ft): def _get_all_snippet_files_for(self, ft):
return set(base_snippet_files_for(ft)) return find_all_snippet_files(ft)
def _parse_snippet_file(self, filedata, filename): def _parse_snippet_file(self, filedata, filename):
for event, data in _parse_snippets_file(filedata): for event, data in _parse_snippets_file(filedata):

View File

@ -6,6 +6,7 @@
from collections import defaultdict from collections import defaultdict
from functools import wraps from functools import wraps
import os import os
import platform
import traceback import traceback
from UltiSnips import _vim from UltiSnips import _vim
@ -14,23 +15,20 @@ from UltiSnips.compatibility import as_unicode
from UltiSnips.position import Position from UltiSnips.position import Position
from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition
from UltiSnips.snippet.source import UltiSnipsFileSource, SnipMateFileSource, \ from UltiSnips.snippet.source import UltiSnipsFileSource, SnipMateFileSource, \
base_snippet_files_for, AddedSnippetsSource find_all_snippet_files, find_snippet_files, AddedSnippetsSource
from UltiSnips.vim_state import VimState, VisualContentPreserver from UltiSnips.vim_state import VimState, VisualContentPreserver
def _ask_snippets(snippets): def _ask_user(a, formatted):
""" Given a list of snippets, ask the user which one they """Asks the user using inputlist() and returns the selected element or
want to use, and return it. None."""
"""
display = [as_unicode("%i: %s") % (i+1, s.description) for
i, s in enumerate(snippets)]
try: try:
rv = _vim.eval("inputlist(%s)" % _vim.escape(display)) rv = _vim.eval("inputlist(%s)" % _vim.escape(formatted))
if rv is None or rv == '0': if rv is None or rv == '0':
return None return None
rv = int(rv) rv = int(rv)
if rv > len(snippets): if rv > len(a):
rv = len(snippets) rv = len(a)
return snippets[rv-1] return a[rv-1]
except _vim.error: except _vim.error:
# Likely "invalid expression", but might be translated. We have no way # Likely "invalid expression", but might be translated. We have no way
# of knowing the exact error, therefore, we ignore all errors silently. # of knowing the exact error, therefore, we ignore all errors silently.
@ -38,6 +36,13 @@ def _ask_snippets(snippets):
except KeyboardInterrupt: except KeyboardInterrupt:
return None return None
def _ask_snippets(snippets):
""" Given a list of snippets, ask the user which one they
want to use, and return it.
"""
display = [as_unicode("%i: %s") % (i+1, s.description) for
i, s in enumerate(snippets)]
return _ask_user(snippets, display)
def err_to_scratch_buffer(func): def err_to_scratch_buffer(func):
"""Decorator that will catch any Exception that 'func' throws and displays """Decorator that will catch any Exception that 'func' throws and displays
@ -495,42 +500,43 @@ class SnippetManager(object):
any arguments.""" any arguments."""
return self._buffer_filetypes[_vim.buf.number][0] return self._buffer_filetypes[_vim.buf.number][0]
# TODO(sirver): this should talk directly to the UltiSnipsFileSource. def _file_to_edit(self, ft, bang): # pylint: disable=no-self-use
def _file_to_edit(self, ft): # pylint: disable=no-self-use """Returns a file to be edited for the given ft. If 'bang' is empty
""" Gets a file to edit based on the given filetype. only private files in g:UltiSnipsSnippetsDir are considered, otherwise
If no filetype is given, uses the current filetype from Vim. all files are considered and the user gets to choose.
Checks 'g:UltiSnipsSnippetsDir' and uses it if it exists
If a non-shipped file already exists, it uses it.
Otherwise uses a file in ~/.vim/ or ~/vimfiles
""" """
# This method is not using self, but is called by UltiSnips.vim and is # This method is not using self, but is called by UltiSnips.vim and is
# therefore in this class because it is the facade to Vim. # therefore in this class because it is the facade to Vim.
edit = None potentials = set()
existing = base_snippet_files_for(ft, False)
filename = ft + ".snippets"
if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == "1": if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == "1":
snipdir = _vim.eval("g:UltiSnipsSnippetsDir") snippet_dir = _vim.eval("g:UltiSnipsSnippetsDir")
edit = os.path.join(snipdir, filename)
elif existing:
edit = existing[-1] # last sourced
else: else:
home = _vim.eval("$HOME") if platform.system() == "Windows":
rtp = [os.path.realpath(os.path.expanduser(p)) snippet_dir = os.path.join(_vim.eval("$HOME"),
for p in _vim.eval("&rtp").split(",")] "_vimfiles", "UltiSnips")
snippet_dirs = ["UltiSnips"] + \ else:
_vim.eval("g:UltiSnipsSnippetDirectories") snippet_dir = os.path.join(_vim.eval("$HOME"),
us = snippet_dirs[-1] ".vim", "UltiSnips")
potentials.update(find_snippet_files(ft, snippet_dir))
potentials.add(os.path.join(snippet_dir, ft + '.snippets'))
path = os.path.join(home, ".vim", us) if bang:
for dirname in [".vim", "vimfiles"]: potentials.update(find_all_snippet_files(ft))
pth = os.path.join(home, dirname)
if pth in rtp:
path = os.path.join(pth, us)
if not os.path.isdir(path): potentials = set(os.path.realpath(p) for p in potentials)
os.mkdir(path)
edit = os.path.join(path, filename) if len(potentials) > 1:
files = sorted(potentials)
formatted = [as_unicode('%i: %s') % (i, fn) for
i, fn in enumerate(files, 1)]
edit = _ask_user(files, formatted)
if edit is None:
return ""
else:
edit = potentials.pop()
dirname = os.path.dirname(edit)
if not os.path.exists(dirname):
os.makedirs(dirname)
return edit return edit