2

I have following

function! s:get_visual_selection()
    let [line_start, column_start] = getpos("'<")[1:2]
    let [line_end, column_end] = getpos("'>")[1:2]
    let lines = getline(line_start, line_end)
    if len(lines) == 0
        return ''
    endif
    let lines[-1] = lines[-1][: column_end - 2]
    let lines[0] = lines[0][column_start - 1:]
    return join(lines, "\n")
endfunction

" dependencies - tpope's surround.vim plugin
function! s:singleDoubleQuotesToggler() "{{{
  " select between "" using
  norm va"
  let doubleq_sel = s:get_visual_selection()
  " echo string(doubleq_sel)
  let doubleq_sel_length = strlen(doubleq_sel)
  echo string(doubleq_sel_length)
  exec "norm! \<Esc>"
  if doubleq_sel_length == 0
    " echo string("single")
    norm cs'"
  else
    " echo string('double')
    norm cs"'
  endif
endfunction "}}}

nnoremap <silent> GS :call <SID>singleDoubleQuotesToggler()<CR>

problem is that GS work through once and I dont know why

video

1
2

For your approach to work, you could define an omap that finds the smallest enclosing pair, and tests the character under the cursor to trigger the mapping from Surround you wish. I remember a plugin that has defined the operator pending mode you'll need. Its approach was quite smart by testing all possible vi{whatever} to find the one with the smallest result. From there, you'll just need to test the character under '<. Alas I can't remember the name of this plugin.

It seems I've implemented an equivalent in lh-brackets (s:outer_blocks()), it doesn't returns the first characters, but the last one. From there, you'll just need to test the character under the closest position, and you'll know which surround mapping you want to execute.

That's the if p[0] =~ '["'']' part that'll be of interest to you. You can assume your s:GetPairs() results in [ ['"', '"'], ["'", "'"] ] -- s:GetPairs() returns the list of brackets pairs registered for the current buffer.

function! s:outer_blocks() abort
  let crt_pairs = copy(s:GetPairs(0))
  call extend(crt_pairs, s:GetPairs(1))
  let matches = {}
  for p in crt_pairs
    if p[0] != p[1] " searchpos doesn't work in that case
      let pos = searchpairpos(p[0], '', p[1], 'cWn', "lh#syntax#is_a_comment('.')")
      call s:Verbose('Testing searchpos(%1) -> %2', p, pos)
    elseif p[0] =~ '["'']'
      " Stuff which can be checked with vi', vi"
      let crt_pos = getpos('.')
      let cleanup = lh#on#exit()
            \.restore('@a')
            \.register('call setpos(".", '.string(crt_pos).')')
      try
        let @a = ''
        silent! exe 'normal! "aya'.p[0]
        " 2 chars are to be expected for open and close
        if lh#encoding#strlen(@a) >= lh#encoding#strlen(p[0].p[1])
          " In two steps because it may fail
          " -- it shouldn't though thanks to len(@a) >= 2 * len(open)
          exe 'normal! v'
          silent! exe 'normal! a'.p[0]
          silent! exe "normal! \<esc>"
          let pos = getpos('.')[1:2]
        else
          let pos = [0,0]
        endif
        if 0
          " getpos doesn't seem to work...
          let pos = getpos('`>')[1:2]
          if getpos('`<')[1:2] == pos
            let pos = [0,0]
          endif
        endif
        call s:Verbose('Testing va%1 -> %2 - %3', p[0], pos, @a)
      finally
        call cleanup.finalize()
      endtry
    else
      let pos = searchpos(p[0], 'cWnb', 'lh#syntax#is_a_comment(".")')
      if  pos != [0,0]
        let pos = searchpos(p[1], 'cWn', 'lh#syntax#is_a_comment(".")')
      endif
      call s:Verbose('Testing /%1 -> %2', p[0], pos)
    endif
    if pos != [0,0]
      let matches[p[0]] = pos
    endif
  endfor
  call s:Verbose('Containing bracket pairs: %1', matches)
  return matches
endfunction
1
  • Possibly you're thinking of rhysd/vim-textobj-anyblock? (Although there are probably a number of similar plugins) Edit: gcmt/wildfire.vim also looks close to what you describe.
    – Mass
    Oct 13 '17 at 5:09
0

You can use vim-surround. It's easy to add " or '.
For example, ysw" will add " to surround the current word.

1
  • 2
    If you read the code of in OP's question they already use vim-surround. What they want to do is a bit more complexe than simply adding the surrounding quotes.
    – statox
    Sep 13 '17 at 7:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.