UltiSnips and YouCompleteMe - vim

I have bundles ultisnips and youcompleteme installed on my macvim.
The problem is that ultisnips doesn't work because tab is bound by ycm.
I tried putting let g:UltiSnipsExpandTrigger = "<s-tab>" so that I can trigger the snippet completion with shift-tab, but it doesn't work for some unknown reason. I could use caps as the trigger, but so far I've found no way to do that.
Do any of you use those two add-ons together?
What can I do to make shift-tab work?
Can you recommend another key to trigger snippets?

Another option is using the SuperTab plugin:
" if you use Vundle, load plugins:
Bundle 'ervandew/supertab'
Bundle 'Valloric/YouCompleteMe'
Bundle 'SirVer/ultisnips'
" make YCM compatible with UltiSnips (using supertab)
let g:ycm_key_list_select_completion = ['<C-n>', '<Down>']
let g:ycm_key_list_previous_completion = ['<C-p>', '<Up>']
let g:SuperTabDefaultCompletionType = '<C-n>'
" better key bindings for UltiSnipsExpandTrigger
let g:UltiSnipsExpandTrigger = "<tab>"
let g:UltiSnipsJumpForwardTrigger = "<tab>"
let g:UltiSnipsJumpBackwardTrigger = "<s-tab>"
Here YouCompleteMe is bound to a different combination Ctrln, but then that combination is bound to tab through SuperTab. UltiSnips and SuperTab play nice together, so you can then just bind UltiSnips to tab directly and everything will work out.

Try this suggestion on a page from the YouCompleteMe issue tracker. In your .vimrc:
let g:UltiSnipsExpandTrigger="<c-j>"
While this setting will make expanding a snippet share the default mapping for jumping forward within a snippet, it simulates TextMates' behavior as mentioned in the UltiSnips help tags.
Since I've mapped my Caps Lock key to Ctrl, this mapping works pretty smoothly.

copy the following code to your vimrc, and enjoy. This function will handle all issues between YCM and UltiSnips.
function! g:UltiSnips_Complete()
call UltiSnips#ExpandSnippet()
if g:ulti_expand_res == 0
if pumvisible()
return "\<C-n>"
else
call UltiSnips#JumpForwards()
if g:ulti_jump_forwards_res == 0
return "\<TAB>"
endif
endif
endif
return ""
endfunction
au BufEnter * exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsListSnippets="<c-e>"
" this mapping Enter key to <C-y> to chose the current highlight item
" and close the selection list, same as other IDEs.
" CONFLICT with some plugins like tpope/Endwise
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"

i have this in my vimrc
"" YouCompleteMe
let g:ycm_key_list_previous_completion=['<Up>']
"" Ultisnips
let g:UltiSnipsExpandTrigger="<c-tab>"
let g:UltiSnipsListSnippets="<c-s-tab>"
thats what i did on my first try, but i misspelled UltiSnips with Ultisnips.. oh well, worked out in the end!

I personally chose to not use <tab> with YouCompleteMe but navigate it manually.
So I added this to my .vimrc:
let g:ycm_key_list_select_completion=[]
let g:ycm_key_list_previous_completion=[]
which simply disables the tab key for YCM. Instead you use the movement keys (arrows or CTRL-N/CTRL-P) and select the entry with CR. UltiSnips works default with tab.

Just putting together answers by Michaelslec, Joey Liu and along with solutions I found in this issue thread and this guy's vimrc, I now have this which solved pretty much all problems.
function! g:UltiSnips_Complete()
call UltiSnips#ExpandSnippet()
if g:ulti_expand_res == 0
if pumvisible()
return "\<C-n>"
else
call UltiSnips#JumpForwards()
if g:ulti_jump_forwards_res == 0
return "\<TAB>"
endif
endif
endif
return ""
endfunction
function! g:UltiSnips_Reverse()
call UltiSnips#JumpBackwards()
if g:ulti_jump_backwards_res == 0
return "\<C-P>"
endif
return ""
endfunction
if !exists("g:UltiSnipsJumpForwardTrigger")
let g:UltiSnipsJumpForwardTrigger = "<tab>"
endif
if !exists("g:UltiSnipsJumpBackwardTrigger")
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
endif
au InsertEnter * exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"
au InsertEnter * exec "inoremap <silent> " . g:UltiSnipsJumpBackwardTrigger . " <C-R>=g:UltiSnips_Reverse()<cr>"

