2013-07-08 4 views
0

Я часто окружаю некоторый код/​​текст некоторыми другими строками текста. Ради конкретного примера, скажем, у меня есть некоторый текст:Удалить окружающие линии в vim

this is 
some text 

Я тогда макрос, который позволяет мне преобразовать, что (после выделения линии), чтобы

if false then 
    this is 
    some text 
end; 

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

nmap <space>i ccif false then<CR><c-r>"end;<esc> 
vmap <space>i cif false then<CR><c-r>"end;<esc> 

Однако я хотел был бы иметь возможность создать макрос для того чтобы извлечь окружающий текст. То есть, если курсор окружен строками «if false then» и «end;» то эти строки должны быть удалены.

Любые идеи о том, как создать такой макрос?

Позвольте мне заметить, что я посмотрел на surround.vim, но не нашел способ сделать это с помощью этого пакета.

+0

только блок 'if-end'? может ли он иметь «else, elif/else if ... end» тоже? как насчет вложенных 'if/else/end'? «это какой-то текст» всегда правильно отступом? может ли он комментировать что-то вроде '// если true, мы этого не делаем? Или вы просто хотите сделать «удаление окружающих линий» на точный пример в вышеупомянутом вопросе? – Kent

+0

с этой работой уже упростит для меня вещи. Да, обработка более сложных конструкций станет следующим шагом (хотя то, что я описал, идеально будет автоматически обрабатывать «вложенные» строки - поскольку он удалит только первый набор, окружающий курсор). – user2562235

ответ

2

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

function! RemoveSurrondingIfCondition() 
    let s:current_line = line('.') 
    "" Look backwards for the key string. 
    let s:beginif = search('\v^if\s+false\s+then\s*$', 'bWn') 
    if s:beginif == 0 || s:current_line <= s:beginif 
     return 
    endif 
    "" Set a mark where the _if_ begins 
    execute s:beginif 'mark b' 
    "" Look forward for the end of the _if_ 
    let s:endif = search('\v^end;\s*$', 'Wn') 
    if s:endif == 0 || s:endif <= s:beginif || s:current_line >= s:endif 
     return 
    endif 
    "" Delete both end points if searches succeed. 
    execute s:endif . 'delete' 
    'b delete 
endfunction 

noremap <space>d :call RemoveSurrondingIfCondition()<CR> 
+0

Большое спасибо за то, что нашли время, чтобы опубликовать это! - он отлично работает. – user2562235

+0

Это ... возможно, намного лучше. Хороший ответ. – ravron

1

я бросил вместе ответ, который будет делать это в одной строке - ты и я, мы оба знаем, что может только означать «регулярное выражение.» В любом случае, это будет работать на ближайший набор if false then и end;. Если вы не находитесь в «видимости» такой пары, она будет удалите ближайшие два, возможно, странным образом! Не стесняйтесь называть это «неопределенным поведением».

:?^\s*if\ false\ then?,/^\s*end;/ g/^\s*if\ false\ then\|^\s*end;/d 

Вы можете копаться там и находить фактические строки и изменять их на то, что на самом деле вам подходит. И, если вы захотите спуститься и засорить регулярное выражение, вы можете, например, сделать его совпадающим с if false then s и if true then s и действительно if <something> then s, и всевозможные забавные вещи.

Если вы хотите получить менее беглое (чтение: несуществующее) объяснение того, как это работает, не стесняйтесь говорить об этом. Я предполагаю, что вы, как минимум, осведомлены о: g, как и я.

+0

Спасибо за сообщение. В моем случае крайне важно, чтобы строки удалялись только тогда, когда курсор находится в тексте между ними (что, по-видимому, делает решение Birei выше). – user2562235

Смежные вопросы