(defvar lurk-debug nil
"If non-nil, enable debug mode.")
+
+;;; Utility procedures
+;;
+
+(defun lurk--filtered-join (&rest args)
+ (string-join (seq-filter (lambda (el) el) args) " "))
+
+(defun lurk--as-string (obj)
+ (if obj
+ (with-output-to-string (princ obj))
+ nil))
+
+
;;; Network process
;;
;;; Server messages
;;
-(defun lurk--as-string (obj)
- (if obj
- (with-output-to-string (princ obj))
- nil))
-
(defun lurk-msg (tags src cmd &rest params)
(list (lurk--as-string tags)
(lurk--as-string src)
(apply #'lurk-msg (append (list tags src cmd) params)))
(error "Failed to parse string " string)))
-(defun lurk--filtered-join (&rest args)
- (string-join (seq-filter (lambda (el) el) args) " "))
-
(defun lurk-msg->string (msg)
(let ((tags (lurk-msg-tags msg))
(src (lurk-msg-src msg))
"Marker for prompt position in LURK buffer.")
(defun lurk-setup-header ()
- (setq-local header-line-format
- '(:eval
- (let ((proc (get-process "lurk")))
- (if proc
- (concat
- "Host: " (car (process-contact proc))
- ", Context: "
- (if lurk-current-context
- (concat
- lurk-current-context
- " ("
- (number-to-string
- (length (lurk-get-context-users lurk-current-context)))
- " users)")
- "Server"))
- "No connection")))))
+ (with-current-buffer "*lurk*"
+ (setq-local header-line-format
+ '((:eval
+ (let ((proc (get-process "lurk")))
+ (if proc
+ (concat
+ "Host: " (car (process-contact proc))
+ ", Context: "
+ (if lurk-current-context
+ (concat
+ lurk-current-context
+ " ("
+ (number-to-string
+ (length (lurk-get-context-users lurk-current-context)))
+ " users)")
+ "Server"))
+ "No connection")))
+ (:eval
+ (if lurk-zoomed " [ZOOMED]" ""))))))
(defun lurk-setup-buffer ()
(with-current-buffer (get-buffer-create "*lurk*")
(opt (group (: ":" (+ digit))))
(opt (group (: "/"
(opt
- (* (any alnum "-/.,#:%=&_?~@"))
- (any alnum "-/#:%=&_~@")))))))
+ (* (any alnum "-/.,#:%=&_?~@+"))
+ (any alnum "-/#:%=&_~@+")))))))
"Imperfect regex used to find URLs in plain text.")
(defun lurk-click-url (button)
(if lurk-debug
(lurk-display-string nil nil string))
(let* ((msg (lurk-string->msg string)))
+ (lurk-process-autoreplies msg)
(pcase (lurk-msg-cmd msg)
("PING"
(lurk-send-msg
(lurk-display-notice nil (lurk-msg->string msg))))))
+;;; User-defined responses
+
+
+(defvar lurk-autoreply-table nil
+ "Table of autoreply messages.
+
+Each autoreply is a list of two elements: (matcher reply)
+
+Here matcher is a list:
+
+(network src cmd params ...)
+
+and reply is another list:
+
+ (cmd params ...)
+
+Each entry in the matcher list is a regular expression tested against the
+corresponding values in the incomming message. Entries can be nil,
+in which case they match anything.")
+
+(defun lurk--lists-equal (l1 l2)
+ (if (and l1 l2)
+ (if (or (not (and (car l1) (car l2)))
+ (string-match (car l1) (car l2)))
+ (lurk--lists-equal (cdr l1) (cdr l2))
+ nil)
+ t))
+
+(defun lurk-process-autoreply (msg autoreply)
+ (let ((matcher (car autoreply))
+ (reply (cadr autoreply)))
+ (let ((network (car matcher)))
+ (when (and (or (not network)
+ (and (get-process "lurk")
+ (equal (car (process-contact (get-process "lurk")))
+ (cadr (assoc network lurk-networks)))))
+ (lurk--lists-equal (cdr matcher)
+ (append (list (lurk-msg-src msg)
+ (lurk-msg-cmd msg))
+ (lurk-msg-params msg))))
+ (lurk-send-msg
+ (lurk-msg nil nil (car reply) (cdr reply)))))))
+
+(defun lurk-process-autoreplies (msg)
+ (mapc
+ (lambda (autoreply)
+ (lurk-process-autoreply msg autoreply))
+ lurk-autoreply-table))
+
;;; Command entering
;;
(defun lurk-enter-string (string)
(if (string-prefix-p "/" string)
(pcase (substring string 1)
- ((rx "DEBUG")
- (setq lurk-debug (not lurk-debug))
+ ((rx (: "DEBUG" (opt (: " " (let setting (or "ON" "OFF"))))))
+ (setq lurk-debug
+ (if setting
+ (if (equal (upcase setting) "ON")
+ t
+ nil)
+ (not lurk-debug)))
(lurk-display-notice nil "Debug mode now " (if lurk-debug "on" "off") "."))
((rx "HEADER")