Based on Siegfried's answer, I am using the following which seems more natural:
let g:ycm_key_list_select_completion = ['<C-j>']
let g:ycm_key_list_previous_completion = ['<C-k>']
let g:UltiSnipsExpandTrigger = "<C-l>"
let g:UltiSnipsJumpForwardTrigger = "<C-j>"
let g:UltiSnipsJumpBackwardTrigger = "<C-k>"
I also use the c-hjkl bindings somewhere else (switching from a pane to another), but that would only be in normal mode, so there's no problem.

Although I know this post is a little old, I have my own function that is a little more optimized than the one given above:
function! g:UltiSnips_Complete()
call UltiSnips#ExpandSnippetOrJump()
if g:ulti_expand_or_jump_res == 0
if pumvisible()
return "\<C-N>"
else
return "\<TAB>"
endif
endif
return ""
endfunction
Of course, if you just keep the settings that Joey Liu provided and then just use this function everything will work just perfectly!
EDIT: Also, I use another function to increase back-stepping functionality between YouCompleteMe and UltiSnips. I'll show you what I mean:
function! g:UltiSnips_Reverse()
call UltiSnips#JumpBackwards()
if g:ulti_jump_backwards_res == 0
return "\<C-P>"
endif
return ""
endfunction
Then just put this in your .vimrc:
au BufEnter * exec "inoremap <silent> " . g:UltiSnipsJumpBackwardTrigger . " <C-R>=g:UltiSnips_Reverse()<cr>"
As well as let g:UltiSnipsJumpBackwardTrigger="<s-tab>" and your set!

I use both of them together. By default YouCompleteMe binds <Tab> and <Down> to select the next completion item and also <S-Tab> and <Up> to select the previous completion item. You can change the YouCompleteMe bindings with the g:ycm_key_list_select_completion and g:ycm_key_list_previous_completion options. Note that the names of these options were recently changed when the option was changed from a single string to a list of strings.

While Many answer works fine in this post, I just want to say that the problem is caused by key binding collision between YCM and UltiSnip, while YCM support UltiSnip snippets by default, it takes the default UltiSnip expand trigger <tab> as its completion select key, so UltiSnip snippets will not be expaned by <tab>. Give them different key binding will solve the problem, I personally use <c-n and <c-p> for YCM and use the default <tab> for UltiSnip. You can get more details with help youcompleteme doc in vim.

I installed the UltiSnips plugin after the YouCompleteMe plugin so I thought they were conflicting, but in reality I had something more interfering:
set paste
Make sure to remove that from .vimrc if it's present.

I use ; to expand UltiSnips, it's so nifty for me
let g:UltiSnipsExpandTrigger = ";"

I use kj. This is what is in my .vimrc:
let g:UltisnipsExpandTrigger="kj".
It rarely happens that I run into word that has kj in it. If this is the case I would just wait a couple of seconds after typing k and that type j.

As mentioned by others, mapping C-j to ultisnips works great.
let g:UltiSnipsExpandTrigger="<c-j>"
Now, if you go a bit further and install xcape and use
xcape -e "Shift_L=Control_R|J"
You unleash the power of using just the shift key for utlitsnips.

Related

How to toggle (Vimplug) plugins on and off on the fly?

Using COC on multiple instances can really take a toll on my intel i3+4GB machine.
So I was wondering if I could toggle it on demand.
I have managed to turn it off by default and toggle it on using Vimplug's built in feature like the following.
Plug 'neoclide/coc.nvim', {'branch': 'release', 'on': 'CocToggle' }
However, I'm not sure how to toggle it off.
Any help would be highly appreciated!
P.S.: I have tried CocDisable and didn't notice any practical benefits that would minimize the resource usage like killing the gazillion node processes started by COC for each instances!
Solution
I ended up writing the following function for my use case.
Plug 'neoclide/coc.nvim', {'branch': 'release' }
let g:coc_start_at_startup = 0
let s:coc_enabled = 0
function! ToggleCoc()
if s:coc_enabled == 0
let s:coc_enabled = 1
CocStart
echo 'COC on'
else
let s:coc_enabled = 0
echo 'COC off'
call coc#rpc#stop()
endif
endfunction
nnoremap <silent> <leader>h :call ToggleCoc()<cr>
My use case (I use vim-plug) can be different but it could help. Normally my nerdtrhee is disabled until I call it throught a mapping
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
nnoremap <F2> :NERDTreeToggle<cr>
And I have a function to load any plugin that is disabled on startup
if !exists('*LoadPluginFunction')
fun! LoadPluginFunction(pluginname)
let l:curpos = getcurpos()
execute plug#load(a:pluginname)
call cursor(l:curpos[1], l:curpos[2])
return ''
endfun
endif
command! -nargs=1 LoadPlugin :call LoadPluginFunction(<q-args>)
If I want to load it manyally I call:
:LoadPlugin nerdtree
Finally I have found a coc option that can help you:
let g:coc_start_at_startup = 0
You can start your vim and create a mapping to load the coc plugin manually

