Удаление «блоков» текста в vim - PullRequest
2 голосов
/ 07 мая 2009

У меня есть файлы, которые выглядят следующим образом:

>>Start-pattern
some text
some more text
>>Start-pattern
some other text

some more other text
>>Start-pattern
[and so on]

То, что я хотел бы иметь, - это отображение, которое позволяет мне удалить текущий «блок» текста. Где «блок» определяется как все строки в диапазоне от «>> Start-pattern» до до следующей строки «>> Start-pattern».

У меня есть следующее:

nnoremap ,d $:?^>>Start-pattern?,/^>>Start-pattern/-1delete<CR>

это работает, если я не стою на последнем "блоке" в файле.

Как я могу заставить эту карту (или совершенно другую, которая делает то же самое) работать со всеми "блоками" в файле?

Ответы [ 4 ]

7 голосов
/ 07 мая 2009

Я думаю, еще раз, мы раздвигаем границы регулярных выражений за пределы того, в чем они хороши. Они хороши в обмене одной строки с другой, это побочный эффект, что вы можете удалить текст с ними.

Вместо этого, почему бы не воспользоваться очаровательным языком сценариев, который предоставляет vim. Это проще и похоже на поездку на обратном пути машиной. Если вы добавите следующую функцию в ваш файл .vimrc, он будет делать то, что вы хотите, и будет более гибким и многократно используемым:

fun! DelBlock(thePattern)
  let origLineNumber = line(".")
  let lineNumber = origLineNumber

  let lineString = getline(lineNumber)
  while lineString !~ a:thePattern
    let lineNumber = lineNumber - 1
    if lineNumber < 0
      echo "Function not found :/"
    endif
    let lineString = getline(lineNumber)
  endwhile
  let startLine = lineNumber

  let lastLineInFile = line("$")
  let lineNumber = origLineNumber + 1
  let lineString = getline(lineNumber)
  while lineNumber != lastLineInFile && lineString !~ a:thePattern
    let lineNumber = lineNumber + 1
    let lineString = getline(lineNumber)
  endwhile
  let endLine = lineNumber
  if endLine != lastLineInFile
    let endLine = endLine - 1
  end

  execute startLine.","endLine."d"
endfunction

map ,d :call DelBlock("^>>Start-pattern")<CR>
6 голосов
/ 07 мая 2009

Вы можете сделать это с помощью одного регулярного выражения:

nnoremap ,d :1,.s/\v%(%(.*%#&(\>\>Start-pattern))%(\1@!\_.)+)\|%((\>\>Start-pattern)%(\2@!\_.)*%#%(\2@!\_.)+)//

Стоит ли вам - это другой вопрос ...

3 голосов
/ 07 мая 2009

Вот возможный взлом.

nnoremap ,d maGo>>Start-pattern<Esc>'a$?^>>Start-pattern<CR>dNmaGdd'a

 ma                     - mark your current position
 G                      - go to the end of the file
 o>>Start-pattern<Esc>  - append your pattern line
 'a                     - go back to your prior position
 $                      - go to the end of the current line
 ?^>>Start-pattern<CR>  - find the previous occurrence of the pattern
 dN                     - delete until the next occurence
 ma                     - mark your current position
 G                      - go to the end of the file
 dd                     - delete the last line of the file
 'a                     - return to your previous position

Изначально я пытался заставить работать \%$ (конец файла), но не смог удалить включить последний символ в файл. Поэтому я попробовал этот способ вместо этого.

Я провел некоторое тестирование, и, похоже, оно работает для меня (промежуточные блоки и последний блок).

2 голосов
/ 08 мая 2009

Большое спасибо за хорошие ответы, ребята!

В конце концов, я выбрал самый надежный и надежный. Основываясь на ответе Whaledawg и принимая во внимание комментарий Люка Эрмита, я получил:

fun! DelBlock(pat)
  let startLine = search(a:pat, "nbcW")
  let endLine = search(a:pat, "nW")

  if startLine == 0
     echo "Block '".a:pat."' not found"
     return
  end

  if endLine == 0
     let endLine = line("$")
  else
     let endLine = endLine-1
  end

  execute startLine.","endLine."delete"
endfunction

nmap ,d :call DelBlock("^>>Start-pattern")<CR>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...