-;;; elpher.el --- A friendly gopher and gemini client -*- lexical-binding:t -*-
-
-;; Copyright (C) 2019-2020 Tim Vaughan
+;;; elpher.el --- A friendly gopher and gemini client -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Jens Östlund <jostlund@gmail.com>
+;; Copyright (C) 2021 F. Jason Park <jp@neverwas.me>
+;; Copyright (C) 2021 Christopher Brannon <chris@the-brannons.com>
+;; Copyright (C) 2021 Omar Polo <op@omarpolo.com>
+;; Copyright (C) 2021 Noodles! <nnoodle@chiru.no>
+;; Copyright (C) 2020-2021 Alex Schroeder <alex@gnu.org>
+;; Copyright (C) 2020 Zhiwei Chen <chenzhiwei03@kuaishou.com>
+;; Copyright (C) 2020 condy0919 <condy0919@gmail.com>
+;; Copyright (C) 2020 Alexis <flexibeast@gmail.com>
+;; Copyright (C) 2020 Étienne Deparis <etienne@depar.is>
+;; Copyright (C) 2020 Simon Nicolussi <sinic@sinic.name>
+;; Copyright (C) 2020 Michel Alexandre Salim <michel@michel-slm.name>
+;; Copyright (C) 2020 Koushk Roy <kroy@twilio.com>
+;; Copyright (C) 2020 Vee <vee@vnsf.xyz>
+;; Copyright (C) 2020 Simon South <simon@simonsouth.net>
+;; Copyright (C) 2019-2020 Tim Vaughan <plugd@thelambdalab.xyz>
;; Author: Tim Vaughan <plugd@thelambdalab.xyz>
;; Created: 11 April 2019
-;; Version: 2.10.2
+;; Version: 2.11.0
;; Keywords: comm gopher
-;; Homepage: http://thelambdalab.xyz/elpher
-;; Package-Requires: ((emacs "26.2"))
+;; Homepage: https://alexschroeder.ch/cgit/elpher
+;; Package-Requires: ((emacs "27.1"))
;; This file is not part of GNU Emacs.
;; Elpher is under active development. Any suggestions for
;; improvements are welcome, and can be made on the official
-;; project page, gopher://thelambdalab.xyz/1/projects/elpher/.
+;; project page, https://alexschroeder.ch/cgit/elpher.
;;; Code:
(require 'url-util)
(require 'subr-x)
(require 'dns)
-(require 'ansi-color)
(require 'nsm)
(require 'gnutls)
(require 'socks)
+;;; 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
;;
-(defconst elpher-version "2.10.2"
+(defconst elpher-version "2.11.0"
"Current version of elpher.")
(defconst elpher-margin-width 6
"Association list from types to getters, renderers, margin codes and index faces.")
+;;; Internal variables
+;;
+
+;; buffer-local
+(defvar elpher--gemini-page-headings nil
+ "List of headings on the page.")
+
+(defvar elpher--gemini-page-links nil
+ "List of links on the page.")
+
+(defvar elpher--gemini-page-links-cache (make-hash-table :test 'equal)
+ "Hash of addresses and page links.")
+
;;; Customization group
;;
(defcustom elpher-auto-disengage-TLS nil
"If non-nil, automatically disengage TLS following an unsuccessful connection.
-While enabling this may seem convenient, it is also potentially dangerous as it
-allows switching from an encrypted channel back to plain text without user input."
+While enabling this may seem convenient, it is also potentially
+dangerous as it allows switching from an encrypted channel back to
+plain text without user input."
:type '(boolean))
(defcustom elpher-connection-timeout 5
:type '(file))
(defcustom elpher-default-url-type "gopher"
- "Default URL type to assume if not explicitly given."
+ "Default URL type (i.e. scheme) to assume if not explicitly given."
:type '(choice (const "gopher")
(const "gemini")))
Otherwise, the SOCKS proxy is only used for connections to onion services."
:type '(boolean))
+(defcustom elpher-gemini-number-links nil
+ "If non-nil, number links in gemini pages when rendering.
+Links can be accessed by pressing `v' ('visit') followed by the link number."
+ :type '(boolean))
+
;; Face customizations
(defgroup elpher-faces nil
"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.
(setq-local elpher-current-page page)
(let* ((address (elpher-page-address page))
(type (elpher-address-type address))
- (type-record (cdr (assoc type elpher-type-map))))
+ (type-record (cdr (assoc type elpher-type-map)))
+ (page-links nil))
(if type-record
- (funcall (car type-record)
- (if renderer
- renderer
- (cadr type-record)))
+ (progn
+ (funcall (car type-record)
+ (if renderer
+ renderer
+ (cadr type-record)))
+ (setq page-links (gethash address elpher--gemini-page-links-cache))
+ (if page-links
+ (setq elpher--gemini-page-links page-links)))
(elpher-visit-previous-page)
(pcase type
(`(gopher ,type-char)
"Preprocess text selector response contained in STRING.
This involes decoding the character representation, and clearing
away CRs and any terminating period."
- (elpher-decode (replace-regexp-in-string "\n\.\n$" "\n"
+ (elpher-decode (replace-regexp-in-string "\n\\.\n$" "\n"
(replace-regexp-in-string "\r" "" string))))
(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
(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
;; Text rendering
(defconst elpher-url-regex
- "\\([a-zA-Z]+\\)://\\([a-zA-Z0-9.\-]*[a-zA-Z0-9\-]\\|\[[a-zA-Z0-9:]+\]\\)\\(:[0-9]+\\)?\\(/\\([0-9a-zA-Z\-_~?/@|:.%#=&]*[0-9a-zA-Z\-_~?/@|#]\\)?\\)?"
+ "\\([a-zA-Z]+\\)://\\([a-zA-Z0-9.-]*[a-zA-Z0-9-]\\|\\[[a-zA-Z0-9:]+\\]\\)\\(:[0-9]+\\)?\\(/\\([0-9a-zA-Z_~?/@|:.%#=&-]*[0-9a-zA-Z_~?/@|#-]\\)?\\)?"
"Regexp used to locate and buttinofy URLs in text files loaded by elpher.")
(defun elpher-buttonify-urls (string)
(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"
- "Wildly incomplete regexp used to strip out some troublesome ANSI escape sequences.")
+ "Incomplete regexp used to strip out some troublesome ANSI escape sequences.")
(defun elpher-process-text-for-display (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))))
+ (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-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)
(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)
(address (elpher-address-from-gemini-url url))
(type (if address (elpher-address-type address) nil))
(type-map-entry (cdr (assoc type elpher-type-map))))
+ (setq elpher--gemini-page-links (append elpher--gemini-page-links `(,address)))
(when display-string
(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
(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)
(insert (make-string level ?#) " "))
(insert (propertize header 'face face))
(defun elpher-gemini-insert-text (text-line)
"Insert a plain non-preformatted TEXT-LINE into a text/gemini document.
This function uses Emacs' auto-fill to wrap text sensibly to a maximum
-width defined by elpher-gemini-max-fill-width."
- (string-match "\\(^[ \t]*\\)\\(\*[ \t]+\\|>[ \t]*\\)?" text-line)
+width defined by `elpher-gemini-max-fill-width'."
+ (string-match "\\(^[ \t]*\\)\\(\\*[ \t]+\\|>[ \t]*\\)?" text-line)
(let* ((line-prefix (match-string 2 text-line))
(processed-text-line
(if line-prefix
(cond ((string-prefix-p "*" line-prefix)
(concat
- (replace-regexp-in-string "\*"
+ (replace-regexp-in-string "\\*"
elpher-gemini-bullet-string
(match-string 0 text-line))
(substring text-line (match-end 0))))
(defun elpher-render-gemini-map (data _parameters)
"Render DATA as a gemini map file, PARAMETERS is currently unused."
(elpher-with-clean-buffer
- (let ((preformatted nil))
+ (setq elpher--gemini-page-headings nil)
+ (let ((preformatted nil)
+ (link-counter 1))
(auto-fill-mode 1)
(setq-local fill-column (min (window-width) elpher-gemini-max-fill-width))
+ (setq elpher--gemini-page-links '())
(dolist (line (split-string data "\n"))
(cond
((string-prefix-p "```" line) (setq preformatted (not preformatted)))
(preformatted (insert (elpher-process-text-for-display
(propertize line 'face 'elpher-gemini-preformatted))
"\n"))
- ((string-prefix-p "=>" line) (elpher-gemini-insert-link line))
+ ((string-prefix-p "=>" line)
+ (progn
+ (if elpher-gemini-number-links
+ (insert
+ (concat
+ "["
+ (number-to-string link-counter)
+ "] ")))
+ (setq link-counter (1+ link-counter))
+ (elpher-gemini-insert-link line)))
((string-prefix-p "#" line) (elpher-gemini-insert-header line))
(t (elpher-gemini-insert-text line)))))
+ (setq elpher--gemini-page-headings (nreverse elpher--gemini-page-headings))
(elpher-cache-content
(elpher-page-address elpher-current-page)
- (buffer-string))))
+ (buffer-string))
+ (puthash
+ (elpher-page-address elpher-current-page)
+ elpher--gemini-page-links
+ elpher--gemini-page-links-cache)))
(defun elpher-render-gemini-plain-text (data _parameters)
"Render DATA as plain text file. PARAMETERS is currently unused."
" - u/mouse-3/U: return to previous page or to the start page\n"
" - o/O: visit different selector or the root menu of the current server\n"
" - g: go to a particular address (gopher, gemini, finger)\n"
+ " - v: visit a numbered link on a gemini page\n"
" - d/D: download item under cursor or current page\n"
" - i/I: info on item under cursor or current page\n"
" - c/C: copy URL representation of item under cursor or current page\n"
"Alternatively, select a search engine and enter some search terms:\n")
(elpher-insert-index-record "Gopher Search Engine (Veronica-2)"
(elpher-make-gopher-address ?7 "/v2/vs" "gopher.floodgap.com" 70))
- (elpher-insert-index-record "Gemini Search Engine (GUS)"
- (elpher-address-from-url "gemini://gus.guru/search"))
+ (elpher-insert-index-record "Gemini Search Engine (geminispace.info)"
+ (elpher-address-from-url "gemini://geminispace.info/search"))
(insert "\n"
"This page contains your bookmarked sites (also visit with B):\n")
(elpher-insert-index-record "Your Bookmarks" 'bookmarks)
;;; Integrations
;;
-(defun elpher-org-link-store ()
- "Store link to an `elpher' page in org-mode."
+(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))))))
+
+;; Avoid byte compilation warnings.
+(declare-function org-link-store-props "ol")
+(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))))
-
-(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 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)))
+
+;; Avoid byte compilation warnings.
+(declare-function org-link-set-parameters "ol")
+(with-eval-after-load 'org
+ (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"))))
+
+;;;###autoload
+(defun elpher-browse-url-elpher (url &rest _args)
+ "Browse URL using Elpher. This function is used by `browse-url'."
+ (interactive (browse-url-interactive-arg "Elpher URL: "))
+ (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))
+
+;; 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://"))
+
+(with-eval-after-load 'mu4e-view
+ ;; Make mu4e aware of the gemini world
+ (setq mu4e~view-beginning-of-url-regexp
+ "\\(?:https?\\|gopher\\|finger\\|gemini\\)://\\|mailto:"))
;;; Interactive procedures
;;
"Go to a particular site read from the minibuffer, initialized with the current URL."
(interactive)
(let ((address (elpher-page-address elpher-current-page)))
- (if (elpher-address-special-p address)
- (error "Command invalid for this page")
- (let ((url (read-string "Gopher or Gemini URL: " (elpher-address-to-url address))))
- (elpher-visit-page (elpher-make-page url (elpher-address-from-url url)))))))
+ (let ((url (read-string "Gopher or Gemini URL: "
+ (unless (elpher-address-special-p address)
+ (elpher-address-to-url address)))))
+ (elpher-visit-page (elpher-make-page url (elpher-address-from-url url))))))
+
+(defun elpher-visit-gemini-numbered-link (n)
+ "Visit link designated by a number N."
+ (interactive "nLink number: ")
+ (if (or (> n (length elpher--gemini-page-links))
+ (< n 1))
+ (user-error "Invalid link number"))
+ (let ((address (nth (1- n) elpher--gemini-page-links)))
+ (elpher-go (url-recreate-url address))))
(defun elpher-redraw ()
"Redraw current page."
(define-key map (kbd "B") 'elpher-bookmarks)
(define-key map (kbd "S") 'elpher-set-gopher-coding-system)
(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 "U") 'elpher-back-to-start
- [mouse-3] 'elpher-back
- (kbd "g") '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 "m") '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))
+ (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.")
This mode is automatically enabled by the interactive
functions which initialize the gopher client, namely
`elpher', `elpher-go' and `elpher-bookmarks'."
+ (setq-local elpher--gemini-page-headings nil)
(setq-local elpher-current-page nil)
(setq-local elpher-history nil)
- (setq-local elpher-buffer-name (buffer-name)))
+ (setq-local elpher-buffer-name (buffer-name))
+
+ (setq-local imenu-create-index-function
+ (lambda ()
+ elpher--gemini-page-headings)))
(when (fboundp 'evil-set-initial-state)
(evil-set-initial-state 'elpher-mode 'motion))
The buffer used for Elpher sessions is determined by the value of
‘elpher-buffer-name’. If there is already an Elpher session active in
that buffer, Emacs will simply switch to it. Otherwise, a new session
-will begin. A numeric prefix arg (as in ‘C-u 42 M-x elpher RET’)
-switches to the session with that number, creating it if necessary. A
-nonnumeric prefix arg means to create a new session. Returns the
-buffer selected (or created)."
+will begin. A numeric prefix ARG (as in ‘\\[universal-argument] 42
+\\[execute-extended-command] elpher RET’) switches to the session with
+that number, creating it if necessary. A non numeric prefix ARG means
+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