(defalias 'elpher-color-filter-apply
(if (fboundp 'xterm-color-filter)
(lambda (s)
- (let ((xterm-color-render nil))
- (xterm-color-filter 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
"Set the address corresponding to PAGE to NEW-ADDRESS."
(setcar (cdr page) new-address))
-(defvar elpher-current-page nil) ; buffer local
-(defvar elpher-history nil) ; buffer local
+(defvar elpher-current-page nil) ; buffer local
+(defvar elpher-history nil) ; buffer local
(defun elpher-visit-page (page &optional renderer no-history)
"Visit PAGE using its own renderer or RENDERER, if non-nil.
(when (> new-hkbytes-received hkbytes-received)
(setq hkbytes-received new-hkbytes-received)
(elpher-buffer-message
- (concat "("
- (number-to-string (/ hkbytes-received 10.0))
- " MB read)")
- 1)))
+ (concat "("
+ (number-to-string (/ hkbytes-received 10.0))
+ " MB read)")
+ 1)))
(setq response-string-parts
(cons string response-string-parts))))
(set-process-sentinel proc
(while (re-search-forward elpher-url-regex nil t)
(let ((page (elpher-make-page (substring-no-properties (match-string 0))
(elpher-address-from-url (match-string 0)))))
- (make-text-button (match-beginning 0)
- (match-end 0)
- 'elpher-page page
- 'action #'elpher-click-link
- 'follow-link t
- 'help-echo #'elpher--page-button-help
- 'face 'button)))
+ (make-text-button (match-beginning 0)
+ (match-end 0)
+ 'elpher-page page
+ 'action #'elpher-click-link
+ 'follow-link t
+ 'help-echo #'elpher--page-button-help
+ 'face 'button)))
(buffer-string)))
(defconst elpher-ansi-regex "\x1b\\[[^m]*m"
(defun elpher-get-gopher-query-page (renderer)
"Getter for gopher addresses requiring input.
The response is rendered using the rendering function RENDERER."
- (let* ((address (elpher-page-address elpher-current-page))
- (content (elpher-get-cached-content address))
- (aborted t))
+ (let* ((address (elpher-page-address elpher-current-page))
+ (content (elpher-get-cached-content address))
+ (aborted t))
(if (and content (funcall renderer nil))
(elpher-with-clean-buffer
(insert content)
(error "Gemini server response unknown: %s %s"
response-code response-meta))))))
+(unless (fboundp 'read-answer)
+ (defun read-answer (question answers)
+ "Backfill for the new read-answer code."
+ (completing-read question (mapcar 'identity answers))))
+
(defun elpher-choose-client-certificate ()
"Prompt for a client certificate to use to establish a TLS connection."
(let* ((read-answer-short t))
(condition-case the-error
(if (and content (funcall renderer nil))
(elpher-with-clean-buffer
- (insert content)
- (elpher-restore-pos))
+ (insert content)
+ (elpher-restore-pos))
(elpher-with-clean-buffer
(insert "LOADING GEMINI... (use 'u' to cancel)\n"))
(setq elpher-gemini-redirect-chain nil)
(2 'elpher-gemini-heading2)
(3 'elpher-gemini-heading3)
(_ '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)))
+ (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)))
(setq elpher--gemini-page-headings (cons (cons header (point))
elpher--gemini-page-headings))
(unless (display-graphic-p)
(propertize text-line 'face 'elpher-gemini-quoted))
(t text-line))
text-line))
- (adaptive-fill-mode nil))
+ (adaptive-fill-mode t))
(insert (elpher-process-text-for-display processed-text-line))
(newline)))
;;; Integrations
;;
+;;; Org
+
;; Avoid byte compilation warnings.
(eval-when-compile
(declare-function org-link-store-props "ol")
(declare-function org-link-set-parameters "ol"))
-(defun elpher-org-link-store ()
- "Store link to an `elpher' page in `org'."
+(defun elpher-org-export-link (link description format protocol)
+ "Export a LINK with DESCRIPTION for the given PROTOCOL and FORMAT.
+
+FORMAT is an Org export backend. DESCRIPTION may be nil. PROTOCOL may be one
+of gemini, gopher or finger."
+ (let* ((url (if (equal protocol "elpher")
+ (string-remove-prefix "elpher:" link)
+ (format "%s:%s" protocol link)))
+ (desc (or description url)))
+ (pcase format
+ (`gemini (format "=> %s %s" url desc))
+ (`html (format "<a href=\"%s\">%s</a>" url desc))
+ (`latex (format "\\href{%s}{%s}" url desc))
+ (_ (if (not description)
+ url
+ (format "%s (%s)" desc url))))))
+
+(defun elpher-org-store-link ()
+ "Store link to an `elpher' page in Org."
(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)
+ (let* ((url (elpher-info-current))
+ (desc (car elpher-current-page))
+ (protocol (cond
+ ((string-prefix-p "gemini:" url) "gemini")
+ ((string-prefix-p "gopher:" url) "gopher")
+ ((string-prefix-p "finger:" url) "finger")
+ (t "elpher"))))
+ (when (equal "elpher" protocol)
+ ;; Weird link. Or special inner link?
+ (setq url (concat "elpher:" url)))
+ (org-link-store-props :type protocol :link url :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))))
+(defun elpher-org-follow-link (link protocol)
+ "Visit a LINK for the given PROTOCOL.
+
+PROTOCOL may be one of gemini, gopher or finger. This method also support old
+paramter elpher, where link is self-contained."
+ (let ((url (if (equal protocol "elpher")
+ (string-remove-prefix "elpher:" link)
+ (format "%s:%s" protocol link))))
+ (elpher-go url)))
(with-eval-after-load 'org
- (org-link-set-parameters "elpher"
- :store #'elpher-org-link-store
- :follow #'elpher-org-link-follow))
+ (org-link-set-parameters
+ "elpher"
+ :store #'elpher-org-store-link
+ :export (lambda (link description format _plist)
+ (elpher-org-export-link link description format "elpher"))
+ :follow (lambda (link _arg) (elpher-org-follow-link link "elpher")))
+ (org-link-set-parameters
+ "gemini"
+ :export (lambda (link description format _plist)
+ (elpher-org-export-link link description format "gemini"))
+ :follow (lambda (link _arg) (elpher-org-follow-link link "gemini")))
+ (org-link-set-parameters
+ "gopher"
+ :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
+ "finger"
+ :export (lambda (link description format _plist)
+ (elpher-org-export-link link description format "finger"))
+ :follow (lambda (link _arg) (elpher-org-follow-link link "finger"))))
+
+;;; Browse URL
+
+;; Avoid byte compilation warnings.
+(eval-when-compile
+ (defvar thing-at-point-uri-schemes))
;;;###autoload
(defun elpher-browse-url-elpher (url &rest _args)
(elpher-go url))
;; Use elpher to open gopher, finger and gemini links
-(with-eval-after-load 'browse-url
- (add-to-list
- 'browse-url-default-handlers
- '("^\\(gopher\\|finger\\|gemini\\)://" . elpher-browse-url-elpher)))
-
-;; Avoid byte compilation warnings.
-(eval-when-compile
- (defvar thing-at-point-uri-schemes)
- (defvar mu4e~view-beginning-of-url-regexp))
+;; For recent version of `browse-url' package
+(if (boundp 'browse-url-default-handlers)
+ (add-to-list
+ 'browse-url-default-handlers
+ '("^\\(gopher\\|finger\\|gemini\\)://" . elpher-browse-url-elpher))
+ ;; Patch browse-url-default-browser for older ones
+ (advice-add 'browse-url-default-browser :before-while
+ (lambda (url &rest _args)
+ (let ((scheme (downcase (car (split-string url ":" t)))))
+ (if (member scheme '("gemini" "gopher" "finger"))
+ ;; `elpher-go' always returns nil, which will stop the
+ ;; advice chain here in a before-while
+ (elpher-go url)
+ ;; chain must continue, then return t.
+ t)))))
;; Register "gemini://" as a URI scheme so `browse-url' does the right thing
(with-eval-after-load 'thingatpt
(add-to-list 'thing-at-point-uri-schemes "gemini://"))
+;;; Mu4e:
+
+(eval-when-compile
+ (defvar mu4e~view-beginning-of-url-regexp))
+
(with-eval-after-load 'mu4e-view
;; Make mu4e aware of the gemini world
(setq mu4e~view-beginning-of-url-regexp
(define-key map (kbd "F") 'elpher-forget-current-certificate)
(define-key map (kbd "v") 'elpher-visit-gemini-numbered-link)
(when (fboundp 'evil-define-key*)
- (evil-define-key* 'motion map
- (kbd "TAB") 'elpher-next-link
- (kbd "C-") 'elpher-follow-current-link
- (kbd "C-t") 'elpher-back
- (kbd "u") 'elpher-back
- (kbd "-") 'elpher-back
- (kbd "^") 'elpher-back
- (kbd "U") 'elpher-back-to-start
- [mouse-3] 'elpher-back
- (kbd "o") 'elpher-go
- (kbd "O") 'elpher-go-current
- (kbd "r") 'elpher-redraw
- (kbd "R") 'elpher-reload
- (kbd "T") 'elpher-toggle-tls
- (kbd ".") 'elpher-view-raw
- (kbd "d") 'elpher-download
- (kbd "D") 'elpher-download-current
- (kbd "J") 'elpher-jump
- (kbd "i") 'elpher-info-link
- (kbd "I") 'elpher-info-current
- (kbd "c") 'elpher-copy-link-url
- (kbd "C") 'elpher-copy-current-url
- (kbd "a") 'elpher-bookmark-link
- (kbd "A") 'elpher-bookmark-current
- (kbd "x") 'elpher-unbookmark-link
- (kbd "X") 'elpher-unbookmark-current
- (kbd "B") 'elpher-bookmarks
- (kbd "S") 'elpher-set-gopher-coding-system
- (kbd "F") 'elpher-forget-current-certificate
- (kbd "v") 'elpher-visit-gemini-numbered-link))
+ (evil-define-key*
+ 'motion map
+ (kbd "TAB") 'elpher-next-link
+ (kbd "C-") 'elpher-follow-current-link
+ (kbd "C-t") 'elpher-back
+ (kbd "u") 'elpher-back
+ (kbd "-") 'elpher-back
+ (kbd "^") 'elpher-back
+ (kbd "U") 'elpher-back-to-start
+ [mouse-3] 'elpher-back
+ (kbd "o") 'elpher-go
+ (kbd "O") 'elpher-go-current
+ (kbd "r") 'elpher-redraw
+ (kbd "R") 'elpher-reload
+ (kbd "T") 'elpher-toggle-tls
+ (kbd ".") 'elpher-view-raw
+ (kbd "d") 'elpher-download
+ (kbd "D") 'elpher-download-current
+ (kbd "J") 'elpher-jump
+ (kbd "i") 'elpher-info-link
+ (kbd "I") 'elpher-info-current
+ (kbd "c") 'elpher-copy-link-url
+ (kbd "C") 'elpher-copy-current-url
+ (kbd "a") 'elpher-bookmark-link
+ (kbd "A") 'elpher-bookmark-current
+ (kbd "x") 'elpher-unbookmark-link
+ (kbd "X") 'elpher-unbookmark-current
+ (kbd "B") 'elpher-bookmarks
+ (kbd "S") 'elpher-set-gopher-coding-system
+ (kbd "F") 'elpher-forget-current-certificate
+ (kbd "v") 'elpher-visit-gemini-numbered-link))
map)
"Keymap for gopher client.")
to create a new session. Returns the buffer selected (or created)."
(interactive "P")
(let* ((name (default-value 'elpher-buffer-name))
- (buf (cond ((numberp arg)
- (get-buffer-create (format "%s<%d>" name arg)))
- (arg
- (generate-new-buffer name))
- (t
- (get-buffer-create name)))))
+ (buf (cond ((numberp arg)
+ (get-buffer-create (format "%s<%d>" name arg)))
+ (arg
+ (generate-new-buffer name))
+ (t
+ (get-buffer-create name)))))
(pop-to-buffer-same-window buf)
(unless (buffer-modified-p)
(elpher-mode)
- (let ((start-page (elpher-make-page "Elpher Start Page"
- (elpher-make-special-address 'start))))
- (elpher-visit-page start-page))
+ (let ((start-page (elpher-make-page
+ "Elpher Start Page"
+ (elpher-make-special-address 'start))))
+ (elpher-visit-page start-page))
"Started Elpher."))); Otherwise (elpher) evaluates to start page string.
;;; elpher.el ends here