ycm-core / YouCompleteMe

A code-completion engine for Vim
http://ycm-core.github.io/YouCompleteMe/
GNU General Public License v3.0
25.46k stars 2.81k forks source link

SnipMate/UltiSnips integration #36

Closed kballenegger closed 11 years ago

kballenegger commented 11 years ago

A killer feature would be for YCM to include SnipMate snippets in its suggestions.

I'm making this an issue in case a contributor sees this. I unfortunately do not have the skills required to build this.

Valloric commented 11 years ago

I'm not a fan of this. I use snippets as well (UltiSnips) but I don't think integrating it with a code-completion system would be the best approach.

Thanks for the feedback though!

capitalist commented 11 years ago

For what it's worth. I think snippet integration would be nice as well. My snippets no longer complete with YCM, so I may have explore changing the trigger.

kballenegger commented 11 years ago

Ditto, see how Xcode does it. It's really nice, your snippets are offered as autocompletion, it's super neat.

drasill commented 11 years ago

+1 (ultisnips)

"snippets offered as autocompletion" is something I didn't imagine, it could be awesome.

drasill commented 11 years ago

Although, binding <C-j> to ultisnips make it easy to use again.

Valloric commented 11 years ago

I'm slowly changing my mind about this. If we could figure out a way for YCM to talk to UltiSnips/Snipmate in a way that doesn't complicate matters too much, I'd support it.

UltiSnips support will probably come first; I'm not sure about Snipmate because upstream has a note about Snipmate dying and it recommends UltiSnips, so that's not a good sign.

Townk commented 11 years ago

The way clang_complete uses Ultisnips is the best approach. Besides allow you to complete snippets with once you accepted a completion and this completion is a function call, than YCM should provide an "anonymous" snippet with the parameters of the function to be completed. Ex:

I type:

prtf

Than YCM offers me "printf" among others. After I press than , YMC shuld give me this:

printf("format string", parameters);

Where:

"format string" - is the first argument of the snippet , parameters - is the optional argument

Also, regarding how to complete a snippets or "other completions", I think YMC should do this:

I type:

if

YMC provides me some options. The snippets should be listed on top of the options and marked somehow so user can clearly see what's this about. If user, press , than Ultisnips should be triggered and if the offered snippet has more than one possibility, than YCM should change the completion list to show all snippets available for the chosen snippet.

I'm pretty sure if you contact the developers of Ultisnips they can help you figure out a way to implement that.

Valloric commented 11 years ago

I'll probably talk to the UltiSnips developer at some point, yes.

I like your first feature, where pressing TAB after "ptrf" also inserts the parameter names. But this can be implemented without UltiSnips actually.

The second feature sound good too, but that will not be easy to implement and will require quite a bit of cooperation with the snippets plugin.

capitalist commented 11 years ago

Wow, how often does a maintainer remain open-minded after dismissing an issue.

Loving YCM and now @Valloric too. Respect.

Townk commented 11 years ago

Agree that "parameter" completion can be achieved without Ultisnips. That being said, Ultisnips already provide a python API to do that, and it'll give you the possibility to use powerful snippets features like python interpolation.

Valloric commented 11 years ago

@Townk I didn't know UltiSnips provided such an API. I'll be using it then.

sotte commented 11 years ago

This is the active clone of snipmate which is used quite a lot: https://github.com/garbas/vim-snipmate

Valloric commented 11 years ago

@sotte From the top of the README in that branch:

See snipmate-snippets readme about how to configure and use Ultisnips as alternative That branch also supports completion menu now Thus there is only one reason left to keep using snipmate from my point of view: not having python support. In other words: upstream of snipmate is almost dead.

Also see the issue linked from the first line in the README. This is written by the maintainers of the snipmate clone. Here's an excerpt:

Dear fellow snipmate community. It was a great honor working for you. [...] However for quite a long time snipmate has been broken in various ways - and me and Rok wonder whether its worth fixing snipmate - cause there are other snippet engines for Vim which are more powerful and which do just work - such as ultisnips or xptemplate.

I think this means that SnipMate is dead, or very close to it.

Townk commented 11 years ago

@sotte another thing is that Ultisnips kind provide some snipmate compatibility. It defines the "Filename" function and the g:snips_author variable that are used by some snippets. It also provides a script called "convert_snipmate_snippets.py", I believe you can just convert your snippets and start using Ultisnips. Give it a try!

pvinis commented 11 years ago

until ultisnips support comes, how can i make to trigger ycm completion, and to trigger ultisnips completion? do you all use another key for ultisnips? i saw on valloric's vimrc a meta key combination, but can't seem to be able to use meta on macvim..

