From 379480e6af030dee3d225fa4f76735fa43db36de Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Tue, 22 Feb 2022 18:15:27 -0600 Subject: using readline. implmented editing of oneliners --- clpmfile.lock | 17 ++++++-------- oneliners.cli.asd | 3 ++- src/lib.lisp | 67 ++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/clpmfile.lock b/clpmfile.lock index e70d3e8..e852e8c 100644 --- a/clpmfile.lock +++ b/clpmfile.lock @@ -52,6 +52,8 @@ ("cl-cookie" :version "2019-10-07" :source "quicklisp" :systems ("cl-cookie")) ("cl-ppcre" :version "2022-02-20" :source "quicklisp" :systems ("cl-ppcre" "cl-ppcre-unicode")) +("cl-readline" :version "2021-10-21" :source "quicklisp" :systems + ("cl-readline")) ("cl-str" :version "2022-02-20" :source "quicklisp" :systems ("str")) ("cl-syntax" :version "2015-04-07" :source "quicklisp" :systems ("cl-syntax" "cl-syntax-annot")) @@ -66,7 +68,6 @@ ("flexi-streams" :version "2022-02-20" :source "quicklisp" :systems ("flexi-streams")) ("jonathan" :version "2020-09-25" :source "quicklisp" :systems ("jonathan")) -("linedit" :version "2018-04-30" :source "quicklisp" :systems ("linedit")) ("local-time" :version "2021-01-24" :source "quicklisp" :systems ("local-time")) ("magic-ed" :version "2020-03-25" :source "quicklisp" :systems ("magic-ed")) ("named-readtables" :version "2022-02-20" :source "quicklisp" :systems @@ -84,7 +85,6 @@ ("split-sequence")) ("static-vectors" :version "2021-06-30" :source "quicklisp" :systems ("static-vectors")) -("terminfo" :version "2021-01-24" :source "quicklisp" :systems ("terminfo")) ("trivial-clipboard" :version "2021-02-28" :source "quicklisp" :systems ("trivial-clipboard")) ("trivial-features" :version "2021-12-09" :source "quicklisp" :systems @@ -110,10 +110,10 @@ ((:system :name "quri") (:system :name "alexandria")) ((:system :name "proc-parse") (:system :name "alexandria")) ((:system :name "osicat") (:system :name "alexandria")) - ((:system :name "linedit") (:system :name "alexandria")) ((:system :name "fast-io") (:system :name "alexandria")) ((:system :name "fast-http") (:system :name "alexandria")) ((:system :name "dexador") (:system :name "alexandria")) + ((:system :name "cl-readline") (:system :name "alexandria")) ((:system :name "cl-cookie") (:system :name "alexandria")) ((:system :name "cl-annot") (:system :name "alexandria")) ((:system :name "cl+ssl") (:system :name "alexandria")) @@ -138,7 +138,7 @@ ((:system :name "osicat") (:system :name "cffi")) ((:system :name "osicat") (:system :name "cffi-grovel")) ((:system :name "net.didierverna.clon.termio") (:system :name "cffi")) - ((:system :name "linedit") (:system :name "cffi")) + ((:system :name "cl-readline") (:system :name "cffi")) ((:system :name "cl+ssl") (:system :name "cffi")) ((:system :name "cffi-toolchain") (:system :name "cffi")) ((:system :name "cffi-grovel") (:system :name "cffi")) @@ -186,6 +186,8 @@ ((:system :name "cl-change-case") (:system :name "cl-ppcre")) ((:system :name "cl-change-case") (:system :name "cl-ppcre-unicode"))) +("cl-readline" ((:system :name "oneliners.cli") (:system :name "cl-readline"))) + ("cl-str" ((:system :name "oneliners.cli") (:system :name "str"))) ("cl-syntax" ((:system :name "jonathan") (:system :name "cl-syntax")) @@ -214,8 +216,6 @@ ("jonathan" ((:system :name "oneliners.cli") (:system :name "jonathan"))) -("linedit" ((:system :name "oneliners.cli") (:system :name "linedit"))) - ("local-time" ((:system :name "cl-cookie") (:system :name "local-time"))) ("magic-ed" ((:system :name "oneliners.cli") (:system :name "magic-ed"))) @@ -231,8 +231,7 @@ ("oneliners.cli.asd" (t (:asd-file :name "oneliners.cli.asd"))) -("osicat" ((:system :name "oneliners.cli") (:system :name "osicat")) - ((:system :name "linedit") (:system :name "osicat"))) +("osicat" ((:system :name "oneliners.cli") (:system :name "osicat"))) ("proc-parse" ((:system :name "jonathan") (:system :name "proc-parse")) ((:system :name "fast-http") (:system :name "proc-parse")) @@ -248,8 +247,6 @@ ("static-vectors" ((:system :name "fast-io") (:system :name "static-vectors"))) -("terminfo" ((:system :name "linedit") (:system :name "terminfo"))) - ("trivial-clipboard" ((:system :name "oneliners.cli") (:system :name "trivial-clipboard"))) diff --git a/oneliners.cli.asd b/oneliners.cli.asd index c255c1d..d71980c 100644 --- a/oneliners.cli.asd +++ b/oneliners.cli.asd @@ -8,7 +8,8 @@ "dexador" "osicat" "net.didierverna.clon" - "linedit" + "cl-readline" + ;"linedit" "magic-ed" "oneliners.api-client") :components ((:module "src" diff --git a/src/lib.lisp b/src/lib.lisp index 173b9aa..147e294 100644 --- a/src/lib.lisp +++ b/src/lib.lisp @@ -3,7 +3,8 @@ (defpackage oneliners.cli (:use :cl) (:local-nicknames (#:api #:oneliners.api-client) - (#:a #:alexandria))) + (#:a #:alexandria) + (#:rl #:cl-readline))) (in-package :oneliners.cli) @@ -59,8 +60,9 @@ (namestring (merge-pathnames (format nil "~a" (gensym "oneliners")) (uiop:temporary-directory)))) -(defun string-from-editor () +(defun string-from-editor (&optional contents) (let ((filename (make-temp-file-name))) + (when contents (a:write-string-into-file contents filename :if-exists :supersede)) (unwind-protect (magic-ed:magic-ed filename :eval nil :output :string) (uiop:delete-file-if-exists filename)))) @@ -94,18 +96,27 @@ the directories that appear in the value of that variable." (defun prompt (prompt &key (expect (constantly t)) - retry-text) - - (loop - with prompt-text = prompt - with should-retry-p = t - while should-retry-p - for line = (linedit:linedit :prompt prompt-text) - when (funcall expect line) - do (setf should-retry-p nil) - when retry-text - do (setf prompt-text retry-text) - finally (return line))) + retry-text + (prefill "")) + ;; register a prefil hook + (rl:register-hook + :pre-input + (lambda () + (rl:insert-text prefill) + (rl:redisplay))) + (unwind-protect + (loop + with prompt-text = prompt + with should-retry-p = t + while should-retry-p + for line = (rl:readline :prompt prompt-text) + when (funcall expect line) + do (setf should-retry-p nil) + when retry-text + do (setf prompt-text retry-text) + finally (return line)) + ;; unregisters the hook. + (rl:register-hook :pre-input nil))) (defun cached-result (&optional n) (when (uiop:file-exists-p (last-search-file)) @@ -235,7 +246,8 @@ the directories that appear in the value of that variable." (string-upcase (prompt "Runstyle (auto or manual): " :expect 'valid-runstyle-p - :retry-text "Must be (auto or manual): "))) + :retry-text "Must be (auto or manual): " + :prefill "auto"))) (explanation (when (y-or-n-p "Provide an explanation?") (string-from-editor)))) @@ -258,25 +270,31 @@ the directories that appear in the value of that variable." (let* ((oneliner (prompt "Oneliner: " :expect 'valid-oneliner-string-p - :retry-text "Oneliners must contain at least one command: ")) - (init-tags - (tags-from-oneliner oneliner)) + :retry-text "Oneliners must contain at least one command: " + :prefill (getf ol :oneliner))) (brief (prompt "Brief Description: " :expect 'valid-brief-description-p - :retry-text "Too long. Must be <= 72 characters: ")) + :retry-text "Too long. Must be <= 72 characters: " + :prefill (getf ol :brief))) + (init-tags + (tags-from-oneliner oneliner)) (tags (append init-tags (ppcre:split " +" - (prompt (format nil "Tags in addition to ~{~a ~} ?" init-tags))))) + (prompt (format nil "Tags in addition to ~{~a ~}? " init-tags) + :prefill (str:join " " (set-difference (getf ol :tags) + init-tags + :test 'equal)))))) (runstyle (string-upcase (prompt "Runstyle (auto or manual): " :expect 'valid-runstyle-p - :retry-text "Must be (auto or manual): "))) + :retry-text "Must be (auto or manual): " + :prefill (getf ol :runstyle)))) (explanation (when (y-or-n-p "Provide an explanation?") - (string-from-editor)))) + (string-from-editor (getf ol :explanation))))) (api:request-with (:host (host) :body (jonathan:to-json @@ -287,10 +305,7 @@ the directories that appear in the value of that variable." :runstyle runstyle)) :content-type "application/json") (api:patch--oneliner-entry-edit (getf ol :id) :token (api-token)) - (format t "OK~%"))) - - - )) + (format t "OK~%"))))) (defun request-invite-code () (ensure-config) -- cgit v1.2.3