Поменяйте местами выбор вокруг оси - PullRequest
4 голосов
/ 27 февраля 2012

(НЕ возможный дубликат Поменять местами текст вокруг знака равенства :)

Очень часто я обмениваюсь вещами. Что боль в заднице.

Скажем сразу после того, как я напишу этот кусок кода

tmp = realloc (words, sizeof (char **) * (*count + 1));

Я заметил, что в строке слишком много звездочек, не нравится, и хочу поменять местами два множителя вокруг звездочки умножения.

Или я пишу

#if !defined(_CONSOLE_H_) && defined (__MINGW32__)

но я вдруг осознаю, что defined (__MINGW32__) по какой-то причине должен прийти первым.

Я думаю, было бы здорово, если бы я мог сделать что-то вроде этого:

(На символе x, [x] обозначает положение курсора. <S> обозначает эту гипотетическую команду "swap around") *

#if [!]defined(_CONSOLE_H_) && defined (__MINGW32__)

команда: vf&<S>$ => выберите от курсора до центра (слово &&) и поменяйте местами выделенный текст с текстом до конца строки.

Или, для первого примера:

tmp = realloc (words, [s]izeof (char **) * (*count + 1));

команда: v3f*<S>f) => выберите отсюда до третьего *, поменяйте местами текст вперед ).

Для меня это было бы невероятно полезно. Есть ли что-то подобное, или я должен написать свой собственный плагин?

Спасибо!

РЕДАКТИРОВАТЬ -

Как @ib. говорит в комментариях к своему ответу, я должен быть более конкретным в отношении что такое это стержень.

Пивот также может быть символом, например здесь:

static char ** tokenize_input (char * input, PDWORD count);

Я могу захотеть поменять местами два аргумента вокруг ",". Точнее, ", ".

Так что, возможно, мне понадобятся две команды:

<s> - char-wise - the pivot is the last character of the selection;
<S> - word-wise - the pivot is the last word of the selection.

Спасибо! (пс. как насчет последнего Word ?:)

Ответы [ 4 ]

5 голосов
/ 27 февраля 2012

Это похоже на работу здесь, дайте мне знать, как это работает:

function! Swap(...) "{{{
  let start_v = col("'<")
  let end_v = col("'>")
  let mv = ''
  let isMv = 0
  while !isMv
    let char = s:GetChar()
    if char == '<Esc>'
      return ''
    endif
    let mv .= char
    let isMv = s:IsMovement(mv)
    echon mv."\r"
  endwhile
  if isMv == 2
    return ''
  endif
  exec "normal! ".end_v.'|'.mv
  let lhs = '\%'.start_v.'c\(.\{-}\S\)'
  if !a:0
    let pivot = '\(\s*\%'.(end_v).'c.\s*\)'
  else
    let pivot = '\(\s*'.a:1.'*\%'.(end_v).'c'.a:1.'\+\s*\)'
  endif
  let rhs = '\(.*\%#.\)'
  exec 's/'.lhs.pivot.rhs.'/\3\2\1/'
endfunction "Swap }}}

function! s:GetChar() "{{{
  let char = getchar()
  if type(char) == type(0) && char < 33
    return '<Esc>'
  elseif char
    let char = nr2char(char)
  endif
  return char
endfunction "GetChar }}}

function! s:IsMovement(mv) "{{{
  let ft = a:mv =~ '^\C\d*[fFtT].$'
  let ft_partial = a:mv =~ '^\C\d*\%([fFtT].\?\)\?$'
  let right = a:mv =~ '^\d*[l$|;,]\|g[m$]$'
  let right_partial = a:mv =~ '^\d*\%([l$|;,]\|g[m$]\?\)\?$'
  if !right_partial && !ft_partial
    return 2
  endif
  return ft || right
endfunction "IsMovement2Right }}}

" Use last char as pivot. e.g.: the comma in the given example.
vmap <silent> <leader>s1 :<C-U>call Swap()<CR>
" Use \S\+ (WORD) as pivot. e.g.: &&
vmap <silent> <leader>ss :<C-U>call Swap('\S')<CR>
" Use \w\+ as pivot.
vmap <silent> <leader>sw :<C-U>call Swap('\w')<CR>

