Blog Original
Installation
Ultisnips plug-in installation is divided into two parts, one is the ultisnips plug-in itself, the other is the code snippet warehouse. In general, the default code snippet repository is downloaded and uploaded to your github as needed. If you and I also use vim-plug to manage plugins, add the following code to your VIMRC to save the refresh
Plug ‘SirVer/ultisnips‘
" Your own code repository git address
Plug ‘keelii/vim-snippets‘
All of the code snippets in the above example are stored under the plug-in installation directory, and thevim-snippets/UltiSnipsfile naming format isft. Snippets,ftwhich is in Vimfiletype, one of whichall.snippetsis the only code snippet that applies to all files
Configuration
Shortcut settings, I usually use the tab to trigger the snippet completion, and do not use YCM (official documents that use YCM can not use tab completion)
Let g:UltiSnipsExpandTrigger="<tab>"
" Use tab to switch to the next trigger point, shit+tab the previous trigger point
Let g:UltiSnipsJumpForwardTrigger="<tab>"
Let g:UltiSnipsJumpBackwardTrigger="<S-tab>"
" Split the screen vertically when using the UltiSnipsEdit command
Let g:UltiSnipsEditSplit="vertical"
Depend on
Ultisnips plug-in requires your VIM support Python, can be used in vim command mode below to detect whether your vim version supports Python, return 1 means support
:echo has("python")
:echo has("python3")
Define a code Snippet definition format
Snippet trigger character ["code snippet description" [parameter]]
Code snippet content
Endsnippet
One of the minimized code snippets
snippet if "if (condition) { ... }"
if (${1:true}) {
$0
}
endsnippet
When you enter the If tab in vim, an If statement is expanded, the first trigger point is an if condition expression, and the last is the IF statement body
${1:true}Indicates that this is the first trigger point, the placeholder istrue, if the placeholder does not have a default value that can be used directly,$1$2$3...
The contents of the visual selection are placeholders
snippet if "if (condition) { ... }"
if (${1:true}) {
$0
}
endsnippet
${VISUAL}Indicates that the text selected in the visual mode is used in Vim, which is useful when refactoring the code (there is a high level of usage later), and the previous figure feels
Parameters for code Snippets
- bIndicates that the trigger character should start at one line
- iIndicates that the trigger character can be within a word (this option is used for continuous presentation)
- wIndicates that the triggering character must be preceded by a letter boundary.
- rIndicates that the trigger character can be a regular expression
- tIndicates that if there is a tab in the expanded code fragment, it is output as is, even if the expandtab is set inside your VIMRC
- mRepresents all whitespace characters to the right of the delete code fragment
- eRepresents a custom context
- AIndicates automatic triggering and does not need to press TAB, similar to the abbr in VIM
Content Interpreter
Three different language injections are supported in the code snippet defined by Ultisnips: Shell, Vimscript, Python, in the code snippet with an inverted quotation mark
Shell Code
Is the code snippet that you can execute in your command line shell, such as the output current time
? date
Monday, August 27, 2018, 19:38 CST
In the code snippet, use the back quote "'" reference.
snippet today
Today is the `date`.
endsnippet
Enter today press TAB to expand (the format is not the same as in the shell above, it is estimated due to the Vim language setting problem):
Today is the Mon Aug 27 18:24:51 CST 2018.
Vimscript Code
Useindentto output the current indent value, using the prefix to!vindicate that it is vimscript
snippet indent
Indent is: `!v indent(".")`.
endsnippet
Python code
Interpreting the Execute Python code in a code snippet is the most powerful feature of Ultisnips, beginning with the prefix!p. The system injects some variables into python that can be manipulated directly using Python code.
- fn-Indicates the current file name
- path-The path of the current file name
- t-Placeholder dictionaries, which can be usedt[1], t[2], t.vto take placeholder content
- snip-an instance of the UltiSnips.TextObjects.SnippetUtil object
- match-The matching element returned when the regular code fragment (very powerful)
The most commonly usedsnipobjects provide some of the following variables:
- snip.rvRepresents the return Value,python code that was processed after the execution of the string assigned to RV
- snip.fnRepresents the current file name
- snip.ftRepresents the current file type
- snip.vRepresents a visual pattern variable that representssnip.v.modea pattern type thatsnip.v.textrepresents a selected character in visual mode
Placeholder Selection
Ultisnips supports using shortcut keys to toggle placeholders, I use<tab>and<shift-tab>to toggle下一个and上一个placeholders, placeholder toggle scopes are inside the current code snippet (even if the placeholder has been modified) and will not work when the cursor moves out
Custom Context
A custom context can determine whether a code fragment is available through a regular match, such as a code fragment that determines the function within the specified if statement, and the format of the definition is as follows:
Snippet Trigger character "description" "expression" parameter
For example, we define aif (DEVELOPMENT) {code fragment that can only be expanded at the beginning of the previous line
snippet dbg "if (DEVELOPMENT) dbg" "re.match(‘^if \(DEVELOPMENT\) \{‘, snip.buffer[snip.line-1])" be
debugger;
endsnippet
Common usage in-line continuous expansion
This is common in situations where code fragments need to be expanded continuously, such as two fragments, one print variable, and one processing JSON serialization. You need to use the parameter optioniN-word
Using regular Code Snippets
It is common to write code that uses log, print, and so on to print variables in the context. It is more complicated to use normal fragments to show Console.log () and then copy the variable characters into parentheses. Using regular to dynamically match the preceding characters can be a good solution to this problem.
snippet "([^\s]\w+)\.log" "console.log(postfix)" r
console.log(`!p snip.rv = match.group(1)`)$0
endsnippet
snippet "([^\s].*)\.upper" "Uppercase(postfix)" r
`!p snip.rv = match.group(1).upper()`$0
endsnippet
snippet "([^\s]\w+)\.lower" "Lowercase(postfix)" r
`!p snip.rv = match.group(1).lower()`$0
endsnippet
Motion Diagram Demo
Note : The regular code fragment is only available for single-line text processing, and if it is a multiline conversion, the following Python + VISUAL code fragment is used to handle
Using Python interpreter + VISUAL mode to implement code annotation functionality
Often we need to use a bunch of plug-ins to implement various code annotation functions. However, Ultisnips provides visual mode to extract the selected contents of the Vim visual mode into the code snippet, so that we can combine to create a code snippet with a comment function
The process is probably like this:
- Enter vim visual mode and select the content to be annotated
- Press TAB to clear the selection
- Enter code snippet trigger character, press TAB to finish
Because the Python code implemented is relatively complex, it is divided into two main methods. Single-line comments and multiline comments, note that Python can be written directly in Ultisnips but the large-segment approach is suggested to be placed under the Pythonx directory under the plug-in directory, using the global Python code in the corresponding snippet to beglobal !pintroduced
Single-line comment (pythonx/javascript_snippets.py):
def comment(snip, START="", END=""):
lines = snip.v.text.split(‘\n‘)[:-1]
first_line = lines[0]
spaces = ‘‘
initial_indent = snip._initial_indent
# Get the first non-empty line
for idx, l in enumerate(lines):
if l.strip() != ‘‘:
first_line = lines[idx]
sp = re.findall(r‘^\s+‘, first_line)
if len(sp):
spaces = sp[0]
break
# Uncomment
if first_line.strip().startswith(START):
result = [line.replace(START, "", 1).replace(END, "", 1) if line.strip() else line for line in lines]
else:
result = [f‘{spaces}{START}{line[len(spaces):]}{END}‘ if line.strip() else line for line in lines ]
# Remove initial indent
if result[0] and initial_indent:
result[0] = result[0].replace(initial_indent, ‘‘, 1)
if result:
return ‘\n‘.join(result)
else:
return ‘‘
Multi-line Comments:
def comment_inline(snip, START="/* ", END=" */"):
text = snip.v.text
lines = text.split(‘\n‘)[:-1]
first_line = lines[0]
initial_indent = snip._initial_indent
spaces = ‘‘
# Get the first non-empty line
for idx, l in enumerate(lines):
if l.strip() != ‘‘:
first_line = lines[idx]
sp = re.findall(r‘^\s+‘, first_line)
if len(sp):
spaces = sp[0]
break
if text.strip().startswith(START):
result = text.replace(START, ‘‘, 1).replace(END, ‘‘, 1)
else:
result = text.replace(spaces, spaces + START, 1).rstrip(‘\n‘) + END + ‘\n‘
if initial_indent:
result = result.replace(initial_indent, ‘‘, 1)
return result
Code Snippet Definition:
global !p
from javascript_snippets import (
comment, comment_inline
)
endglobal
# ...
snippet c "Toggle comment every single line"
`!p
snip.rv = comment(snip, START=‘// ‘, END=‘‘)
`$0
endsnippet
snippet ci "Toggle comment inline."
`!p
snip.rv = comment_inline(snip, START="/* ", END=" */")
`$0
endsnippet
Motion Diagram Demo
Different languages can be defined in the corresponding fragment file and passed the annotation symbol parameter, with this function can happily delete other vim comment plugin
VIM Snippet Plugin ultisnips use tutorial