21

Same question as this, however the solution there didn't work.

I set these variables in my ~/.vimrc:

set shellcmdflag=-ic
set shell=/bin/bash\ -i

and I have an alias in my ~/.bash_aliases:

rgr() { if [ ! -z "$2" ]; then grep -rI --exclude=\*.svn\* "$1" * --include=$2 ; else grep -rI --exclude=*svn* "$1" * ; fi ; }

which works when executed from the command line, but when I try to call it from Vim with :!rgr test, I get an error message and Vim exits:

bash: rgr: command not found

[4]+  Stopped                 vi ~/somefile

If I disable the interactive mode, I just get the "command not found" message and Vim doesn't exit.

How can I get Vim to recognize my aliases? I've reproduced this behavior on both OS X and Ubuntu.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
ashgromnies
  • 3,266
  • 4
  • 27
  • 43
  • 3
    Worth noting that `rtr` is a function, not an alias. – richo Jan 13 '12 at 01:46
  • When you put `set shell=/bin/bash\ -i` into your `~/.vimrc` and open `vim`, does it keep? (`:set shell` will show you what shell you're using). It looks like you're invoking it with `vi` (or is it a real `vi`?), perhaps you need to use `~/.virc` instead. – Kevin Jan 20 '12 at 19:26
  • Kevin: It does print out "/bin/bash -i" when I do :set shell, but as soon as I try running my function: bash: rgr: command not found [2]+ Stopped vim -u ~/.vimrc – ashgromnies Jan 20 '12 at 22:08
  • Strictly speaking, vim isn't exiting, it's just being sent to the background (that's the source of the "[4]+ Stopped..." line). Typing 'fg' will return you to vim. – chepner Jan 22 '12 at 23:39
  • @ashgromnies, have you tried my solution yet? please see: http://stackoverflow.com/a/9014154/1040358 – kikuchiyo Jan 27 '12 at 12:42

4 Answers4

36

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
  • 3,570
  • 3
  • 36
  • 49
  • 2
    For anyone else out there on a Mac, this solution worked for Mac OS X 10.9 Mavericks. Good job! – EmpathicSage Nov 06 '13 at 17:34
  • 2
    Works for OS/X Yosemite as well. This was the 30th attempt to fix this problem. It is amazing how many wrong answers there are out there. One after the other until this one. The only thing I would add is that you only need to put the "shopt -s expand_aliases" in your .bashrc/.bash_profile before any aliases. – Eric apRhys May 07 '15 at 22:06
  • 1
    By far, the _bashiest_ answer of them all :) – el.atomo Jun 03 '15 at 22:46
  • @EricapRhys - just because an answer didn't work for your case does, but did answer the op, does not make it 'wrong'; – kikuchiyo Sep 14 '17 at 21:37
23

Try adding this line to your ~/.vimrc:

set shell=/bin/bash\ -i

Then vim will use an interactive shell (-i) which reads from ~/.bashrc, by default. See :h shell for more information on shell.


I see this is essentially the same as the previous answers that you say don't work. Please try the sample session below on your machine to see if you have similar results ( and post any errors / divergences from the output you see in the sample ).

$ cat .bash_aliases 
alias test_alias="echo test alias"
test_func () {
        echo test func
}
$ vim 
[vim]:set shell=/bin/bash
[vim]:!type test_alias
/bin/bash: line 0: type: test_alias: not found

shell returned 1

Press ENTER or type command to continue
[vim]:!type test_func
/bin/bash: line 0: type: test_func: not found

shell returned 1

Press ENTER or type command to continue
[vim]:set shell=/bin/bash\ -i
[vim]:!type test_alias
test_alias is aliased to `echo test alias'

Press ENTER or type command to continue
[vim]:!type test_func
test_func is a function
test_func () 
{ 
    echo test func
}

Press ENTER or type command to continue

As for why it wasn't working to begin with, when bash is simply run (i.e. neither interactive nor login; default for vim and most other purposes), it reads whatever file is specified in $BASH_ENV:

   When bash is started non-interactively, to  run  a  shell  script,  for
   example, it looks for the variable BASH_ENV in the environment, expands
   its value if it appears there, and uses the expanded value as the  name
   of  a  file to read and execute.  Bash behaves as if the following com‐
   mand were executed:
          if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
   but the value of the PATH variable is not used to search for  the  file
   name.

By adding the -i, we make the shell interactive and it therefore it reads ~/.bashrc:

   When an interactive shell that is not a login shell  is  started,  bash
   reads  and  executes  commands  from /etc/bash.bashrc and ~/.bashrc, if
   these files exist.  This may be inhibited by using the  --norc  option.
   The  --rcfile  file option will force bash to read and execute commands
   from file instead of /etc/bash.bashrc and ~/.bashrc.

The *profile files are read when starting a login shell:

   When  bash is invoked as an interactive login shell, or as a non-inter‐
   active shell with the --login option, it first reads and executes  com‐
   mands  from  the file /etc/profile, if that file exists.  After reading
   that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile,
   in  that order, and reads and executes commands from the first one that
   exists and is readable.  The --noprofile option may be  used  when  the
   shell is started to inhibit this behavior.
kikuchiyo
  • 3,391
  • 3
  • 23
  • 29
Kevin
  • 53,822
  • 15
  • 101
  • 132
11

I got this to work, via the man page for bash:

set shell=/bin/bash\ --rcfile\ ~/.bash_profile

Similarly, --init-file works.

Note that \ -i is not necessary, though it can be added to the command:

set shell=/bin/bash\ --rcfile\ ~/.bash_profile\ -i

Example:

~/.bash_profile contains

  source ~/.bash_aliases

~/.bash_aliases contains

  alias rdc="open -a \"Remote Desktop Connection\""

~/.vimrc contains

  set shell=/bin/bash\ --rcfile\ ~/.bash_profile
  map ,r :!rdc &<cr>
kikuchiyo
  • 3,391
  • 3
  • 23
  • 29
  • 1
    @ashgromnies, does this work for you? If so, and the others do not, can I have the bounty? Thanks :) – kikuchiyo Jan 27 '12 at 05:58
  • 1
    It does not work for me. The `-i` does, but I have to type `fg` at the end to return to vim. – cdunn2001 Oct 27 '12 at 18:22
  • Hi @cdunn2001 , what os are you using? I can try to simulate and come up with fix possibly if you are still having issues. – kikuchiyo Oct 27 '12 at 18:50
  • This causes the vim job to immediately stop as soon as it starts. Then when I move it to the foreground it quits my vim session and exits out of my terminal. – Rob Mosher Aug 16 '18 at 12:02
  • Hi @RobMosher, I'm sorry this solution did not work for you. Perhaps you'll have more luck with one of the more popular solutions below. Just to clarify, by including the line `set shell=/bin/bash\ --rcfile\ ~/.bash_profile` vim stops? Without any error messages? Does bash_profile exist? What is your OS? You should at the very least get an error message. Perhaps things have changed a lot since 2012 when the answer was provided. I'll test later and if I can reproduce, I'll remove the answer. Thanks. – kikuchiyo Aug 16 '18 at 17:11
0

I have this in my ~/.vimrc:

set shell=bash\ -i

All the custom functions:

mkcd () {
  mkdir -p "$*"
  cd "$*"
}

and aliases:

alias lsvn='svn list -vR'

work when used from Vim.

But I don't use ~/.bash_aliases, I've added them directly to my ~/.bashrc.

Do you source ~/.bash_aliases from ~/.bashrc?

romainl
  • 186,200
  • 21
  • 280
  • 313
  • Yup. if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi – ashgromnies Jan 13 '12 at 20:05
  • 1
    That can work for some, but since I run a script (which I do not own) that takes over the terminal, when it finishes, vim is suspended. I then have to type `fg` to get back into vim. Not ideal. If I need an interactive shell, it seems simpler to let vim save state, exit, run a command, and restart vim. – cdunn2001 Oct 27 '12 at 18:07
  • 2
    `` then `fg` is very useful. – romainl Oct 27 '12 at 18:31