通常在查看vim中的日志文件时,我会使用标记突出显示有趣的行。在某些时候,我希望能够将所有有趣的行(或者所有标记的行或标记列表)复制到寄存器或其他文件中(这并不重要;目标是便于撰写摘要)。我无法找到任何内置的方法来做到这一点;是不是可能在vim?
我想这可能是一个相当简单的功能;可能看起来像这样,但我的vimscript能力非常弱:
for cur_mark in list_of_marks
goto mark
yank current line and append to register
有没有人写过他们可以指出的类似的东西?
由于
发布了已接受的解决方案答案 0 :(得分:7)
与往常一样,有些事情比寻求帮助更具激励性。这就是我想出来的;反馈欢迎。
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
答案 1 :(得分:6)
":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 :(得分:4)
实现此目的的另一种方法可能是使用: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
答案 3 :(得分:3)
您可以执行以下操作:
:redir @a
:silent marks XYZN
:redir END
"ap
这样,:marks
命令的输出将被重定向到a
寄存器。请注意,它仅列出(在上述情况下)X
,Y
,Z
和N
标记(作为参数),以及是否有{ {1}}注册,它将被删除/覆盖。
另请注意,它可能无法提供所需的输出,但会为您提供一个起点......
答案 4 :(得分:3)
我喜欢Mikeage的解决方案,不过我可能会使用multiselect - Create multiple selections and operate插件来解决这个问题。这样做的好处是你不会用完标记。
使用该插件,您可以选择<Leader>msa
或:MSAdd
行。最后,用以下方式猛拉所有行:
:let @a=''
:MSExecCmd yank A
答案 5 :(得分:2)
如果在进入特定寄存器时使用大写寄存器名称,Vim将附加被拉出的内容,而不是覆盖寄存器的值。
所以,例如:
“ a y y - 向当前行注册a
,覆盖
[移动]
“ A y y - 将此行追加至注册a
[移动]
“ a p - 粘贴所有被拽的材料
有关详细信息,请参阅:help quotea
。