Get Vimwiki working with SnipMate (the vim plugins)

My issue is that <Tab> completion for SnipMate does not work when I'm in a vimwiki file. I am testing by typing APACHE<Tab> in insert mode, but I don't get the snippet as I do when I'm in, say, .vimrc.
And even though i_<Tab> doesn't work in a vimwikie file, i_<C-R><Tab> does. I get a list of available snippets. Strange.
To make it stranger (well, to me at least), here's the partial output of :imap in a vimwiki file:
i <Tab> * <C-G>u<C-R>=snipMate#TriggerSnippet()<CR>
i <C-R><Tab> * <C-R>=snipMate#ShowAvailableSnips()<CR>
I think these are correct, and in other files where <Tab> completion does work, the mappings are the same.
oh, and in case you are thinking to suggest putting let g:vimwiki_table_auto_fmt = 0 in my .vimrc as suggested in http://code.google.com/p/vimwiki/wiki/ChangeLog, I tried it and it doesn't solve my problem. That's the only suggestion I found in my search, so that's why I'm here.
I don't know how much of my .vimrc you would want, so I'm just going to give you the ones I think are relevant to keep this question short:
" Vundle: The plugin manager for vim.
set runtimepath+=~/.vim/bundle/vundle/
call vundle#rc()
Bundle 'gmarik/vundle'
" SnipMate: TextMate snippets for vim.
Bundle "MarcWeber/vim-addon-mw-utils"
Bundle "tomtom/tlib_vim"
Bundle "honza/snipmate-snippets"
Bundle "garbas/vim-snipmate"
" Vimwiki: A personal wiki for vim.
Bundle 'vim-scripts/vimwiki'
let g:vimwiki_hl_headers = 1
let g:vimwiki_hl_cb_checked = 1
let g:vimwiki_folding = 1
let g:vimwiki_fold_lists = 1
let s:vimwiki = {}
let s:vimwiki.path = '~/Vimwiki/wiki'
let s:vimwiki.path_html = '~/Vimwiki/html'
let s:vimwiki.ext = '.md'
let s:vimwiki.syntax = 'markdown'
let s:vimwiki.maxhi = 1
let s:vimwiki.diary_rel_path = 'Journal/'
let s:vimwiki.diary_index = 'index'
let s:vimwiki.diary_header = 'Journal'
let s:vimwiki.diary_sort = 'asc'
let g:vimwiki_list = [s:vimwiki]
Thanks
Edit:
I don't know why I forgot about this while writing the above. The output of :imap above is incomplete. It also shows:
i <Tab> *#vimwiki#tbl#kbd_tab()
Regardless of the value of g:vimwiki_table_auto_fmt. It's probably the source of my problem.. and if so I'd like to get rid of it from .vimrc somehow.
The # in the :imap output shows that Vimwiki defines a buffer-local <Tab> mapping that overrides snipMate's global one. A
:iunmap <buffer> <Tab>
should fix that. You can put that command into ~/.vim/after/ftplugin/vimwiki.vim to make it permanent. But apparently Vimwiki allows customization:
" Table mappings
if g:vimwiki_table_mappings
inoremap <expr> <buffer> <Tab> vimwiki#tbl#kbd_tab()
inoremap <expr> <buffer> <S-Tab> vimwiki#tbl#kbd_shift_tab()
endif
So, :let g:vimwiki_table_mappings = 0 in your .vimrc should work, too.
Used Ingo Karkat's solution for the longest time but Shift-Tab in insert mode is broken again.
" New fix.
" SOURCE: https://github.com/vimwiki/vimwiki/issues/1268#issuecomment-1312192484
" SOURCE[*g:vimwiki_key_mappings*]: https://github.com/vimwiki/vimwiki/blob/0629b39815c97f1e4ee31e26faa6891b0e13d2d5/doc/vimwiki.txt#L3671
"
" Disable table mappings:
let g:vimwiki_key_mappings =
\ {
\ 'table_mappings': 0,
\ 'table_format': 0,
\ }

