如何使.bashrc中的别名在Vim shell命令(:!...)中可用?

115

我在Mac上使用bash,其中一个别名是这样的:

alias gitlog='git --no-pager  log -n 20 --pretty=format:%h%x09%an%x09%ad%x09%s --date=short --no-merges'

但是当我这样做时

 :! gitlog

我得到

/bin/bash: gitlog: command not found 

我知道可以像这样在 .gitconfig 文件中添加别名:

[alias]
    co = checkout
    st = status
    ci = commit
    br = branch
    df = diff

然而,我不想将所有的Bash别名添加到.gitconfig文件中。这样做是不符合DRY原则的。

有更好的解决方案吗?


如果别名在.gitconfig中,那么你就不需要在Bash别名中重复它们,使用git的所有内容都会知道它们,而不仅仅是Bash。因此,DRY(Don't Repeat Yourself)是令人钦佩的,但还有SPOT(Single Point Of Truth),将你的SPOT放在正确的位置意味着更容易实现DRY。 - Jonathan Leffler
请参见:https://dev59.com/aWox5IYBdhLWcg3w_ZR0#9014154 - kikuchiyo
可能是跨站点重复问题: http://superuser.com/questions/47821/vim-ignores-aliases - Ciro Santilli OurBigBook.com
5个回答

126

Bash在非交互式的情况下不会加载你的.bashrc文件。

运行:set shellcmdflag=-ic将其设置为当前会话的交互式模式。

要使设置永久生效,请在你的.vimrc文件末尾添加命令set shellcmdflag=-ic

在发送命令到shell之前加一个感叹号 (!)。例如::! cd folder/


7
编辑您的 .vimrc 文件(vim ~/.vimrc),并将其放在那里的一行中(不要包括冒号)。 - skeept
10
这个很好,但我遇到了问题 - 如果我启用交互模式(i标志),那么我可以成功地执行我的别名shell命令,但是一旦命令执行完毕,vim就会退出,这是不希望发生的。例如,我尝试使用 shellcmdflag = -ic: :!ls [4]+ Stopped vi ~/.vimrc。 - ashgromnies
6
@Kevin:在交互式 Bash 中没有办法获得 viw 的正常行为吗?(执行命令,等待任何键,返回到 vim) - Mayeu
8
当我在.vimrc中使用命令时,会出现suspended (tty output)的提示,这会影响到我使用git commit命令。 - has2k1
32
告诉 Vim 总是使用交互式 shell 可能会产生问题。更好的解决方案是找出你的 bash 配置中设置别名的部分,并将其移动到即使在非交互式 shell 中也加载的位置。例如,zshell 仅为交互式 shell 加载 ~/.zshrc,但它为所有 shell 加载 ~/.zshenv,因此我将我的别名设置移到那里,现在可以在 Vim 中使用它了。有关更多信息,请参阅 man zsh(或您所使用 shell 的 man 手册)。 - Nathan Long
显示剩余11条评论

95

我知道这个问题已经被 "回答"过了,但是我对答案有些疑问。在Vim中,shell 不需要被设置为交互式的。请查看此线程以获得另一种不需要退出交互式 shell 的替代方案。

If you want non-interactive shell (as default) but expansion of bash aliases, put your alias definitions in a file, e.g. .bash_aliases and explicitly enable alias expansion in this file:

shopt -s expand_aliases  
alias la='ls -la'

Then add this to your .vimrc so the aliases file is actually read each time you run a shell command from within vim:

let $BASH_ENV = "~/.bash_aliases"

这个解决方案是由"Jakob"提出的。请参见下面的链接获取原始内容。我在Mac OS X 10.9上测试过,它完美地工作了!

vim -- not recognizing aliases when in interactive mode?


7
迄今为止最好的解决方案。个人而言,我在.bashrc文件中设置了$BASH_ENV变量(在任何自定义交互模式检查之前),这样我就可以在各种应用程序中使用所有我的别名。 - el.atomo
2
这可能是此页面上最佳的解决方案,因为更改的范围将仅限于 Vim 内部。甚至可以进一步执行 let $BASH_ENV="~/.vim/vim_bash",这将用于 Vim 中所有的 :! 调用。 - Teeeeeeeeeeeeeeeeeeeeeeeeeeeej
1
这在 macOS 10.15.2 的默认 shell,即 zsh 中不起作用。很遗憾。 - Ben Quigley

14

我知道这可能是一个老问题,但以上回答都不能满足我的需求。因此,对于那些通过Google来到这里且使用 (oh-my-)zsh 的用户:

我的解决方案就是简单地将 .zshrc 复制到 .zshenv 上 - 根据 http://zsh.sourceforge.net/Intro/intro_3.html:

`.zshenv' 在shell的所有调用中都会被调用,除非设置了-f选项。它应该包含设置命令搜索路径和其他重要环境变量的命令。 `.zshenv' 不应包含产生输出或假定shell连接到tty的命令。

所以运行$ cp ~/.zshrc ~/.zshenv即可。


2
谢谢您!只想注意一下,如果您的shell别名存储在一个文件中,那么您可以在.zshenv中直接源化它们。就像这样:. $HOME/.aliases - scifisamurai

8
请注意,根据您的bash dotfiles配置方式,您可能需要使用-l选项而不是-i选项。这将作为登录Shell启动Shell。

4
为了让这对我起作用,必须使用-lic选项,否则vim会返回“未找到命令”的错误信息。 - dreftymac

2

我不太喜欢使用-i选项,因为它会对系统产生很大影响,而且我经常在vim中使用shell。相反,我会使用以下命令:!bash -c“.〜/ .alias; gitlog”


这似乎是最好的解决方案,但对我不起作用。它仍然显示命令未找到。 - still_dreaming_1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接