'Running shell command in VIM Script

In my vimrc file, I have an if statement that contains a variable that gets output from a shell command. The idea is if the command output is not Hyper run some few commands and if it is run other commands.

Minor update: I run vim inside tmux sessions so when using $TERM_PROGRAM it produces tmux as my $TERM_PROGRAM

System command:

ps -p $(ps -p $$ -o ppid=) -o args | grep -o Hyper

The issue is that I am unable to escape the shell expansion in vim

" change vim theme depending on the terminal

" need some help here on the term variable
silent! let term = system('ps -p $(ps -p $$ -o ppid=) -o args | grep -o Hyper')                                                                                                                                                 
                                                                                                                                                                                                                   
if term != 'Hyper'                                                                                                                                                                                                  
  set background=dark                                                                                                                                                                                              
  " set contrast                                                                                                                                                                                                   
  let g:everforest_background = 'hard'                                                                                                                                                                             
  colorscheme everforest                                                                                                                                                                                           
else                                                                                                                                                                                                               
  colorscheme spacecamp                                                                                                                                                                                            
endif     
vim


Solution 1:[1]

Everything in the provided snippet "works".

I put "Works" in quotes because the syntax of your Vim stuff and the syntax of your shell stuff are correct: everything is passed correctly to the shell and then handled properly. The Vim stuff is fine as-is and the shell stuff is also syntactically fine.

The problem, here, is that the shell command doesn't do what you expect because the process tree is deeper than you anticipated, not that the command needs escaping (which it doesn't).

Here is an ideal view of your shell command's process tree in Vim:

terminal
 shell
  vim
   your shell command
  • The external command executed via system() ends up being executed as bash -c <your command> so $$ is really the PID of your shell command.
  • ps -p $$ -o ppid= gives you the PID of the parent of your shell command, which is Vim.
  • and finally, ps -p $(ps -p $$ -o ppid=) -o args= only ends up giving you the full command that you used to start Vim.

Basically, your shell command is not deep enough to reach your terminal emulator, so you will need to addd more levels.

But your problems don't stop here.

Your first new problem is that the tree gets bigger when you run Vim in Tmux:

terminal
 shell
  tmux
   shell
    vim
     your shell command

which means that the already heavily nested shell command you wrote to handle the simple case might require even more levels… which leads to another interesting problem: how to decide which version (non-tmux-aware or tmux-aware) of the command to run?

The last problem is the best: Tmux having a client/server architecture, the idealized tree above might actually be completely detached from any terminal emulator:

/sbin/launchd
  tmux
   shell
    vim
     your shell command

Good luck finding the name of the current terminal emulator with ps in those conditions.

You may have more luck with pstree but I wouldn't hold my breath.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 romainl