app/irc: general rewrite (#103)

+ Refactor initialization process.
+ Refactor for consistency.
+ Add +irc-defer-notifications (for ZNC users).
+ Rewrote =irc (opens separate workspace + auto-connects to registered
  networks).
+ Add +irc/connect (connect to specific network).
+ Add +irc/quit (kill whole circe session).
+ Add +irc/ivy-jump-to-channel command.
+ Rewrite README.
+ Silence QUIT/PART default messages; they're cute, but no thanks.
+ Truncate nicks non-destructively.
+ Jump to prompt when entering insert mode (with evil).
+ Activate solaire-mde in channel buffers to visually distinguish them
  from server buffers.
This commit is contained in:
Henrik Lissner 2017-06-12 12:37:38 +02:00
parent 07299c5020
commit b3dafe96d3
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
3 changed files with 201 additions and 90 deletions

View file

@ -1,9 +1,5 @@
;;; app/irc/config.el -*- lexical-binding: t; -*-
;;
;; Config
;;
(defvar +irc-left-padding 13
"TODO")
@ -19,13 +15,18 @@
(defvar +irc-notifications-watch-strings nil
"TODO")
(defvar +irc-connections nil
"A list of connections set with :irc. W")
(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.")
(def-setting! :irc (server letvars)
"Registers an irc server for circe."
`(progn
(push ',(cons server letvars) +irc--accounts)
(push ',(cons server letvars) circe-network-options)))
(defvar +irc--accounts nil)
`(cl-pushnew (cons ,server ,letvars) +irc-connections
:test #'equal :key #'car))
;;
@ -33,93 +34,92 @@
;;
(def-package! circe
;; need a low impact function just to force an eval
:commands (circe circe--version)
:init
(setq circe-network-defaults nil)
:commands (circe circe-server-buffers)
:init (setq circe-network-defaults nil)
:config
(set! :evil-state 'circe-channel-mode 'emacs)
;; change hands
(setq circe-network-options +irc-connections)
(defvaralias '+irc-connections 'circe-network-options)
(defun +irc|circe-format-padding (left right)
(format (format "%%%ds | %%s" +irc-left-padding) left right))
(defsubst +irc--pad (left right)
(format (format "%%%ds | %%s" +irc-left-padding)
(concat "*** " left) right))
(setq circe-use-cycle-completion t
(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-topic
(+irc|circe-format-padding "*** Topic" "{userhost}: {topic-diff}")
(+irc--pad "Topic" "{userhost}: {topic-diff}")
circe-format-server-join-in-channel
(+irc|circe-format-padding "*** Join" "{nick} ({userinfo}) joined {channel}")
(+irc--pad "Join" "{nick} ({userinfo}) joined {channel}")
circe-format-server-join
(+irc|circe-format-padding "*** Join" "{nick} ({userinfo})")
(+irc--pad "Join" "{nick} ({userinfo})")
circe-format-server-part
(+irc|circe-format-padding "*** Part" "{nick} ({userhost}) left {channel}: {reason}")
(+irc--pad "Part" "{nick} ({userhost}) left {channel}: {reason}")
circe-format-server-quit
(+irc|circe-format-padding "*** Quit" "{nick} ({userhost}) left IRC: {reason}]")
(+irc--pad "Quit" "{nick} ({userhost}) left IRC: {reason}]")
circe-format-server-quit-channel
(+irc|circe-format-padding "*** Quit" "{nick} ({userhost}) left {channel}: {reason}]")
(+irc--pad "Quit" "{nick} ({userhost}) left {channel}: {reason}]")
circe-format-server-rejoin
(+irc|circe-format-padding "*** Re-join" "{nick} ({userhost}), left {departuredelta} ago")
(+irc--pad "Re-join" "{nick} ({userhost}), left {departuredelta} ago")
circe-format-server-nick-change
(+irc|circe-format-padding "*** Nick" "{old-nick} ({userhost}) is now known as {new-nick}")
(+irc--pad "Nick" "{old-nick} ({userhost}) is now known as {new-nick}")
circe-format-server-nick-change-self
(+irc|circe-format-padding "*** Nick" "You are now known as {new-nick} ({old-nick})")
(+irc--pad "Nick" "You are now known as {new-nick} ({old-nick})")
circe-format-server-nick-change-self
(+irc|circe-format-padding "*** Nick" "{old-nick} ({userhost}) is now known as {new-nick}")
(+irc--pad "Nick" "{old-nick} ({userhost}) is now known as {new-nick}")
circe-format-server-mode-change
(+irc|circe-format-padding "*** Mode" "{change} on {target} by {setter} ({userhost})")
(+irc--pad "Mode" "{change} on {target} by {setter} ({userhost})")
circe-format-server-lurker-activity
(+irc|circe-format-padding "*** Lurk" "{nick} joined {joindelta} ago"))
(+irc--pad "Lurk" "{nick} joined {joindelta} ago"))
(defun +irc*circe-truncate-nicks (orig-func keywords)
"If nick is too long, truncate it. Uses `+irc-left-padding'
to determine length."
(when (plist-member keywords :nick)
(let* ((long-nick (plist-get keywords :nick))
(short-nick (s-left (- +irc-left-padding 1) long-nick)))
;; only change the nick if it's needed
(unless (or (= +irc-left-padding
(length long-nick))
(equal long-nick short-nick))
(plist-put keywords :nick (s-concat short-nick "")))))
(funcall orig-func keywords))
(advice-add 'circe--display-add-nick-property :around #'+irc*circe-truncate-nicks)
(enable-circe-new-day-notifier)
(defun +irc*circe-disconnect-hook (&rest _)
(run-hooks '+irc-disconnect-hook))
(advice-add 'circe--irc-conn-disconnected :after #'+irc*circe-disconnect-hook)
(defun +irc*circe-truncate-nicks ()
"Truncate long nicknames in chat output (non-destructive)."
(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
?…)))))
(add-hook 'lui-pre-output-hook #'+irc*circe-truncate-nicks)
(add-hook! '+irc-disconnect-hook
(run-at-time "5 minute" nil #'circe-reconnect-all))
(defun +irc|circe-message-option-bot (nick &rest ignored)
(when (member nick +irc-bot-list)
'((text-properties . (face circe-fool-face
lui-do-not-track t)))))
'((text-properties . (face circe-fool-face lui-do-not-track t)))))
(add-hook 'circe-message-option-functions #'+irc|circe-message-option-bot)
(enable-circe-new-day-notifier)
(add-hook! 'circe-server-connected-hook
(run-at-time "5 minutes" nil #'enable-circe-notifications))
(add-hook! 'circe-channel-mode-hook
#'(enable-circe-color-nicks enable-lui-autopaste turn-on-visual-line-mode)))
#'(enable-circe-color-nicks enable-lui-autopaste turn-on-visual-line-mode))
(after! evil
;; Let `+irc/quit' and `circe' handle buffer cleanup
(map! :map circe-mode-map [remap doom/kill-this-buffer] #'bury-buffer)
;; Ensure entering insert mode will put us at the prompt.
(add-hook! 'lui-mode-hook
(add-hook 'evil-insert-state-entry-hook #'end-of-buffer nil t)))
(after! solaire-mode
;; distinguish chat/channel buffers from server buffers.
(add-hook 'circe-chat-mode-hook #'solaire-mode)))
(def-package! circe-color-nicks
@ -131,22 +131,33 @@ to determine length."
(def-package! circe-new-day-notifier
:commands enable-circe-new-day-notifier
:config (setq circe-new-day-notifier-format-message
(+irc|circe-format-padding
"*** Day"
"Date changed [{day}]")))
:config
(setq circe-new-day-notifier-format-message
(+irc--pad "Day" "Date changed [{day}]")))
(def-package! circe-notifications
:commands enable-circe-notifications
:config (setq circe-notifications-watch-strings
+irc-notifications-watch-strings))
:init
(if +irc-defer-notifications
(add-hook! 'circe-server-connected-hook
(run-at-time +irc-defer-notifications nil #'enable-circe-notifications))
(add-hook 'circe-server-connected-hook #'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))))
(def-package! lui
:commands lui-mode
:config
(map! :map lui-mode-map "C-u" #'lui-kill-to-beginning-of-line)
(when (featurep! :feature spellcheck)
(setq lui-flyspell-p t
lui-fill-type nil))
(enable-lui-logging)
(defun +irc|lui-setup-margin ()
@ -157,10 +168,7 @@ to determine length."
(setq fringes-outside-margins t
word-wrap t
wrap-prefix (s-repeat (+ +irc-left-padding 3) " ")))
(add-hook! 'lui-mode-hook '(+irc|lui-setup-margin +irc|lui-setup-wrap))
(when (featurep! :feature spellcheck)
(setq lui-flyspell-p t
lui-fill-type nil)))
(add-hook! 'lui-mode-hook #'(+irc|lui-setup-margin +irc|lui-setup-wrap)))
(def-package! lui-autopaste