Nick Vanderbilt
Nick Vanderbilt

Reputation: 38540

How to make .bashrc aliases available within a vim shell command? (:!...)

I use bash on mac and one of the aliases is like this

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

However when I do

 :! gitlog

I get

/bin/bash: gitlog: command not found 

I know I can add aliases like this in my .gitconfig

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

However I don't want to add all my bash aliases to .gitconfig. That is not DRY.

Is there a better solution?

Upvotes: 119

Views: 27677

Answers (6)

Thomas Guyot-Sionnest
Thomas Guyot-Sionnest

Reputation: 2520

It's possible to use shell aliases without using an interactive shell, which avoid the issues that comes with it (without looking into what happens exactly, when I run a command with the -i flag vim ends up backgrounded after the command and I have to bring it back with fg, making it a very odd workflow).

This assumes bash as your shell, other shells likely have different syntax.

In your ~/.vimrc add the following line to enable aliases expansions and read login shell scripts:

set shellcmdflag=-O\ expand_aliases\ -lc

Make sure your .bash_profile sources .bashrc or your aliases, as we're using a login shell to force bash to read rc scripts despites being non-interactive, and login shells read .bash_profile by default.

In my most complex shell setups I also skip most of .bashrc initialisation for non-interactive shell, so I had to also detect when invoked by vim. This could be used to load specific aliases for vim too.

In my .bashrc this line skips the rest of the script except if interactive or - 2nd condition I added - invoked by vim:

# Early bail-out on non-interactive shell (except vim subshell)
[ "$-" != "${-/i}" ] || [[ $(ps -o comm= $PPID) = *vim* ]] || return

if [ -f ~/.bash_aliases ]; then
  . ~/.bash_aliases
fi

NB: I made it match any process containing vim so it also matches gvim, vimdiff, etc...

Upvotes: 0

Josh Lee
Josh Lee

Reputation: 177895

Bash doesn’t load your .bashrc unless it’s interactive.

Run :set shellcmdflag=-ic to set it to interactive for the current session.

To make the setting permanent, add set set shellcmdflag=-ic to the end of your .vimrc file.

Use a bang (!) before sending a command to shell. For example: :! cd folder/.

Upvotes: 128

Damian Borowski
Damian Borowski

Reputation: 171

I know it may be an old question, however none of the above answers worked for me as desired. So for the ones who came here from googling and for (oh-my-)zsh users:

My solution to this was as simply as copying .zshrc to .zshenv - as per http://zsh.sourceforge.net/Intro/intro_3.html:

`.zshenv' is sourced on all invocations of the shell, unless the -f option is set. It should contain commands to set the command search path, plus other important environment variables. `.zshenv' should not contain commands that produce output or assume the shell is attached to a tty.

So $ cp ~/.zshrc ~/.zshenv will do the thing.

Upvotes: 14

EmpathicSage
EmpathicSage

Reputation: 1323

I know this question was already previously "answered", but I have a problem with the answer. The shell doesn't need to be set to interactive in Vim. See this thread for an alternative answer without having to exit an interactive 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"

This solution was suggested by "Jakob". See the link below for the original. I tested this on Mac OS X 10.9 and it worked flawlessly!

vim -- not recognizing aliases when in interactive mode?

Upvotes: 101

pfnuesel
pfnuesel

Reputation: 15360

I don't feel too comfortable with setting the -i option, as it has quite some impact and I am using the shell often from vim. What I'd do instead is something like :!bash -c ". ~/.alias; gitlog"

Upvotes: 2

user836003
user836003

Reputation: 421

Note that depending on how your bash dotfiles are configured you may want to use the -l rather than the -i option. This will launch the shell as login shell.

Upvotes: 8

Related Questions