如何在VIm和终端中始终拥有相同的当前目录?

时间:2012-09-02 21:40:26

标签: unix vim vim-plugin

我想我的终端当前目录跟随我的VIM。

示例:

在TERMINAL:

> pwd
=> /Users/rege
> vim

然后在VIM

:cd /Users/rege/project
<Ctrl-z>(for suspend)

在终端

> pwd
=> /Users/rege/project

我正在使用MacOS,zsh,tmux。

我需要这个,因为当我试图在VIM中使用标签时,标签是从我的终端目录检查项目而不是vim。

所以当我更改VIM当前目录时,我总是需要更改终端当前目录。

4 个答案:

答案 0 :(得分:2)

在bash或zsh和Unix上你可以这样做:进程的当前工作目录在/proc/{PID}/cwd中表示为真实目录的符号链接。说到zsh,下面的代码将完成这项工作:

function precmd()
{
    emulate -L zsh
    (( $#jobstates == 1 )) || return
    local -i PID=${${${(s.:.)${(v)jobstates[1]}}[3]}%\=*}
    cd $(readlink /proc/$PID/cwd)
}

。注意:使用此代码,您将无法在终端中逐个地切换目录,仅在vim中或在一个命令的持续时间内(使用cd other-dir && some command)。

注2:我不知道如何在bash中表达这一点。直接的方法是获取shell的所有子节点的PID(使用ps --ppid $$ -o CMD),过滤掉ps进程(它也将显示为子进程),检查是否只有一个其他子进程在上面的最后一行中使用它并使用它的PID。但我很确定有一种更好的方法可以像使用zsh的$jobstates关联数组一样使用一些shell内置函数。我也不记得bash中precmd的类似物。


另一个想法是当你执行<C-z>并让shell在precmd中读取它时,让vim将当前目录保存到某个文件中:

" In .vimrc:
function s:CtrlZ()
    call writefile([fnamemodify('.', ':p')], $CWDFILE, 'b')
    return "\<C-z>"
endfunction
nnoremap <expr> <C-z> <SID>CtrlZ()

# In .zshrc
function vim()
{
    local -x CWDFILE=~/.workdirs/$$
    test -d $CWDFILE:h || mkdir $CWDFILE:h
    vim $@
}
function precmd()
{
    local CWDFILE=~/.workdirs/$$
    test -e $CWDFILE && cd "$(cat $CWDFILE)"
}

。将代码移植到bash上应该更容易。

答案 1 :(得分:2)

暂停Vim后,你在shell中发出什么样的命令? Vim的:!command不够吗?

使用set autochdir时,当您从一个文件跳转到另一个文件时,Vim的当前目录会跟随您。使用此设置,简单的:!ctags -R .将始终在当前文件的目录中创建tags文件。

另一个有用的设置是set tags=./tags,tags;$HOME,它告诉Vim在当前文件的目录中查找tags文件,然后在“当前目录”中向上和向上查找,直到它到达{{1} 1}}。您可以修改端点以满足您的需要。这允许您在编辑属于项目的任何文件时在项目的根目录中使用~/

所以,基本上,你可以在不离开Vim的情况下走很长的路。

如果您真的需要返回shell发出命令,tags(或:shell)会启动一个包含Vim当前目录的新shell。完成后,您只需要:sh返回Vim:

$ exit

答案 2 :(得分:0)

你可以像这样打开一个新终端

:!xterm -e bash -c "cd %:p:h;bash" &

实际上我在.vimrc中写了这个

nmap <F3> :!xterm -e bash -c "cd %:p:h;bash" &<CR> | :redraw!

答案 3 :(得分:0)

对于来自的bash用户:

Vim:pwd保存在<c-z>mapgetpwd())。
Bash:在提示命令之前,转到vim用PROMPT_COMMAND指示的目录。

<强>的.bashrc

PROMPT_COMMAND='read -r line 2>/dev/null </tmp/cd_vim'\
'&& > /tmp/cd_vim && cd ${line##\r};'$PROMPT_COMMAND

<强>的vimrc

function! s:CtrlZ() call writefile([getcwd(),''], '/tmp/cd_vim', 'b')
    return "\<C-z>"
endfunction
nnoremap <expr> <C-z> <SID>CtrlZ()

这是针对bash Server-Side Encryption编辑的ZyX答案