How to set iterm2 Badge from vim? - vim

I want to call the function iterm2_set_user_var VARIABE VALUE from vim/neovim using call system(). However, I get the following.
zsh:1: command not found: iterm2_set_user_var
shell returned 127
This is already done in node.js: How to exec script to set iterm2 Badge from nodejs?

I'm guessing you've defined iterm2_set_user_var as a shell function in your zsh config somewhere. Vim doesn't invoke a login shell with the system function. I think you have two options:
Change shellcmdflag to force a login shell by adding l to the flags currently there. This would affect all :! commands in vim as well.
Define iterm2_set_user_var as an executable somewhere in your $PATH.
Either should work fine.

Related

Vim makeprg make environment variable expansion

This is bothering me more than it should and has me completely stumped. I feel like like finding the answer will have some good learning opportunities so hopefully it's relevant.
I do embedded C development with Vim and have a setup for hobbyist stuff with Arduino (using Arduino Makefile). I use :make with some shortcuts with build projects.
An external define resolves the Arduino Makefile root directory in the project level Makefile: 'ARDMK_DIR=/usr/local/opt/arduino-mk'. This is define as an export in my shell (zsh). This is where it gets weird:
Using make at the shell prompt the project builds fine:
make -d
This program built for i386-apple-darwin11.3.0
Reading makefiles...
Reading makefile `Makefile'...
Reading makefile `/usr/local/opt/arduino-mk/Arduino.mk' (search path) (no ~ expansion)...
However using :make in Vim the define becomes something from an old install:
:make
This program built for i386-apple-darwin11.3.0
Reading makefiles...
Reading makefile `Makefile'...
Reading makefile `/usr/local/Cellar/arduino-mk/1.5.2/Arduino.mk' (search path) (no ~ expansion)...
Makefile:24: /usr/local/Cellar/arduino-mk/1.5.2/Arduino.mk: No such file or directory
I cannot for the life of me find where ARDMK_DIR is being re-defined to '/usr/local/Cellar/arduino-mk/1.5.2'. Things I have tried:
setlocal makeprg=echo\ $ARDMK_DIR\ &&\ make\ -d\: echo comes back with my shell define (/usr/local/opt/arduino-mk), but make fails with the error above!!
:echo $ARDMK_DIR: again returns my shell define.
ag my home directory for ARDMK_DIR, the only place it is defined is in my shell exports. Did since for my root directory to and same thing. Same thing for $VIMRUNTIME
Even vim-disptach works fine calling the same makeprg?!
Re-define ARDMK_DIR in the project Makefile. Everything builds find as expected. I don't want to do this however as I compile with different systems.
The same vim config works on other macOS and Linux systems with expected behaviour.
Some where between echo and the actual execution of make, ARDMK_DIR is being re-defined. Why and can anyone think of a way of finding out where and solving this?
Zsh has multiple init files that are sourced. The file .zshenv is always sourced, when the shell starts and the file .zshrc is only sourced when the shell is started in interactive mode.
If you define the variable ARDMK_DIR with different values in .zshenv and in .zshrc, the value from .zshrc will be used when you work interactive with the shell (entering commands, starting Vim, ...).
But when Vim starts a command it will start a non-interactive shell. In that case only the file .zshenv will be sourced, so you get the value from that file.
One question left:
Why did the following command first echo the correct value, but make uses the wrong?
:setlocal makeprg=echo\ $ARDMK_DIR\ &&\ make\ -d\
For testing, I started Vim under strace. Then :
:set makeprg=echo\ $EDITOR
:make
In the strace file I found the following line:
execve("/usr/bin/zsh", ["/usr/bin/zsh", "-c", "echo vi 2>&1| tee /tmp/vdxR5DH/"...], [/* 86 vars */]) = 0
As you can see, Vim executes echo vi, so it already expanded the environment variable $EDITOR to its value before calling the shell.
So the answer to the above question is, that the echo command echos the text, that Vim inserted into the command line while the make command gets the the variable value from the environment. As it is a non-interactive shell, it is the value from .zshenv.

Running gvim from MSYS --- how to avoid/change MSYS enviroment variables?

