9

In vi, I can get a shell terminal with :sh command. And later, I can return to vi by exit shell.

But, if I was using the shell terminal for a long time, and I forgot whether exit will close anything or return me the vi.

Is there any way to check whether I will return to vi? jobs or fg is not working.

1
  • 3
    I stopped using the :sh command many years ago due to issues with the separate shell that Vim starts and the inability to return to it. Instead, I started putting Vim in the background (ctrl-z) to get back to the normal shell. Getting back to Vim from the normal shell is easy using the bash job control functions.
    – bsnyder
    May 4, 2017 at 21:51

3 Answers 3

8

In a regular shell:

$ env | grep -i vim
EDITOR=vim

After using :shell

$ env | grep -i vim
EDITOR=vim
VIMRUNTIME=/usr/share/vim/vim80
VIM=/usr/share/vim
MYVIMRC=/home/martin/.vim/vimrc

So it looks like Vim sets the VIMRUNTIME, VIM, and MYVIMRC environment variables. Of those, VIM seems the most reliable to me (you may not have a vimrc or even vim runtime).

You can also set your own environment variables:

:let $HELLO = "test"
:shell
$ echo $HELLO
test

This is especially useful to communicate info about the buffer you're editing; for example:

:let $VIM_FILETYPE = &filetype
:let $VIM_FILENAME = expand('%:p')

Will show up as something like:

VIM_FILETYPE=go
VIM_FILENAME=/home/martin/a.go
3

I have my command prompt set up to add a red "+" symbol that indicates if I am in a vim ":sh" as opposed to a normal shell session. The cornerstone of it is that "$$" is the pid of the current process so:

MY_PPID=$(ps --no-header -o ppid -p $$)          # Gets the pid of the parent
                                                 # process.
MY_PCMDLINE=$(ps --no-header -o cmd -p $MY_PPID) # Gets its command line.
MY_CMDDASH=$(awk '{print $1}' <<<$MY_PCMDLINE)   # Gets the command name, possibly
                                                 # with a preceding hyphen.
MY_CMD=${MY_CMDDASH#-}                           # Get the bare command name.

Once you have this you can easily inline and construct something like I described to use in your ".bashrc" or similar.

Note: The environment variable ($VIM) method described elsewhere seems better than this but I'll leave this as it works in identifying if you are a child process of anything (not just vim).

1
  • 1
    Vim puts three variables into the environment of the shell it lauches with :sh: MYVIMRC, VIM and VIMRUNTIME. All you have to do to know you're running in a sub-shell of Vim is to test for the presence of any of those.
    – garyjohn
    May 5, 2017 at 0:04
2

Execute ps, or better, ps -fH. Ex:

$ ps -fH
UID        PID  PPID  C STIME TTY          TIME CMD
garyjohn 31140 31139  0 10:26 pts/11   00:00:00 bash
garyjohn 31267 31140  2 10:26 pts/11   00:00:00   vim hello.txt
garyjohn 31271 31267  0 10:26 pts/11   00:00:00     /bin/bash
garyjohn 31332 31271  0 10:26 pts/11   00:00:00       ps -fH

The advantage to using ps -fH over just ps is that it lets you see whether you are in a sub-shell of vim or if you put vim in the background. In that case, ps -fH would look like this:

$ ps -fH
UID        PID  PPID  C STIME TTY          TIME CMD
garyjohn 31140 31139  0 10:26 pts/11   00:00:00 bash
garyjohn 31267 31140  0 10:26 pts/11   00:00:00   vim hello.txt
garyjohn 31924 31140  0 10:29 pts/11   00:00:00   ps -fH

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.