Alias does not take effect when I use Vim to execute external commands

49 views Asked by At

Aliases don't take effect when I use Vim to execute external commands, for example:

:! ll

I want it to support aliases like normal shells do.

2

There are 2 answers

1
romainl On BEST ANSWER

There is no such thing as a "normal shell". You have "interactive shells" and "non-interactive shells", which differ, among other things, by what *rc file they source at startup and by whether aliases are expanded or not. And there are other types, even.

By default Vim uses a non-interactive shell for :! and $ man bash as the following to say about aliases in non-interactive shells:

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS below).

Now, you could try to play with shopt or try to convince Vim to use an interactive shell with :help 'shellcmdflag' but these don't sound like solutions to me.

The only proper solution, IMO, is to turn your aliases into actual shell scripts, somewhere in your $PATH, where they will be accessible to all kinds of shells.

--- EDIT ---

FWIW, I don't like the suggestion made in :help :! because…

  • As illustrated in the other answer, it creates other problems which in turn requires solutions and so on.

  • The "shell" in which :! commands are executed is a very dumb one that is not made at all for interactive stuff (no colors, etc.).

  • I much prefer to suspend Vim and end up in a proper shell than to execute lots of commands in the bastardized :!.

    And there's even :help :terminal nowadays if that's your thing.

  • I find it a lot cleaner, portable, and scalable to create proper shell scripts in general.

That said, I still have a bunch of aliases, like everyone, but none of them is of any use in a :! context so there is no point a) adding -i to shellcmdflag or b) turning them into scripts:

alias fgrep='LC_ALL=C fgrep -nsH --color=auto'
alias flush='sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder'
alias g='git'
alias grep='LC_ALL=C grep -nsH --color=auto'
alias la='ls -alhGF --color=auto'
alias ld='ls -dlhGF --color=auto *'
alias ll='ls -lhGF --color=auto'
alias majports='sudo port selfupdate && port outdated && sudo port upgrade outdated && sudo port uninstall inactive && sudo port uninstall rleaves && sudo port clean all'
alias mgc='magento-cloud'
alias python='python2.7'
alias tigb='tig blame'
alias tigd='tig show'
alias tigg='tig grep'
alias tigl='tig log'
alias tigs='tig status'
alias up='cd ..'
alias vim='mvim -v'
alias webshare='python2.7 -c "import SimpleHTTPServer;SimpleHTTPServer.test()"'

:! is just not a good enough environment for running interactive commands.

0
Friedrich On

Contrary to what romainl writes in his answer, Vim's own :help :! suggests the following:

On Unix the command normally runs in a non-interactive shell. If you want an interactive shell to be used (to use aliases) set 'shellcmdflag' to "-ic".

That would be :set shellcmdflag=-ic.

The caveat is that your shell will not terminate after running your command but prompt you for input instead. You'll have to fg to return to Vim. I would guess that's why romainl discarded it as a solution.

FWIW, I wrote a tiny alias a while ago which will return me to Vim when I type fg regardless of whether I'm in the shell through Vim's :shell or :terminal commands or Ctrl-Z:

alias fg="[[ -v VIM ]] && exit || fg"

This will work for :! with 'shellcmdflag' set to "-ic" as well.