I wanted to bind a single hot key to open and close gnome-terminal in a way similar to terminal emulators such as tilda or guake. I use Ubuntu, and have configured this script to be executed when I press the key F1
The script will focus or minimize the first gnome-terminal window that is running. If no gnome-terminal is running, it will start a new one and place it in the top half of the screen.
#!/bin/bash
# Bind this script to a keyboard shortcut to add "pull-down" behaviour to
# the Gnome terminal similar to guake or tilda
# It seems to work with gnome-terminal or xfce4-terminal
# I haven't tested any other terminal emulators
TERMINAL_EMULATOR=gnome-terminal
function main {
if [[ -z $(terminal_process) ]]; then
# no running terminal emulator
# open new terminal at top of the screen
$TERMINAL_EMULATOR --geometry 80x1+0+0 &
win_id=$(get_terminal_window)
# set initial width to 100% and height to 45%
xdotool windowsize $win_id $(absolute_window_size 100 45)
xdotool windowactivate $win_id
else
win_id=$(get_terminal_window)
if [[ $(xdotool getactivewindow) == $win_id ]]; then
# if terminal window is active, mimize
xdotool getactivewindow windowminimize
else
# if terminal window is inactive, bring in focus
xdotool windowactivate $win_id
fi
fi
}
function terminal_process {
# Is gnome-terminal already running
echo $( ps aux | grep $TERMINAL_EMULATOR | grep -v grep)
}
function get_terminal_window {
# get id of open terminal window. Will wait for window to open if neccessary
echo $(xdotool search --onlyvisible --sync --limit 1 --class $TERMINAL_EMULATOR)
}
function absolute_window_size {
# convert relative window size to absolute pixel size, based on screen res
width_percent=1ドル
height_percent=2ドル
IFS=x
screen_dimensions=$(xrandr | grep connected | grep -o '[1-9]\+x[0-9]\+')
set $screen_dimensions
echo $(($width_percent*1ドル/100)) $(($height_percent*2ドル/100))
}
main
As someone coming from python, bash feels quite unfamiliar, and I would like some feedback on whether this script follows best practices. I also wonder if there's anything that can be simplified without losing readability.
1 Answer 1
Instead of this:
function terminal_process { # Is gnome-terminal already running echo $( ps aux | grep $TERMINAL_EMULATOR | grep -v grep) }
You don't need the echo
, you can let the standard output simply go through:
terminal_process() {
# Is gnome-terminal already running
ps aux | grep $TERMINAL_EMULATOR | grep -v grep
}
The same goes for get_terminal_window
too.
Notice that I also changed the wording style of the function definition. This is the recommended style in bash, I suggest to apply this to all your functions.
You can actually go even further. [[ -z $(terminal_process) ]]
is actually a text comparison, checking if the output of the command as a string is empty. Instead of that, it would be better to use the exit code of the function, like this:
if ! terminal_process; then
# ...
This works, because the exit of grep
will be success (= 0) if it matched something (process exists), and failure (non-zero) if it didn't match.
However, when using the function like this, since the output of grep
is not captured within a $(...)
, it will be printed on stdout
, which you probably want to avoid. You can easily suppress that by adding the -q
flag:
terminal_process() {
# Is gnome-terminal already running
ps aux | grep $TERMINAL_EMULATOR | grep -qv grep
}
This can also be simplified:
echo $(($width_percent*1ドル/100)) $(($height_percent*2ドル/100))
Like this:
echo $((width_percent * 1ドル / 100)) $((height_percent * 2ドル / 100))
-
\$\begingroup\$ Will
$(function_call)
, catch everything that goes to stdout in the function? \$\endgroup\$Håken Lid– Håken Lid2016年02月05日 08:12:04 +00:00Commented Feb 5, 2016 at 8:12 -
1\$\begingroup\$ Yes it will. But actually I added an even better solution that doesn't need
stdout
at all, see my updated answer. \$\endgroup\$janos– janos2016年02月05日 08:48:28 +00:00Commented Feb 5, 2016 at 8:48