Yanking все отмеченные строки в vim
Часто при просмотре журнальных файлов в vim я выделяю интересные строки с помощью меток. В какой-то момент я хотел бы иметь возможность копировать все интересные строки (либо все отмеченные строки, либо список меток) в регистр или другой файл (на самом деле это не имеет значения, цель облегчить написание резюме). Я не смог найти какой-либо встроенный способ сделать это; возможно ли это в vim?
Я полагаю, что это, вероятно, довольно простая функция; вероятно, выглядит примерно так, но мои способности vimscript очень слабы:
for cur_mark in list_of_marks
goto mark
yank current line and append to register
Кто-нибудь когда-либо писал что-либо подобное, что они могут мне указать?
Спасибо
EDIT: я опубликовал принятое решение на https://github.com/mikeage/vim-yankmarks
Ответы
Ответ 1
У Mikeage была отличная идея; здесь более утонченная версия его функции превратилась в команду:
":YankMarks [{marks}] [{register}]
" Yank all marked (with [a-z] / {marks} marks) lines into
" the default register / {register} (in the order of the
" marks).
function! s:YankMarks( ... )
let l:marks = 'abcdefghijklmnopqrstuvwxyz'
let l:register = '"'
if a:0 > 2
echohl ErrorMsg
echomsg 'Too many arguments'
echohl None
return
elseif a:0 == 2
let l:marks = a:1
let l:register = a:2
elseif a:0 == 1
if len(a:1) == 1
let l:register = a:1
else
let l:marks = a:1
endif
endif
let l:lines = ''
let l:yankedMarks = ''
for l:mark in split(l:marks, '\zs')
let l:lnum = line("'" . l:mark)
if l:lnum > 0
let l:yankedMarks .= l:mark
let l:lines .= getline(l:lnum) . "\n"
endif
endfor
call setreg(l:register, l:lines, 'V')
echomsg printf('Yanked %d line%s from mark%s %s',
\ len(l:yankedMarks),
\ len(l:yankedMarks) == 1 ? '' : 's',
\ len(l:yankedMarks) == 1 ? '' : 's',
\ l:yankedMarks
\) . (l:register ==# '"' ? '' : ' into register ' . l:register)
endfunction
command! -bar -nargs=* YankMarks call <SID>YankMarks(<f-args>)
Ответ 2
Как всегда, есть несколько вещей, которые более мотивируют, чем просить о помощи. Вот что я придумал; приветствуем приветствие.
function! Yankmark()
let save_cursor = getpos(".")
let n = 0
" I should really make this a parameter...
let marks_to_yank="abcdefghijklmnopqrstuvwxyz"
let nummarks = strlen(marks_to_yank)
" Clear the a register
let @a=''
while n < nummarks
let c = strpart(marks_to_yank, n, 1)
" Is the mark defined
if getpos("'".c)[2] != 0
" using g' instead of ' doesn't mess with the jumplist
exec "normal g'".c
normal "Ayy
endif
let n = n + 1
endwhile
call setpos('.', save_cursor)
endfunction
Ответ 3
Другим способом выполнения этого может быть команда :global
. Глобальная команда принимает форму :g/{pattern}/{cmd}
. Команда {cmd}
будет выполнена во всех строках, соответствующих {pattern}
.
Добавить строки, соответствующие шаблону, в регистр:
:g/pattern/yank A
Добавить соответствующую строку в файл журнала:
:g/pattern/w >> file.log
Конечно, если вы хотите найти строку, соответствующую знаку, вы можете сопоставить его в своем шаблоне. Следующий шаблон соответствует строке с меткой m
.
:g/\%'m/w >> file.log
Чтобы сделать что-то подобное. (Примечание: я использую \v
, чтобы включить очень магию)
:g/\v(%'a|%'b|%'m)/yank A
Конечно, если шаблон не будет работать, вы можете сделать это вручную. Вместо того, чтобы маркировать линии, просто создавайте линии, когда идете. Просто добавьте строку в регистр верхнего регистра, чтобы добавить.
"Ayy
Или добавьте запись с диапазоном одной строки
:.w >> file.log
Подробнее см.
:h :g
:h :w_a
:h /\%'m
:h /\v
Ответ 4
Вы можете сделать что-то вроде:
:redir @a
:silent marks XYZN
:redir END
"ap
Таким образом, вывод команды :marks
будет перенаправлен в регистр a
. Обратите внимание, что он будет перечислять только (в приведенном выше случае) отметки X
, Y
, Z
и N
(в качестве аргументов), и если бы существовал регистр a
, он будет удален/перезаписаны.
Также обратите внимание, что он может не дать желаемый результат, но дает вам отправную точку...
Ответ 5
Если вы используете имя регистра верхнего регистра, когда янки в определенный регистр, Vim добавит yanked-содержимое вместо перезаписывания значения регистра.
Итак, например:
-
" a y y - текущая текущая строка для регистрации a
, перезапись
-
[движение]
-
" A y y - добавьте эту строку для регистрации a
-
[движение]
-
" a p - вставить весь выдернутый материал
Подробнее см. :help quotea
.
Ответ 6
Мне нравится решение от Mikeage, хотя я бы, вероятно, решил это с помощью multiselect - создать несколько вариантов и управлять плагином. Это также имеет то преимущество, что у вас не закончились отметки.
С помощью плагина вы можете выбрать строки с <Leader>msa
или :MSAdd
. Наконец, yank все строки с:
:let @a=''
:MSExecCmd yank A