diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-11 17:17:54 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-11 17:17:54 -0500 |
| commit | bbd1b73cbaf1716734b1193467564a0c7122dec7 (patch) | |
| tree | a229758b212f324c4a2e4d8102c60e6503dedee0 /modules/slack-config.el | |
| parent | eddc103fd251e324f8bd5c9000ed8d29cb59c602 (diff) | |
| download | dotemacs-bbd1b73cbaf1716734b1193467564a0c7122dec7.tar.gz dotemacs-bbd1b73cbaf1716734b1193467564a0c7122dec7.zip | |
fix(slack): harden and curate the C-; S ! reaction workflow
Two problems with `C-; S !'. First, emacs-slack's `slack-reaction-echo-description' runs in a buffer-local `post-command-hook' and can error on every keystroke when a reaction widget's text properties are malformed, which makes it hard to leave the Slack buffer or recover with C-g. It's now wrapped in `condition-case' that, on error, removes the hook from that buffer's local `post-command-hook' and messages once. Second, without emojify the upstream reaction picker is a flat completing-read over 1600+ names. `cj/slack-message-add-reaction' now offers a curated common list (`thumbsup', `pray', `eyes', `white_check_mark', `heart', `joy', `thinking_face', `rocket', `tada') with "Other..." delegating back to `slack-message-reaction-input' for the full set. Tests cover the hook hardening, the curated picker, and the `C-; S !' rebinding.
Diffstat (limited to 'modules/slack-config.el')
| -rw-r--r-- | modules/slack-config.el | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/modules/slack-config.el b/modules/slack-config.el index d8fd3f83..14d15ecf 100644 --- a/modules/slack-config.el +++ b/modules/slack-config.el @@ -35,6 +35,30 @@ ;;; Code: (require 'auth-source) +(require 'cl-lib) + +(defvar slack-current-buffer) +(defvar slack-message-compose-buffer-mode-map) +(defvar slack-message-custom-notifier) +(defvar slack-teams) + +(declare-function slack-buffer-add-reaction-to-message "slack-buffer") +(declare-function slack-buffer-latest-ts "slack-buffer") +(declare-function slack-buffer-team "slack-buffer") +(declare-function slack-buffer-update-mark-request "slack-buffer") +(declare-function slack-get-ts "slack-util") +(declare-function slack-im-p "slack-im") +(declare-function slack-message-body "slack-message") +(declare-function slack-message-embed-channel "slack-message-buffer") +(declare-function slack-message-embed-mention "slack-message-buffer") +(declare-function slack-message-mentioned-p "slack-message") +(declare-function slack-message-minep "slack-message") +(declare-function slack-message-reaction-input "slack-message-reaction") +(declare-function slack-message-send-from-buffer "slack-message-sender") +(declare-function slack-message-write-another-buffer "slack-message-buffer") +(declare-function slack-reaction-echo-description "slack-buffer") +(declare-function slack-room-display-name "slack-room") +(declare-function slack-ws-close "slack") (defvar cj/slack-workspace "deepsatworkspace.slack.com" "Slack workspace domain for auth-source lookup.") @@ -91,6 +115,75 @@ :config (setq slack-message-custom-notifier #'cj/slack-notify)) +;; ------------------------------ Reactions ------------------------------------ + +(defvar cj/slack-common-reactions + '(("thumbs up" . "+1") + ("thumbsup" . "thumbsup") + ("thumbs down" . "-1") + ("pray" . "pray") + ("raised hands" . "raised_hands") + ("eyes" . "eyes") + ("white check mark" . "white_check_mark") + ("heavy check mark" . "heavy_check_mark") + ("plus one" . "+1") + ("heart" . "heart") + ("heart eyes" . "heart_eyes") + ("joy" . "joy") + ("laughing" . "laughing") + ("smile" . "smile") + ("thinking face" . "thinking_face") + ("rocket" . "rocket") + ("fire" . "fire") + ("party" . "tada") + ("clap" . "clap") + ("ok hand" . "ok_hand")) + "Curated common Slack reaction labels mapped to Slack emoji names.") + +(defun cj/slack--safe-reaction-echo-description (orig-fun &rest args) + "Call ORIG-FUN safely from `post-command-hook'. +If emacs-slack sees a malformed reaction text property, remove the local hook +so the Slack buffer stays usable." + (condition-case err + (apply orig-fun args) + (error + (remove-hook 'post-command-hook #'slack-reaction-echo-description t) + (message "Slack reaction hover disabled in this buffer: %s" + (error-message-string err))))) + +(defun cj/slack--reaction-candidates () + "Return display candidates for `cj/slack-common-reactions'." + (append + (mapcar (lambda (entry) + (let ((label (car entry)) + (name (cdr entry))) + (cons (format "%-18s :%s:" label name) name))) + cj/slack-common-reactions) + '(("Other..." . :other)))) + +(defun cj/slack-select-reaction (team) + "Select a Slack reaction for TEAM, preferring a short common list." + (let* ((candidates (cj/slack--reaction-candidates)) + (choice (completing-read "Reaction: " candidates nil t)) + (reaction (cdr (assoc choice candidates)))) + (if (eq reaction :other) + (slack-message-reaction-input team) + reaction))) + +(defun cj/slack-message-add-reaction () + "Add a reaction to the current Slack message using a curated shortlist." + (interactive) + (when-let* ((buf slack-current-buffer) + (team (slack-buffer-team buf)) + (reaction (cj/slack-select-reaction team))) + (slack-buffer-add-reaction-to-message buf + reaction + (slack-get-ts)))) + +(with-eval-after-load 'slack-buffer + (advice-add 'slack-reaction-echo-description + :around #'cj/slack--safe-reaction-echo-description)) + ;; ----------------------------- Notifications --------------------------------- (defun cj/slack-notify (message room team) @@ -153,7 +246,7 @@ swallows exceptions via `websocket-try-callback'." (define-key cj/slack-keymap (kbd "w") #'slack-message-write-another-buffer) (define-key cj/slack-keymap (kbd "r") #'slack-thread-show-or-create) (define-key cj/slack-keymap (kbd "e") #'slack-insert-emoji) -(define-key cj/slack-keymap (kbd "!") #'slack-message-add-reaction) +(define-key cj/slack-keymap (kbd "!") #'cj/slack-message-add-reaction) (define-key cj/slack-keymap (kbd "@") #'slack-message-embed-mention) (define-key cj/slack-keymap (kbd "#") #'slack-message-embed-channel) (define-key cj/slack-keymap (kbd "q") #'cj/slack-mark-read-and-bury) |
