Блокировать движение для любого типа кронштейна?

8

Если я хочу, скажем, удалить блок, я могу использовать движения текстовых объектов.

Т.е. если мой текст выглядит так:

(let [a 1 b {:x 3  :y 4}]
      a)

И курсор находится например на символе 3.

Если я наберу, diBто :x 3 :y 4будет удален. Если это так, daBто и блок, и окружающие скобки будут удалены:{:x 3 :y 4}

Итак, шаблон таков:

operation inclusion block-motion

Где операция может быть:

  • d - удалять

  • c - изменение

  • y - скопировать ...

включение это либо:

  • i - внутренний (без скобок) или

  • a - все

и блок-движение:

  • b, (Или )для ()скобок

  • B, {Или }для {}фигурной скобки

  • [или ]и <или >для своих соответствующих скобок и т. д.

Теперь возникает вопрос: есть ли движение блока для самого внутреннего блока в скобках любого из этих типов?

Я хотел бы быть в состоянии сделать da?с ?тем движением я ищу. И если курсор в моем примере выше находится в пределах, {}скажем, 3я бы удалил только то, {}но если бы мой курсор был включен, bя бы удалил []блок и т. Д.

Горан Йович
источник

Ответы:

3

Вот почему вопрос должен был быть на SO: нетривиальные сценарии требуются ...

" Public Mappings {{{1
onoremap <silent> i% :<c-u>call <sid>SelectFirstPair(1,0)<cr>
xnoremap <silent> i% :<c-u>call <sid>SelectFirstPair(1,1)<cr><esc>gv
onoremap <silent> a% :<c-u>call <sid>SelectFirstPair(0,0)<cr>
xnoremap <silent> a% :<c-u>call <sid>SelectFirstPair(0,1)<cr><esc>gv
" Public Mappings }}}1
"------------------------------------------------------------------------
" Private Functions {{{1
" Note: most functions are best placed into
" autoload/«your-initials»/«omap_any_bracket».vim
" Keep here only the functions are are required when the plugin is loaded,
" like functions that help building a vim-menu for this plugin.
let s:k_pairs = {
      \ '(': ')',
      \ '[': ']',
      \ '{': '}',
      \ '<': '>'
      \ }

let s:k_begin = '[([{<]'
let s:k_end   = '[)\]}>]'

function! s:SelectFirstPair(inner, visual)
  " In case we already are in visual mode, we may have to extend the current
  " zone if it selects a pair of brackets
  if a:visual
    let char_b = lh#position#char_at_mark("'<")
    if char_b =~ s:k_begin
      \ && s:k_pairs[char_b] == lh#position#char_at_mark("'>")
      call search('.', 'bW') " previous char
    elseif a:inner
      " handle case the case "vi%i%i%"
      let current_pos = getpos('.')
      call setpos('.', getpos("'<"))
      call search('.', 'bW') " previous char
      let pos_b = getpos('.')
      call setpos('.', getpos("'>"))
      call search('.', 'W') " next char
      let pos_e = getpos('.')
      let char_b = lh#position#char_at_pos(pos_b)
      let char_e = lh#position#char_at_pos(pos_e)
      echomsg "chars = ".char_b.char_e
      if char_b =~ s:k_begin
        \ && s:k_pairs[char_b] == char_e
    call setpos('.', pos_b) " restore start_pos
    call search('.', 'bW') " previous char
      else
    call setpos('.', current_pos) " restore init_pos
      endif
    endif
  endif

  " Searching the n outer blocks requested
  let cnt = v:count <= 0 ? 1 : v:count
  while cnt > 0
    let cnt -= 1
    let char_c = lh#position#char_at_pos(getpos('.'))
    let accept_at_current = char_c =~ s:k_begin ? 'c' : ''

    " Begin of the current outer block
    if 0 ==searchpair(s:k_begin, '', s:k_end, 'bW'.accept_at_current, 'lh#syntax#skip()')
      throw "No outer bloc"
    endif
    if cnt > 0
      call search('.', 'bW') " previous char
    endif
  endwhile

  let char_b = lh#position#char_at_pos(getpos('.'))

  normal! v

  " End of the outer block
  let pos_e = searchpair(s:k_begin, '', s:k_end, 'W', 'lh#syntax#skip()')
  let char_e = lh#position#char_at_pos(getpos('.'))
  if pos_e == 0
    throw "pos_e == 0"
  elseif s:k_pairs[char_b] != char_e
    echomsg "unbalanced blocks"
  endif

  " Adjusting the extremities
  if a:inner
    call search('.', 'b')
    normal! o
    call search('.')
    normal! o
  endif
endfunction
" Private Functions }}}1

NB: я повторно использовал функцию из lh-vim-lib - кстати, в версии lh#position#char_at_pos()conf есть небольшая ошибка : ее col()нельзя использовать.

Люк Эрмитт
источник
Я получаю синтаксическую ошибку с вашим кодом: line 13: E15: Invalid expression: E15: Invalid expression: {(…). У меня vim 7.2, ваш код требует 7.3? Между прочим, в то время как вопросы программирования обычно перенаправляются на SO, ответы на сценарии (для оболочек, редакторов и других программ с поддержкой сценариев) распространены здесь.
Жиль "ТАК ... перестать быть злым"
Поддерживаете ли вы vim словари? Если да, что произойдет, если вы добавите set cpo&vimв начале сценарий, который был протестирован и разработан на vim 7.2.148 на ... Windows XP. (Я немного устал от этого рассеяния сообщества vim, см. Комментарии к этому ответу stackoverflow.com/questions/4488979/… )
Люк Эрмит
Спасибо! Как мне это вызвать? Я попытался использовать bдля всех блоков, но он по-прежнему выбирает только ()тип блока. Нужно ли называть его по-другому или я его неправильно установил?
Горан Йович
ibуже что-то значит. Вы можете использовать этот с i%или a%(см отображения) => di%, va%i%, c2a%и т.д.
Luc Hermitte
1

Не по умолчанию, но может быть какой-то механизм для добавления этой функциональности. В visual.txt, разделе о работе с визуальной областью, он имеет следующее:

The objects that can be used are:
    aw      a word (with white space)                       |v_aw|
    iw      inner word                                      |v_iw|
    aW      a WORD (with white space)                       |v_aW|
    iW      inner WORD                                      |v_iW|
    as      a sentence (with white space)                   |v_as|
    is      inner sentence                                  |v_is|
    ap      a paragraph (with white space)                  |v_ap|
    ip      inner paragraph                                 |v_ip|
    ab      a () block (with parenthesis)                   |v_ab|
    ib      inner () block                                  |v_ib|
    aB      a {} block (with braces)                        |v_aB|
    iB      inner {} block                                  |v_iB|
    at      a <tag> </tag> block (with tags)                |v_at|
    it      inner <tag> </tag> block                        |v_it|
    a<      a <> block (with <>)                            |v_a<|
    i<      inner <> block                                  |v_i<|
    a[      a [] block (with [])                            |v_a[|
    i[      inner [] block                                  |v_i[|
    a"      a double quoted string (with quotes)            |v_aquote|
    a'      a single quoted string (with quotes)            |v_a'|
    i'      inner simple quoted string                      |v_i'|
    a`      a string in backticks (with backticks)          |v_a`|
    i`      inner string in backticks                       |v_i`|
Шон Дж. Гофф
источник
0

Есть vim addon, называемый textobj-user, который поддерживает что-то вроде этого. На самом деле я не уверен, что понял, что вы ищете, но я думаю, что аддон предназначен для того, чтобы было удобнее написать аддон для реализации того, что вы хотите.

созерцаемое
источник