"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.
'((t :inherit fixed-pitch))
"Face used for pre-formatted gemini text blocks.")
+(defface elpher-gemini-quoted
+ '((t :inherit font-lock-doc-face))
+ "Face used for gemini quoted texts.")
+
;;; Model
;;
(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")))
(if previous-page
(elpher-visit-page previous-page nil t)
(error "No previous page"))))
-
+
(defun elpher-reload-current-page ()
"Reload the current page, discarding any existing cached content."
(elpher-cache-content (elpher-page-address elpher-current-page) nil)
(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))
(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.)
(elpher-get-gopher-response search-address renderer))
(if aborted
(elpher-visit-previous-page))))))
-
+
;; Raw server response rendering
(defun elpher-render-raw (data &optional mime-type-string)
'help-echo #'elpher--page-button-help))
(insert (propertize display-string 'face 'elpher-unknown)))
(insert "\n"))))
-
+
(defun elpher-gemini-insert-header (header-line)
"Insert header described by HEADER-LINE into a text/gemini document.
The gemini map file line describing the header is given
(when (string-match "^\\(#+\\)[ \t]*" header-line)
(let* ((level (length (match-string 1 header-line)))
(header (substring header-line (match-end 0)))
- (face (pcase level
+ (face (pcase level
(1 'elpher-gemini-heading1)
(2 'elpher-gemini-heading2)
(3 'elpher-gemini-heading3)
(_ 'default)))
- (fill-column (/ (* fill-column
- (font-get (font-spec :name (face-font 'default)) :size))
- (font-get (font-spec :name (face-font face)) :size))))
+ (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))
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)
- (let* ((processed-text-line (if (match-string 2 text-line)
- (concat
- (replace-regexp-in-string "\*"
- elpher-gemini-bullet-string
- (match-string 0 text-line))
- (substring text-line (match-end 0)))
- text-line))
- (adaptive-fill-mode nil)
- (fill-prefix (if (match-string 2 text-line)
- (replace-regexp-in-string "[>\*]" " " (match-string 0 text-line))
- nil)))
+ (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 "\*"
+ elpher-gemini-bullet-string
+ (match-string 0 text-line))
+ (substring text-line (match-end 0))))
+ ((string-prefix-p ">" line-prefix)
+ (propertize text-line 'face 'elpher-gemini-quoted))
+ (t text-line))
+ text-line))
+ (adaptive-fill-mode nil))
(insert (elpher-process-text-for-display processed-text-line))
(newline)))
'help-echo help-string))
(insert "\n")
(elpher-restore-pos)))
-
+
;;; Bookmarks
;;
DISPLAY-STRING determines how the bookmark will appear in the
bookmark list, while URL is the url of the entry."
(list display-string url))
-
+
(defun elpher-bookmark-display-string (bookmark)
"Get the display string of BOOKMARK."
(elt bookmark 0))
(defun elpher-save-bookmarks (bookmarks)
"Record the bookmark list BOOKMARKS to the user's bookmark file.
Beware that this completely replaces the existing contents of the file."
+ (let ((bookmark-dir (file-name-directory elpher-bookmarks-file)))
+ (unless (file-directory-p bookmark-dir)
+ (make-directory bookmark-dir)))
(with-temp-file elpher-bookmarks-file
(erase-buffer)
(insert "; Elpher bookmarks file\n\n"
(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."
(message "Bookmark removed.")))
(error "No link selected"))))
+;;;###autoload
(defun elpher-bookmarks ()
"Visit bookmarks page."
(interactive)
(if button
(elpher-info-page (button-get button 'elpher-page))
(error "No item selected"))))
-
+
(defun elpher-info-current ()
"Display information on current page."
(interactive)