Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yanking all marked lines in vim

Tags:

vim

Often times when reviewing log files in vim, I'll highlight interesting lines using marks. At some point, I'd like to be able to copy all of the interesting lines (either all marked lines, or a list of marks) to either a register or another file (it doesn't really matter which; the goal is to facilitate writing a summary). I haven't been able to find any built in way to do this; is it possible in vim?

I suppose it's probably a fairly straightforward function; probably looking something like this, but my vimscript abilities are very weak:

for cur_mark in list_of_marks
    goto mark
    yank current line and append to register

Has anyone ever written anything similar that they can point me to?

Thanks

EDIT: I posted the accepted solution at https://github.com/mikeage/vim-yankmarks

like image 338
Mikeage Avatar asked May 01 '13 07:05

Mikeage


People also ask

How do I copy a range of lines in vi editor?

Press the ESC key to be sure you are in vi Command mode. Place the cursor on the line you wish to copy. Type yy to copy the line. Move the cursor to the place you wish to insert the copied line.

How do I copy an entire text in vi editor?

You can use a movement command or up, down, right, and left arrow keys. Press y to copy, or d to cut the selection. Move the cursor to the location where you want to paste the contents. Press P to paste the contents before the cursor, or p to paste it after the cursor.

How do I copy highlighted text in vim?

Copying in Vim Copying text in Vim is also referred to as yanking. Use the y key on the keyboard when performing this operation. There are a number of yank commands, mainly differing on the amount of text you want to copy. Once in normal mode, move the cursor to the needed place and use the appropriate command.


2 Answers

As always, there are few things that are more motivating than asking for help. Here's what I came up with; feedback welcome.

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
like image 140
Mikeage Avatar answered Nov 20 '22 08:11

Mikeage


Mikeage had a great idea; here's a more refined version of his function turned into a command:

":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>)
like image 44
Ingo Karkat Avatar answered Nov 20 '22 08:11

Ingo Karkat