Skip to content

Instantly share code, notes, and snippets.

@alphapapa
Last active August 12, 2023 06:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alphapapa/86a64b748012915961a83cd7e400a4af to your computer and use it in GitHub Desktop.
Save alphapapa/86a64b748012915961a83cd7e400a4af to your computer and use it in GitHub Desktop.
Raise an Emacs window or run Emacs
#!/bin/bash
# ** Vars
# *** Emacs version
emacs="emacs"
emacsclient="emacsclient"
emacsWindowClass="Emacs"
# ** Functions
function findEmacsWindows {
# Searching by window class or classname is not enough, because it
# also finds Emacs' invisible windows. But the invisible windows
# do not have WM_HINTS (although they do have
# WM_NORMAL_HINTS...sigh). So to find the regular Emacs windows,
# find the ones that have WM_HINTS. ... But sometimes Emacs
# opens more than one invisible window (?!). And one of those
# windows may have WM_HINTS! But it seems that only the real,
# usable window has "_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL".
# So grep for that to find the One True Window.
#
# ...the next day...
#
# Unbelievable. 24 hours later and I haven't changed anything but
# it is picking up one of the TWO invisible windows since now one
# of those invisible windows now has "_NET_WM_WINDOW_TYPE(ATOM) =
# _NET_WM_WINDOW_TYPE_NORMAL" even though it didn't before. So
# now I have to try something like the FOURTH different method of
# determining which Emacs window is the ACTUAL WINDOW...
#
# Ok, let's try looking for "window state:" which SHOULD only be
# listed for an actual, usable window...
for windowID in $(xdotool search --class $emacsWindowClass)
do
if [[ $(xprop -id $windowID WM_STATE) =~ "window state:" ]]
then
# Test against excludes
if ! [[ $(xprop -id $windowID WM_ICON_NAME) =~ "Matrix" ]]
then
# No excludes match: return window ID
echo $windowID
fi
fi
done
}
function ifset {
# Call like: if ifset command varname
# then
# for i in $varname
declare -n ref=$2
ref=$($1)
[[ $ref ]] && return 0 || return 1
}
# ** Main
# *** Check for xdotool
if ! type xdotool &>/dev/null # type works and is a bash builtin
then
message="Install xdotool."
echo "$message"
notify-send "$message"
exit 1
fi
# *** Get current window
currentWindow=$(xdotool getwindowfocus)
# Get current window class (not classname)
currentWindowClass=$(xprop -id $currentWindow WM_CLASS | awk '{ print $4 }' | tr -d '"')
# *** Minimize, raise, or run Emacs
if [[ $currentWindowClass = $emacsWindowClass ]]
then
# Emacs is the active window. Minimize it.
$emacsclient -e "(switch-to-buffer \"*scratch*\")"
xdotool windowminimize $currentWindow &>/dev/null
else
# Emacs is not the active window. Try to raise an Emacs window.
if ifset findEmacsWindows emacsWindows
then
# Emacs windows found
for window in $emacsWindows
do
# Restore/unminimize, raise to top, and activate/focus
xdotool windowmap --sync $window windowraise $window windowactivate $window &>/dev/null
done
else
# No Emacs windows found. Run Emacs.
if pgrep -f "emacs --daemon"
then
$emacsclient -c -n
else
$emacs # NOTE: [2017-12-06 Wed 09:03] Launching the daemon directly causes theme issues, so don't for now: --daemon
#$emacsclient -c -n
fi
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment