;;; acdw-erc.el -*- lexical-binding: t; coding: utf-8-unix -*- ;; Author: Case Duckworth <(rot13-string "npqj@npqj.arg")> ;; Created: 24 May 2021 ;; Keywords: configuration ;; URL: https://tildegit.org/acdw/emacs ;; This file is NOT part of GNU Emacs. ;;; License: ;; Everyone is permitted to do whatever with this software, without ;; limitation. This software comes without any warranty whatsoever, ;; but with two pieces of advice: ;; - Don't hurt yourself. ;; - Make good choices. ;;; Commentary: ;; `acdw-erc' is a dumping ground for functions and stuff for ERC, so they ;; don't clutter up `init.el'. ;;; Code: (defgroup acdw-erc nil "Customizations for ERC." :group 'erc) ;;; Show a different header-line face when ERC is disconnected. ;; https://www.emacswiki.org/emacs/ErcModeline#h5o-1 (defface erc/header-line-disconnected '((t (:foreground "black" :background "indianred"))) "Face to use when ERC has been disconnected.") (defun erc/update-header-line-show-disconnected () "Use a different face in the header-line when disconnected." (erc-with-server-buffer (cond ((erc-server-process-alive) 'erc-header-line) (t 'erc/header-line-disconnected)))) ;;; Convenience functions ;; from Prelude: ;; https://github.com/bbatsov/prelude/blob/master/modules/prelude-erc.el#L114 (defcustom erc/servers nil "The list of IRC servers to connect to with `erc/connect'." :type '(list string)) (defcustom erc/bye-message "See You Space Cowpokes." "Quit message sent when calling `erc/disconnect'." :type 'string) (defun connect-to-erc (server &optional use-tls port nick) "Connects to IRC SERVER at PORT with NICK. If USE-TLS is non-nil, use TLS." (let* ((use-tls (or use-tls t)) (erc-fn (if use-tls #'erc-tls #'erc)) (port (or port (if use-tls 6697 6667))) (nick (or nick erc-nick))) (funcall erc-fn :server server :port port :nick nick))) (defun erc/connect () "Connect to all the servers in `erc/servers'." (interactive) (require 'erc) (mapcar #'connect-to-erc erc/servers)) (defun filter-server-buffers () (delq nil (mapcar (lambda (x) (and (erc-server-buffer-p x) x)) (buffer-list)))) (defun erc/reconnect () "Reconnect to all IRC servers." (interactive) (dolist (buffer (filter-server-buffers)) (with-current-buffer buffer (ignore-errors (erc-cmd-RECONNECT))))) (defun erc/disconnect () "Disconnect from all IRC servers." (interactive) (dolist (buffer (filter-server-buffers)) (with-message (format "Killing server buffer: %s" (buffer-name buffer)) (with-current-buffer buffer (erc-quit-server erc/bye-message)))) ;; TODO: kill all channel buffers (force-mode-line-update)) (defun acdw-erc/prompt () "The prompt to show for ERC." ;; Rewrite s-truncate to avoid dependency. (let ((name (buffer-name)) (ellipsis "~") (len erc-fill-static-center)) (if (and len (> (length name) (- len 2))) (format "%s%s>" (substring name 0 (- len 2 (length ellipsis))) ellipsis) (propertize (format "%s%s>" name (let ((ss) ; Rewrite s-repeat to avoid dependency. (num (- len 2 (length name)))) (while (> num 0) (setq ss (cons " " ss)) (setq num (1- num))) (apply #'concat ss))) 'read-only t 'intangible t 'cursor-intangible t)))) (defcustom erc-nick-truncate nil "The width at which to truncate a nick with `erc-format-truncate-@nick'." :group 'erc :type 'integer) (defalias 'erc-propertize 'propertize) ; I guess...taken out in 28 ? (defun erc-format-truncate-@nick (&optional user channel-data) "Format the nickname of USER as in `erc-format-@nick', with truncation. Truncation is customized using the `erc-nick-truncate' variable. See also `erc-format-nick-function'." (when user (let* ((nick (erc-server-user-nickname user)) (prefix (erc-get-user-mode-prefix nick)) (ellipsis "~") (max-len (- erc-nick-truncate 2 ; one each for < and > (length ellipsis) (length prefix)))) (concat (erc-propertize prefix 'font-lock-face 'erc-nick-prefix-face) (if (and max-len (> (length nick) max-len)) (format "%s%s" (substring nick 0 max-len) ellipsis) nick))))) ;;; Uh (defun acdw-erc/erc-switch-to-buffer (&optional arg) "Prompt for ERC buffer to switch to. Reverse prefix argument from `erc-switch-to-buffer'." (interactive "P") (erc-switch-to-buffer (not arg))) ;;; ERC-Bar ;; NEEDS MUCH WORK (defun erc-bar-move-back (n) "Moves back n message lines. Ignores wrapping, and server messages." (interactive "nHow many lines ? ") (re-search-backward "^.*<.*>" nil t n)) (defun erc-bar-update-overlay () "Update the overlay for current buffer, based on the content of erc-modified-channels-alist. Should be executed on window change." (interactive) (let* ((info (assq (current-buffer) erc-modified-channels-alist)) (count (cadr info))) (if (and info (> count erc-bar-threshold)) (save-excursion (end-of-buffer) (when (erc-bar-move-back count) (let ((inhibit-field-text-motion t)) (move-overlay erc-bar-overlay (line-beginning-position) (line-end-position) (current-buffer))))) (delete-overlay erc-bar-overlay)))) (defvar erc-bar-threshold 0 "Display bar when there are more than erc-bar-threshold unread messages.") (defvar erc-bar-overlay nil "Overlay used to set bar") (setq erc-bar-overlay (make-overlay 0 0)) (overlay-put erc-bar-overlay 'face '(:overline "gray")) (with-eval-after-load 'erc-track ;;put the hook before erc-modified-channels-update (defadvice erc-track-mode (after erc-bar-setup-hook (&rest args) activate) (add-hook 'window-configuration-change-hook 'erc-bar-update-overlay -90)) (add-hook 'erc-send-completed-hook (lambda (str) (erc-bar-update-overlay)))) ;;; ZNC babeee ;; needed variables are stored in private.el (defun znc/connect (znc-server znc-port znc-nick irc-servers) (interactive (let ((zserv (or znc/server (read-string "ZNC Server: "))) (zport (or znc/port (read-number "ZNC Port: "))) (znick (or znc/nick (read-string "ZNC Nick: "))) (servers (or znc/irc-servers (list (cons (read-string "IRC Server to connect to: ") (read-passwd "Password: ")))))) (list zserv zport znick servers))) (let ((si 0)) (dolist (server irc-servers) (run-at-time si nil (lambda () (erc-tls :server znc-server :port znc-port :nick znc-nick :password (format "%s/%s:%s" znc-nick (car server) (cdr server))))) (setq si (1+ si))))) (provide 'acdw-erc) ;;; acdw-erc.el ends here