2

I am trying to make a snippet that will help me choose the right revision number for migration, by reading all migration files from application/migrations.

What I managed to do myself is that my filenames are being filtered while I am typing, and when only one match left insert its revision number at the cursor position (which are first 14 chars of filename always).

The problem is that when I hit TAB to select, I am also left with what I have typed so far to search for that revision number, meaning something like this remo20160812110447.

Question is, how to get rid of that remo in this case!?

NOTE: Example uses hardcoded values, for easier testing, those will be later replaced by # lst = os.listdir('application/migrations') line.

Also an added bonus effect would be to present those 20160710171947 values as human readable date format while choosing, but after hitting TAB insert their original source version.

global !p
import datetime
def complete(t, opts):
if t:
    opts = [ m for m in opts if t in m ]
if len(opts) == 1:
    return opts[0][:14]
return "(" + '|'.join(opts) + ')'
endglobal

snippet cimigration "Inserts desired migration number, obtained via filenames"
$1`!p import os
# lst = os.listdir('application/migrations')
lst = [
    '20160710171947_create.php',
    '20160810112347_delete.php',
    '20160812110447_remove.php'
]
snip.rv = complete(t[1], lst)`
endsnippet
branquito
  • 3,864
  • 5
  • 35
  • 60
  • I would be more than happy to know the reason, why the person `x` down-voted this question. The question isn't about python itself, as that would be easily solved than, but the plugin behavior in this case. – branquito Jul 10 '16 at 23:13
  • I'm not the downvoter but I'd like to argue two things: You might want to hit the `flag` button an ask a moderator to move the question to [vi.SE](http://vi.stackexchange.com/), more people may be able to help there. Also, I never used ultisnips, but I'd argue this is not too hard to write in pure vimscript. You can use `split(globpath('application/migrations', '*.php'))` to get a list and then `viwc` once you hit ``. – grochmal Jul 10 '16 at 23:41
  • the point is filtering results while typing, thus narrowing search results, not obtaining plain list of files – branquito Jul 10 '16 at 23:54

2 Answers2

2

This can definitely be performed in pure vimscript.

Here is a working prototype. It does work but has some issues with portability: global variables, reliance on iskeyword and uses two keybindings instead of one. But it was put together in an hour or so:

set iskeyword=@,48-57,_,-,.,192-255
let g:wordidx = 0
let g:word = ''
let g:match = 0
function! Suggest()
  let l:glob = globpath('application/migrations', '*.php')
  let l:files = map(split(l:glob), 'fnamemodify(v:val, ":t")')
  let l:char = getline('.')[col('.')-1]
  let l:word = ''
  let l:suggestions = []
  if l:char =~# '[a-zA-Z0-9_]'
    if g:word ==# ''
      let g:word = expand('<cword>')
      let g:match = matchadd('ErrorMsg', g:word)
    endif
    let l:word = g:word
    "let l:reg = '^' . l:word
    let l:suggestions = filter(l:files, 'v:val =~ l:word')
    if !empty(l:suggestions)
      call add(l:suggestions, l:word)
      "echo l:suggestions
      let l:change = l:suggestions[g:wordidx]
      let g:wordidx = (g:wordidx + 1) % len(l:suggestions)
      "echo g:wordidx + 10
      execute "normal! mqviwc" . l:change . "\<esc>`q"
    endif
  endif
  "echo [l:word, l:suggestions]
endfunction

function! SuggestClear()
  call matchdelete(g:match)
  let g:wordidx = 0
  let g:word = ''
  let g:match = 0
endfunction

nnoremap <leader><tab> :call Suggest()<cr>
nnoremap <leader><cr>  :call SuggestClear()<cr>

Adding this to your ~/.vimrc will allow you to steps through search matches with <leader><tab>. It will highlight the part that is being matched, to drop the highlight you need to type <leader><cr>.

You should always drop the highlight after use because the original search word is kept internally until you destroy it. Using <leader><tab> before clearing the match will substitute for the suggestions from the previous match.

Screencast (my leader is -):

enter image description here


If you have more vim questions join the vi.SE subsection of the website. You can probably get better answers there.

Community
  • 1
  • 1
grochmal
  • 2,901
  • 2
  • 22
  • 28
2

This can be achieved using post-expand-actions: https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt#L1602

SirVer
  • 1,397
  • 1
  • 16
  • 15