Merge remote-tracking branch 'upstream/patch_integrate_with_browse_url' into main
[elpher.git] / elpher.el
index 5ce6992..da4d11d 100644 (file)
--- a/elpher.el
+++ b/elpher.el
@@ -145,6 +145,11 @@ These certificates may be used for establishing authenticated TLS connections."
   "The command used to launch openssl when generating TLS client certificates."
   :type '(file))
 
+(defcustom elpher-default-url-type "gopher"
+  "Default URL type to assume if not explicitly given."
+  :type '(choice (const "gopher")
+                 (const "gemini")))
+
 (defcustom elpher-gemini-TLS-cert-checks nil
   "If non-nil, verify gemini server TLS certs using the default security level.
 Otherwise, certificate verification is disabled.
@@ -282,13 +287,17 @@ Otherwise, the SOCKS proxy is only used for connections to onion services."
             (setf (url-filename url)
                   (url-unhex-string (url-filename url)))
             (unless (url-type url)
-              (setf (url-type url) "gopher"))
+              (setf (url-type url) elpher-default-url-type))
+            (unless (url-host url)
+              (let ((p (split-string (url-filename url) "/" nil nil)))
+                (setf (url-host url) (car p))
+                (setf (url-filename url)
+                      (if (cdr p)
+                          (concat "/" (mapconcat #'identity (cdr p) "/"))
+                        ""))))
             (when (or (equal "gopher" (url-type url))
                       (equal "gophers" (url-type url)))
               ;; Gopher defaults
-              (unless (url-host url)
-                (setf (url-host url) (url-filename url))
-                (setf (url-filename url) ""))
               (when (or (equal (url-filename url) "")
                         (equal (url-filename url) "/"))
                 (setf (url-filename url) "/1")))
@@ -631,7 +640,8 @@ the host operating system and the local network capabilities."
     (unless (< (elpher-address-port address) 65536)
       (error "Cannot establish network connection: port number > 65536"))
     (when (and (eq use-tls 'gemini) (not elpher-gemini-TLS-cert-checks))
-      (setq-local network-security-level 'low))
+      (setq-local network-security-level 'low)
+      (setq-local gnutls-verify-error nil))
     (condition-case nil
         (let* ((kill-buffer-query-functions nil)
                (port (elpher-address-port address))
@@ -829,7 +839,7 @@ base for the installed key and certificate files."
   (mapcar
    (lambda (file)
      (file-name-sans-extension file))
-   (directory-files elpher-certificate-directory nil "\.key$")))
+   (directory-files elpher-certificate-directory nil "\\.key$")))
 
 (defun elpher-forget-current-certificate ()
   "Causes any current certificate to be forgotten.)
@@ -1391,7 +1401,11 @@ by HEADER-LINE."
                    (1 'elpher-gemini-heading1)
                    (2 'elpher-gemini-heading2)
                    (3 'elpher-gemini-heading3)
-                   (_ 'default))))
+                   (_ 'default)))
+          (fill-column (if (display-graphic-p)
+                           (/ (* fill-column
+                                 (font-get (font-spec :name (face-font 'default)) :size))
+                              (font-get (font-spec :name (face-font face)) :size)) fill-column)))
       (unless (display-graphic-p)
         (insert (make-string level ?#) " "))
       (insert (propertize header 'face face))
@@ -1686,6 +1700,50 @@ If ADDRESS is already bookmarked, update the label only."
                    (not (equal (elpher-bookmark-url bookmark) url)))
                  (elpher-load-bookmarks)))))
 
+;;; Integrations
+;;
+
+(defun elpher-org-link-store ()
+  "Store link to an `elpher' page in org-mode."
+  (when (eq major-mode 'elpher-mode)
+    (let ((link (concat "elpher:" (elpher-info-current)))
+          (desc (car elpher-current-page)))
+      (org-link-store-props :type "elpher"
+                            :link link
+                            :description desc)
+      t)))
+
+(defun elpher-org-link-follow (link _args)
+  "Follow an `elpher' link in an `org' buffer."
+  (require 'elpher)
+  (message (concat "Got link: " link))
+  (when (or
+         (string-match-p "^gemini://.+" link)
+         (string-match-p "^gopher://.+" link)
+         (string-match-p "^finger://.+" link))
+    (elpher-go (string-remove-prefix "elpher:" link))))
+
+(with-eval-after-load "org"
+  ;; Use `org-link-set-parameters' if defined (org-mode 9+)
+  (if (fboundp 'org-link-set-parameters)
+      (org-link-set-parameters "elpher"
+                               :store #'elpher-org-link-store
+                               :follow #'elpher-org-link-follow)
+    (org-add-link-type "mu4e" 'elpher-org-link-follow)
+    (add-hook 'org-store-link-functions 'elpher-org-link-store)))
+
+(defun browse-url-elpher (url &rest _args)
+  "Browse URL. This function is used by `browse-url'."
+  (interactive (browse-url-interactive-arg "Elpher URL: "))
+  (elpher-go url))
+
+(with-eval-after-load "browse-url"
+  ;; Use elpher to open gopher, finger and gemini links
+  (add-to-list 'browse-url-default-handlers
+               '("^\\(gopher\\|finger\\|gemini\\)://" . browse-url-elpher))
+  ;; Register "gemini://" as a URI scheme so `browse-url' does the right thing
+  (add-to-list 'thing-at-point-uri-schemes "gemini://"))
+
 ;;; Interactive procedures
 ;;
 
@@ -1704,6 +1762,7 @@ If ADDRESS is already bookmarked, update the label only."
   (interactive)
   (push-button))
 
+;;;###autoload
 (defun elpher-go (host-or-url)
   "Go to a particular gopher site HOST-OR-URL.
 When run interactively HOST-OR-URL is read from the minibuffer."
@@ -1889,6 +1948,7 @@ When run interactively HOST-OR-URL is read from the minibuffer."
             (message "Bookmark removed.")))
       (error "No link selected"))))
 
+;;;###autoload
 (defun elpher-bookmarks ()
   "Visit bookmarks page."
   (interactive)