115

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?

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
Nick Vanderbilt
  • 36,724
  • 29
  • 83
  • 106
  • If the aliases were in the .gitconfig, then you wouldn't need to repeat them in your Bash aliases, and everything that uses git would know them, rather than just Bash. So, DRY is admirable, but there's also SPOT (Single Point Of Truth), and getting your SPOT in the right place means it is easier to be DRY too. – Jonathan Leffler May 29 '11 at 14:34
  • see: http://stackoverflow.com/a/9014154/1040358 – kikuchiyo Jan 28 '12 at 17:09
  • Possible cross site duplicate of: http://superuser.com/questions/47821/vim-ignores-aliases – Ciro Santilli OurBigBook.com Apr 09 '14 at 21:35

5 Answers5

126

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/.

ib.
  • 27,830
  • 11
  • 80
  • 100
Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • Is there a way I can tell vim to execute that command when vim starts. thanks – Nick Vanderbilt Jan 10 '11 at 17:02
  • 7
    edit your .vimrc file (vim ~/.vimrc) and put that in a line there (without the :) – skeept Jan 10 '11 at 17:25
  • 1
    wow I should have tried that first. Looks like time to read a book on vim. thanks. – Nick Vanderbilt Jan 11 '11 at 16:21
  • 1
    My vim didn't recognize this flag, and some searching pointed me to `shellcmdflag` so if the above answer doesn't work try using `shellcmdflag` instead of `shellcommandflag` – Khaja Minhajuddin May 29 '11 at 04:08
  • I get the same results as Khaja. My vim only recognizes `shellcmdflag`. – zachwill May 29 '11 at 07:36
  • 10
    This is good but I'm having problems -- if I enable interactive mode(the i flag), then I can execute my aliased shell commands fine, but as soon as commands are done executing, vim exits which is undesirable. Ex, I tried doing :!ls with shellcmdflag=-ic: [4]+ Stopped vi ~/.vimrc – ashgromnies Jan 08 '12 at 08:18
  • 2
    @ashgromnies That `[4]+ Stopped` means it was paused, use `fg` to run it in the foreground. – Kevin Jan 22 '12 at 03:35
  • 6
    @Kevin: there is no way to get the normal behavior of viw with the interactive bash ? (execute the command, wait for any key, come back to vim) – Mayeu Oct 24 '12 at 13:21
  • 8
    For me, having the command in .vimrc leads to ```suspended (tty output)``` When i use ```git commit``` – has2k1 Aug 13 '13 at 02:36
  • 2
    @ashgromnies still better, run the command as :! COMMAND && fg – user13107 Sep 13 '13 at 12:24
  • 32
    Telling Vim to always use an interactive shell can create problems. A better solution is to figure out what in your bash configuration sets up aliases and how you can move that to a place that is loaded even in non-interactive shells. For example, zshell only loads `~/.zshrc` for interactive shells, but it loads `~/.zshenv` for all shells, so I moved my alias setup there and it now works from within Vim. See `man zsh` (or your shell's man pages) for more. – Nathan Long Feb 08 '14 at 22:52
  • Even with this solution, my aliases are still not not recognized. It still says command not found. – still_dreaming_1 Apr 15 '15 at 23:19
  • 2
    This only worked for me in conjunction with `:set shell=bash\ --login` – cdosborn Jun 05 '17 at 18:34
  • 1
    This crashed vim 7.0 in High Sierra, when invoking shell commands in command mode. – Niloct Dec 08 '18 at 03:27
  • 1
    "Telling Vim to always use an interactive shell can create problems" Any example? Putting alias to .zshenv seems dangerous for me , because I have something like `alias ed=nvim -d` (I have over writed many command with alias) – Good Pen May 03 '22 at 12:09
  • @NathanLong: loading interactive-only commands on _all_ shells (both non-interactive and interactive) is equally, if not more, worse. – nishanthshanmugham Feb 12 '23 at 13:29
95

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?

Community
  • 1
  • 1
EmpathicSage
  • 1,265
  • 8
  • 11
  • 7
    The best solution by far. Personally, I set the `$BASH_ENV` var in my `.bashrc` (before any custom interactive mode check), so I can use all my aliases accross applications. – el.atomo Jun 03 '15 at 22:32
  • 2
    This is probably the best solution on this page because the scope of changes would be limited to within Vim. One could even go further and `let $BASH_ENV="~/.vim/vim_bash"`, and this would get used for all `:!` invocations within Vim. – Teeeeeeeeeeeeeeeeeeeeeeeeeeeej Dec 15 '15 at 17:11
  • 1
    This does not work in the macOS 10.15.2 default shell, zsh, unfortunately. – Ben Quigley Feb 24 '20 at 15:52
14

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.

Damian Borowski
  • 171
  • 1
  • 5
  • 2
    Thank you for this! Just wanted to note that if you have your shell aliases in a file that you can just source them in .zshenv. Something like: `. $HOME/.aliases` – scifisamurai Jul 31 '20 at 15:37
8

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.

user836003
  • 421
  • 6
  • 10
  • 4
    dreftymac wrote: "In order to get this to work for me, it was necessary to do -lic option, otherwise vim returned 'command not found'" – dreftymac Sep 26 '12 at 20:12
2

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"

pfnuesel
  • 14,093
  • 14
  • 58
  • 71