vim-CtrlXA icon indicating copy to clipboard operation
vim-CtrlXA copied to clipboard

[request] Toggle phrases / support keywords cycles with spaces

Open martinhj opened this issue 7 years ago • 2 comments

I tried today to add a toggling cycle for markdown:

autocmd Filetype markdown let b:CtrlXA_Toggles = [['- [ ]', '- [x]']] + g:CtrlXA_Toggles

and

autocmd Filetype markdown let b:CtrlXA_Toggles = [['-\ [\ ]', '- [x]']] + g:CtrlXA_Toggles

which did not work.

I would love to toggle github markdown checkboxes with this plug-in.

Other than that, thank you for this plug-in.

martinhj avatar Aug 19 '18 11:08 martinhj

Thanks for the suggestion. Toggling strings without delimiters (such as, currently, <space>) is however difficult to do right, especially in a plug-in that tries to keep it simple. I tried mimicking https://github.com/AndrewRadev/switch.vim/tree/master/autoload/switch but somehow it didn't work out. For example, the cursor didn't move on search(), or replacing by setline() was not allowed.

Please give one of these full-fletched plug-ins a try in the mean while:

https://github.com/Konfekt/vim-CtrlXA/issues/1

I leave this abandoned scriplet for reference:

  " " use vim-repeat to ensure @. = <C-A/X>
  " let repeat = ":silent! call repeat#set('" . a:CtrlAX . "','" . v:count . "')\<cr>"

  " " first try matching cWORD, then cword
  " let cWORD = expand('<cWORD>')
  " let cword = expand('<cword>')

  for toggle in get(b:, 'CtrlXA_Toggles', g:CtrlXA_Toggles)
    let len = len(toggle)
    let i = 0
    while i < len
      let current = toggle[i]
      let next = toggle[ (i + 1) % len]

      " if cWORD is# current
      "   return "\"_ciW" . next . "\<esc>" . repeat
      " endif
      "
      " if cword is# current
      "   return ":\<c-u>call search('\\v(\\k|\\x)','cz')\<cr>" . "\"_ciw" . next . "\<esc>" . repeat
      " endif

      let lnum = line('.')
      let col = col('.')

      let pattern = '\V' . escape(current, '\')
      " find start of the pattern
      if search(pattern, 'bcW', lnum) <= 0
        " not found, try the next pattern
        let i = i+1
        continue
      endif
      let match_start = col('.')

      " find end of the pattern
      call search(pattern, 'cWe', lnum)
      let match_end = col('.')

      if match_start > col || match_end <= col
        " cursor is outside the pattern
        let i = i+1
        continue
      else
        " limit pattern to [match_start, match_end[ interval
        if match_start > 1
          let pattern = '\m\%>' . (match_start - 1) . 'c' . pattern
        endif
        if match_end > 1 && match_end < col('$')
          let pattern = pattern . '\m\%<' . (match_end + 1) . 'c'
        endif
        let pattern = escape(pattern, '/')
        let replacement = escape(next, '\')
        let replacement = escape(replacement, '/&')
        exe ':substitute/' . pattern . '/' . replacement . '/I'
      endif
      " silent! call setpos('.', col)

      let i = i+1
    endwhile
  endfor

  " return a:CtrlAX . repeat
endfunction

Pull requests are of course welcome.

Konfekt avatar Aug 19 '18 20:08 Konfekt

Thanks for looking in to it! I totally see your points.

martinhj avatar Aug 19 '18 20:08 martinhj