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