diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2022-09-26 10:55:22 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2022-09-30 22:34:04 -0700 |
commit | ab1dbe94462d611ce482d3d52ddd4262bdd69228 (patch) | |
tree | fb4307f62870cb235ccea11e7efd7a08e491b099 | |
parent | 124632f7aca4beaca62ab10c711be3b1c65b851d (diff) | |
download | dotfiles-ab1dbe94462d611ce482d3d52ddd4262bdd69228.tar.gz |
gdbmacs instance, s.t. can always run Emacs under gdb, and for Gnus
-rw-r--r-- | .bashrc | 2 | ||||
-rw-r--r-- | .config/i3/config | 5 | ||||
-rw-r--r-- | .config/sway/config | 4 | ||||
-rw-r--r-- | .emacs.d/eshell/profile | 6 | ||||
-rw-r--r-- | .emacs.d/init.el | 58 | ||||
-rwxr-xr-x | bin/doccheckin | 6 | ||||
-rwxr-xr-x | bin/emacsclient | 35 |
7 files changed, 95 insertions, 21 deletions
@@ -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 |