Search code examples
svntortoisesvnvim

How to define a command to commit the n-th parent directory of the current one in Vim?


I have this shortcut in my .vimrc file:

map cmt :!start TortoiseProc.exe /command:commit /path:"%" /closeonend:3 <CR>

What this does is whenever I type cmt, Vim opens the commit dialog for the file I'm currently editing with Vim.

What I'd like to do is to write this command in such a way that if I put a number in front of it, it will open the commit dialog for the n-th level directory.

To give an example, let's say that I'm editing the project/logs/access.log file. Then,

  • cmt should bring the dialog for committing access.log;
  • 1cmt should bring the dialog for committing the logs directory;
  • 2cmt should bring the dialog for committing the project directory; and so on.

Note: I'm using gVim on Windows 7.


Solution

  • I have implemented the desired functionality in the following function.

    function! TortoiseCommitDialog(path, count)
        let pat = '[/\\]\@<=\%([^/\\]\+[/\\]\?\)\{' . a:count . '}$'
        let path = substitute(a:path, pat, '', '')
        let cmd = 'TortoiseProc.exe /command:commit ' .
        \   '/path:' . shellescape(path) . ' /closeonend:3'
        let out = system(cmd)
        if v:shell_error
            echoerr 'Failed to run Tortoise commit dialog'
            echo out
        end
    endfunction
    

    It takes two arguments: a path to the file to start from and a number of levels to go up. Then it cuts the specified number of tailing path components and builds the command to run (according to your example). Then it runs the command and checks its exit code returned by the shell after execution. If an error is occurred, an error message is shown followed by the output of the command.

    To use this function during editing, I recommend to define a command (because, unlike a mapping, it can take arguments):

    command! -count Cmt call TortoiseCommitDialog(expand('%:p'), <count>)
    

    Because of the -count flag you can run the command with a count in two ways: both :3Cmt and :Cmt 3 (or even :Cmt3) have the same effect.