229 lines
7.5 KiB
EmacsLisp
229 lines
7.5 KiB
EmacsLisp
;;; acdw-erc.el -*- lexical-binding: t; coding: utf-8-unix -*-
|
||
|
||
;; Author: Case Duckworth <acdw@acdw.net>
|
||
;; 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
|