vim call a function from inside a vmap

I have created a vmap text object for selecting the text of a single LaTeX \item:
vmap im ?\\item<CR>o/\\item\\|\\end{itemize}<CR>b$
But this has the annoying feature that I lose my current search term. I have read that search terms are restored when the search happens inside a function call, so I wanted to convert the map to just call a function that would do the searches:
function! ItemizeTextObject()
?\\item
normal o
/\\item|\\end{itemize}
normal b$
endfunction
vmap in :call ItemizeTextObject()<CR>
Unfortunately, this does not work: I get an error ("Pattern not found: \item|\end{itemize}"), no text at all is selected, and a new line is inserted below the line my cursor is on. I tried several variations of this, and had no success.
I think the basic problem is that I have to preserve the visual mode when calling the function (the o in my command should switch to the other end of the selection, but it inserts a new line instead), but I don't know how.
Update:
I try to get the following behaviour: In a text like this:
\begin{itemize}
\item lorem ipsum...
\item piece of text I want to select,
the *CURSOR* is here, and there is more text
that follows
\item lorem ipsum...
\end{itemize}
I want to hit vin, and then the text block in the middle should be selected:
\item piece of text I want to select,
the *CURSOR* is here, and there is more text
that follows
that means the text from the beginning of the previous \item, until but not including the next \item or \end{itemize}.
I've used the doc on operatorfunc to come up with the following, which should be (close to) what you want1:
function! ItemizeTextObject(type, ...)
let sel_save = &selection
let &selection = "inclusive"
let reg_save = ##
if a:0 " Invoked from Visual mode, use '< and '> marks.
silent! 1,+1?\\item
norm v | " use V for linewise visual mode
"" use V for linewise visual mode:
"norm V
silent! /\\item\|\\end{itemize}
"elseif a:type == 'line'
"elseif a:type == 'block'
else
silent! 1,+1?\\item
norm v
silent! /\\item
endif
norm b$
let &selection = sel_save
let ## = reg_save
endfunction
silent! unmap in
xnoremap <silent> in :<C-U>call ItemizeTextObject(visualmode(), 1)<CR>
If you want the mapping in both visual and select modes, you should use vnoremap
Notes of things to address:
you can now implement the motion from another mode (fill in the branches in the function)
if wrapscan is on, no search should wrap (perhaps temporarily set nowrapscan?)
you might want to make the operator repeating so you can extend the selection by saying vininin (see https://stackoverflow.com/a/7292271/85371 for an example)
it looks like you want 'linewise' behaviour (due to b$?)
consider using norm V (see comment)
Edit I compared the behaviour with this simple mapping:
xnoremap <silent>in ?\\item<CR>o/\\item\\|\\end{itemize}<CR>b$
1 Disclaimer: I don't know LateX

VIM: How can i know which highlight rule is being used for a keyword?

:colorscheme default
The filetype is php.
Can anyone help me to find out the highlight rule ?
:hi[light]
will list all defined rules with a preview. You can also query single items:
:hi Keyword
To manually look up any syntax group under the cursor, there are choices. Mine is a function bounded to a key like this:
" Show syntax highlighting groups for word under cursor
nmap <F2> :call <SID>SynStack()<CR>
function! <SID>SynStack()
if !exists("*synstack")
return
endif
echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
endfunc
It'll list every syntax group the word belongs to.
I've had the following snippet tucked away for a while now, not sure where I got it. This will set your statusline to show the highlight group of the word currently under the cursor:
:set statusline=%{synIDattr(synIDtrans(synID(line('.'),col('.'),1)),'name')}
This will update your statusline as you move around the file.
I have something like this in my _gvimrc:
function! SyntaxBalloon()
let synID = synID(v:beval_lnum, v:beval_col, 0)
let groupID = synIDtrans(synID)
let name = synIDattr(synID, "name")
let group = synIDattr(groupID, "name")
return name . "\n" . group
endfunction
set balloonexpr=SyntaxBalloon()
set ballooneval

Vim script: Buffer/CheatSheet Toggle

I want to make a vim cheat sheet plugin. It's real simple:
I want to toggle my cheatsheets. A vertsplit toggle, like Taglist or NERDTree.
I want the cheatsheet to be filetype specific. So I toggle my c++ cheatsheet when I have opened a .cpp file.
I want the cheatsheet to be horizontally split. So it shows two files, my syntax cheat sheet and my snippet trigger cheat sheet.
I already have a collection of these cheatsheets, in vimhelp format, but now I have to manually open them.
I haven't really done any vim scripting, but I imagine this would be really simple to put together. I'm sorta sick of googling unrelated codesnippets, so what I'm asking here is:
Could anyone give me a short sum-up of what I need to learn in regards to vim scripting to piece this together. What I have a hard time finding is how to toggle the buffer window.
If you know any intro tutorials that covers the material I need to get this up and running, please provide a link.
tx,
aktivb
The function below may not do exactly what you want, and I haven't tested it, but it should give you some ideas.
The main idea is that the function reads the filetype of the current buffer (you can test this by typing :echo &ft) and then sets the path of the appropriate cheat sheat. If it exists, this path is then opened (read-only and non-modifiable) in a split window. You can then call this function any way you wish, for example by mapping it to the {F5} key as shown.
I'm not sure about the toggling possibilities (is this really easier than just closing the split window?) but you could look at the bufloaded() function, which returns whether or not a given file is currently being accessed.
function! Load_Cheat_Sheet()
let l:ft = &ft
if l:ft == 'html'
let l:path = 'path/to/html/cheat/sheet'
elseif l:ft == 'c'
let l:path = 'path/to/c/cheat/sheet'
elseif l:ft == 'tex'
let l:path = 'path/to/tex/cheat/sheet'
endif
if l:path != '' && filereadable(l:path)
execute ':split +setlocal\ noma\ ro ' l:path
endif
endfunction
map <F5> :call Load_Cheat_Sheet()<CR>
Hope this helps. Just shout if anything is unclear, or you want to know more.
I had forgotten about this until I got a notice about Eduan's answer. Since I posted this question I've done quite a bit of vim scripting, including getting this to work:
let g:cheatsheet_dir = "~/.vim/bundle/cheatsheet/doc/"
let g:cheatsheet_ext = ".cs.txt"
command! -nargs=? -complete=customlist,CheatSheetComplete CS call ToggleCheatSheet(<f-args>)
nmap <F5> :CS<CR>
" strip extension from complete list
function! CheatSheetComplete(A,L,P)
return map(split(globpath(g:cheatsheet_dir, a:A.'*'.g:cheatsheet_ext)),
\ "v:val[".strlen(expand(g:cheatsheet_dir)).
\ ":-".(strlen(g:cheatsheet_ext) + 1)."]")
endfun
" specify cheatsheet or use filetype of open buffer as default
" instead of saving window status in a boolean variable,
" test if the file is open (by name). If a boolean is used,
" you'll run into trouble if you close the window manually with :wq etc
function! ToggleCheatSheet(...)
if a:0
let s:file = g:cheatsheet_dir.a:1.g:cheatsheet_ext
else
if !exists("s:file") || bufwinnr(s:file) == -1
let s:file = g:cheatsheet_dir.&ft.g:cheatsheet_ext
endif
endif
if bufwinnr(s:file) != -1
call ToggleWindowClose(s:file)
else
call ToggleWindowOpen(s:file)
endif
endfun
" stateless open and close so it can be used with other plugins
function! ToggleWindowOpen(file)
let splitr = &splitright
set splitright
exe ":vsp ".a:file
exe ":vertical resize 84"
if !splitr
set splitright
endif
endfun
function! ToggleWindowClose(file)
let w_orig = bufwinnr('%')
let w = bufwinnr(a:file)
exe w.'wincmd w'
exe ':silent wq!'
if w != w_orig
exe w_orig.'wincmd w'
endif
endfun
Thought I would add to Goulash's answer.
I think in order to implement the toggle you would simply use some if statements and a global variable.
let g:cheatsheet_toggle_on=0
if (g:cheatsheet_toggle_on == 0)
" Turn the cheatsheet on
" Also make sure to know that the toggle is on:
let g:cheatsheet_toggle_on=1
elseif (g:cheatsheet_toggle_on=1
" Do whatever you need to turn it off, here
endif
Hope this figures out that logic. :)

Resources