In vimscript, is there any events triggered by the internal commands? - vim

for example,
in command mode, if I type ":cd /Home"
A events can be triggered by the cd command and I can get the path of the destination directory (/Home) of the command.
something like:
autocmd cd * : echo "blabla"

Unfortunately not. You'll find the entire event list at :help autocmd-events. I see the following options:
If it's just the :cd command, you could create an override :Cd command that triggers your additional functionality after delegating to the original :cd. To avoid having to type the uppercase :Cd, you can use cmdalias.vim - Create aliases for Vim commands. I would prefer this approach.
Though there's no hook for Ex commands, you could intercept all interactively entered commands by hooking into :cmap <CR> and using getcmdline(), but that requires parsing by yourself and the global hook doesn't play well with other plugins / configurations.
As the effects of :cd can be observed with getcwd(), you could hook into other regular events such as CursorHold,CursorMoved, if you live with a small delay.

Related

make from within vim

I am using gvim for coding c++. Since my program involves cmake, my sources are located in a different directory than my build.
How can I still invoke :make from within vim so that the correct make file within the build directory is found?
how can I then subsequently start my application with the very same command line style and one keystroke?
TD;LR: just assign 'cd "compi/dir" && make $*' to &makeprg (with :let) and run :make youroptionaltarget -j 4.
In another Q/A, I've already criticised the :!make approach. This is what we had to do 20-ish years ago with vi. Vim has introduced integrated compilation through quickfix mode. Please learn vim way to compile code.
In CMake case, we can indeed compile with cmake --someoption compil/dir. I use it when I compile with VC++ compiler, piloted by CMake, from vim. The rest of the time, I'd rather avoid it as it messes compiler outputs by prepending each line with number>, which breaks vim quickfix feature. Unfortunately there is no neat way to ignore this noise by tweaking &errorformat. So far I postprocess cmake and ctest outputs to remove ^\d+>.
So. What can, and shall, we really do? We should take advantage of vim quickfix feature. This is done by tweaking &makeprg and &efm options. In your case, the first one should be enough. Use it to change directory and execute make. And finally compile with :make and navigate errors with :cn, :cp, :cc, etc.
If you want also to compile in background, you'll need a plugin that knows how to compile in background in a directory which is not the current one. This is where I advertise my build-tool-wrappers plugin that provides these features and a few more CMake related features.
PS: It's also possible to use make (and ninja) -c parameter.
The easiest solution I came up with is the following:
:! (cd /path/to/your/cmake/build/directory; make)
To execute the program at the same time, you can append commands with ; or &&:
:! (cd /path/to/your/cmake/build/directory; make && ./myProgram)
In this page, you can find a tutorial how to bind this in order to do this in one key stroke.
Explanation:
In vim, you can execute any command with :! command (for instance, :! ls).
With (cd [...]; [...]), you specify that the execution directory is different by creating a subshell and changing to this directory in the subshell.
You can use the following:
autocmd filetype cpp nnoremap <F8> :w<CR> :!clear<CR> :!make && ./%<<CR>
This will allow you to Compile/Run C++ using Makefile with <F8> and clear console

meaning of "command" prefix and suffix of "!"

I am learning vim from vimtutor and I am currently on lesson 5 where they introduce external command prefix !command and external command suffix command!. I tested the command ls and did the following:
After typing :!ls, I got:
Desktop Downloads Music Public TEST
Documents Pictures Templates Videos
Press ENTER or type command to continue
When I saw the lists of folders and files, I knew that it acted like typing ls in the terminal, but when I typed :ls!, it got:
:ls!
1 %a "/tmp/tutorhN8t15" line 600
Press ENTER or type command to continue
Which made me confused of what the external command ! really means. What does it really mean?
:!command executes external command command.
:command! executes internal command command with a "bang" that usually modifies its behavior.
So…
:!ls executes your shell's ls command, which lists the files and directories in the working directory.
See :help :!.
:ls! executes Vim's ls command in a way that forces it to show listed and unlisted buffers.
See :help :ls.

Vim interrupted after shell command

I don't get why when I type something like :
:! bash -ic 'p4 diff %:p'
My Vim get interrupted and I get
[3]+ Stopped vim ~/.vimrc
as a consequence I have to put that job in foreground to see the effect of the command.
Do you know how can I solve this annoying issue ?
You are telling Vim to run an interactive command so it has no choice but to suspend itself to allow you to do what you want.
It's hard to be sure without more information about your setup but this command:
:!p4 diff %:p
should be enough to run p4 diff on the the current file without side-effects.

Calling command from `-c` command line argument doesn't work in Vim

I'm using the Fugitive plugin.
It has a command(?) Git! which executes a command and opens the result in a new buffer.
Example:
:Git! diff --cached
I have a function which calls this, and does some other things after that.
And I have this command declaration:
command! Hello execute ":Git! diff"
If I run :Hello from within vim, it works as it should. But when I run vim -c Hello, it throws this error:
Not an editor command :Git! diff
How can I do this?
(PS: How can I make this error message to stay until I press ? It appears for about a second and disappears.)
The reason is that Fugitive only defines its commands for buffers whose files are under Git version control. Precisely, the code in plugin/fugitive.vim only sets up autocmds that detect files under Git control, and only then defines buffer-local commands.
So at least you need to pass a Git-controlled file to your Vim invocation. If that still doesn't work, try explicitly triggering the detection via
:doautocmd User Fugitive

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.

Resources