How to use GNOME Terminal instead of XTerm here? - vim

I have the following variable defined in ~/.vimrc. This works well with XTerm but I can't get it working with GNOME Terminal. Please help.
let g:slimv_client = 'python /home/dumrat/.vim/ftplugin/slimv.py -r "xterm -e sbcl --core /home/dumrat/.sbcl/sbcl.core -s"'

The option -e makes XTerm run the command specified by all of the remaining
command line arguments following -e. Consequently, xterm -e sbcl --core
/home/dumrat/.sbcl/sbcl.core -s opens an XTerm instance running sbcl --core
/home/dumrat/.sbcl/sbcl.core -s command.
GNOME Terminal has the option -x with the same meaning that -e has for
XTerm.1 Thus, change the configuration file, as follows.
let g:slimv_client = 'python /home/dumrat/.vim/ftplugin/slimv.py -r "gnome-terminal -x sbcl --core /home/dumrat/.sbcl/sbcl.core -s"'
1 Note that -e has somewhat different behavior in GNOME
Terminal—the whole command is expected to be in the next argument, while -x
assumes that everything to the end is the command to run.

Related

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
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.

Programmatically open Gnome Terminal and run command

How do you programmatically opening a terminal application, like Gnome Terminal, and running cd /some/path; source ./setup.bash? I'm trying to write a script that will automatically launch some common terminals and IDEs for work.
I tried:
gnome-terminal --tab --working-directory="/some/path" -e 'source ./setup.bash'
but that launches a gnome-terminal window, but the window shows the error:
Failed to execute child process "source" (No such file or directory)
Presumably, that's because it's not executing the command in bash, so I instead tried:
gnome-terminal --tab --working-directory="/some/path" -e 'bash -c "source ./setup.bash"'
However, that seems to do nothing at all. It launches no window nor produces any stdout or stderr output.
The closest I could get was:
gnome-terminal --tab --working-directory="/some/path" -e 'bash -c "source ./setup.bash; bash -i"'
That launches gnome-terminal and seems to source setup.bash correctly, but some of the terminal formatting set by setup.bash isn't shown, presumably because I'm launching a new bash shell.
Is there a better way?
When you use the -e option the gnome-terminal will run that command without starting a new shell (you can even run something like: gnome-terminal -e gedit), so if you want to run a command into the bash shell into a new terminal/tab you have to do something like this:
gnome-terminal -x bash -c "command"
But note that when "command" ends the terminal/tab will end too.
You can specify the bash startup file to set variables. You might want that file to have source $HOME/.bashrc in it:
$ gnome-terminal --working-directory="/some/path" -e 'bash --rcfile ./setup.bash -c gdb'
You can put a command in after that,as I have -c gdb.

Open terminal windows and execute custom commands in them?

I just figured out how I can open a new terminal and immediately send it commands. The command I'm using on Linux Mint is "mate-terminal -x zsh -c '(stuff here) ; exec /bin/zsh". But, I hit a wall in regards to calling functions and aliases defined in my .zshrc file. Instead it says "zsh:1: command not found: ".
.zshrc file is only used for interactive shells, http://linux.die.net/man/1/zsh
Then, if the shell is interactive, commands are read from /etc/zshrc and then $ZDOTDIR/.zshrc
There is -i option ("Force shell to be interactive.") which may help you, try:
mate-terminal -x zsh -c '(stuff here) ; exec /bin/zsh -i'
or if you have zshrc commands in stuff:
mate-terminal -x zsh -ci '(stuff here) ; exec /bin/zsh -i'

How to execute multiple statements in multiple terminals? (Linux, Bash)

I'm trying to write a script that opens 3 terminal windows and runs a couple of statements in those windows. But it's not working. I've tried using the && operator as well as " " but I can't get it to work. I've also tried it with the statements on the same line as well as below each other. The error I'm receiving is that the cd child process failed to execute stating that there is no such Directory. But the directory ~/Projects/catkin_ws is correct.
#!/bin/bash
# ROS opstarten
gnome-terminal -e cd ~/Projects/catkin_ws source devel/setup.bash roscore
# gazebo opstarten
gnome-terminal -e cd ~/Projects/catkin_ws
source devel/setup.bash
roslaunch cvg_sim_gazebo Qr_Chessboard.launch
# programma opstarten
gnome-terminal -e cd ~/Projects/catkin_ws
source devel/setup.bash
/usr/bin/python /home/user/Projects/catkin_ws/src/drone7_project/src/drone_program.py
If you really want to run them on separate terminals programmatically you can use a terminal multiplexer such as GNU screen for that.
First you have to start a session:
$ screen -S demo
Then open all the terminals you need inside it with Ctrl-a c and configure their environments as needed, and then you can send commands to any screen page (tab) from your script using the "-X stuff" option (to stuff characters into a virtual screen terminal):
$ screen -S demo -p <page_number> -X stuff 'ls -l
'
Note that you also have to send the newline character to really enter the command.
I try add main enviornment path to bash and I success run roscore in another terminal.
#!/bin/bash
# ROS opstarten
PATH=/opt/ros/kinetic/bin
gnome-terminal --tab -e /opt/ros/kinetic/bin/roscore
You need to quote the statements and use a statement separator between them.
gnome-terminal -e 'cd ~/Projects/catkin_ws; source devel/setup.bash; /usr/bin/python /home/user/Projects/catkin_ws/src/drone7_project/src/drone_program.py'
or alternatively with newline as statement separator
gnome-terminal -e 'cd ~/Projects/catkin_ws
source devel/setup.bash
/usr/bin/python /home/user/Projects/catkin_ws/src/drone7_project/src/drone_program.py'
However, running these commands in a separate terminal seems rather misdirected. Why don't you run them as regular background jobs in your current terminal with output to a file?