xgalaxy commented 11 years ago

In your vimrc you have to :set macmeta for the options key to work correctly. If your using macvim in terminal, it wont work regardless.

mindfulmonk commented 11 years ago

Can someone give me their config with working keybindings? Can't get UltiSnips to work in terminal.

bmedicke commented 11 years ago

Mapping UltiSnips to ctrl-j/k works fine for me.

let g:UltiSnipsExpandTrigger="<c-j>"
let g:UltiSnipsJumpForwardTrigger="<c-j>"
let g:UltiSnipsJumpBackwardTrigger="<c-k>"

See :h UltiSnips-triggers.

That said I like the idea of it being more integrated with YCM.

jbeja commented 11 years ago

Thanks @bmedicke, works like a charm

neersighted commented 11 years ago

:+1:

UncleBill commented 11 years ago

+1 for UltiSnips. It is awesome!

AllisonV commented 11 years ago

+1

fatih commented 11 years ago

:+1:

johntyree commented 11 years ago

Neocomplcache also has a feature like this, although it basically reimplemented the snippets engine.

That said, it's a great feature for the same reasons as identifier autocompletion, namely you don't want to have your entire snippet collection in your head at all times. Almost all of the snippets I use I discovered because neocomplcache popped them up as I was typing.

As a final point, I don't know if this still "under vote" or something, but having an endless chain of "+1" and :+1: is pretty terrible for everyone else that has commented in this thread. Please don't.

dbrgn commented 11 years ago

In the meantime you should mention the g:snips_trigger_key option (and the UltraSnips equivalent) in your FAQ.

JazzCore commented 11 years ago

I've managed to get this working, you can check this branch. If you wish to try it, you will need a quite recent version of UltiSnips. I will not make a pull request for this because it's mainly a hack to add general completers and I agree with @Valloric that this is not so useful. Maybe someday @Valloric or I will make a nice implementation for general completers and there will be a better implementation.

For correct completion and snippet expanding with a TAB key you can use this function:

" UltiSnips completion function that tries to expand a snippet. If there's no
" snippet for expanding, it checks for completion window and if it's
" shown, selects first element. If there's no completion window it tries to
" jump to next placeholder. If there's no placeholder it just returns TAB key 
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

Due to fact that YCM maps its keys in autoload script after all plugins, mapping in .vimrc will not help. So, you need to map it manually or some other way. I've used this mapping:

exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"
johntyree commented 11 years ago

Due to fact that YCM maps its keys in autoload script after all plugins, mapping in .vimrc will not help. So, you need to map it manually or some other way.

This is probably the single most annoying thing about Vim plugins. Especially "revolutionary" ones. If I want to steamroll all of my key maps, I'll do so. Please don't do it for me. Some of us use more than one plugin at a time and this kind of thing breaks them in unexpected, unpredictable ways with no hope of debugging.

Valloric commented 11 years ago

@johntyree YCM provides options for changing pretty much all of the default mappings. There have to be some defaults set because the defaults work for most people. Nobody wants to install a plugin and then create 10 different mappings just to be able to use it. They should all me remappable, sure, but every plugin should come with defaults.

dbrgn commented 11 years ago

I just took a look at the UltiSnips screencasts. This definitely needs to be integrated with YCM! Awesome stuff.

mikebobroski commented 11 years ago

@JazzCore, thanks for the UltiSnips completion function posted above.
I was able to add the mapping to .vimrc by calling it on BufEnter. Here's the line:

au BufEnter * exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"
sethfowler commented 11 years ago

@JazzCore, thanks for working on this. I felt like I got the most benefit out of simply having the snippets listed in the completion list. The overloaded functionality for the tab key was somewhat problematic, though. What happened for me was that as soon as a snippet got expanded, the YCM completion menu disappeared and selecting the fields of the snippet took priority. This flow doesn't seem right to me, as it means that you can't easily tab past a snippet to access another completion. I'd prefer if the expanded snippet only served as a preview of sorts until I took some action to confirm that I wanted that snippet. (Maybe hitting the Enter key?)

If I get some time in the next couple of weeks I may take a look at what it would take to integrate this more cleanly.

johntyree commented 11 years ago

I had the same issue with <Tab> as a super catch-all key in SPF13.

I'm using <C-K> for snippet expansion in neocomplcache+neosnippets and I'm very happy with it.

capitalist commented 11 years ago

Ok, this feature works really well and is a pleasure to use.

