I feel my current VIM setup is pretty sweet, but there is one thing that annoys me time and time again: how can I open a file or add a file to the same directory as the current file I am editing?

If I should open NerdTree it will just list the contents of $PWD and I need to manually browse down to where I want to go. I'd like to have a workflow a bit like this:

  1. Find a file somehow (NerdTree, Ctrl-P or :e the/file/path.txt)
  2. :SwitchCWDToSameAsCurrentFile (change working directory to same as the current file)
  3. Open NerdTree or :e . and go to the current working directory
  4. Add/Open a file from the current working directory
  • 3
    Does :e %:p:h do what you want? – Christian Brabandt Nov 6 '19 at 7:00
  • Yeah, kind of does. Impossible to remember, though :) – oligofren Nov 7 '19 at 21:06
  • Well, you can map it away ;) – Christian Brabandt Nov 8 '19 at 9:56

:Ex<CR> followed by % will prompt you for a new filename in that directory, which can be a pretty smooth process.

Note that there's also set autochdir if that fits your patterns/plugins better (always change directory to match the current file).

| improve this answer | |
  • 1
    That was pretty sweet, as it didn't actually rely on any plugins or similar. The lcd mapping and commands was probably more what I was looking for though, as that went well along with the CD shortcut in NERDTree for changing tree root to CWD. autochdir unfortunately didn't play nice along with NERDTree, as it just affected the current buffer/window (not sure about the terminology), not the new NT window. Good tip, anyhow! – oligofren Nov 7 '19 at 21:04

SwitchCWDToSameAsCurrentFile (change working directory to same as the current file)

I use the following mapping:

nnoremap <Leader>= :lcd %:p:h \| pwd<CR>
| improve this answer | |

Here are my edit in same directory mappings:

" Explore
nnoremap <silent> <Leader>ed :Explore<CR>
" Quickly input the directory of the current file on the command line
cnoremap <expr> %% filename#command_dir('%%')
" Need 'recursive' mapping here for %%
nmap <Leader>ew :e %%
nmap <Leader>ev :vs %%
nmap <Leader>es :sp %%
nmap <Leader>et :tabe %%

" Get the directory of a file
" - On Ex command lines, returns the directory of the file ('./' for new files)
" - On other command lines (/,?) returns the keymap used to trigger it
function! filename#command_dir(keymap) abort
  let l:command_type = getcmdtype()
  if l:command_type isnot# ':'
    return a:keymap
  let l:dir = expand('%:h')
  if empty(l:dir)
    let l:dir = '.'
  return l:dir . '/'

You can also then do :cd %% if you really need to change directories (and 'autochdir' can make that easier, as pointed out).

Honestly, I prefer to stay at the root project level most of the time though. It makes more sense in many ways. I have tools like ack, grep, git subcommands, and others which, combined with some bash functions and the quickfix list, make it easy to jump into vim at various parts of my code base. I’ll add them here later as needed.

| improve this answer | |
  • I just got an error after putting that in my config: E746: Function name does not match script file name: filename#command_dir. – oligofren Nov 7 '19 at 21:01
  • You’ll need to place that function in the autoload directory, apologies. – D. Ben Knoble Nov 7 '19 at 22:12

Your Answer

