Ensure certificate directory exists
[elpher.git] / elpher.el
index b57f2b8..5b0f132 100644 (file)
--- a/elpher.el
+++ b/elpher.el
 (require 'url-util)
 (require 'subr-x)
 (require 'dns)
 (require 'url-util)
 (require 'subr-x)
 (require 'dns)
-(require 'ansi-color)
 (require 'nsm)
 (require 'gnutls)
 
 (require 'nsm)
 (require 'gnutls)
 
+;;; ANSI colors or XTerm colors
+
+(or (require 'xterm-color nil t)
+    (require 'ansi-color))
+
+(defalias 'elpher-color-filter-apply
+  (if (fboundp 'xterm-color-filter)
+      (lambda (s)
+       (let ((xterm-color-render nil))
+         (xterm-color-filter s)))
+    'ansi-color-filter-apply)
+  "A function to filter out ANSI escape sequences.")
+(defalias 'elpher-color-apply
+  (if (fboundp 'xterm-color-filter)
+      'xterm-color-filter
+    'ansi-color-apply)
+  "A function to apply ANSI escape sequences.")
 
 ;;; Global constants
 ;;
 
 ;;; Global constants
 ;;
@@ -513,8 +529,9 @@ unless NO-HISTORY is non-nil."
                                           '("gophers" "gemini")))
                              " [TLS encryption]"
                            ""))
                                           '("gophers" "gemini")))
                              " [TLS encryption]"
                            ""))
-             (header (concat display-string
-                             (propertize tls-string 'face 'bold))))
+             (header (url-unhex-string
+                     (concat display-string
+                              (propertize tls-string 'face 'bold)))))
         (setq header-line-format header))))
 
 (defmacro elpher-with-clean-buffer (&rest args)
         (setq header-line-format header))))
 
 (defmacro elpher-with-clean-buffer (&rest args)
@@ -809,6 +826,8 @@ base for the installed key and certificate files."
 
 (defun elpher-list-existing-certificates ()
   "Return a list of the persistent certificates in `elpher-certificate-directory'."
 
 (defun elpher-list-existing-certificates ()
   "Return a list of the persistent certificates in `elpher-certificate-directory'."
+  (unless (file-directory-p elpher-certificate-directory)
+    (make-directory elpher-certificate-directory))
   (mapcar
    (lambda (file)
      (file-name-sans-extension file))
   (mapcar
    (lambda (file)
      (file-name-sans-extension file))
@@ -934,7 +953,7 @@ 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))
     (if type-map-entry
         (let* ((margin-code (elt type-map-entry 2))
                (face (elt type-map-entry 3))
-               (filtered-display-string (ansi-color-filter-apply display-string))
+               (filtered-display-string (elpher-color-filter-apply display-string))
                (page (elpher-make-page filtered-display-string address)))
           (elpher-insert-margin margin-code)
           (insert-text-button filtered-display-string
                (page (elpher-make-page filtered-display-string address)))
           (elpher-insert-margin margin-code)
           (insert-text-button filtered-display-string
@@ -999,8 +1018,8 @@ If ADDRESS is not supplied or nil the record is rendered as an
   "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
   "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))))
+                             (elpher-color-filter-apply string)
+                           (elpher-color-apply string))))
 
 (defun elpher-render-text (data &optional _mime-type-string)
   "Render DATA as text.  MIME-TYPE-STRING is unused."
 
 (defun elpher-render-text (data &optional _mime-type-string)
   "Render DATA as text.  MIME-TYPE-STRING is unused."
@@ -1352,7 +1371,7 @@ treatment that a separate function is warranted."
       (insert elpher-gemini-link-string)
       (if type-map-entry
           (let* ((face (elt type-map-entry 3))
       (insert elpher-gemini-link-string)
       (if type-map-entry
           (let* ((face (elt type-map-entry 3))
-                 (filtered-display-string (ansi-color-filter-apply display-string))
+                 (filtered-display-string (elpher-color-filter-apply display-string))
                  (page (elpher-make-page filtered-display-string address)))
             (insert-text-button filtered-display-string
                                 'face face
                  (page (elpher-make-page filtered-display-string address)))
             (insert-text-button filtered-display-string
                                 'face face
@@ -2029,6 +2048,7 @@ With an optional argument, add all the history items, too."
     (define-key map "\C-m" 'elpher-menu-this-window)
     (define-key map "o" 'elpher-menu-other-window)
     (define-key map "\C-o" 'elpher-menu-switch-other-window)
     (define-key map "\C-m" 'elpher-menu-this-window)
     (define-key map "o" 'elpher-menu-other-window)
     (define-key map "\C-o" 'elpher-menu-switch-other-window)
+    (define-key map "c" 'elpher-menu-copy-current-url)
     (define-key map "d" 'Buffer-menu-delete)
     (define-key map "k" 'Buffer-menu-delete)
     (define-key map "\C-k" 'Buffer-menu-delete)
     (define-key map "d" 'Buffer-menu-delete)
     (define-key map "k" 'Buffer-menu-delete)
     (define-key map "\C-k" 'Buffer-menu-delete)
@@ -2172,6 +2192,23 @@ and apply FUNC to ARGS."
          (t
           (error "There's no entry on this line of the menu")))))
 
          (t
           (error "There's no entry on this line of the menu")))))
 
+(defun elpher-menu-copy-current-url ()
+  "Copy the URL of the current menu item."
+  (interactive)
+  (let ((data (tabulated-list-get-id)))
+    (cond ((bufferp data)
+          (with-current-buffer data
+            (elpher-copy-page-url elpher-current-page)))
+         ((listp data)
+          (elpher-copy-page-url (nth 2 data)))
+         (t
+          (error "There's no entry on this line of the menu")))))
+
+  (defun elpher-copy-current-url ()
+  "Copy URL of current page to `kill-ring'."
+  (interactive)
+  (elpher-copy-page-url elpher-current-page))
+
 (defvar elpher-title nil)
 
 (defun elpher-find-title ()
 (defvar elpher-title nil)
 
 (defun elpher-find-title ()
@@ -2195,8 +2232,8 @@ that there are no buffers for history items so many of the buffer
 menu commands won't work on them."
     (setq tabulated-list-format
          (vector '("T" 1 t)
 menu commands won't work on them."
     (setq tabulated-list-format
          (vector '("T" 1 t)
-                 '("URL" 40 t)
-                 '("Name" 30 t))
+                 '("Name" 30 t)
+                 '("URL" 40 t))
          tabulated-list-sort-key nil)
     ;; Collect info for each buffer we're interested in.
     (let (entries)
          tabulated-list-sort-key nil)
     ;; Collect info for each buffer we're interested in.
     (let (entries)
@@ -2220,25 +2257,25 @@ list established by `elpher-menu-refresh'. See
   (list (current-buffer)
        (cond ((eq major-mode 'elpher-mode)
               (vector "G"
   (list (current-buffer)
        (cond ((eq major-mode 'elpher-mode)
               (vector "G"
-                      (or (elpher-address-to-url
-                           (elpher-page-address elpher-current-page))
-                          "none")
                       (or (elpher-find-title)
                           (elpher-page-display-string elpher-current-page)
                       (or (elpher-find-title)
                           (elpher-page-display-string elpher-current-page)
-                          (buffer-name))))
+                          (buffer-name))
+                      (or (elpher-address-to-url
+                           (elpher-page-address elpher-current-page))
+                          "none")))
              ((eq major-mode 'gemini-mode)
               (vector "E"
              ((eq major-mode 'gemini-mode)
               (vector "E"
+                      (or (elpher-page-display-string elpher-current-page)
+                          (buffer-name))
                       (or (elpher-address-to-url
                            (elpher-page-address elpher-current-page))
                       (or (elpher-address-to-url
                            (elpher-page-address elpher-current-page))
-                          "none")
-                      (or (elpher-page-display-string elpher-current-page)
-                          (buffer-name))))
+                          "none")))
              ((eq major-mode 'eww-mode)
               (vector "W"
              ((eq major-mode 'eww-mode)
               (vector "W"
-                      (or (eww-current-url)
-                          "none")
                       (or (plist-get eww-data :title)
                       (or (plist-get eww-data :title)
-                          (buffer-name)))))))
+                          (buffer-name))
+                      (or (eww-current-url)
+                          "none"))))))
 
 (defun elpher-menu-refresh-history ()
   "Return current entries for `elpher-menu-refresh'.
 
 (defun elpher-menu-refresh-history ()
   "Return current entries for `elpher-menu-refresh'.
@@ -2265,9 +2302,9 @@ list established by `elpher-menu-refresh'. See
                     (if (cdr pair)
                         (list (car pair)
                               (vector "G"
                     (if (cdr pair)
                         (list (car pair)
                               (vector "G"
+                                      (or (elpher-page-display-string (cdr pair)) "?")
                                       (or (elpher-address-to-url
                                       (or (elpher-address-to-url
-                                           (elpher-page-address (cdr pair))) "none")
-                                      (or (elpher-page-display-string (cdr pair)) "?")))
+                                           (elpher-page-address (cdr pair))) "none")))
                       separator))
                   (cons (cons (current-buffer) elpher-current-page)
                         (mapcar (lambda (page)
                       separator))
                   (cons (cons (current-buffer) elpher-current-page)
                         (mapcar (lambda (page)
@@ -2278,10 +2315,10 @@ list established by `elpher-menu-refresh'. See
           ;; No history means a list of one item. Add a separator.
           (list (list (current-buffer)
                       (vector "E"
           ;; No history means a list of one item. Add a separator.
           (list (list (current-buffer)
                       (vector "E"
-                              (or (elpher-address-to-url
-                                   (elpher-page-address elpher-current-page)))
                               (or (elpher-page-display-string elpher-current-page)
                               (or (elpher-page-display-string elpher-current-page)
-                                  (buffer-name))))
+                                  (buffer-name))
+                              (or (elpher-address-to-url
+                                   (elpher-page-address elpher-current-page)))))
                 separator))
           ((eq major-mode 'eww-mode)
           ;; A pair is (BUFFER-OR-DATA . PAGE) where BUFFER-OR-DTA is
                 separator))
           ((eq major-mode 'eww-mode)
           ;; A pair is (BUFFER-OR-DATA . PAGE) where BUFFER-OR-DTA is
@@ -2290,14 +2327,14 @@ list established by `elpher-menu-refresh'. See
           ;; what function to call. Add the separator at the end.
            (nconc (cons (list (current-buffer)
                               (vector "W"
           ;; what function to call. Add the separator at the end.
            (nconc (cons (list (current-buffer)
                               (vector "W"
-                                      (or (plist-get eww-data :url) "none")
-                                      (or (plist-get eww-data :title) "none")))
+                                      (or (plist-get eww-data :title) "none")
+                                      (or (plist-get eww-data :url) "none")))
                         (mapcar (lambda (data)
                                   (list
                                    (list (current-buffer) 'eww-restore-history data)
                                    (vector "W"
                         (mapcar (lambda (data)
                                   (list
                                    (list (current-buffer) 'eww-restore-history data)
                                    (vector "W"
-                                           (or (plist-get data :url) "none")
-                                           (or (plist-get data :title) "none"))))
+                                           (or (plist-get data :title) "none")
+                                           (or (plist-get data :url) "none"))))
                                 eww-history))
                   (list separator))))))
 
                                 eww-history))
                   (list separator))))))