doomemacs/modules/app/irc/config.el
Henrik Lissner ad6a3d0f33
refactor: deprecate featurep! for modulep!
featurep! will be renamed modulep! in the future, so it's been
deprecated. They have identical interfaces, and can be replaced without
issue.

featurep! was never quite the right name for this macro. It implied that
it had some connection to featurep, which it doesn't (only that it was
similar in purpose; still, Doom modules are not features). To undo such
implications and be consistent with its namespace (and since we're
heading into a storm of breaking changes with the v3 release anyway),
now was the best opportunity to begin the transition.
2022-08-14 20:43:35 +02:00

258 lines
9.9 KiB
EmacsLisp

;;; app/irc/config.el -*- lexical-binding: t; -*-
(defvar +irc-left-padding 13
"By how much spaces the left hand side of the line should be padded.
Below a value of 12 this may result in uneven alignment between the various
types of messages.")
(defvar +irc-truncate-nick-char ?…
"Character to displayed when nick > `+irc-left-padding' in length.")
(defvar +irc-scroll-to-bottom-on-commands
'(self-insert-command yank hilit-yank)
"If these commands are called pre prompt the buffer will scroll to `point-max'.")
(defvar +irc-disconnect-hook nil
"Runs each hook when circe noticies the connection has been disconnected.
Useful for scenarios where an instant reconnect will not be successful.")
(defvar +irc-bot-list '("fsbot" "rudybot")
"Nicks listed have `circe-fool-face' applied and will not be tracked.")
(defvar +irc-time-stamp-format "%H:%M"
"The format of time stamps.
See `format-time-string' for a full description of available
formatting directives. ")
(defvar +irc-notifications-watch-strings nil
"A list of strings which can trigger a notification. You don't need to put
your nick here.
See `circe-notifications-watch-strings'.")
(defvar +irc-defer-notifications nil
"How long to defer enabling notifications, in seconds (e.g. 5min = 300).
Useful for ZNC users who want to avoid the deluge of notifications during buffer
playback.")
(defvar +irc--defer-timer nil)
(defsubst +irc--pad (left right)
(format (format "%%%ds | %%s" +irc-left-padding)
(concat "*** " left) right))
;;
;; Packages
(use-package! circe
:commands circe circe-server-buffers
:config
(setq circe-default-quit-message nil
circe-default-part-message nil
circe-use-cycle-completion t
circe-reduce-lurker-spam t
circe-format-say (format "{nick:+%ss} │ {body}" +irc-left-padding)
circe-format-self-say circe-format-say
circe-format-action (format "{nick:+%ss} * {body}" +irc-left-padding)
circe-format-self-action circe-format-action
circe-format-server-notice
(let ((left "-Server-")) (concat (make-string (- +irc-left-padding (length left)) ? )
(concat left " _ {body}")))
circe-format-notice (format "{nick:%ss} _ {body}" +irc-left-padding)
circe-format-server-topic
(+irc--pad "Topic" "{userhost}: {topic-diff}")
circe-format-server-join-in-channel
(+irc--pad "Join" "{nick} ({userinfo}) joined {channel}")
circe-format-server-join
(+irc--pad "Join" "{nick} ({userinfo})")
circe-format-server-part
(+irc--pad "Part" "{nick} ({userhost}) left {channel}: {reason}")
circe-format-server-quit
(+irc--pad "Quit" "{nick} ({userhost}) left IRC: {reason}]")
circe-format-server-quit-channel
(+irc--pad "Quit" "{nick} ({userhost}) left {channel}: {reason}]")
circe-format-server-rejoin
(+irc--pad "Re-join" "{nick} ({userhost}), left {departuredelta} ago")
circe-format-server-netmerge
(+irc--pad "Netmerge" "{split}, split {ago} ago (Use /WL to see who's still missing)")
circe-format-server-nick-change
(+irc--pad "Nick" "{old-nick} ({userhost}) is now known as {new-nick}")
circe-format-server-nick-change-self
(+irc--pad "Nick" "You are now known as {new-nick} ({old-nick})")
circe-format-server-nick-change-self
(+irc--pad "Nick" "{old-nick} ({userhost}) is now known as {new-nick}")
circe-format-server-mode-change
(+irc--pad "Mode" "{change} on {target} by {setter} ({userhost})")
circe-format-server-lurker-activity
(+irc--pad "Lurk" "{nick} joined {joindelta} ago"))
(add-hook 'doom-real-buffer-functions #'+circe-buffer-p)
(add-hook 'circe-channel-mode-hook #'turn-on-visual-line-mode)
(add-hook 'circe-mode-hook #'+irc--add-circe-buffer-to-persp-h)
(add-hook 'circe-mode-hook #'turn-off-smartparens-mode)
;; HACK Fix #1862: circe hangs on TLS connections when using OpenSSL versions
;; > 1.1.0, where tls.el does not correctly determine the end of the info
;; block. This fixes proposed in jorgenschaefer/circe#340
(setq-hook! 'circe-mode-hook
tls-end-of-info
(concat "\\("
;; `openssl s_client' regexp. See ssl/ssl_txt.c lines 219-220.
;; According to apps/s_client.c line 1515 `---' is always the last
;; line that is printed by s_client before the real data.
"^ Verify return code: .+\n\\(\\|^ Extended master secret: .+\n\\)\\(\\|^ Max Early Data: .+\n\\)---\n\\|"
;; `gnutls' regexp. See src/cli.c lines 721-.
"^- Simple Client Mode:\n"
"\\(\n\\|" ; ignore blank lines
;; According to GnuTLS v2.1.5 src/cli.c lines 640-650 and 705-715 in
;; `main' the handshake will start after this message. If the
;; handshake fails, the programs will abort.
"^\\*\\*\\* Starting TLS handshake\n\\)*"
"\\)"))
(defadvice! +irc--circe-run-disconnect-hook-a (&rest _)
"Runs `+irc-disconnect-hook' after circe disconnects."
:after #'circe--irc-conn-disconnected
(run-hooks '+irc-disconnect-hook))
(add-hook! 'lui-pre-output-hook
(defun +irc-circe-truncate-nicks-h ()
"Truncate long nicknames in chat output non-destructively."
(when-let (beg (text-property-any (point-min) (point-max) 'lui-format-argument 'nick))
(goto-char beg)
(let ((end (next-single-property-change beg 'lui-format-argument))
(nick (plist-get (plist-get (text-properties-at beg) 'lui-keywords)
:nick)))
(when (> (length nick) +irc-left-padding)
(compose-region (+ beg +irc-left-padding -1) end
+irc-truncate-nick-char))))))
(add-hook! 'circe-message-option-functions
(defun +irc-circe-message-option-bot-h (nick &rest ignored)
"Fontify known bots and mark them to not be tracked."
(when (member nick +irc-bot-list)
'((text-properties . (face circe-fool-face lui-do-not-track t))))))
;; Let `+irc/quit' and `circe' handle buffer cleanup
(define-key circe-mode-map [remap kill-buffer] #'bury-buffer)
;; Fail gracefully if not in a circe buffer
(global-set-key [remap tracking-next-buffer] #'+irc/tracking-next-buffer)
(when (modulep! :completion vertico)
(after! consult
(add-to-list 'consult-buffer-sources '+irc--consult-circe-source 'append)))
(map! :localleader
(:map circe-mode-map
"a" #'tracking-next-buffer
"j" #'circe-command-JOIN
"m" #'+irc/send-message
"p" #'circe-command-PART
"Q" #'+irc/quit
"R" #'circe-reconnect
"c" #'+irc/jump-to-channel)
(:map circe-channel-mode-map
"n" #'circe-command-NAMES)))
(use-package! circe-color-nicks
:hook (circe-channel-mode . enable-circe-color-nicks)
:config
(setq circe-color-nicks-min-constrast-ratio 4.5
circe-color-nicks-everywhere t))
(use-package! circe-new-day-notifier
:after circe
:config
(enable-circe-new-day-notifier)
(setq circe-new-day-notifier-format-message
(+irc--pad "Day" "Date changed [{day}]")))
(use-package! circe-notifications
:commands enable-circe-notifications
:init
(add-hook! 'circe-server-connected-hook
(defun +irc-init-circe-notifications-h ()
(if (numberp +irc-defer-notifications)
(setq +irc--defer-timer
(run-at-time +irc-defer-notifications nil
#'enable-circe-notifications))
(enable-circe-notifications))))
:config
(setq circe-notifications-watch-strings +irc-notifications-watch-strings
circe-notifications-emacs-focused nil
circe-notifications-alert-style
(cond (IS-MAC 'osx-notifier)
(IS-LINUX 'libnotify)
(circe-notifications-alert-style))))
(use-package! lui
:commands lui-mode
:config
(define-key lui-mode-map "\C-u" #'lui-kill-to-beginning-of-line)
(setq lui-fill-type nil)
(when (modulep! :checkers spell)
(setq lui-flyspell-p t))
(after! evil
(defun +irc-evil-insert-h ()
"Ensure entering insert mode will put us at the prompt, unless editing
after prompt marker."
(when (> (marker-position lui-input-marker) (point))
(goto-char (point-max))))
(add-hook! 'lui-mode-hook
(add-hook 'evil-insert-state-entry-hook #'+irc-evil-insert-h
nil 'local))
(mapc (lambda (cmd) (push cmd +irc-scroll-to-bottom-on-commands))
'(evil-paste-after evil-paste-before evil-open-above evil-open-below)))
(defun +irc-preinput-scroll-to-bottom-h ()
"Go to the end of the buffer in all windows showing it.
Courtesy of esh-mode.el"
(when (memq this-command +irc-scroll-to-bottom-on-commands)
(let* ((selected (selected-window))
(current (current-buffer)))
(when (> (marker-position lui-input-marker) (point))
(walk-windows
(function
(lambda (window)
(when (eq (window-buffer window) current)
(select-window window)
(goto-char (point-max))
(select-window selected))))
nil t)))))
(add-hook! 'lui-mode-hook
(add-hook 'pre-command-hook #'+irc-preinput-scroll-to-bottom-h nil t))
;; enable a horizontal line marking the last read message
(add-hook 'lui-mode-hook #'enable-lui-track-bar)
(add-hook! 'lui-mode-hook
(defun +irc-init-lui-margins-h ()
(setq lui-time-stamp-position 'right-margin
lui-time-stamp-format +irc-time-stamp-format
right-margin-width (length (format-time-string lui-time-stamp-format))))
(defun +irc-init-lui-wrapping-a ()
(setq fringes-outside-margins t
word-wrap t
wrap-prefix (make-string (+ +irc-left-padding 3) ? )))))
(use-package! lui-logging
:after lui
:config (enable-lui-logging))
(use-package! lui-autopaste
:hook (circe-channel-mode . enable-lui-autopaste))