Нет необходимости нажимать Enter, чтобы указать движение сейчас. «Сводка» всегда включает любые окружающие пробелы, и ее можно определить с помощью одного класса символов, заданного в качестве аргумента для Swap () в отображении.

Если вы хотите, чтобы оно было выделено, отметьте https://gist.github.com/1921196

1 голос
/ 14 марта 2012

Я придумал решение с несколько иным рабочим процессом.Вы выбираете текст в визуальном режиме, а затем указываете символ / текст, который вы хотите развернуть.В большинстве случаев я хотел, чтобы пробелы учитывались, поэтому по умолчанию пробел вокруг текста сводки включается как часть фактической сводки.Я сопоставил его с последовательностями, такими как \ a, для поворота вокруг запятой (с явными сопоставлениями для ',', ';', '.' И пробела) и \ aa запрашивает сводный текст, поэтому вы можете использовать \ aaandчтобы развернуться вокруг слова "и".

Вот vimscript:

vmap <silent> <leader>aa :call SwapAround()<CR>
vmap <silent> <leader>a, :call SwapAround(',')<CR>
vmap <silent> <leader>a. :call SwapAround('\.')<CR>
vmap <silent> <leader>a; :call SwapAround(';')<CR>
vmap <silent> <leader>a<Space> :call SwapAround("[ \t\n]*")<CR>

function! SwapAround(...) range
  if 1 == a:0
    let exp = a:1
  else
    call inputsave()
    let exp = input('pivot:')
    call inputrestore()
  endif
  if exp !~ '[ \t\n]' 
    let exp = '[ \t\n]*'.exp.'[ \t\n]*'
  endif
  call s:SwapAroundBase(exp, getpos("'<"), getpos("'>"))
endfunction

function! s:SwapAroundBase(sepExp, start, end) range
    let save_a = @a
    try
      let originalText = s:getText(a:start, a:end)
      let sepStart = match(originalText, a:sepExp)
      let sepEnd = matchend(originalText, a:sepExp)
      let firstOne = strpart(originalText, 0, sepStart)
      let sep = strpart(originalText, sepStart, sepEnd - sepStart)
      let secondOne = strpart(originalText, sepEnd)
      let @a = secondOne.sep.firstOne
      let posStatus = setpos(".", a:start)
      normal! v
      let posStatus = setpos(".", a:end)
      normal "ap
    finally
      let @a = save_a
    endtry
endfunction

function! s:getText(start, end)
  let lines = getline(a:start[1], a:end[1])
  let lines[-1] = lines[-1][: a:end[2] - 1]
  let lines[0] = lines[0][a:start[2] - 1:]
  return join(lines, "\n")
endfunction

Это хорошо работает для замены одной строки, но я думаю, что случаи с несколькими строками должны быть очищены.

1 голос
/ 27 февраля 2012

Я использую следующий плагин , который был вдохновлен vim tip.

Сначала я удаляю (одним ударом - diw также считается как единицу, а xx нет) первую часть, которую я хочу поменять. Затем я визуально выбираю вторую часть. И наконец я ударил g".

Et voilà! Два текста поменялись местами.

Конечно, это не так просто, как выбрать опору. Это нормально, так как речь идет не только о сводке: мы должны указать в тот или иной момент, когда оба текста должны поменяться местами, начинаются и заканчиваются, а также случаи, когда сводка имеет нулевую длину (ed?).

1 голос
/ 27 февраля 2012

Позвольте мне предложить следующее отображение в качестве реализации гипотетического <S> команда.

vnoremap <silent> <leader>m xm':<c-u>set opfunc=PasteAfter<cr>g@
function! PasteAfter(type)
    let [sl, sc] = getpos("'[")[1:2]
    let [cl, cc] = getpos("''")[1:2]
    let back = sl < cl || (sl == cl && sc < cc)
    undojoin | exe 'norm!' ['`]p`[', '`[P`]'][back]
endfunction

Эта реализация работает не только для посимвольного выбора на одном строка, но также для линейного и блочного выбора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...