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
endfunction
function! UltiSnips#Edit(...)
function! UltiSnips#Edit(bang, ...)
if a:0 == 1 && a:1 != ''
let type = a:1
else
exec g:_uspy "vim.command(\"let type = '%s'\" % UltiSnips_Manager._primary_filetype)"
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'
if exists('g:UltiSnipsEditSplit')

View File

@ -167,10 +167,10 @@ https://github.com/honza/vim-snippets
3.1 Commands *UltiSnips-commands*
------------
*:UltiSnipsEdit*
The UltiSnipsEdit command opens the private snippet definition file for the
current filetype for editing. If a definition file does not exist, a new file
is opened with the appropriate name. Snippet definition files are standard
text files and can be edited directly. UltiSnipsEdit makes it easier.
The UltiSnipsEdit command opens a private snippet definition file for the
current filetype. If no snippet file exists, a new file is created. If used as
UltiSnipsEdit! all public snippet files are taken into account too. If
multiple files match the search, the user gets to choose the file.
There are several variables associated with the UltiSnipsEdit command.
@ -191,6 +191,7 @@ g:UltiSnipsSnippetsDir
directories named "snippets" are reserved for
snipMate snippets and cannot be used.
*:UltiSnipsAddFiletypes*
The UltiSnipsAddFiletypes command allows for explicit merging of other snippet
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
" The Commands we define.
command! -nargs=? -complete=customlist,UltiSnips#FileTypeComplete UltiSnipsEdit
\ :call UltiSnips#Edit(<q-args>)
command! -bang -nargs=? -complete=customlist,UltiSnips#FileTypeComplete UltiSnipsEdit
\ :call UltiSnips#Edit(<q-bang>, <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.file.snipmate import SnipMateFileSource
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.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():
"""Calculates the plugin directory for UltiSnips."""
directory = __file__
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.
"""
def find_all_snippet_files(ft):
"""Returns all snippet files matching 'ft' in the given runtime path
directory."""
if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1":
snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories")
else:
snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories")
base_snippets = os.path.realpath(os.path.join(_plugin_dir(), "UltiSnips"))
ret = []
patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")]
ret = set()
for rtp in _vim.eval("&runtimepath").split(','):
for snippet_dir in snippet_dirs:
if snippet_dir == "snippets":
@ -50,14 +42,9 @@ def base_snippet_files_for(ft, default=True):
"directory for UltiSnips snippets.")
pth = os.path.realpath(os.path.expanduser(
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 fn in glob.glob(os.path.join(pth, pattern % ft)):
if fn not in ret:
ret.append(fn)
ret.add(fn)
return ret
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."""
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):
for event, data in _parse_snippets_file(filedata):

View File

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