;;; elpher.el --- A friendly gopher and gemini client -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2022 Tim Vaughan <plugd@thelambdalab.xyz>
+;; Copyright (C) 2019-2023 Tim Vaughan <plugd@thelambdalab.xyz>
;; Copyright (C) 2020-2022 Elpher contributors (See info manual for full list)
;; Author: Tim Vaughan <plugd@thelambdalab.xyz>
;; Created: 11 April 2019
-;; Version: 3.4.2
+;; Version: 3.4.3
;; Keywords: comm gopher
;; Homepage: https://thelambdalab.xyz/elpher
;; Package-Requires: ((emacs "27.1"))
(require 'gnutls)
(require 'socks)
(require 'bookmark)
+(require 'rx)
;;; Global constants
;;
-(defconst elpher-version "3.4.2"
+(defconst elpher-version "3.4.3"
"Current version of elpher.")
(defconst elpher-margin-width 6
(elpher-with-clean-buffer
(insert "Gemini server is requesting input."))
(let* ((query-string
- (if (eq (elt response-code 1) ?1)
- (read-passwd (concat response-meta ": "))
- (read-string (concat response-meta ": "))))
+ (with-local-quit
+ (if (eq (elt response-code 1) ?1)
+ (read-passwd (concat response-meta ": "))
+ (read-string (concat response-meta ": ")))))
(query-address (seq-copy (elpher-page-address elpher-current-page)))
(old-fname (url-filename query-address)))
- (setf (url-filename query-address)
- (concat old-fname "?" (url-build-query-string `((,query-string)))))
- (elpher-get-gemini-response query-address renderer)))
+ (if (not query-string)
+ (elpher-visit-previous-page)
+ (setf (url-filename query-address)
+ (concat old-fname "?" (url-build-query-string `((,query-string)))))
+ (elpher-get-gemini-response query-address renderer))))
(?2 ; Normal response
(funcall renderer response-body response-meta))
(?3 ; Redirect
(filename (elpher-address-filename address)))
(unless (file-exists-p filename)
(elpher-visit-previous-page)
- (error "File not found"))
+ (error "File not found"))
(unless (file-readable-p filename)
(elpher-visit-previous-page)
- (error "Could not read from file"))
+ (error "Could not read from file"))
(let ((body (with-temp-buffer
(let ((coding-system-for-read 'binary)
(coding-system-for-write 'binary))
:export (lambda (link description format _plist)
(elpher-org-export-link link description format "gopher"))
:follow (lambda (link _arg) (elpher-org-follow-link link "gopher")))
+ (org-link-set-parameters
+ "gophers"
+ :export (lambda (link description format _plist)
+ (elpher-org-export-link link description format "gophers"))
+ :follow (lambda (link _arg) (elpher-org-follow-link link "gophers")))
(org-link-set-parameters
"finger"
:export (lambda (link description format _plist)
(if (boundp 'browse-url-default-handlers)
(add-to-list
'browse-url-default-handlers
- '("^\\(gopher\\|finger\\|gemini\\)://" . elpher-browse-url-elpher))
+ '("^\\(gopher\\|gophers\\|finger\\|gemini\\)://" . elpher-browse-url-elpher))
;; Patch `browse-url-browser-function' for older ones. The value of
;; that variable is `browse-url-default-browser' by default, so
;; that's the function that gets advised. If the value is an alist,
(lambda (url &rest _args)
"Handle gemini, gopher, and finger schemes using Elpher."
(let ((scheme (downcase (car (split-string url ":" t)))))
- (if (member scheme '("gemini" "gopher" "finger"))
+ (if (member scheme '("gemini" "gopher" "gophers" "finger"))
;; `elpher-go' always returns nil, which will stop the
;; advice chain here in a before-while
(elpher-go url)
;; Make mu4e aware of the gemini world
(setq mu4e~view-beginning-of-url-regexp
- "\\(?:https?\\|gopher\\|finger\\|gemini\\)://\\|mailto:")
+ "\\(?:https?\\|gopher\\|gophers\\|finger\\|gemini\\)://\\|mailto:")
;; eww:
;; Let elpher handle gemini, gopher links in eww buffer.
(setq eww-use-browse-url
- "\\`mailto:\\|\\(\\`gemini\\|\\`gopher\\|\\`finger\\)://")
+ "\\`mailto:\\|\\(\\`gemini\\|\\`gopher\\|\\`gophers\\|\\`finger\\)://")
;;; Interactive procedures
"Go to a particular gopher site HOST-OR-URL.
When run interactively HOST-OR-URL is read from the minibuffer."
(interactive (list
- (read-string (format "Visit URL (default scheme %s): " (elpher-get-default-url-scheme)))))
+ (read-string (format "Visit URL (default scheme %s): "
+ (elpher-get-default-url-scheme)))))
(let ((trimmed-host-or-url (string-trim host-or-url)))
(unless (string-empty-p trimmed-host-or-url)
(let ((page (elpher-page-from-url trimmed-host-or-url
current page."
(interactive)
(let* ((address (elpher-page-address elpher-current-page))
- (url (read-string (format "Visit URL (default scheme %s): " (elpher-get-default-url-scheme))
+ (url (read-string (format "Visit URL (default scheme %s): "
+ (elpher-get-default-url-scheme))
(elpher-address-to-url address))))
- (unless (string-empty-p (string-trim url))
- (elpher-visit-page (elpher-page-from-url url)))))
+ (let ((trimmed-url (string-trim url)))
+ (unless (string-empty-p trimmed-url)
+ (elpher-with-clean-buffer
+ (elpher-visit-page
+ (elpher-page-from-url trimmed-url (elpher-get-default-url-scheme))))))))
(defun elpher-redraw ()
"Redraw current page."
(if (elpher-address-about-p (elpher-page-address elpher-current-page))
(error "Cannot download %s"
(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-visit-page elpher-current-page
#'elpher-render-download
t)))