aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Okay <colin@cicadas.surf>2022-08-05 08:58:35 -0500
committerColin Okay <colin@cicadas.surf>2022-08-05 08:58:35 -0500
commitf116178dcf8b450c76400e2a0fbd2991f2c227b4 (patch)
tree67fcc6a6e7035eb0b1929e495bceca2dc4fa564b
parent5c590a614544c977964692e41b0e5c19043b142c (diff)
[wip] [refactor] [add] subcommands.
-rw-r--r--app/app.lisp23
-rw-r--r--app/clip.lisp17
-rw-r--r--app/draft.lisp95
-rw-r--r--app/run.lisp22
-rw-r--r--app/search.lisp14
-rw-r--r--app/show.lisp16
-rw-r--r--app/util.lisp11
-rw-r--r--lib/client.lisp92
8 files changed, 226 insertions, 64 deletions
diff --git a/app/app.lisp b/app/app.lisp
index a4ff596..5af7006 100644
--- a/app/app.lisp
+++ b/app/app.lisp
@@ -28,7 +28,28 @@
(defun toplevel/subcommands ()
"Returns a list of the subcommands for the top level command"
(list
- (search/command)))
+ (search/command)
+ (run/command)
+ (clip/command)
+ (show/command)
+ (draft/command)
+ ))
+
+
+;; ol delete <ID>
+
+;; ol account login <USER> <PW>
+;; ol account logout
+;; ol account signature <new sig>
+;; ol account password <new pw> <repeat>
+;; ol account whois <user>
+;; ol invite new
+;; ol invite redeem
+
+;; ol account use <SERVER> ;; for switchign servers
+
+;; new edit delete publish trash drafts flag unflag lockated unlock
+;; redeem login logout password signature whois
(defun toplevel/handler (cmd)
"Prints usage statement and then exits"
diff --git a/app/clip.lisp b/app/clip.lisp
new file mode 100644
index 0000000..922cacc
--- /dev/null
+++ b/app/clip.lisp
@@ -0,0 +1,17 @@
+;;;; clip.lisp
+
+(in-package :oneliners.cli.app)
+
+(defun clip/handler (cmd)
+ (a:if-let (args (cli:command-arguments cmd))
+ (ol::run-item
+ (parse-identifier (first args)) (rest args)
+ :force-clip t)
+ (cli:print-usage-and-exit cmd t)))
+
+(defun clip/command ()
+ (cli:make-command
+ :name "clip"
+ :usage "<IDENTIFIER> [ARG ...]"
+ :description "attempt to copy the oneliner to the clipboard"
+ :handler #'clip/handler))
diff --git a/app/draft.lisp b/app/draft.lisp
new file mode 100644
index 0000000..ea71e49
--- /dev/null
+++ b/app/draft.lisp
@@ -0,0 +1,95 @@
+;;;; draft.lisp
+
+(in-package :oneliners.cli.app)
+
+(defun draft/new/handler (cmd)
+ (ol:add-new-oneliner))
+
+(defun draft/new/command ()
+ (cli:make-command
+ :name "new"
+ :description "interactively draft a new oneliner"
+ :handler #'draft/new/handler))
+
+
+(defun draft/publish/handler (cmd)
+ (a:if-let (name (first (cli:command-arguments cmd)))
+ (ol::publish-draft name)
+ (cli:print-usage-and-exit cmd t)))
+
+(defun draft/publish/command ()
+ (cli:make-command
+ :name "publish"
+ :usage "<DRAFT>"
+ :description "publish draft to the server"
+ :handler #'draft/publish/handler))
+
+(defun draft/test/handler (cmd)
+ (a:if-let (args (cli:command-arguments cmd))
+ (ol:run-item (first args) (rest args)
+ :verbose (cli:getopt cmd :verbose)
+ :confirm (cli:getopt cmd :confirm)
+ :timeout (cli:getopt cmd :timeout)
+ :draftp t)
+ (cli:print-usage-and-exit cmd t)))
+
+(defun draft/test/command ()
+ (cli:make-command
+ :name "test"
+ :usage "<DRAFT> [ARG ...]"
+ :description "runs a draft oneliner, same options as `ol run`"
+ :options (run/options)
+ :handler #'draft/new/handler))
+
+(defun draft/edit/handler (cmd)
+ (a:if-let (name (first (cli:command-arguments cmd)))
+ (ol:edit-item name t)
+ (cli:print-usage-and-exit cmd t)))
+
+(defun draft/edit/command ()
+ (cli:make-command
+ :name "edit"
+ :usage "<DRAFT>"
+ :description "interactively edits a draft"
+ :handler #'draft/edit/handler))
+
+(defun draft/trash/handler (cmd)
+ (a:if-let (name (first (cli:command-arguments cmd)))
+ (ol::drop-draft name)
+ (cli:print-usage-and-exit cmd t)))
+
+(defun draft/trash/command ()
+ (cli:make-command
+ :name "trash"
+ :usage "<DRAFT>"
+ :description "trash a draft"
+ :handler #'draft/trash/handler))
+
+(defun draft/list/handler (cmd)
+ (declare (ignore cmd))
+ (ol::print-drafts))
+
+(defun draft/list/command ()
+ (cli:make-command
+ :name "list"
+ :description "list drafted oneliners"
+ :handler #'draft/list/handler))
+
+(defun draft/subcommands ()
+ (list
+ (draft/new/command)
+ (draft/publish/command)
+ (draft/test/command)
+ (draft/edit/command)
+ (draft/trash/command)
+ (draft/list/command)))
+
+(defun draft/handler (cmd)
+ (cli:print-usage-and-exit cmd t))
+
+(defun draft/command ()
+ (cli:make-command
+ :name "draft"
+ :description "draft, test, and publish new oneliners"
+ :handler #'draft/command
+ :sub-commands (draft/subcommands)))
diff --git a/app/run.lisp b/app/run.lisp
index 2591927..987ecad 100644
--- a/app/run.lisp
+++ b/app/run.lisp
@@ -24,13 +24,27 @@
:key :confirm
:description "prompts the user for confirmation before running the command")))
-(defun run/handler (cmd))
+(defun run/handler (cmd)
+ (a:if-let (args (cli:command-arguments cmd))
+ (ol::run-item
+ (first args) (rest args)
+ :verbose (cli:getopt cmd :verbose)
+ :confirm (cli:getopt cmd :confirm)
+ :timeout (cli:getopt cmd :timeout))
+ (cli:print-usage-and-exit cmd t)))
(defparameter +run/examples+
- '(()))
-
+ '(("Run a hypothetical command called echo-stuff with positional arguments" .
+ "ol run echo-stuff one two three")
+ ("Run a hypothetical command with id 341 with a timeout and confirmation" .
+ "ol run -c -t 10 341")))
(defun run/command ()
(cli:make-command
:name "run"
- :description ""))
+ :usage "<IDENTIFIER> [ARG ...]"
+ :description "run the identified oneliner with any arguments it might take"
+ :options (run/options)
+ :handler #'run/handler
+ :examples +run/examples+))
+
diff --git a/app/search.lisp b/app/search.lisp
index 015a749..afc8f84 100644
--- a/app/search.lisp
+++ b/app/search.lisp
@@ -29,7 +29,19 @@
:short-name #\n
:long-name "newest"
:description "the newest matching oneliners are returned"
- :key :newest)))
+ :key :newest)
+
+ ;; TODO
+ ;; (cli:make-option
+ ;; :flag
+ ;; :short-name #\c
+ ;; :long-name "cache"
+ ;; :description "restrict search to what is already in the local cache"
+ ;; :env-vars '("OL_CACHE_ONLY")
+ ;; :key :cache)
+
+
+ ))
(defun search/handler (cmd)
"Handler function for the search command. "
diff --git a/app/show.lisp b/app/show.lisp
new file mode 100644
index 0000000..1ed3493
--- /dev/null
+++ b/app/show.lisp
@@ -0,0 +1,16 @@
+;;;; show.lisp
+
+(in-package :oneliners.cli.app)
+
+(defun show/handler (cmd)
+ (a:if-let (ident
+ (parse-identifier (first (cli:command-arguments cmd))))
+ (ol:print-item-explanation ident)
+ (cli:print-usage-and-exit cmd t)))
+
+(defun show/command ()
+ (cli:make-command
+ :name "show"
+ :usage "<IDENTIFIER>"
+ :description "show detailed information about a oneliner"
+ :handelr #'show/handler ))
diff --git a/app/util.lisp b/app/util.lisp
new file mode 100644
index 0000000..d9d5ea2
--- /dev/null
+++ b/app/util.lisp
@@ -0,0 +1,11 @@
+;;;; utils.lisp
+
+(in-package :oneliners.cli.app)
+
+(defun parse-identifier (str)
+ "If STR holds digits representing an integer, parse them. otherwise
+ return the string. Oneliner identifiers may be names or ID
+ numbers. Returns NIL in the case that STR is NIL"
+ (when str
+ (or (parse-integer str :junk-allowed t)
+ str)))
diff --git a/lib/client.lisp b/lib/client.lisp
index b39e0ac..e3f304e 100644
--- a/lib/client.lisp
+++ b/lib/client.lisp
@@ -125,7 +125,7 @@ running the body. If such a oneliner can be found."
(format t "Attempting to run:~%")
(princ oneliner)
(princ #\newline))
- ;; substitute positional args
+
(when (or (not confirm)
(y-or-n-p "Proceed?"))
(handle-run-oneliner oneliner (or force-clip (equalp runstyle "manual")))))))
@@ -141,11 +141,7 @@ running the body. If such a oneliner can be found."
(defun add-new-oneliner ()
(api-token) ;; fails with error if not set.
;; read each field required to make a onelienr in from a prompt.
- (let* ((oneliner-string
- (prompt "Oneliner: "
- :expect 'valid-oneliner-string-p
- :retry-text "Oneliners must contain at least one command: "))
- (name
+ (let* ((name
(string-trim
'(#\space #\newline #\tab #\linefeed)
(prompt "Name (leave blank for none): "
@@ -153,13 +149,16 @@ running the body. If such a oneliner can be found."
:retry-text "Must begin with a letter contain only letters, numbers, - and _.")))
(draft-name
- (unless (y-or-n-p "Upload immediately instead of keeping a draft?")
- (if (plusp (length name))
- name
- (prompt "No name was provided, name this draft: "
- :expect 'valid-oneliner-name-p
- :retry-text "Must begin with a letter contain only letters, numbers, - and _."))))
+ (if (plusp (length name))
+ name
+ (prompt "No name was provided, name this draft: "
+ :expect 'valid-oneliner-name-p
+ :retry-text "Must begin with a letter contain only letters, numbers, - and _.")))
+ (oneliner-string
+ (prompt "Oneliner: "
+ :expect 'valid-oneliner-string-p
+ :retry-text "Oneliners must contain at least one command: "))
(init-tags
(parse-oneliner-tags oneliner-string))
@@ -191,32 +190,16 @@ running the body. If such a oneliner can be found."
:brief brief
:explanation explanation
:runstyle runstyle)))
- (if draft-name
- ;; if this is a draft, save it to disk.
- (progn
- (put-draft draft-name local)
- (format t "Saved draft ~a~%Do `ol --draft run ~a` to test~%"
- draft-name
- draft-name))
- ;; otherwise, format the oneliner as json and make a request
- ;; to create a new oneliner in the wiki
- (api:request-with
- (:body (oneliner-to-json-body local)
- :content-type "application/json")
- (api:post--oneliner :token (api-token)) ;TODO: update api to return the instance created.
- (format t "Added Oneliner~%"))))))
+ (progn
+ (put-draft draft-name local)
+ (format t "Saved draft ~a~%" draft-name)))))
;;; EDITING ONELINERS
(defun edit-item (ident &optional draftp)
- (api-token) ;; fails with error if not set.
+ ;;(unless draftp (api-token)) ;; fails with error if not set.
(let ((ol (if draftp (fetch-draft ident) (the-oneliner ident))))
- (let* ((oneliner-string
- (prompt "Oneliner: "
- :expect 'valid-oneliner-string-p
- :retry-text "Oneliners must contain at least one command: "
- :prefill (oneliner-oneliner ol)))
- (name
+ (let* ((name
(string-trim
'(#\space #\newline #\tab #\linefeed)
(prompt "Name (leave blank for none): "
@@ -225,12 +208,16 @@ running the body. If such a oneliner can be found."
:prefill (or (oneliner-name ol) ""))))
(draft-name
- (unless (y-or-n-p "Upload edits immediately instead of keeping a draft?")
- (if (plusp (length name))
- name
- (prompt "No name was provided, name this draft: "
- :expect 'valid-oneliner-name-p
- :retry-text "Must begin with a letter contain only letters, numbers, - and _."))))
+ (if (plusp (length name))
+ name
+ (prompt "No name was provided, name this draft: "
+ :expect 'valid-oneliner-name-p
+ :retry-text "Must begin with a letter contain only letters, numbers, - and _.")))
+ (oneliner-string
+ (prompt "Oneliner: "
+ :expect 'valid-oneliner-string-p
+ :retry-text "Oneliners must contain at least one command: "
+ :prefill (oneliner-oneliner ol)))
(brief
(prompt "Brief Description: "
:expect 'valid-brief-description-p
@@ -271,31 +258,20 @@ running the body. If such a oneliner can be found."
:brief brief
:explanation explanation
:runstyle runstyle)))
- (if draft-name
- (progn
- (put-draft draft-name local)
- (format t "Saved draft ~a~%Do `ol --draft run ~a` to test~%"
- draft-name
- draft-name))
- (api:request-with
- (:body (oneliner-to-json-body local)
- :content-type "application/json")
- (let ((updated
- (jonathan:parse
- (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token)))))
- (merge-oneliners (list updated)))
-
- (format t "Edits accepted~%")))))))
+ (progn
+ (put-draft draft-name local)
+ (format t "Saved draft ~a~%" draft-name))))))
-;;TODO: need to sync cache here.
(defun publish-draft (name)
(when-draft (ol name)
(api:request-with
(:body (oneliner-to-json-body ol)
:content-type "application/json")
- (if (oneliner-id ol)
- (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token))
- (api:post--oneliner :token (api-token)))
+ (let ((updated
+ (if (oneliner-id ol)
+ (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token))
+ (api:post--oneliner :token (api-token)))))
+ (merge-oneliners (list updated)))
;; if that worked, no http error occured, so this next part will run
(drop-draft name)
(format t "Draft ~a published and removed from drafts.~%" name))))