blob: c261d4697af631e70b0632b947916b1837e1511d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/bin/bash
# Copyright (C) 2022 Sean Whitton
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# emacsclient(1) wrapper to handle updating the environment of existing
# daemons and choosing between installed and in-tree builds of Emacs.
min_arg=0
command -v ss >/dev/null || exit 1
socket_dir="/run/user/$(id -u)/emacs/"
get_listener () {
local socket="$1"
local listener=$(ss -Hplx src "$socket" \
| perl -wne'/pid=(\d+)/ and print $1')
if [ -z "$listener" -a -e "$socket" ]; then
# Nothing is listening: remove dangling socket.
rm "$socket"
else
echo "$listener"
fi
}
for arg do
shift
case "$arg" in
'--spw/installed') mode=--spw/installed ;;
'--spw/no-start') start=false ;;
'--spw/update-environment') update=true ;;
'-s'|'--socket-name') min_arg=2; daemon_name="$1" ;;&
'-s'?*) min_arg=1; daemon_name="${arg:2}" ;;&
'--socket-name='?*) min_arg=1; daemon_name="${arg:14}" ;;&
*) set -- "$@" "$arg" ;;
esac
done
socket="$socket_dir${daemon_name:-server}"
listener="$(get_listener $socket)"
if [ -n "$listener" ]; then
case "$(ps h -o exe $listener | sed -e 's/ (deleted)$//')" in
"$HOME/src/emacs/src/emacs") devel_running=true ;;
"$(realpath $(command -v emacs))") installed_running=true ;;
*) echo >&2 "Unknown Emacs listening on $socket"; exit 1 ;;
esac
fi
if [ "$devel_running" = true -a "$mode" = --spw/installed ]; then
kill "$listener"
# Detach gdb so that Emacs can handle the SIGTERM.
# We also have to quit gdb so that `gdb-inferior-status' is reset from
# "signal-received"; see `spw/gdbmacs-attach' command.
[ -n "$(get_listener ${socket_dir}gdbmacs)" ] \
&& emacsclient -sgdbmacs --eval '(gud-basic-call "detach")' \
--eval '(gud-basic-call "quit")'
[ -e "$socket" ] && inotifywait -qqt 2 -e delete "$socket"
devel_running=false
fi
[ "$start" = false -a -z "$listener" ] && exit 0
# We check whether there is something which looks like the installed Emacs
# running because we do not want the in-tree emacsclient to try to connect to
# that, and we check whether there is a build in progress and no running
# daemon, as we don't want to start a new daemon until the build is finished.
# The idea is that I can always hit C-i e without worrying about builds.
if [ "$mode" != --spw/installed -a "$installed_running" != true \
-a -e "$HOME/src/emacs/admin/flagfile.melete" \
-a -x "$HOME/src/emacs/lib-src/emacsclient" \
-a -d "/usr/share/emacs-snapshot/site-lisp/elpa" ] \
&& ! ( [ "$devel_running" != true ] && ps h -o pid -C make \
| xargs pwdx | grep -q "$HOME/src/emacs" ); then
emacs="$HOME/src/emacs/src/emacs"
emacsclient="$HOME/src/emacs/lib-src/emacsclient"
else
emacs=$(command -v emacs)
emacsclient=$(PATH=$(echo "$PATH" | sed -e "s#$HOME/src/dotfiles/bin:##") \
command -v emacsclient)
fi
# Update Emacs daemon environment vars for a new interactive session. This
# allows us to have the Emacs daemon survive restarts of the graphical desktop
# environment, and to update Emacs on a remote host when there is a new
# forwarded SSH agent socket. See 'upenv' in .bash_defns.
if [ "$update" = true -a -n "$listener" ]; then
for var in DISPLAY WAYLAND_DISPLAY \
XAUTHORITY WINDOWID \
XDG_SESSION_TYPE XDG_CURRENT_DESKTOP \
SWAYSOCK I3SOCK \
SSH_ASKPASS SSH_CONNECTION \
SSH_AUTH_SOCK SSH_AGENT_PID; do
eval isset=\${$var+x}
if [ "$isset" = "x" ]; then
eval val=\$$var
args="$args"' "'$var'" "'$val'"'
fi
done
[ -n "$args" ] \
&& "$emacsclient" -s"${daemon_name:-server}" \
--eval "(spw/update-environment$args))"
fi
# emacsclient(1) requires an argument. As a special case, if there are no
# arguments except -s/--socket-name, and no daemon is running, just start one.
# And if there were no arguments but we were requested just to update env
# vars, exit peacefully.
if [ "$#" -eq "$min_arg" -a -z "$listener" ]; then
exec "$emacs" --daemon"${daemon_name:+=$daemon_name}"
elif ! [ "$#" -eq "$min_arg" -a "$update" = true ]; then
exec "$emacsclient" -a "" "$@"
fi
|