mindfulmonk commented 11 years ago
let g:UltiSnipsExpandTrigger = '<c-l>'
let g:UltiSnipsJumpForwardTrigger = '<c-j>'
let g:UltiSnipsJumpBackwardTrigger = '<c-k>'
let g:UltiSnipsListSnippets = '<c-m>'

It would be great to be able to use TAB instead of a different mapping

JazzCore commented 11 years ago

take a look at function I've posted above. It will work, but with some limitations

mindfulmonk commented 11 years ago

@JazzCore Got it working by putting your function into vimrc + @mikewho mapping. Cheers :)

Valloric commented 11 years ago

I'll probably be adding something like what @JazzCore added above to YCM.

jcostello commented 11 years ago

The integration isnt working for me. YCM didnt show the list of snippets that ultisnip provides me. Any sugestion?

JazzCore commented 11 years ago

Please elaborate. Try opening a python file and write de. Does it list any snippets ( like desc or defn) in completions? If not, try running :py print UltiSnips_Manager in command mode.

jcostello commented 11 years ago

de doesnt bring me any snippet. :py print UltiSnips_Manager prints the object <UltiSnips.SnippetManager object at 0x7fc37514d390>

Did i have to configure something in the .vimrc?

PD: I installed Ultisnips and YCM with Vundler

" YouCompleteMe
Bundle 'Valloric/YouCompleteMe'
" Ultisnips
Bundle 'SirVer/ultisnips'  
JazzCore commented 11 years ago

No, you dont need to configure anything. I dont really know whats wrong, all should run fine with this settings. Try opening a python file and run :py print UltiSnips_Manager._snips( '', 1 ).

To clarify this, take a look at gif here: https://github.com/Valloric/YouCompleteMe/pull/257. You should get something like this ( lines with <snip> are snippets ).

jcostello commented 11 years ago

Yeah, i saw that yesterday but i dont get any snippet completion. When i run :py print UltiSnips_Manager._snips( '', 1 ). i get:

[Snippet(box,"A nice box with the current comment symbol",b), Snippet(bbox,"A nice box over the full width",b), Snippet(lorem,"Lorem Ipsum - 50
 Words",b)]

Ultsnips clearly is working correctly. Maybe is something in my .vimrc

colorscheme molokai
syntax on

  filetype plugin on

  autocmd FileType python set omnifunc=pythoncomplete#Complete
  autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
  autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
  autocmd FileType css set omnifunc=csscomplete#CompleteCSS
  autocmd FileType xml set omnifunc=xmlcomplete#CompleteTags
  autocmd FileType php set omnifunc=phpcomplete#CompletePHP
  autocmd FileType c set omnifunc=ccomplete#Complete
  autocmd FileType ruby,eruby set omnifunc=rubycomplete#Complete
  autocmd FileType ruby,eruby let g:rubycomplete_buffer_loading = 1
  autocmd FileType ruby,eruby let g:rubycomplete_rails = 1
  autocmd FileType ruby,eruby let g:rubycomplete_classes_in_global = 1

" Basics {
  set nocompatible        " must be first line

  set modelines=0
  set tabstop=2
  set shiftwidth=2
  set softtabstop=2
  set smarttab      " insert tabs on the start of a line according to shiftwidth, not tabstop
  set expandtab
  set encoding=utf-8
  set scrolloff=3
  set autoindent    " always set autoindenting on
  set copyindent    " copy the previous indentation on autoindenting
  set showmode
  set showcmd
  set hidden
  set wildmenu
  set wildmode=list:longest,full
  set completeopt=menu,menuone,longest
  set cursorline
  set ttyfast
  set ruler
  set backspace=indent,eol,start
  set laststatus=2
  set relativenumber
  set undofile
  set history=1000         " remember more commands and search history
  set undolevels=1000      " use many muchos levels of undo
" }

" Paste {
  if has ('x') && has ('gui') " on Linux use + register for copy-paste
      set clipboard=unnamedplus
  elseif has ('gui') " one mac and windows, use * register for copy-paste
      set clipboard=unnamed
  endif

  set pastetoggle=<F2>
" }

" Search {
  set ignorecase
  set smartcase
  set gdefault
  set incsearch
  set hlsearch
  set showmatch
  nnoremap <leader><space> :noh<cr>
  nnoremap <tab> %
  vnoremap <tab> %
  nnoremap / /\v
  vnoremap / /\v
" }

" Mappings {
  let mapleader = ","

  nnoremap <up> <nop>
  nnoremap <down> <nop>
  nnoremap <left> <nop>
  nnoremap <right> <nop>
  inoremap <up> <nop>
  inoremap <down> <nop>
  inoremap <left> <nop>
  inoremap <right> <nop>
  nnoremap j gj
  nnoremap k gk
  nnoremap ; :
  au FocusLost * :wa

  nnoremap <leader>w <C-w>v<C-w>l
  nnoremap <leader>q <C-w>q
  " Quickly edit/reload the vimrc file
  nmap <silent> <leader>vo :e $MYVIMRC<CR>
  nmap <silent> <leader>vl :so $MYVIMRC<CR>

  nnoremap <C-h> <C-w>h
  nnoremap <C-j> <C-w>j
  nnoremap <C-k> <C-w>k
  nnoremap <C-l> <C-w>l
" }

" Setting up the directories {
    set nobackup
    set noswapfile
    if has('persistent_undo')
      set undofile                "so is persistent undo ...
      set undodir=~/.vim/.undo
      set undolevels=1000         "maximum number of changes that can be undone
      set undoreload=10000        "maximum number lines to save for undo on a buffer reload
    endif
" }

" Vundle

  "filetype off

  set rtp+=~/.vim/bundle/vundle/
  call vundle#rc() " let Vundle manage Vundle

  " required
  Bundle 'gmarik/vundle' 

  " Command-T
  Bundle 'Command-T'                
  " Ack
  Bundle 'ack.vim'                  
  " YouCompleteMe
  Bundle 'Valloric/YouCompleteMe'
  " Ultisnips
  Bundle 'SirVer/ultisnips'         
  " Syntastic
  Bundle 'scrooloose/syntastic'
  " EasyTags
  Bundle 'xolox/vim-easytags'

  filetype plugin indent on

" END VUNDLE

" Plugins {

  " Ack {
    let g:ackprg="ack-grep -H --nocolor --nogroup --column"
  " }

  " Snippets {
   " let g:UltiSnipsExpandTrigger="<tab>"
   " let g:UltiSnipsJumpForwardTrigger="<tab>"
   " let g:UltiSnipsListSnippets="<c-e>"
  " }
  " Syntastic
    let g:syntastic_error_symbol='✗'
    let g:syntastic_warning_symbol='⚠'
    let g:syntastic_enable_highlighting=0
    let g:syntastic_auto_loc_list=1

  " EasyTags
    set tags=./tags;

    let g:easytags_always_enabled = 1
    let g:easytags_file = './tags'
    let g:easytags_dynamic_files = 1
    let g:easytags_auto_highlight = 1
    let g:easytags_updatetime_min = 5000

  " You Complete Me
    let g:ycm_global_ycm_extra_conf = '~/.vim/.ycm_extra_conf.py'
    let g:ycm_allow_changing_updatetime = 0
    let g:ycm_complete_in_comments = 1
    au BufWritePost *.c,*.cpp,*.h YcmForceCompileAndDiagnostics
    nnoremap <F5> :YcmForceCompileAndDiagnostics<CR>

    if has("autocmd")
      autocmd FileType cpp,c,ruby,python,java let g:easytags_include_members = 1
    endif
JazzCore commented 11 years ago

Well, it IS problem in your .vimrc. Bundles must be on top of config and be preceeded with filetype off line. Rewrite it to something like this:

set nocompatible
filetype off " required
" Vundle
set rtp+=~/.vim/bundle/vundle/
call vundle#rc() " let Vundle manage Vundle

" required
Bundle 'gmarik/vundle' 
" Command-T
Bundle 'Command-T'        
" rest of the bundles       
filetype plugin indent on " required

" rest of the config here

I've tested this before and after the change so it should work fine. Most probably the problem here it that YCM tries to load UltiSnips python module before ultisnips is actually initialized.

jcostello commented 11 years ago

Thank you very much. That solves the problem. :+1: :tada:

JazzCore commented 11 years ago

Good, glad to help.

mgutz commented 11 years ago

@Valloric, @JazzCore you guys rock!

YCM + UltiSnips = Ultimate Editor

jbeja commented 11 years ago

@mgutz I think that VIM was already the Ultimate Editor even without it XD.

gbataille commented 11 years ago

arf. I followed what you did JazzCore but I can't get Tab to expand the snippet. in case somebody can spare a minute: here is my vimrc (certainly a bit cluttered) https://gist.github.com/gbataille/5548857

thanks

mgutz commented 11 years ago

@gbataille Did you add the autocmd snippet by @mikewho above? That binds it to tab

gbataille commented 11 years ago

well unless I misunderstood something, I did yes (look at the last line in the Gist)