;;; acdw-circe.el --- bespoke circe customizations -*- lexical-binding: t -*- ;;; Commentary: ;; Besoke Circe customizations. ;;; Code: (require 'circe) (require 'el-patch) ;;; Functions (defun irc () "Connect to all IRC networks in `circe-network-options'." (interactive) (dolist (network (mapcar #'car circe-network-options)) (unless (member network circe-network-inhibit-autoconnect) (circe-maybe-connect network)))) (defun circe-network-connected-p (network) "Return whether circe is connected to NETWORK." (catch 'return (dolist (buffer (circe-server-buffers)) (with-current-buffer buffer (if (string= network circe-server-network) (throw 'return t)))))) (defun circe-maybe-connect (network) "Connect to NETWORK, asking for confirmation to reconnect." (interactive "sNetwork: ") (if (or (not (circe-network-connected-p network)) (y-or-n-p (format "Already connected to %s, reconnect? " network))) (circe network))) (defun circe-current-topic (&optional message) "Return the topic of the current channel. When called with MESSAGE set to non-nil (or interactively), also message the current topic." (interactive "p") (let ((topic (save-excursion (goto-char (point-max)) (or (re-search-backward (rx (group "*** Topic" (+ (not ":")) ": ") (group (+ nonl))))) (buffer-substring-no-properties (match-beginning 2) (match-end 2))))) (when message (message "%s" topic)) topic)) ;;; Chat commands (defun circe-command-SHORTEN (url) "Shorten URL using `0x0-shorten-uri'." (interactive "sURL to shorten: ") (require '0x0) ;; TODO: enable /shorten URL comment syntax (let ((short-url (0x0-shorten-uri (0x0--choose-server) url))) (circe-command-SAY short-url))) (defun circe-command-SLAP (nick) "Slap NICK around a bit with a large trout." (interactive "sWho we slappin' today, boss? ") (circe-command-ME (concat "slaps " (string-trim nick) " around a bit with a large trout"))) ;;; Hooks (defun circe-chat@set-prompt () "Set the prompt to the buffer name, shortening it." (interactive) ; set interactive to unfuck the prompt when need be (lui-set-prompt (propertize (concat (acdw-irc/margin-format (buffer-name) "" ">") " ") 'face 'circe-prompt-face 'read-only t 'intangible t 'cursor-intangible t))) ;;; Advices (defun circe-part@kill-buffer (&rest _) "Advice to kill the channel buffer after PART." (let ((circe-channel-killed-confirmation nil)) (kill-buffer))) (defun circe-quit@kill-buffer (&rest _) "Advice to kill all buffers of a server after QUIT." ;; `circe-server-killed-confirmation' set to nil, and manually ;; deleting all chat buffers, pending Github issue #402 ;; (https://github.com/emacs-circe/circe/issues/402) (let ((circe-server-killed-confirmation nil)) (with-circe-server-buffer (dolist (buf (circe-server-chat-buffers)) (let ((circe-channel-killed-confirmation nil)) (run-with-timer 0.1 nil #'kill-buffer buf))) (run-with-timer 0.1 nil #'kill-buffer)))) (defun circe-gquit@kill-buffer (&rest _) "Advice to kill all Circe related buffers after GQUIT." ;; `circe-server-killed-confirmation' set to nil, and manually ;; deleting all chat buffers, pending Github issue #402 ;; (https://github.com/emacs-circe/circe/issues/402) (let ((circe-server-killed-confirmation nil)) (dolist (buf (circe-server-buffers)) (with-current-buffer buf (dolist (buf (circe-server-chat-buffers)) (let ((circe-channel-killed-confirmation nil)) (run-with-timer 0.1 nil #'kill-buffer buf))) (run-with-timer 0.1 nil #'kill-buffer))))) ;;; Patches (el-patch-feature circe) (with-eval-after-load 'circe (defvar circe-server-buffer-action 'pop-to-buffer-same-window "What to do with `circe-server' buffers when created.") (el-patch-defun circe (network-or-server &rest server-options) "Connect to IRC. Connect to the given network specified by NETWORK-OR-SERVER. When this function is called, it collects options from the SERVER-OPTIONS argument, the user variable `circe-network-options', and the defaults found in `circe-network-defaults', in this order. If NETWORK-OR-SERVER is not found in any of these variables, the argument is assumed to be the host name for the server, and all relevant settings must be passed via SERVER-OPTIONS. All SERVER-OPTIONS are treated as variables by getting the string \"circe-\" prepended to their name. This variable is then set locally in the server buffer. See `circe-network-options' for a list of common options." (interactive (circe--read-network-and-options)) (let* ((options (circe--server-get-network-options network-or-server server-options)) (buffer (circe--server-generate-buffer options))) (with-current-buffer buffer (circe-server-mode) (circe--server-set-variables options) (circe-reconnect)) (el-patch-swap (pop-to-buffer-same-window buffer) (funcall circe-server-buffer-action buffer))))) ;;; Dumb modes (define-minor-mode circe-cappy-hour-mode "ENABLE CAPPY HOUR IN CIRCE!" :lighter "CAPPY HOUR" (when (derived-mode-p 'circe-chat-mode) (if circe-cappy-hour-mode (setq-local lui-input-function (lambda (input) (circe--input (upcase input)))) ;; XXX: It'd be better if this were more general, but whatever. (setq-local lui-input-function #'circe--input)))) (provide 'acdw-circe) ;;; acdw-circe.el ends here