From 8209d5739c3c0d68449107db8b305e77a2bc886d Mon Sep 17 00:00:00 2001 From: cage Date: Sun, 25 Jul 2021 18:36:06 +0200 Subject: [PATCH] - [gemini] added "no wait" directive when downloading non gemini text format from gemini allow opening file before it is downloaded completely. --- etc/shared.conf | 14 +++++++-- src/gemini-viewer.lisp | 56 ++++++++++++++++++++++----------- src/software-configuration.lisp | 40 ++++++++++++++++++----- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/etc/shared.conf b/etc/shared.conf index 409fb4a..a4ea4c4 100644 --- a/etc/shared.conf +++ b/etc/shared.conf @@ -169,9 +169,17 @@ color-regexp = ":rendering" cyan # open png files with gimp but cache them before # ▼▼▼▼▼▼▼▼▼ # open "https?://png$" with "gimp" use cache -# if you want to open some kind of file with tinmop try the following -# valid values are "tinmop" "me" "internal" + +# using "no wait" allow for content to be opened before download is +# completed; note that not all file types can be opened before the +# whole file is available to the opening program +# ▼▼▼▼▼▼▼ +# open "mp3$" with "xterm -e mpv" no wait +# + +# finally if you want to open some kind of file with tinmop try the +# following: valid values are "tinmop" "me" "internal" # ▼▼▼▼▼▼▼▼ open "^((gemini://)|(\\.)|(/)).+gmi$" with "tinmop" open "^((gemini://)|(\\.)|(/)).+txt$" with "tinmop" -open "^((gemini://)|(\\.)|(/)).+sh$" with "tinmop" \ No newline at end of file +open "^((gemini://)|(\\.)|(/)).+sh$" with "tinmop" diff --git a/src/gemini-viewer.lisp b/src/gemini-viewer.lisp index 9253df7..650eac9 100644 --- a/src/gemini-viewer.lisp +++ b/src/gemini-viewer.lisp @@ -19,9 +19,12 @@ (defparameter *gemini-db-streams-lock* (bt:make-recursive-lock)) -(define-constant +read-buffer-size+ 1024 +(define-constant +read-buffer-size+ 2048 :documentation "Chunk's size of the buffer when reading non gemini contents from stream") +(define-constant +buffer-minimum-size-to-open+ 4096 + :documentation "Minimum size of the saved contents (non gemini text) before attempt to opening with an user defined program: see configuration directive 'use program foo *no wait*'") + (defparameter *gemini-streams-db* ()) (defun push-db-stream (stream-object) @@ -462,25 +465,42 @@ (when-let ((extension (fs:get-extension path))) (setf support-file (fs:temporary-file :extension extension))) (with-open-support-file (file-stream support-file) - (labels ((%fill-buffer () + (let ((partial-content-not-opened t)) + (labels ((download-completed-p (buffer read-so-far) + (< read-so-far (length buffer))) + (opening-partial-contents-p (read-so-far) + (> read-so-far +buffer-minimum-size-to-open+)) + (%fill-buffer () (declare (optimize (debug 0) (speed 3))) (when (downloading-allowed-p wrapper-object) - (multiple-value-bind (buffer read-so-far) - (read-array download-stream +read-buffer-size+) - (declare ((vector (unsigned-byte 8)) buffer)) - (declare (fixnum read-so-far)) - (increment-bytes-count wrapper-object read-so-far) - (if (< read-so-far (length buffer)) - (progn - (write-sequence buffer file-stream :start 0 :end read-so-far) - (force-output file-stream) - (setf (stream-status wrapper-object) :completed) - (gemini-client:close-ssl-socket socket) - (os-utils:open-resource-with-external-program support-file nil)) - (progn - (write-sequence buffer file-stream) - (%fill-buffer))))))) - (%fill-buffer)))))) + (multiple-value-bind (program-exists y wait-for-download) + (swconf:link-regex->program-to-use support-file) + (declare (ignore y)) + (multiple-value-bind (buffer read-so-far) + (read-array download-stream +read-buffer-size+) + (declare ((vector (unsigned-byte 8)) buffer)) + (declare (fixnum read-so-far)) + (increment-bytes-count wrapper-object read-so-far) + (if (download-completed-p buffer read-so-far) + (progn + (write-sequence buffer file-stream :start 0 :end read-so-far) + (force-output file-stream) + (setf (stream-status wrapper-object) :completed) + (gemini-client:close-ssl-socket socket) + (when wait-for-download + (os-utils:open-resource-with-external-program support-file + nil))) + (progn + (write-sequence buffer file-stream) + (when (and partial-content-not-opened + program-exists + (not wait-for-download) + (opening-partial-contents-p (octect-count wrapper-object))) + (setf partial-content-not-opened nil) + (os-utils:open-resource-with-external-program support-file + nil)) + (%fill-buffer)))))))) + (%fill-buffer))))))) (defun request-success-dispatched-clrs (enqueue) (lambda (status code-description meta response socket iri parsed-iri) diff --git a/src/software-configuration.lisp b/src/software-configuration.lisp index 9d7f3f4..e8eda7d 100644 --- a/src/software-configuration.lisp +++ b/src/software-configuration.lisp @@ -29,7 +29,7 @@ ;; COMMENT* ;; SERVER-ASSIGN := SERVER-KEY BLANKS ASSIGN BLANKS GENERIC-VALUE BLANKS ;; USERNAME-ASSIGN := USERNAME-KEY BLANKS WITH BLANKS GENERIC-VALUE BLANKS -;; OPEN-LINK-HELPER := OPEN-LINK-HELPER-KEY BLANKS ASSIGN BLANKS REGEXP PROGRAM-NAME BLANKS USE-CACHE +;; OPEN-LINK-HELPER := OPEN-LINK-HELPER-KEY BLANKS ASSIGN BLANKS REGEXP PROGRAM-NAME BLANKS USE-CACHE? NOWAIT? ;; GENERIC-ASSIGN := (and key blanks assign blanks ;; (or quoted-string ;; hexcolor @@ -44,6 +44,9 @@ ;; FILEPATH := QUOTED-STRING ;; PROGRAM-NAME := QUOTED-STRING ;; USE-CACHE := USE BLANKS CACHE +;; NOWAIT := NO BLANKS WAIT +;; NO := "no" +;; WAIT := "wait" ;; CACHE := "cache" ;; USE := "use" ;; SERVER-KEY := "server" @@ -294,7 +297,12 @@ :initform t :initarg :use-cache :reader use-cache-p - :writer (setf use-cache))) + :writer (setf use-cache)) + (wait + :initform t + :initarg :wait + :reader waitp + :writer (setf wait))) (:documentation "When a gemini link matches `re' try to open it with 'program-name'")) (defmethod print-object ((object open-link-helper) stream) @@ -304,13 +312,14 @@ (use-cache-p use-cache-p)) object (format stream "re: ~s program: ~s use cache? ~a" re program-name use-cache-p)))) -(defun make-open-link-helper (re program-name use-cache) +(defun make-open-link-helper (re program-name use-cache &key (wait t)) (assert (stringp program-name)) (assert (stringp re)) (make-instance 'open-link-helper :re re :program-name program-name - :use-cache use-cache)) + :use-cache use-cache + :wait wait)) (defrule use "use" (:text t)) @@ -318,7 +327,17 @@ (defrule cache "cache" (:text t)) -(defrule use-cache (and use blanks cache)) +(defrule no "no" + (:text t)) + +(defrule wait "wait" + (:text t)) + +(defrule use-cache (and use blanks cache) + (:constant t)) + +(defrule no-wait (and no blanks wait) + (:constant t)) (defrule open-link-helper (and open-link-helper-key @@ -330,11 +349,15 @@ regexp ; 6 program to use blanks (? (and use-cache ; 8 use cache? + blanks)) + (? (and no-wait ; 9 wait download? blanks))) (:function (lambda (args) (list :open-link-helper - (make-open-link-helper (elt args 2) (elt args 6) (elt args 8)))))) - + (make-open-link-helper (elt args 2) + (elt args 6) + (elt args 8) + :wait (not (elt args 9))))))) (defrule filepath quoted-string) (defparameter *already-included-files* ()) @@ -883,7 +906,8 @@ (cl-ppcre:scan (re a) link)) (config-all-link-open-program)))) (values (program-name found) - (use-cache-p found)))) + (use-cache-p found) + (waitp found)))) (defun use-tinmop-as-external-program-p (program) (cl-ppcre:scan "(^me$)|(^internal$)|(tinmop)" program))