Problem: Find how many shells deep I am.Details:I open the shell from vim a lot. Build and run and exit. Sometimes I forget and open another vim inside and then yet another shell. :(I want to know how many shells deep I am, perhaps even have it on my shell screen at all times. (I can manage that part).My solution: Parse the process tree and look for vim and bash/zsh and figure out the current process's depth within it. Does something like that already exist? I could not find anything.
How many shells deep I am?
bash;shell script;shell;vim;zsh
When I read your question, my first thought was $SHLVL.Then I saw that you wanted to count vim levelsin addition to shell levels.A simple way to do this is to define a shell function:vim()  { ( ((SHLVL++)); command vim  $@);}This will automatically and silently increment SHLVLeach time you type a vim command.You will need to do this for each variant of vi/vim that you ever use; e.g.,vi()   { ( ((SHLVL++)); command vi   $@);}view() { ( ((SHLVL++)); command view $@);}The outer set of parentheses creates a subshell,so the manual change in the value of SHLVLdoesnt contaminate the current (parent) shell environment.Of course the command keyword is there to prevent the functionsfrom calling themselves (which would result in an infinite recursion loop).And of course you should put these definitionsinto your .bashrc or other shell initialization file.Theres a slight inefficiency in the above.In some shells (bash being one), if you say(cmd1; cmd2; ; cmdn)where cmdn is an external, executable program(i.e., not a built-in command), the shell keeps an extra process lying around,just to wait for cmdn to terminate.This is (arguably) not necessary;the advantages and disadvantages are debatable.If you dont mind tying up a bit of memory and a process slot(and to seeing one more shell process than you need when you do a ps),then do the above and skip to the next section.Ditto if youre using a shell that doesnt keep the extra process lying around.But, if you want to avoid the extra process, a first thing to try isvim()  { ( ((SHLVL++)); exec vim  $@);}The exec command is there to prevent the extra shell process from lingering.But, theres a gotcha.The shells handling of SHLVL is somewhat intuitive:When the shell starts, it checks whether SHLVL is set.If its not set (or set to something other than a number),the shell sets it to1.If it is set (to a number), the shell adds1 to it.But, by this logic, if you say exec sh, your SHLVL should go up.But thats undesirable, because your real shell level hasnt increased.The shell handles this by subtracting one from SHLVLwhen you do an exec:$ echo $SHLVL1$ set | grep SHLVLSHLVL=1$ env | grep SHLVLSHLVL=1$ (env | grep SHLVL)SHLVL=1$ (env) | grep SHLVLSHLVL=1$ (exec env) | grep SHLVLSHLVL=0Sovim()  { ( ((SHLVL++)); exec vim  $@);}is a wash; it increments SHLVL only to decrement it again.You might as well just say vim, without benefit of a function.Note:According to Stphane Chazelas (who knows everything),  some shells are smart enough not to do this if the exec is in a subshell.To fix this, you would dovim()  { ( ((SHLVL+=2)); exec vim  $@);}Then I saw that you wanted to count vim levelsindependently of shell levels.Well, the exact same trick works (well, with a minor modification):vim() { ( ((SHLVL++, VILVL++)); export VILVL; exec vim $@);}(and so on for vi, view, etc.)The export is necessarybecause VILVL isnt defined as an environment variable by default.But it doesnt need to be part of the function;you can just say exportVILVL as a separate command (in your .bashrc).And, as discussed above, if the extra shell process isnt an issue for you,you can do commandvim instead of execvim, and leave SHLVL alone: vim() { ( ((VILVL++)); command vim $@);}Personal Preference:  You may want to rename VILVL to something like VIM_LEVEL.  When I look at VILVL, my eyes hurt;  they cant tell whether its a misspelling of vinyl  or a malformed Roman numeral.If you are using a shell that doesnt support SHLVL (e.g., dash),you can implement it yourself as long as the shell implements a startup file.Just do something likeif [ $SHELL_LEVEL =  ]then    SHELL_LEVEL=1else    SHELL_LEVEL=$(expr $SHELL_LEVEL + 1)fiexport SHELL_LEVELin your .profile or applicable file.(You should probably not use the name SHLVL, as that will cause chaosif you ever start using a shell that supports SHLVL.)Other answers have addressed the issueof embedding environment variable value(s) into your shell prompt,so I wont repeat that, especially you say you already know how to do it.