--- /dev/null
+;;; MURK --- Multiserver Unibuffer iRc Klient -*- lexical-binding:t -*-
+
+;; Copyright (C) 2024 plugd
+
+;; Author: plugd <plugd@thelambdalab.xyz>
+;; Created: 11 May 2024
+;; Version: 0.0
+;; Keywords: network
+;; Homepage: http://thelambdalab.xyz/metalurk
+;; Package-Requires: ((emacs "26"))
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this file. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(provide 'murk)
+
+
+;;; Customizations
+
+(defgroup murk nil
+ "Multiserver Unibuffer iRc Klient"
+ :group 'network)
+
+(defcustom murk-nick "plugd"
+ "Default nick.")
+
+(defcustom murk-default-quit-msg "Bye"
+ "Default quit message when none supplied.")
+
+(defcustom murk-networks
+ '(("libera" "irc.libera.chat" 6697)
+ ("tilde" "tilde.chat" 6697))
+ "IRC networks.")
+
+
+;;; Faces
+;;
+
+
+;;; Global variables
+;;
+
+(defvar murk-version "Murk v0.0"
+ "Value of this string is used in response to CTCP version queries.")
+
+(defvar murk-notice-prefix "-!-")
+(defvar murk-error-prefix "!!!")
+(defvar murk-prompt-string ">")
+
+;;; Utility procedures
+;;
+
+(defun murk--filtered-join (&rest args)
+ (string-join (seq-filter (lambda (el) el) args) " "))
+
+(defun murk--as-string (obj)
+ (if obj
+ (with-output-to-string (princ obj))
+ nil))
+
+;;; Network processes
+;;
+
+(defvar murk-connection-table nil
+ "An alist associating servers to connection information.
+This includes the process and the response string.")
+
+(defun murk-connection-process (server)
+ (elt (assoc server murk-connection-table) 1))
+
+(defun murk-connection-response (server)
+ (elt (assoc server murk-connection-table) 2))
+
+(defun murk-set-connection-response (server string)
+ (setf (elt (assoc server murk-connection-table) 3) string))
+
+(defun murk-connection-close (server)
+ (setq murk-connection-table (assoc-delete-all server murk-connection-table)))
+
+(defun murk-make-server-filter (server)
+ (lambda (proc string)
+ (dolist (line (split-string (concat (murk-connection-response server) string)
+ "\n"))
+ (if (string-suffix-p "\r" line)
+ (murk-eval-msg-string server (string-trim line))
+ (murk-set-connection-response line)))))
+
+(defun murk-make-server-sentinel (server)
+ (lambda (proc string)
+ (unless (equal "open" (string-trim string))
+ (murk-display-error "Disconnected from server.")
+ (murk-remove-contexts-for-server server)
+ (murk-render-prompt)
+ (murk-connection-close server))))
+
+(defun murk-start-process (server)
+ (let* ((row (assoc server murk-networks))
+ (host (elt row 1))
+ (port (elt row 2))
+ (flags (seq-drop row 3)))
+ (make-network-process :name (concat "lurk" server)
+ :host host
+ :service port
+ :family nil
+ :filter (murk-make-server-filter server)
+ :sentinel (murk-make-server-sentinel server)
+ :nowait nil
+ :tls-parameters (if (memq :notls flags)
+ nil
+ (cons 'gnutls-x509pki
+ (gnutls-boot-parameters
+ :type 'gnutls-x509pki
+ :hostname host)))
+ :buffer "*lurk*")))
+
+(defvar murk-ping-period 60)
+
+;; IDEA: Have a single ping timer which pings all connected hosts
+
+(defun murk-connect (server)
+ (if (assoc server murk-connection-table)
+ (murk-display-error "Already connected to this network.")
+ (if (not (assoc server murk-networks))
+ (murk-display-error "Network '" server "' is unknown.")
+ (murk-start-process server)
+ (murk-send-msg (murk-msg nil nil "USER" murk-nick 0 "*" murk-nick))
+ (murk-send-msg (murk-msg nil nil "NICK" murk-nick)))))
+
+;;; Contexts and Servers
+;;
+
+;; A context is a list (server name ...) where name is a string
+;; representing either a channel name or nick, and server is a symbol
+;; identifying the server.
+;;
+;; Each server has a special context (server) used for messages
+;; to/from the server itself.
+
+(defvar murk-current-context nil)
+(defvar murk-context-members nil)
+
+;;; Main start procedure
+;;
+
+(defun metalurk)
+
+;;; metalurk.el ends here