8

I use vim's :! external command function all the time, usually providing % as an argument to the shell command. For example :

:!psql -f %

I also have a lot of bash shell functions in my .bashrc that I use. For example:

psql-h1 () 
{ 
    /usr/bin/psql -hh1 -d mydb "$@"
}

These bash functions aren't available from :! inside of vim. Is there a way to make them available?

2
  • Are you sure you're using bash from inside vim? Does running :!echo $0 print bash? Commented Oct 25, 2017 at 17:54
  • Two solutions: 1. :help 'shellcmdflag', 2. turn your function into actual scripts and put them somewhere in your $PATH. Commented Oct 25, 2017 at 18:01

4 Answers 4

8

Export your functions. That is:

psql-h1() { /usr/bin/psql -hh1 -d mydb "$@"; }

export -f psql-h1  ### <-- THIS RIGHT HERE

This will make them available to any copy of bash run as a child process, even if it's a noninteractive shell and so doesn't read .bashrc.

Sign up to request clarification or add additional context in comments.

2 Comments

bingo. this right here. I knew you exported ENV variables to child processes. Had no idea about bash functions.
It's basically the same thing -- an exported function is just an exported variable with an unusual name and the function's code as a value; bash scans the environment for any names matching the convention and parses them as code. Double-edged sword, that feature -- it's what was responsible for shellshock.
4

An alternative to exporting your functions (which may no reach Vim is there's a non-Bash shell in between; see here for such a case), you can instruct Vim to start an interactive shell, so that your .bashrc is read. Just pass the -i flag to Bash, via Vim's :help 'shellcmdflag'.

:set shcf=-ic

Comments

0

This answer assumes your vim isn't actually using bash to invoke the remote commands - this can be tested by running :!echo $0 in vim.

Specifically for vim, add:

set shell=/bin/bash

to your .vimrc.


In general, there's two strategies I've found to sometimes work when trying to get other programs to invoke my preferred shell:

export SHELL=/bin/bash

in eg. the .profile file, or:

ln -fsn /bin/bash /bin/sh

which updates the sh symlink to point to bash instead.

On many systems (certainly Ubuntu), /bin/sh is a symlink to a sh-compatible shell (such as bash), rather than the sh shell itself. Given this fact, some programs (I've seen this behaviour in GHC) seem to invoke /bin/sh, so changing where it points to will cause the programs to use bash instead.

2 Comments

Ensuring that the shell is bash is necessary, but not sufficient: Copies of bash that don't have the interactive flag (that is, those where [[ $- = *i* ]] is not true) don't read .bashrc.
Also, making /bin/sh a link to bash doesn&#39;t mean you get bash syntax when it&#39;s invoked -- the bash executable runs in POSIX compatibility mode when invoked under that name. Some extensions still work in that mode, but by no means all of them.
0

The accepted answer didn't work for me. I'm going to go with setting shcf, as suggested elsewhere:

:set shcf=-ic

but another solutions is

!source ~/.bashrc && psql ...

Unfortunately, no solution allows the auto-completion for the command I'm creating to work properly. (The auto_completions suggested are for names of files in my current directory, rather than the ones I specified as follows in .bashrc

complete -F _generate_foo_completions foo

3 Comments

If the accepted answer didn't work, the first place I'd start looking in debugging is whether vim is starting the same shell release you did the export from pre-invocation. Pre- and post-shellshock versions of bash use different formats for storing exported functions in the environment, and if one shell isn't bash at all but is zsh or something else, well, there's your issue.
...if the source command works at all, that tells us vim isn't starting /bin/sh (at least, not on a platform where /bin/sh is provided by dash or another non-bash shell), but unfortunately, "doesn't work" isn't a lot of details to debug from.
(Whether the environment is having variables with nonconformant names cleaned up by an intermediate process is another place to look; Ingo's link goes into some detail).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.