Adding finger support.
[elpher.git] / elpher.el
index 5be827f..4feb520 100644 (file)
--- a/elpher.el
+++ b/elpher.el
@@ -2,9 +2,9 @@
 
 ;; Copyright (C) 2019 Tim Vaughan
 
-;; Author: Tim Vaughan <tgvaughan@gmail.com>
+;; Author: Tim Vaughan <timv@ughan.xyz>
 ;; Created: 11 April 2019
-;; Version: 2.5.1
+;; Version: 2.5.2
 ;; Keywords: comm gopher
 ;; Homepage: http://thelambdalab.xyz/elpher
 ;; Package-Requires: ((emacs "26"))
 (require 'url-util)
 (require 'subr-x)
 (require 'dns)
+(require 'ansi-color)
 
 
 ;;; Global constants
 ;;
 
-(defconst elpher-version "2.5.1"
+(defconst elpher-version "2.5.2"
   "Current version of elpher.")
 
 (defconst elpher-margin-width 6
@@ -88,6 +89,7 @@
     ((gopher ?s) elpher-get-gopher-page elpher-render-download "snd" elpher-binary)
     ((gopher ?h) elpher-get-gopher-page elpher-render-html "htm" elpher-html)
     (gemini elpher-get-gemini-page elpher-render-gemini "gem" elpher-gemini)
+    (finger elpher-get-finger-page elpher-render-text "txt" elpher-text)
     (telnet elpher-get-telnet-page nil "tel" elpher-telnet)
     (other-url elpher-get-other-url-page nil "url" elpher-other-url)
     ((special bookmarks) elpher-get-bookmarks-page nil "/" elpher-index)
@@ -177,10 +179,10 @@ allows switching from an encrypted channel back to plain text without user input
   "Specifies the number of seconds to wait for a network connection to time out."
   :type '(integer))
 
-(defcustom elpher-strip-ansi-from-text t
-  "If non-nil, strip ANSI escape sequences from gopher menus and text/gemini files.
-This is occasionally desirable, as these sequences are not understood natively by
-Emacs, and tend to result in a garbled display."
+(defcustom elpher-filter-ansi-from-text nil
+  "If non-nil, filter ANSI escape sequences from text.
+The default behaviour is to use the ansi-color package to interpret these
+sequences."
   :type '(boolean))
 
 ;;; Model
@@ -336,12 +338,15 @@ If no address is defined, returns 0.  (This is for compatibility with the URL li
 ;; Page
 
 (defun elpher-make-page (display-string address)
+  "Create a page with DISPLAY-STRING and ADDRESS."
   (list display-string address))
 
 (defun elpher-page-display-string (page)
+  "Retrieve the display string corresponding to PAGE."
   (elt page 0))
 
 (defun elpher-page-address (page)
+  "Retrieve the address corresponding to PAGE."
   (elt page 1))
 
 (defvar elpher-current-page nil)
@@ -615,9 +620,10 @@ If ADDRESS is not supplied or nil the record is rendered as an
     (if type-map-entry
         (let* ((margin-code (elt type-map-entry 2))
                (face (elt type-map-entry 3))
-               (page (elpher-make-page display-string address)))
+               (filtered-display-string (ansi-color-filter-apply display-string))
+               (page (elpher-make-page filtered-display-string address)))
           (elpher-insert-margin margin-code)
-          (insert-text-button display-string
+          (insert-text-button filtered-display-string
                               'face face
                               'elpher-page page
                               'action #'elpher-click-link
@@ -675,22 +681,12 @@ If ADDRESS is not supplied or nil the record is rendered as an
 (defconst elpher-ansi-regex "\x1b\\[[^m]*m"
   "Wildly incomplete regexp used to strip out some troublesome ANSI escape sequences.")
 
-(defun elpher-strip-ansi (string)
-  "Strip ANSI escape codes from STRING."
-  (with-temp-buffer
-    (insert string)
-    (goto-char (point-min))
-    (while (re-search-forward elpher-ansi-regex nil t)
-      (delete-region (match-beginning 0) (match-end 0)))
-    (buffer-string)))
-
-
 (defun elpher-process-text-for-display (string)
-  "Perform any desired processing of text prior to display.
-Currently includes buttonifying URLs and optionally stripping ANSI escape codes."
-  (elpher-buttonify-urls (if elpher-strip-ansi-from-text
-                             (elpher-strip-ansi string)
-                           string)))
+  "Perform any desired processing of STRING prior to display as text.
+Currently includes buttonifying URLs and processing ANSI escape codes."
+  (elpher-buttonify-urls (if elpher-filter-ansi-from-text
+                             (ansi-color-filter-apply string)
+                           (ansi-color-apply string))))
 
 (defun elpher-render-text (data &optional _mime-type-string)
   "Render DATA as text.  MIME-TYPE-STRING is unused."
@@ -826,7 +822,9 @@ to ADDRESS."
           (set-process-coding-system proc 'binary)
           (set-process-filter proc
                               (lambda (_proc string)
-                                (cancel-timer timer)
+                                (when timer
+                                  (cancel-timer timer)
+                                  (setq timer nil))
                                 (setq response-string
                                       (concat response-string string))))
           (set-process-sentinel proc
@@ -1033,6 +1031,26 @@ For instance, the filename /a/b/../c/./d will reduce to /a/c/d"
     (elpher-page-address elpher-current-page)
     (buffer-string))))
 
+;; Finger page connection
+
+(defun elpher-get-finger-page (renderer)
+  "Opens a finger connection to the current page address and renders it using RENDERER."
+  (let* ((address (elpher-page-address elpher-current-page))
+         (host (elpher-address-host address))
+         (port (elpher-address-port address))
+         (content (elpher-get-cached-content address)))
+    (if (and content (funcall renderer nil))
+        (elpher-with-clean-buffer
+         (insert content)
+         (elpher-restore-pos))
+      (elpher-with-clean-buffer
+       (insert "LOADING... (use 'u' to cancel)"))
+      (condition-case the-error
+          (elpher-get-selector address renderer)
+        (error
+         (elpher-network-error address the-error))))))
+
+
 ;; Other URL page opening
 
 (defun elpher-get-other-url-page (renderer)
@@ -1328,8 +1346,7 @@ When run interactively HOST-OR-URL is read from the minibuffer."
              (elpher-page-display-string elpher-current-page))
     (elpher-visit-page (elpher-make-page
                         (elpher-page-display-string elpher-current-page)
-                        (elpher-page-address elpher-current-page)
-                        elpher-current-page)
+                        (elpher-page-address elpher-current-page))
                        #'elpher-render-download
                        t)))