summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2022-09-26 10:55:22 -0700
committerSean Whitton <spwhitton@spwhitton.name>2022-09-30 22:34:04 -0700
commitab1dbe94462d611ce482d3d52ddd4262bdd69228 (patch)
treefb4307f62870cb235ccea11e7efd7a08e491b099
parent124632f7aca4beaca62ab10c711be3b1c65b851d (diff)
downloaddotfiles-ab1dbe94462d611ce482d3d52ddd4262bdd69228.tar.gz
gdbmacs instance, s.t. can always run Emacs under gdb, and for Gnus
-rw-r--r--.bashrc2
-rw-r--r--.config/i3/config5
-rw-r--r--.config/sway/config4
-rw-r--r--.emacs.d/eshell/profile6
-rw-r--r--.emacs.d/init.el58
-rwxr-xr-xbin/doccheckin6
-rwxr-xr-xbin/emacsclient35
7 files changed, 95 insertions, 21 deletions
diff --git a/.bashrc b/.bashrc
index 5d35be85..3759e392 100644
--- a/.bashrc
+++ b/.bashrc
@@ -51,6 +51,7 @@ alias ta="tmux new-session -A -s default"
alias rax="screen -URaAx"
alias new-login-shell="exec su -l $USER" # get new UNIX group without relog
alias mrs="src-register-all && mr -m status"
+alias gdbmacs="emacsclient -tc -sgdbmacs --spw/installed"
alias b="bts --mbox show"
@@ -79,6 +80,7 @@ upenv () {
done
fi
emacsclient --spw/update-environment
+ emacsclient -sgdbmacs --spw/no-start --spw/update-environment
}
# --- host-specific aliases/functions
diff --git a/.config/i3/config b/.config/i3/config
index 4ec955ee..7c9291cd 100644
--- a/.config/i3/config
+++ b/.config/i3/config
@@ -64,6 +64,9 @@ mode "C-i-" {
# override the script's usual logic to start a fresh, non-debug daemon
bindsym Shift+e exec emacsclient -nc --spw/installed, mode "default"
+ # special daemon instance for debugging primary instance & Gnus
+ bindsym Mod1+e exec emacsclient -nc -sgdbmacs --spw/installed, mode "default"
+
# Fresh Emacs frame and get a shell in HOME. Without this it's
# C-i e M-& which is too many keys esp. compared to C-i DEL
bindsym Return exec emacsclient -nce \
@@ -352,6 +355,8 @@ bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle
exec --no-startup-id emacsclient --spw/update-environment
+exec --no-startup-id emacsclient \
+ -sgdbmacs --spw/no-start --spw/update-environment
exec --no-startup-id xss-lock --transfer-sleep-lock -- \
i3lock --nofork --ignore-empty-password --color=FFFFF6
diff --git a/.config/sway/config b/.config/sway/config
index 0a38700d..e258f6b5 100644
--- a/.config/sway/config
+++ b/.config/sway/config
@@ -49,6 +49,9 @@ mode "C-i-" {
# override the script's usual logic to start a fresh, non-debug daemon
bindsym Shift+e exec emacsclient -nc --spw/installed, mode "default"
+ # special daemon instance for debugging primary instance & Gnus
+ bindsym Mod1+e exec emacsclient -nc -sgdbmacs --spw/installed, mode "default"
+
# Fresh Emacs frame and get a shell in HOME. Without this it's
# C-i e M-& which is too many keys esp. compared to C-i DEL
bindsym Return exec emacsclient -nce \
@@ -378,6 +381,7 @@ seat * hide_cursor 5000
exec mako
exec emacsclient --spw/update-environment
+exec emacsclient -sgdbmacs --spw/no-start --spw/update-environment
exec_always fcitx5 -d --replace
diff --git a/.emacs.d/eshell/profile b/.emacs.d/eshell/profile
index 59099604..42eb0e8a 100644
--- a/.emacs.d/eshell/profile
+++ b/.emacs.d/eshell/profile
@@ -1,7 +1,7 @@
# for processes spawned by Eshell, drop the -c/-t set in ~/.shenv, so that the
-# Emacs frame containing Eshell gets reused
-export EDITOR=emacsclient
-export VISUAL=emacsclient
+# Emacs frame containing Eshell gets reused, and pass -s if necessary
+export EDITOR="emacsclient$(if (stringp (daemonp)) (concat \" -s\" (daemonp)) \"\")"
+export VISUAL="$EDITOR"
# debconf will fall back to this frontend but emit a warning; set it ourselves
# to avoid that warning
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
index c85c779e..559ed09f 100644
--- a/.emacs.d/init.el
+++ b/.emacs.d/init.el
@@ -77,7 +77,10 @@
;; we're probably a shortlived instance of Emacs just to test something.
;; Set a different background colour to more easily distinguish frames
;; belonging to shortlived instances from those belonging to main instance.
- `(,ws . ((background-color . ,(if (daemonp) "#FFFFF6" "alice blue"))))))
+ `(,ws
+ . ((background-color
+ . ,(pcase (daemonp)
+ ('nil "alice blue") ("gdbmacs" "honeydew") (_ "#FFFFF6")))))))
(defun spw/maybe-scale-basic-faces (frame)
"Entry for `window-size-change-functions' to increase font sizes
@@ -2233,6 +2236,43 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
(let ((slime-dispatching-connection connection))
(slime-eval cl-form))))))
+(defvar-local spw/gdbmacs-target-emacs nil)
+
+(defun spw/gdbmacs-attach (pid)
+ (interactive "nEmacs PID: ")
+ (when-let ((proc (and (boundp 'gud-comint-buffer)
+ (get-buffer-process gud-comint-buffer))))
+ (if (string= gdb-inferior-status "signal-received")
+ ;; Avoid wiping out useful info.
+ (error "Possibly Emacs just crashed; not attaching for now")
+ (set-process-query-on-exit-flag proc nil)
+ (kill-buffer gud-comint-buffer)))
+ (require 'gdb-mi)
+ (let ((default-directory (expand-file-name "~/src/emacs/")))
+ (gdb-reset)
+ (gdb (format "gdb -i=mi --pid=%d src/emacs" pid))
+ (setq spw/gdbmacs-target-emacs pid)
+ (gud-basic-call "continue")))
+
+(defun spw/remote-gdbmacs-attach ()
+ (interactive)
+ (call-process "emacsclient" nil "*gdbmacs-emacsclient*" nil
+ "--socket-name=gdbmacs" "--spw/installed"
+ "-e" (prin1-to-string `(spw/gdbmacs-attach ,(emacs-pid)))))
+
+(defun spw/maybe-remote-gdbmacs-attach ()
+ (when (and (eq (daemonp) t)
+ (file-in-directory-p invocation-directory "~/src/emacs/"))
+ (spw/remote-gdbmacs-attach)))
+(add-hook 'after-init-hook #'spw/maybe-remote-gdbmacs-attach)
+
+;; C-c C-z to attempt to return control to the debugger.
+(defun spw/comint-stop-subjob (orig-fun)
+ (if spw/gdbmacs-target-emacs
+ (signal-process spw/gdbmacs-target-emacs 'SIGTSTP)
+ (funcall orig-fun)))
+(advice-add 'comint-stop-subjob :around #'spw/comint-stop-subjob)
+
;; open a frame on a new workspace with only the relevant dired buffer open,
;; eval this form: (global-set-key "\C-cG" #'spw/grading-advance)
;; and then use C-c G to open the first item (will need C-c f t after just
@@ -2678,13 +2718,15 @@ mutt's review view, after exiting EDITOR."
(defvar gnus-always-read-dribble-file)
(defun spw/gnus-startup-wrapper (orig-fun &rest args)
- (if (and (daemonp) (file-directory-p "~/.fmail/")
- (not (file-exists-p "~/.newsrc.eld")))
- (user-error "Must use dedicated Emacs for Gnus first run")
- (let ((gc-cons-percentage 0.6)
- (gc-cons-threshold 402653184)
- (gnus-always-read-dribble-file (file-exists-p "~/.newsrc.eld")))
- (apply orig-fun args))))
+ (when-let ((daemon (and (file-directory-p "~/.fmail/") (daemonp))))
+ (unless (file-exists-p "~/.newsrc.eld")
+ (user-error "Must use dedicated Emacs for Gnus first run"))
+ (unless (string= "gdbmacs" daemon)
+ (user-error "This is not the Gnusmacs you're looking for")))
+ (let ((gc-cons-percentage 0.6)
+ (gc-cons-threshold 402653184)
+ (gnus-always-read-dribble-file (file-exists-p "~/.newsrc.eld")))
+ (apply orig-fun args)))
(advice-add 'gnus :around #'spw/gnus-startup-wrapper)
(advice-add 'gnus-no-server :around #'spw/gnus-startup-wrapper)
diff --git a/bin/doccheckin b/bin/doccheckin
index 92afe12b..b7a1eb35 100755
--- a/bin/doccheckin
+++ b/bin/doccheckin
@@ -7,8 +7,10 @@ cd ~/doc/
# also want to use it as the myrepos autoci action for ~/doc/.
# If emacs is running, try to save all ~/doc/ buffers.
-[ -n "$LOGNAME" ] && pgrep -u "$LOGNAME" emacs >/dev/null \
- && emacsclient --eval '(spw/save-my-doc-buffers)'
+if [ -n "$LOGNAME" ] && pgrep -u "$LOGNAME" emacs >/dev/null; then
+ emacsclient --eval '(spw/save-my-doc-buffers)'
+ emacsclient -sgdbmacs --spw/no-start --eval '(spw/save-my-doc-buffers)'
+fi
# don't do anything if waiting on a manual merge; don't want just
# blanket commit that merge
diff --git a/bin/emacsclient b/bin/emacsclient
index 0e6ab7a6..c261d469 100755
--- a/bin/emacsclient
+++ b/bin/emacsclient
@@ -21,11 +21,25 @@
# 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}" ;;&
@@ -34,14 +48,9 @@ for arg do
esac
done
-command -v ss >/dev/null || exit 1
-socket="/run/user/$(id -u)/emacs/${daemon_name:-server}"
-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"
-elif [ -n "$listener" ]; then
+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 ;;
@@ -51,10 +60,20 @@ 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