11

Sometimes I use marks to navigate easily through different files using mA, mB... and 'A, 'B...

And sometime (more often than I'd like to admit) because of inattention or whatever the reason is, I use m[LETTER] with an already existing mark which erase its previous value when I don't want to. Most of the time when I do that I don't have open the file originally pointed by the mark.

In this case when I immedialy realized that I made a mistake, is it possible to get the previous value of my mark other than remembering where it was pointing to, navigating to this location and setting it again?

I haven't found a command like that in the doc so if that doesn't exist is there a clever workaround that some of you use in this situation?

3
  • 1
    Also you could look at this post for further informations : superuser.com/questions/687441/…
    – nobe4
    Commented Jul 24, 2015 at 9:43
  • @Nobe4 thanks for your link I hadn't found it but it seems to confirm that it isn't really possible to do that easily.
    – statox
    Commented Jul 24, 2015 at 9:50
  • Use the jump commands (ctrl-o, ctrl-i and :jumps) with your own personal memory :)
    – VanLaser
    Commented Jul 24, 2015 at 11:45

3 Answers 3

7

Here is some basic VimScript which roughly does what you want.

We override the ma through mz mappings to store the current value in g:previous_marks before calling the original m to actually set the mark. We also define <Leader>ma through <Leader>mz to show the history for said mark.

You will probably want to store the info in g:previous_marks in a more organized way, and add the ability to quickly restore a mark (rather than just seeing the locations), but this example shows how it can be done, further tweaks are left as an exercise to the reader ;-)

let g:previous_marks = {}
fun! MyMark(mark)
    let l:marks = ''
    redir => l:marks
        try
            silent! execute 'marks ' . a:mark
        catch
        endtry
    redir END

    if l:marks != ''
        if !has_key(g:previous_marks, a:mark)
            let g:previous_marks[a:mark] = []
        endif
        call add(g:previous_marks[a:mark], split(l:marks, "\n")[1])
    endif

    execute 'normal! m' . a:mark
endfun

fun! ShowHistory(mark)
    if !has_key(g:previous_marks, a:mark)
        echoerr 'No history for ' . a:mark
        return
    endif

    for l:line in g:previous_marks[a:mark]
        echo l:line
    endfor
endfun

fun! MakeMappings()
    for l:char in range(97, 122)
        let l:char = nr2char(l:char)

        execute 'nnoremap <silent> m' . l:char . ' :call MyMark("' . l:char . '")<CR>'
        execute 'nnoremap <silent> <Leader>m' . l:char . ' :call ShowHistory("' . l:char . '")<CR>'
    endfor
endfun

call MakeMappings()
1
  • Wow as usual amazing answer! I'll try take time this weekend to implement the exercice for the reader ;)
    – statox
    Commented Jul 24, 2015 at 11:53
2

Not exactly what you want, but perhaps more useful: the signature plugin. It shows the current marks as signs in the gutter margin, and has simple shortcuts for editing them. It can also put the list of signs in a location list for quick access.

3
  • I'm not a great fan of the visible mark on the margin but it seems to have some interesting features I'll take a look at it.
    – statox
    Commented Jul 24, 2015 at 11:55
  • @statox In the same vein, there's also showmarks. It shows literally all marks (the plugin above only deals with alphabetic ones), and can be toggled with a key. I find it useful occasionally. Commented Jul 24, 2015 at 12:09
  • Yes I've been using showmarks for a few time (unlike signature) that's why I said I'm not a fan of marks in the margin but I'm trying signature right now to see if I like it :-)
    – statox
    Commented Jul 24, 2015 at 12:14
2

Since the actual problem seems to be navigation between multiple files/positions, I'd suggest this simple solution, which is based on the Unite plugin:

:Unite jump -auto-preview

This command (which can be mapped to something like <leader>j for example) will show the jump list, with a preview: each time you navigate the list with j/k, several lines around the cursor position in that file will be displayed.

enter image description here


Alternative:

The default marks are so easy to be overwritten: perhaps named bookmarks would better fit your use case, e.g. with the simple_bookmarks plugin.

3
  • I can't really say that the problem is this type of navigation because I use those marks really occasionnaly and most of the time I navigate differently through my files. Nevertheless I've been thinking for a long time that I should use the jump list more often so that seems like a nice way to do it!
    – statox
    Commented Jul 24, 2015 at 12:00
  • Even if they can be saved between vim sessions, it's too easy to overwrite marks. I added an alternative solution.
    – VanLaser
    Commented Jul 24, 2015 at 12:46
  • Indeed your alternative solution seems to be worth a try thanks a lot!
    – statox
    Commented Jul 24, 2015 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.