Avoid gnome-terminal close after script execution?

I created a bash script that opens several gnome-terminals, connect to classroom computers via ssh and run a script.
How can I avoid that the gnome-terminal closes after the script is finished? Note that I also want to be able to enter further commands in the terminal.
Here is an example of my code:
gnome-terminal -e "ssh root#<ip> cd /tmp && ls"
As I understand you want gnome-terminal to open, have it execute some commands, and then drop to the prompt so you can enter some more commands. Gnome-terminal is not designed for this use case, but there are workarounds:
Let gnome-terminal run bash and tell bash to run your commands and then start a new bash
$ gnome-terminal -- bash -c "echo foo; echo bar; exec bash"
or if the commands are in a script
$ gnome-terminal -- bash -c "./scripttorun; exec bash"
The first bash will terminate once all the commands are done. But the last command is a new bash which will then just keep running. And since something is still running gnome-terminal will not close.
Let gnome-terminal run bash with a prepared rcfile which runs your commands
Prepare somercfile:
source ~/.bashrc
echo foo
echo bar
Then run:
$ gnome-terminal -- bash --rcfile somercfile
bash will stay open after running somercfile.
i must admit i do not understand completely why --rcfile has this behaviour but it does.
Let gnome-terminal run a script which runs your commands and then drops to bash
Prepare scripttobash:
#!/bin/sh
echo foo
echo bar
exec bash
Set this file as executable.
Then run:
$ gnome-terminal -- ./scripttobash
for completeness
if you just want to be able read the output of the command and need no interactivity
go to preferences (hamburger button -> preferences)
go to profiles (standard or create a new one)
go to command tab
when command exits -> hold the terminal open
i recommend to create a new profile for just for this use case.
use the profile like this:
gnome-terminal --profile=holdopen -- ./scripttorun
Every method has it's quirks. You must choose, but choose wisely.
I like the first solution. it does not need extra files or profiles. and the command says what it does: run commands then run bash again.
All that said, since you used ssh in your example, you might want to take a look at pssh (parallel ssh). here an article: https://www.cyberciti.biz/cloud-computing/how-to-use-pssh-parallel-ssh-program-on-linux-unix/
Finally this one works for me:
gnome-terminal --working-directory=WORK_DIR -x bash -c "COMMAND; bash"
Stack Overflow answer: the terminal closes when the command run inside it has finished, so you need to write a command that doesn't terminate immediately. For example, to leave the terminal window open until you press Enter in it:
gnome-terminal -e "ssh host 'cd /tmp && ls'; read line"
Super User answer: Create a profile in which the preference “Title and Command/When command exits” is set to “Hold the terminal open”. Invoke gnome-terminal with the --window-with-profile or --tab-with-profile option to specify the terminal name.
Run with -ic instead -i to make terminal close bash proccess when you close your terminal gui:
gnome-terminal -e "bash -ic \"echo foo; echo bar; exec bash\""
As of January 2020, the -e option in gnome-terminal still runs properly but throws out the following warning:
For -e:
# Option “-e” is deprecated and might be removed in a later version
of gnome-terminal.
# Use “-- ” to terminate the options and put the command line to
execute after it.
Based on that information above, I confirmed that you can run the following two commands without receiving any warning messages:
$ gnome-terminal -- "./scripttobash"
$ gnome-terminal -- "./genericscripttobash \"echo foo\" \"echo bar\""
I hope this helps anyone else presently having this issue :)
The ideal solution would be to ask for a user input with echo "Press any key".
But if double-click in Nautis or Nemo and select run in a terminal, it doesn't seem to work.
In case of Ubuntu a shell designed for fast start-up and execution with only standard features is used, named dash I believe.
Because of this the shebang is the very first line to start with to enable proper use of bash features.
Normally this would be: #!/bin/bash or similar.
In Ubuntu I learned this should be: #!/usr/bin/env bash.
Many workarounds exist to keep hold of the screen before the interpreter sees a syntax error in a bash command.
The solution in Ubuntu that worked for me:
#!/usr/bin/env bash
your code
echo Press a key...
read -n1
For a solution applicable to any terminal, there is a script that opens a terminal, runs the command specified and gives you back the prompt in that new terminal:
https://stackoverflow.com/a/60732147/1272994
I really like the bash --rcfile method
I just source ~/.bashrc then add the commands I want to the new startrc.sh
now my automated start.sh work environment is complete... for now 😼
If running a bash script just add gedit afile to the end of the script and that will hold gnome-terminal open. "afile" could be a build log which it was in my case.
Did not try just using gedit alone but, that would properly work too.
Use nohup command.
nohup gnome-terminal -e "ssh root# cd /tmp && ls"
Hope this will help you.

Resources