2019-10-09 13:13:56 +02:00
|
|
|
;;; irc.el --- Configuration for IRC chat -*- lexical-binding: t -*-
|
2020-09-01 11:17:43 +02:00
|
|
|
|
2019-10-09 13:13:56 +02:00
|
|
|
;; Author: William Carroll <wpcarro@gmail.com>
|
2020-09-01 11:17:43 +02:00
|
|
|
;; Version: 0.0.1
|
|
|
|
;; URL: https://git.wpcarro.dev/wpcarro/briefcase
|
2020-09-01 14:44:18 +02:00
|
|
|
;; Package-Requires: ((emacs "25.1"))
|
2019-10-09 13:13:56 +02:00
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
;; Need to decide which client I will use for IRC.
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Dependencies
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(require 'erc)
|
|
|
|
(require 'cycle)
|
|
|
|
(require 'string)
|
2019-12-24 14:38:06 +01:00
|
|
|
(require 'prelude)
|
2020-09-02 15:00:43 +02:00
|
|
|
(require 'al)
|
2019-12-24 14:38:06 +01:00
|
|
|
(require 'set)
|
|
|
|
(require 'maybe)
|
|
|
|
(require 'macros)
|
2020-09-01 17:26:39 +02:00
|
|
|
(require '>)
|
2019-12-24 14:38:06 +01:00
|
|
|
(require 'password-store)
|
2020-09-02 16:01:43 +02:00
|
|
|
(require 'general)
|
2019-10-09 13:13:56 +02:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Configuration
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defconst irc-enable-tests? t
|
2019-12-24 14:38:06 +01:00
|
|
|
"When t, run the tests defined herein.")
|
|
|
|
|
2019-10-09 13:13:56 +02:00
|
|
|
(setq erc-rename-buffers t)
|
|
|
|
|
2019-12-24 14:38:06 +01:00
|
|
|
;; TODO: Find a way to avoid putting "freenode" and "#freenode" as channels
|
|
|
|
;; here. I'm doing it because when erc first connects, it's `(buffer-name)' is
|
2020-09-01 11:17:43 +02:00
|
|
|
;; "freenode", so when `irc-next-channel' is called, it 404s on the
|
|
|
|
;; `cycle-contains?' call in `irc-channel->cycle" unless "freenode" is there. To
|
2019-12-24 14:38:06 +01:00
|
|
|
;; make matters even uglier, when `erc-join-channel' is called with "freenode"
|
|
|
|
;; as the value, it connects to the "#freenode" channel, so unless "#freenode"
|
2020-09-01 11:17:43 +02:00
|
|
|
;; exists in this cycle also, `irc-next-channel' breaks again. This doesn't
|
2019-12-24 14:38:06 +01:00
|
|
|
;; pass my smell test.
|
2020-09-01 11:17:43 +02:00
|
|
|
(defconst irc-server->channels
|
|
|
|
`(("irc.freenode.net" . ,(cycle-new "freenode" "#freenode" "#nixos" "#emacs" "#pass"))
|
|
|
|
("irc.corp.google.com" . ,(cycle-new "#omg" "#london" "#panic" "#prod-team")))
|
2019-12-24 14:38:06 +01:00
|
|
|
"Mapping of IRC servers to a cycle of my preferred channels.")
|
|
|
|
|
|
|
|
;; TODO: Assert that no two servers have a channel with the same name. We need
|
2020-09-01 11:17:43 +02:00
|
|
|
;; this because that's the assumption that underpins the `irc-channel->server'
|
2019-12-24 14:38:06 +01:00
|
|
|
;; function. This will probably be an O(n^2) operation.
|
2020-08-31 18:05:31 +02:00
|
|
|
(prelude-assert
|
2020-09-01 11:17:43 +02:00
|
|
|
(set-distinct? (set-from-list
|
|
|
|
(cycle-to-list
|
2020-09-02 15:00:43 +02:00
|
|
|
(al-get "irc.freenode.net"
|
|
|
|
irc-server->channels)))
|
2020-09-01 11:17:43 +02:00
|
|
|
(set-from-list
|
|
|
|
(cycle-to-list
|
2020-09-02 15:00:43 +02:00
|
|
|
(al-get "irc.corp.google.com"
|
|
|
|
irc-server->channels)))))
|
2020-09-01 11:17:43 +02:00
|
|
|
|
|
|
|
(defun irc-channel->server (server->channels channel)
|
2020-09-01 14:44:18 +02:00
|
|
|
"Using SERVER->CHANNELS, resolve an IRC server from a given CHANNEL."
|
2020-09-02 15:00:43 +02:00
|
|
|
(let ((result (al-find (lambda (k v) (cycle-contains? channel v))
|
|
|
|
server->channels)))
|
2020-08-31 18:05:31 +02:00
|
|
|
(prelude-assert (maybe-some? result))
|
2019-12-24 14:38:06 +01:00
|
|
|
result))
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-channel->cycle (server->channels channel)
|
2020-09-01 14:44:18 +02:00
|
|
|
"Using SERVER->CHANNELS, resolve an IRC's channels cycle from CHANNEL."
|
2020-09-02 15:00:43 +02:00
|
|
|
(al-get (irc-channel->server server->channels channel)
|
|
|
|
server->channels))
|
2019-10-09 13:13:56 +02:00
|
|
|
|
|
|
|
;; Setting `erc-join-buffer' to 'bury prevents erc from stealing focus of the
|
|
|
|
;; current buffer when it connects to IRC servers.
|
|
|
|
(setq erc-join-buffer 'bury)
|
|
|
|
|
2019-12-24 14:38:06 +01:00
|
|
|
;; TODO: Here is another horrible hack that should be revisted.
|
2019-10-09 13:13:56 +02:00
|
|
|
(setq erc-autojoin-channels-alist
|
2020-09-01 11:17:43 +02:00
|
|
|
(->> irc-server->channels
|
2020-09-02 15:00:43 +02:00
|
|
|
(al-map-values #'cycle-to-list)
|
|
|
|
(al-map-keys (>-> (s-chop-prefix "irc.")
|
|
|
|
(s-chop-suffix ".net")))))
|
2019-10-09 13:13:56 +02:00
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defcustom irc-install-kbds? t
|
2019-10-09 13:13:56 +02:00
|
|
|
"When t, install the keybindings defined herein.")
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Library
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-message (x)
|
2019-10-09 13:13:56 +02:00
|
|
|
"Print message X in a structured way."
|
2020-09-01 00:28:47 +02:00
|
|
|
(message (string-format "[irc.el] %s" x)))
|
2019-10-09 13:13:56 +02:00
|
|
|
|
2019-12-24 14:38:06 +01:00
|
|
|
;; TODO: Integrate Google setup with Freenode setup.
|
|
|
|
|
|
|
|
;; TODO: Support function or KBD for switching to an ERC buffer.
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-kill-all-erc-processes ()
|
2020-09-01 14:44:18 +02:00
|
|
|
"Kill all ERC buffers and processes."
|
2019-12-24 14:38:06 +01:00
|
|
|
(interactive)
|
|
|
|
(->> (erc-buffer-list)
|
|
|
|
(-map #'kill-buffer)))
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-switch-to-erc-buffer ()
|
2019-12-24 14:38:06 +01:00
|
|
|
"Switch to an ERC buffer."
|
|
|
|
(interactive)
|
|
|
|
(let ((buffers (erc-buffer-list)))
|
2020-09-01 11:17:43 +02:00
|
|
|
(if (list-empty? buffers)
|
2019-12-24 14:38:06 +01:00
|
|
|
(error "[irc.el] No ERC buffers available")
|
2020-09-01 11:17:43 +02:00
|
|
|
(switch-to-buffer (list-head (erc-buffer-list))))))
|
2019-12-24 14:38:06 +01:00
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-connect-to-freenode ()
|
2019-12-24 14:38:06 +01:00
|
|
|
"Connect to Freenode IRC."
|
|
|
|
(interactive)
|
|
|
|
(erc-ssl :server "irc.freenode.net"
|
|
|
|
:port 6697
|
|
|
|
:nick "wpcarro"
|
2020-09-01 11:17:43 +02:00
|
|
|
:password (password-store-get "programming/irc-freenode")
|
2019-12-24 14:38:06 +01:00
|
|
|
:full-name "William Carroll"))
|
|
|
|
|
|
|
|
;; TODO: Handle failed connections.
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-connect-to-google ()
|
2019-10-09 13:13:56 +02:00
|
|
|
"Connect to Google's Corp IRC using ERC."
|
|
|
|
(interactive)
|
|
|
|
(erc-ssl :server "irc.corp.google.com"
|
|
|
|
:port 6697
|
|
|
|
:nick "wpcarro"
|
|
|
|
:full-name "William Carroll"))
|
|
|
|
|
2019-12-24 14:38:06 +01:00
|
|
|
;; TODO: Prefer defining these with a less homespun solution. There is a
|
|
|
|
;; function call `erc-buffer-filter' that would be more appropriate for the
|
2020-09-01 11:17:43 +02:00
|
|
|
;; implementation of `irc-next-channel' and `irc-prev-channel'.
|
|
|
|
(defun irc-next-channel ()
|
2019-12-24 14:38:06 +01:00
|
|
|
"Join the next channel for the active server."
|
2019-10-09 13:13:56 +02:00
|
|
|
(interactive)
|
2019-12-24 14:38:06 +01:00
|
|
|
(with-current-buffer (current-buffer)
|
2020-09-01 11:17:43 +02:00
|
|
|
(let ((cycle (irc-channel->cycle irc-server->channels (buffer-name))))
|
2019-12-24 14:38:06 +01:00
|
|
|
(erc-join-channel
|
2020-09-01 11:17:43 +02:00
|
|
|
(cycle-next cycle))
|
|
|
|
(irc-message
|
|
|
|
(string-format "Current IRC channel: %s" (cycle-current cycle))))))
|
2019-10-09 13:13:56 +02:00
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun irc-prev-channel ()
|
2019-12-24 14:38:06 +01:00
|
|
|
"Join the previous channel for the active server."
|
2019-10-09 13:13:56 +02:00
|
|
|
(interactive)
|
2019-12-24 14:38:06 +01:00
|
|
|
(with-current-buffer (current-buffer)
|
2020-09-01 11:17:43 +02:00
|
|
|
(let ((cycle (irc-channel->cycle irc-server->channels (buffer-name))))
|
2019-12-24 14:38:06 +01:00
|
|
|
(erc-join-channel
|
2020-09-01 11:17:43 +02:00
|
|
|
(cycle-prev cycle))
|
|
|
|
(irc-message
|
|
|
|
(string-format "Current IRC channel: %s" (cycle-current cycle))))))
|
2019-12-24 14:38:06 +01:00
|
|
|
|
2020-09-01 00:28:47 +02:00
|
|
|
(add-hook 'erc-mode-hook (macros-disable auto-fill-mode))
|
|
|
|
(add-hook 'erc-mode-hook (macros-disable company-mode))
|
2020-01-27 12:40:05 +01:00
|
|
|
|
2019-12-24 14:38:06 +01:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Keybindings
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2019-10-09 13:13:56 +02:00
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(when irc-install-kbds?
|
2019-10-09 13:13:56 +02:00
|
|
|
(general-define-key
|
|
|
|
:keymaps 'erc-mode-map
|
2020-09-01 11:17:43 +02:00
|
|
|
"<C-tab>" #'irc-next-channel
|
|
|
|
"<C-S-iso-lefttab>" #'irc-prev-channel))
|
2019-10-09 13:13:56 +02:00
|
|
|
|
2019-12-24 14:38:06 +01:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Tests
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(when irc-enable-tests?
|
2020-08-31 18:05:31 +02:00
|
|
|
(prelude-assert
|
2019-12-24 14:38:06 +01:00
|
|
|
(equal
|
2020-09-01 11:17:43 +02:00
|
|
|
(irc-channel->server `(("irc.dairy.com" . ,(cycle-new "#cheese" "#milk"))
|
|
|
|
("irc.color.com" . ,(cycle-new "#red" "#blue")))
|
2019-12-24 14:38:06 +01:00
|
|
|
"#cheese")
|
|
|
|
"irc.dairy.com")))
|
|
|
|
|
2019-10-09 13:13:56 +02:00
|
|
|
(provide 'irc)
|
|
|
|
;;; irc.el ends here
|