Search code examples
vimtransformultisnips

How Ultisnips transforms text instantly in Vim?


SirVer/ultisnips is a very productive plugin for writing scripts in Vim. But anyone knows How Ultisnips transforms text instantly in Vim as shown in the gif. Ultisnips in this example is transforming every character in text "This is the subtitle" into minus sign immediately after character is being typed.

ultisnip transformation


Solution

  • What it looks like

    From what I understand it looks like they are cheating ;) Here's a hint that will give you the basice idea. So step one, enter some text. enter image description here Then just yyp and s/./_/g and you are done

    enter image description here

    Or s/./-/g: enter image description here

    How it's done (Well, most likely)

    So they are basically intercepting each symbol insertion. But how? It looks like they are using autocommand for specifc event, namely, for CursorMovedI, which is triggered "after the cursor was moved in Insert mode".

    You can easily find autocommand binding if you take a look to the source code.

    Alternative approach

    VIM is a console text editor and text formatting of this kind is not something widely supported in terminals. There are some workarounds though, like using special utf-8 characters (of course, text should be encoded accordingly). Here's a code snippet that you can use for this approach:

    " modify selected text using combining diacritics
    command! -range -nargs=0 Overline        call s:CombineSelection(<line1>, <line2>, '0305')
    command! -range -nargs=0 Underline       call s:CombineSelection(<line1>, <line2>, '0332')
    command! -range -nargs=0 DoubleUnderline call s:CombineSelection(<line1>, <line2>, '0333')
    command! -range -nargs=0 Strikethrough   call s:CombineSelection(<line1>, <line2>, '0336')
    
    function! s:CombineSelection(line1, line2, cp)
      execute 'let char = "\u'.a:cp.'"'
      execute a:line1.','.a:line2.'s/\%V[^[:cntrl:]]/&'.char.'/ge'
    endfunction
    

    But as you can see it's not ideal: enter image description here