13

When I edit file:

/home/me/projects/myproj/src/util.c

I would like to start terminal at:

/home/me/projects/myproj/src.

With Vim version > 8 I can run :terminal but it always starts at folder in which I've opened Vim (which is /home/me/projects/myproj)

How can I do this?

4 Answers 4

15

I am grateful to @statox for useful hints, but as I don't wont to change current dir each time I come to following:

map <F6> :let $VIM_DIR=expand('%:p:h')<CR>:terminal<CR>cd $VIM_DIR<CR>
6
  • I don't quite get why this doesn't work for me; typing :echo $VIM_DIR outputs the correct directory, but the command fails :(
    – Krish
    Mar 12, 2021 at 20:33
  • 1
    @Krish How to debug a mapping might help.
    – statox
    Apr 16, 2021 at 13:53
  • 2
    @Krish try :terminal<CR>Acd $VIM_DIR<CR> in Neovim atleast, terminal opens up in normal mode, so you get into insert mode first (a/i/A/I) to type in the rest of the command Jan 20, 2022 at 3:22
  • Is there a way to do this as a command instead of as a mapping?
    – Thayne
    Oct 18, 2022 at 20:21
  • @Thayne here is what i have in my vimrc for neovim. (replace terminal with shell for vim, also don't need the A<CR> i don't think): command Cdot normal! :lcd%:h<CR>:terminal<CR>A<CR>
    – John Huynh
    Mar 2, 2023 at 23:00
10

See :h :cd and :h :lcd.

:cd changes the current directory for all the windows while :lcd changes the current directory for the current window.

You can change the current directory to the directory containing the current file with:

:cd %:p:h

And you can use set autochdir in your .vimrc to change the current working directory whenever you open a file, switch buffers, delete a buffer or open/close a window. It will change to the directory containing the file which was opened or selected. (see :h 'autochdir')

Also note that the doc mentions that autochdir may break some plugin and this wikia page suggests the following autocommand to replace this setting:

autocmd BufEnter * silent! lcd %:p:h
4
  • 1
    Note that when a local directory is in use for the current window, it's best to avoid :cd. When exists('*haslocaldir') && haslocaldir() is true, always use :lcd. Otherwise, we have the choice. Dec 13, 2017 at 13:29
  • 2
    Put it all together: split | lcd %:h | terminal ++curwin. May want to wrap this up into a command. e.g. command! -nargs=* Terminal split | lcd %:h | terminal ++curwin <args> Dec 13, 2017 at 16:03
  • @PeterRincker With the ++curwin option to `terminal, it seems to be passing the "++curwin" as an argument to my shell rathe rthan opening the terminal in the current window
    – Thayne
    Oct 18, 2022 at 20:34
  • According to :h :term: ++curwin is a valid option. Is it possible you are using an older version of Vim or maybe Neovim? Oct 19, 2022 at 20:30
3

Building on the other answers, in neovim, you can do:

command! LocalTerm let s:term_dir=expand('%:p:h') | below new | call termopen([&shell], {'cwd': s:term_dir })

(this assumes that your shell is a single command with no options)

3
  • this is neovim only Oct 19, 2022 at 7:04
  • very helpful. I`m using project.nvim and just this answer worked for me. Jan 17 at 9:09
  • I add |:startinsert to last for going to insert mode, how can I use <UP> arrow for getting the last termianl command? Jan 17 at 9:59
0

You can use a Vim keymap with a single function. In my case, the leader is a space.

Short cut to open terminal Space+t.

What the Lua function does:

  1. It switches to directory of current file.
  2. Opens terminal on current file's directory.
  3. Switches to "insert" mode by itself.

The Lua function is as following:

vim.keymap.set("n", "<leader>t", function()
   vim.cmd("cd %:p:h")
   vim.cmd("terminal")
   vim.cmd("startinsert")
end)
1
  • This changes Vim's pwd, which as a side-effect is not present in other answers and might be worth highlighting as a tradeoff.
    – D. Ben Knoble
    Sep 6, 2023 at 23:21

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.