Use /usr/bin/less for text file - clic - Clic is an command line interactive client for gopher written in Common LISP HTML git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/ DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit a14e99ad9030bfb5141e762542098fe8ea902363 DIR parent efe07395e09bc6d6495dd651671c5d48e4a502ee HTML Author: Solene Rapenne <solene@perso.pw> Date: Thu, 28 Dec 2017 16:48:32 +0100 Use /usr/bin/less for text file Diffstat: M clic.lisp | 107 +++++++++++++++++++------------ 1 file changed, 66 insertions(+), 41 deletions(-) --- DIR diff --git a/clic.lisp b/clic.lisp @@ -47,6 +47,8 @@ ;;; array of lines in buffer (defparameter *buffer* nil) +;;; array of lines of last menu +(defparameter *previous-buffer* nil) ;;; a list containing the last viewed pages (defparameter *history* '()) @@ -245,6 +247,9 @@ (format stream "~a~%" uri) (force-output stream) + ;; save current buffer to display it back if needed + (setf *previous-buffer* *buffer*) + ;; for each line we receive we display it (loop for line = (read-line stream nil nil) while line @@ -255,10 +260,8 @@ "browse to the N-th link" (let ((destination (gethash key *links*))) (when destination - (print destination) (cond - - ;; visit a gopher link + ;; visit a gopher link (type 0 or 1) ((location-p destination) (visit destination)) @@ -420,45 +423,67 @@ (defun display-buffer(type) "display the buffer" - ;; stdout is a terminal or not ? + ;;;; stdout is a terminal or not ? (if (ttyp) - ;; yes it is - (let ((rows (- (c-termsize) 1))) ; -1 for command bar - - ;; we store the user input outside of the loop - ;; so if the user doesn't want to scroll - ;; we break the loop and then execute the command - (let ((input nil)) - (loop for line across *buffer* - counting line into row - do - ;; display lines - (cond - ((string= "1" type) - (formatted-output line)) - ((string= "0" type) - (format t "~a~%" line))) - - ;; split and ask to scroll or to type a command - (when (= row rows) - (setf row 0) - (format t "~a press enter or a shell command ~a : " - (get-color 'bg-black) - (get-color 'reset)) - (force-output) - (let ((first-input (read-char))) - (when (not (char= #\NewLine first-input)) - (unread-char first-input) - (let ((input-text (format nil "~a" (read-line nil nil)))) - (setf input input-text) - (loop-finish)))))) - - ;; in case of shell command, do it - (if input - (user-input input) - (when (< (length *buffer*) rows) - (dotimes (i (- rows (length *buffer*))) - (format t "~%")))))) + ;;;; we are in interactive mode + (cond + ;;;; output is a text file ? + ;;;; call the $PAGER ! + ((string= "0" type) + (pop *history*) ;; it's not a menu, we need to remove it from history + ;;; generate a string from *buffer* array + (let ((text (string-right-trim ; remove last newline + (string #\Newline) + (format nil "~{~a~%~}" ; concatenate lines + (loop for line across *buffer* + collect line))))) + ;; create input stream used as stdin for $PAGER + (let ((input (make-string-input-stream text))) + (uiop:run-program (list #+ecl + (si:getenv "PAGER") + #+sbcl + (sb-unix::posix-getenv "PAGER")) + :input input + :output :interactive)) + ;; display last menu + (setf *buffer* *previous-buffer*) + (display-buffer "1"))) + + ;;;; output is a menu ? + ;;;; display the menu and split it in pages if needed + ((string= "1" type) + + ;; we store the user input outside of the loop + ;; so if the user doesn't want to scroll + ;; we break the loop and then execute the command + (let ((input nil)) + (let ((rows (- (c-termsize) 1))) ; -1 for command bar + + (loop for line across *buffer* + counting line into row + do + (formatted-output line) + + ;; split and ask to scroll or to type a command + (when (= row rows) + (setf row 0) + (format t "~a press enter or a shell command ~a : " + (get-color 'bg-black) + (get-color 'reset)) + (force-output) + (let ((first-input (read-char))) + (when (not (char= #\NewLine first-input)) + (unread-char first-input) + (let ((input-text (format nil "~a" (read-line nil nil)))) + (setf input input-text) + (loop-finish)))))) + + ;; in case of shell command, do it + (if input + (user-input input) + (when (< (length *buffer*) rows) + (dotimes (i (- rows (length *buffer*))) + (format t "~%")))))))) ;; not interactive ;; display and quit