When I run gvim from MSYS, things go wrong during initialization. Namely, gvim can't find the initialization files that are in 'C:\Documents and Settings\username\vimfiles.
[Specifically, gvim reports the error E117: Unknown function: pathogen#infect during initialization, so it never found autoload\pathogen.vim. Doing :scriptnames also confirms that none of the setup files from vimfiles\ are run.]
I think I've debugged why it goes wrong. When you start MSYS, the MSYS shell inherits the windows enviroment variables, but changes some of them to it's custom values. C:\Documents and Settings\username is the value of $HOME in Windows, but MSYS sets it to something like C:/msys/user name. And of course, Vim uses $HOME to find the right initialization files.
I also notice set shell? has changed to something like shell=C:/msys/bin/sh instead of shell=C:\WINDOWS\system32\cmd.exe, but I hope this isn't important for fixing the initialization problem.
I need to run gvim with the normal windows environment variables. At least I need to be able to manually override a few important ones like $HOME to something I specify (i.e., I'm not concerned about my windows $HOME changing, so it's fine to use a static value).
I tried to reset $HOME manually in my vimrc, but by then it is too late.
Is there some trick to specifying $HOME early on during initialization, or as an extra command line parameter?
Alternatively, is there some trick with running commands from msys differently? I know almost nothing about how the shell C:/msys/bin/sh works, but I could conceive of some extra arguments that changes the visibile environment for the command (e.g. gvim.exe) you are typing.
---Edit---
Reposting the solution that worked (it achieves the later idea):
Instead of running gvim.exe, run the command HOME="C:\Documents and Settings\username" gvim.exe
In bash and other UNIX shells, you can do:
$ HOME='/path/to/dir' gvim
to temporarily set $HOME to a different value.
I admit I'm not familiar at all with the Windows command line, but it might be worth a try.
I believe you can define $HOME just like any other environment variable.
Try adding this to the start of your .vimrc.
let $HOME="C:\Documents and Settings\username"
I had a similar issue when running Cygwin (which is similar to MSYS).
The easiest solution for me was to simply set the HOME environment variable to an empty string. Otherwise, the Cygwin HOME value would be appended to the Windows USERPROFILE in GVim and it would fail to start correctly. Not explicitly setting the full path of the HOME means that I can use the same start-up files on different systems where the USERNAME may not be the same.
Likewise, the SHELL environment variable should not be inherited from Cygwin Bash. This results in errors when running shell or external programs via !. Again, I set this to be an empty variable since Vim is smart enough to figure out what it should be.
In my .bashrc, I set the following alias for running Windows gvim which starts GVim with the HOME and SHELL variables set to an empty string – just for that command.
gvim="/cygdrive/c/Program Files (x86)/Vim/vim74/gvim"
if [ -x "$gvim" ]; then
alias gvim="HOME= SHELL= \"$gvim\""
fi
unset gvim
I achieved this by making a windows symbol link (Win 7 or higher).
Via a symbol link, you can even make vim and gvim to use the same configuration and plugin.

VIM. Sending commands to the terminal?

I'm trying to configure vim as my primary coding program. I have figured how to compile single files, but when I go to execute the program from within vim, I keep getting a 127 error code. I have a aliased on my box to ./a.out, however when I issue the command :!a from vim, it doesn't work. :!./a.out does. Does anyone know why this is?
Aliases are defined in rc files that are sourced by interactive shell only and work only in interactive mode (vim does pass everything to shell, it never executes anything except the shell directly with fork+execve).
By default shell launched from vim starts in non-interactive mode hence bashrc is not read and no aliases are defined (though even if they were defined, they won’t be used in non-interactive mode). You may set
set shellcmdflag=-ic
, then shell will be launched in interactive mode and .bashrc file with your alias will be read.
Aliases are a feature of your shell (say, bash). ! operator directly executes a file - shell never sees it, and can't do alias expansion on it. (EDIT: See ZyX)
If you want to make executing your ./a.out easy, you can do something like:
command XX !./a.out
then you can do :XX. Or,
nnoremap X :!./a.out<CR>
then a single key X will suffice.
Another option (which is frowned upon for security reasons) is to add the current directory to your PATH:
PATH="./$PATH"
which will allow you to run your program with just a.out as opposed to ./a.out. If you then compile your program with (a language-dependent isomorphism of) -o switch, you can have it named just a:
gcc -o a foo.c
Given this, !a would work. Use at your own risk.
EDIT: ZyX is correct-er. :) I'll leave the answer here for the other information.

How to check if it's still in Vim shell mode

In vim, type :sh will switch to shell, and exit can exit the shell and get back to vim. Is there any command to check if it's in vim shell mode? So that I won't accidentally vim to open the same file again. I want to avoid below scenario:
vim myfile > :sh > exit > vim myfile // get warning of another vim instance is editing the same file
These are the normal scenario:
vim myfile > :sh > exit // keep editing
vim myfile > :wq > vim myfile // keep editing
In addition to #a3nm answer, what you can do is
use pstree -h: it will output process tree with current branch highligted and all you need to check is whether there is vim in the highlight.
Another possibility is ps t: it will show all processes using the current terminal and should show vim in a list when you are inside :sh. ps -oargs t may be more useful in case you want to know arguments you ran vim with.
These methods are more reliable because VIMRUNTIME, VIM and MYVIMRC environment variables may be overrided by you in order to do some customizations (BTW, they are defined by vim for use in vimscripts, not by :sh). They also work for other processes that allow you to run a subshell, but do not define any environment variables.
I would also suggest to consider using <C-z> in normal mode or :suspend/:stop in Ex because these use shell vim was launched from instead of creating new. This behavior gives you access to history of commands you typed before running vim and also makes you able to write more complex and time-consuming shell configuration without needing to wait every time.
In case you use <C-z> both methods still work, but first method won’t highlight vim because it will be at the same level (has the same parent) as pstree itself, likely just below or above pstree in graph. This also enables third method: jobs shell builtin.
In order to restore from <C-z> you should use fg (a single % in zsh and bash also works) which is less to type then exit (but more then <C-d>).
The :sh command in vim seems to define the VIMRUNTIME, VIM and MYVIMRC environment variables, so you can just check if they are defined. To do so, you can run echo $VIM, for instance, which should return an empty line in a normal shell and something like /usr/share/vim in a shell run from vim.

Why doesn't my vim know my alias?

I have used "alias ruby=ruby1.9.1", so I can execute my ruby with this:
ruby 123.rb
or
ruby1.9.1 123.rb
But in my vim, I use :!ruby and get
/bin/bash: ruby: command not found.
I must use :!ruby1.9.1
How does alias work? Why vim doesn't know it?
When Vim starts a process it makes a system call. It has only inherited the environment variables from your shell if you started it from the shell. But it won't know your bash aliases.
Bash aliases are only a convenience when you enter a command line in the Bash shell. They are expanded by Bash only.
If you want real aliases put symlinks in a private hidden folder, and add that folder to your PATH, or use the alternatives facility.
You can try
:set shellcmdflag+=i
to call bass as "interactive" although that does give an annoying message for every shell command executed.
Aliases (unlike environment variables) are not inherited by subshells. So if you want an alias always available, you need to set it in your .bashrc file, so every instance of the shell will get it on startup

Resources