How to restart vim from a bash script? - bash

I want to restart vim from a bash script so that vim picks up out-of-band changes. I almost have it working but I am stuck trying to determine what to use to launch vim.
Here's what I have:
#!/usr/bin/env bash
local servername=$(vim --serverlist)
[ -n "$servername" ] && {
vim --servername "$servername" --remote-send '<C-\><C-N>:mks! _session.vim<CR>:wqa<CR>'
vim -S _session.vim
sleep 1
rm _session.vim
}
The problem is the vim called by the script is the very obsolete system vim at /usr/bin/vim, not "my" vim which is an alias to mvim -v (where mvim is the launch script which comes with MacVim).
This has two unfortunate consequences: (1) the system vim doesn't recognise --serverlist; (2) even if it did my script would subsequently launch the wrong vim.
What's the best way to invoke the vim on my path?

The default vim is never built with +clientserver so the portability you are afraid to loose was never there to begin with.
Aliases are not expanded in bash scripts so your script won't see mvim -v if you don't tell it explicitly to use that. Furthermore, your vim is an alias so it is not in your PATH.
You could define an environment variable somewhere near the top of your script and use it instead of vim:
#!/usr/bin/env bash
VIM='/path/to/mvim'
"$VIM" -v whatever
Or turn your alias into a proper script.
Or, maybe, place mvim earlier in your PATH and call mvim -v explicitly.

Related

Executing MSYS2 Emacs from Windows command line or shortcut

I recently installed MSYS2 with Emacs (64-bit) and am currently calling that Emacs from a Windows shortcut. It works fine, exactly like if I had downloaded the Emacs executable for Windows and unzipped it somewhere. Which is to say, it picks up all of my Windows environment variables and such.
For various reasons, I would prefer to run Emacs from an MSYS2 bash shell and use the environment variables in that shell. As it stands, I can open an MSYS2 MINGW64 shell, type emacs on the command line, and everything works the way I want it to.
Now I would like to package the whole thing up into either a one-liner I can stuff into to a Windows shortcut or a script I can call from a Windows shortcut. With the help of this post, I came up with the following:
C:\msys64\bin\mintty.exe /bin/env MSYSTEM=MINGW64 /bin/bash -l -c /mingw64/bin/emacs
This successfully opens Emacs, but fails to load the .bashrc file that I source in .bash_profile in the usual manner:
if [ -f "${HOME}/.bashrc" ] ; then
source "${HOME}/.bashrc"
fi
I define a function in .bashrc that I call in .bash_profile, so this is kind of important. It did not take much effort to realize that the problem is that HOME is not defined, so .bashrc is simply not found. However, if I define HOME like so:
C:\msys64\bin\mintty.exe /bin/env HOME=/home/alanhr MSYSTEM=MINGW64 /bin/bash -l -c /mingw64/bin/emacs
I get exactly the same result: .bashrc is not found and my function is not executed. Here's where it gets weird. If I simply leave off the call to emacs like so:
C:\msys64\bin\mintty.exe /bin/env HOME=/home/alanhr MSYSTEM=MINGW64 /bin/bash -l
I get a bash shell where .bashrc has been loaded correctly and my function is correctly executed. I can type emacs on the command line and have it function exactly as I want it to.
This feels like a classic case of missing something that is right under my nose, but I have read the bash man page to no avail. Does anyone have any idea how I can make this work?
It is the -i option to load .bashrc. The following works for me:
C:\msys64\usr\bin\mintty.exe -w hide /bin/env MSYSTEM=MINGW64 /bin/bash -l -i -c /mingw64/bin/emacs

Setting up emacsformacosx as default from command line

I tried to set emacsformaxosx as the emacs command called from the command line (in order to install mu4e) by putting the following inside /usr/bin/emacs:
#!/bin/bash
/Applications/Emacs.app/Contents/MacOS/Emacs "$#"
When calling . /usr/bin/emacs emacs get launched but when calling which emacs I get nothing in my prompt, neither do I with just emacs. whereis emacs seem to find well that emacs is in /usr/bin/emacs.
You need to run
chmod a+x /usr/bin/emacs
to make the /usr/bin/emacs script executable.
The reason it works with the command
. /usr/bin/emacs
is that in that case, your shell sources the contents of the /usr/bin/emacs script and directly runs each command it finds there.
Also, note that since the shell script has nothing else to do after running emacs, you could add the command exec in front of the emacs command in the script so that the emacs process replaces the shell script process:
#!/bin/bash
exec /Applications/Emacs.app/Contents/MacOS/Emacs "$#"

Call bash function using vim external command

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

Cygwin Terminal and zsh strange characters used in username

Hi I've recently installed zsh using cygwin on my Windows machince but when I type zsh to start this I get the following:
GG#GG-PC ~
$ zsh
\[\e]0;\w\a\]\n\[\e[32m\]\u#\h \[\e[33m\]\w\[\e[0m\]\n\$
On my mac I am using iTerm2 and this is so much easier to setup on here. Also I am having trouble in setting up the aliases and this is becauses its not setup properly in terms of config file where I can set this up in a separate file.
Any ideas how I can resolve?
It looks like zsh is inheriting the value of PS1 from the previous shell. The PS1 environment variable sets the shell prompt, and zsh used a different format for prompt substitutions than other shells. Try entering the following command after you start zsh:
PS1=$'%{\e]0;%d\a%}\n%F{green}%n#%m %F{yellow}%d%f\n%# '
If that works, add that line to your ~/.zshrc file.
That's also probably a good place to put your aliases.
There might be an issue because you launch zsh from bash actually and not cygwin.
One thing you can do is to launch zsh as the starting shell of mintty (the window that wraps your shell)
Create a shortcut with this inside:
c:\<cygwin-folder>\bin\mintty.exe -i /Cygwin-Terminal.ico /usr/bin/zsh --login -
Yo need to update .zshrc with your required theme and then
source .zshrc

Source my .zshrc in a bash script

Lets say I have this bash script (test):
#!/usr/bin/env bash
source ~/.zshrc
In my .zshrc, I have the following:
autoload -U compinit
compinit
When I try and run 'bash test' from my terminal window (zsh), I get errors saying autoload and compinit commands are not found. If I just do source ~/.zshrc from the command line, it works fine.
I am trying to setup my development environment, similar to this blog, but when the scripts try and source the .zshrc file it fails.
Any insight would be appreciated.
In your script, you're using bash to run a zsh script. You might as well ask the python interpreter to parse perl.
Either change bash to zsh in the shebang line or write the script with bash commands.
It's not quite as bad as python vs. perl. Both bash and zsh are derived from the Bourne shell (whose behavior is standardized by POSIX), so any script designed to work with /bin/sh is likely to work with either bash or zsh.
Normally your ~/.zshrc, as the name implies, is designed to be used with zsh, and will typically include zsh-specific commands like autoload and compinit.
You can make those commands conditional, for example:
if [ "$ZSH_VERSION" ] ; then
autoload -U compinit
compinit
fi
But of course that means you won't get the functionality of those commands, unless you can figure out a way to emulate them in bash. (I'm not familiar with either command, so I can't help you there.)
(Note that this will fail if you've done set -u or set -o nounset in your bash shell.)
But if you're going to be using both zsh and bash, it probably makes a lot more sense to have separate ~/.bashrc and ~/.zshrc files, and use each one only with the shell for which it's designed. If you want to avoid duplication, each one can source a third file containing common commands.
(And based on the comments, it's likely you're doing the wrong thing in the first place.)

Resources