From f39523d713c538f81d6f0cdc056fa750ae8a257e Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 09:58:09 -0500 Subject: rewrote clon synopsis form --- app/app.lisp | 147 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 76 insertions(+), 71 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 32f3ad2..ff8322c 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -84,91 +84,95 @@ export EDITOR=/usr/bin/zile ;;; CLON SYNOPSIS DEFINITION -(defsynopsis (:postfix "[ARGUMENTS ...]") - (group (:header "SEARCH OPTIONS") - (text :contents "By default, ARGUMENTS are interpeted as search terms for oneliners. For example:") - (text :contents "$ ol grep awk # search for oneliners involving both grep and awk") +(defsynopsis (:postfix "COMMAND [ARGS...]") + (group (:header "SEARCHING FOR ONELINERS" :hidden t) (text :contents " ") - - (lispobj :long-name "limit" + (text :contents "Usage: ol [OPTIONS] search [TERMS...]") + (text :contents "Search for oneliners that have been tagged with all of TERMS") + (text :contents "E.g. `ol search grep awk`") + (text :contents " ") + (text :contents "Options include:") + (lispobj :long-name "limit" :argument-type :optional :argument-name "NUMBER" :default-value 10 :description "The maximum number of results to return." :typespec 'integer) (flag :long-name "all-flagged" - :description "Request that only flagged oneliners are returned. Without any ARGUMENTS, simply returns all flagged oneliners.") + :description "Request that only flagged oneliners are returned. Without any TERMS, simply returns all flagged oneliners.") (flag :long-name "not-flagged" - :description "Request that no flagged oneliners are returned with the search results. Does nothing without ARGUMENTS") + :description "Request that no flagged oneliners are returned with the search results. Does nothing without TERMS") (flag :long-name "newest" - :description "Return newest oneliners that match. Without any ARGUMENTS, simply returns the newest oneliners.")) - (text :contents " ") - (group (:header "EXECUTION OPTIONS") - (text :contents "Several options override the default interpretation of ARGUMENTS.") - (text :contents "Execution options interpret the first argument as the identifier of a oneliner: ") - (text :contents "$ ol [MORE ARGUMENTS...]") + :description "Return newest oneliners that match. Without any TERMS, simply returns the newest oneliners.")) + (group (:header "RUNNING ONELINERS" :hidden t) (text :contents " ") - (flag :long-name "run" - :description "Executes a oneliner by NAME or ID. See also help topic 'variables'.") - (flag :long-name "clip" - :description "Like --run, but puts the oneliner into the clipboard.")) - (text :contents " ") - (group (:header "OTHER OPTIONS") - (flag :long-name "show" - :description "View all information for the oneliner given by NAME or ID") + (text :contents "Usage: ol [OPTIONS] run [ARGS...]") + (text :contents "Run the oneliner identified by IDENTIFIER, if it exists, with optionally supplied ARGS") + (text :contents "IDENTIFIER should either be the name or the unique numeric ID of a oneliner.") + (text :contents "E.g. `ol run demo foo bar` # run \"demo\" with args \"foo\" and \"bar\"") + (text :contents " ") + (text :contents "Options include:") (lispobj :long-name "timeout" + :short-name "t" :argument-type :optional :argument-name "SECONDS" - :default-value 2 + :default-value 1 :typespec 'integer - :description "How long to wait for standard output before giving up.")) - (text :contents " ") - (group (:header "HELP OPTIONS") - (flag :long-name "whois" - :description "View information about a contributor. The first argument is a contributor handle.") - (flag :long-name "help" - :description "Print help for a topic. Topics: wiki, account, invites, variables, editor") - (flag :long-name "version" - :description "Print the client's version")) - (group (:header "Advanced Options" :hidden t) - (flag :long-name "clear-cache" - :description "Clears all cached search results from your system.")) - (group (:header "Editor" :hidden t) - (text :contents +configure-your-edtior+)) - (group (:header "Variables" :hidden t) - (text :contents +oneliners-variables-help-text+)) - (group (:header "Wiki" :hidden t) - (text :contents "Options For Managing Oneliners") - (flag :long-name "add" - :description "Intaractively add a oneliner and update the wiki.") - (flag :long-name "edit" - :description "Interactively edit a oneliner and update the wiki.") - (flag :long-name "flag" - :description "Flag a oneliner for review.") - (flag :long-name "unflag" - :description "If you have admin priviliges, unflag a oneliner.") - (flag :long-name "lock" - :description "If you have admin priviliges, lock a oneliner from being edited.") - (flag :long-name "unlock" - :description "If you have admin priviliges, unlock a oneliner.")) - (group (:header "Account" :hidden t) - (text :contents "Options for Managing Your Contributor Account") - (flag :long-name "login" - :description "Attempt to login to your contributor account. ARGS are interpreted as USERNAME PASSWORD.") - (flag :long-name "logout" - :description "Revoke your own access token.") - (flag :long-name "change-password" - :description "Change your password. ARGS are interpreted as CURRENTPW NEWPW NEWPWAGAIN") - (flag :long-name "change-signature" - :description "Change your contributor signature. You will be prompted.")) - (group (:header "Invites" :hidden t) + :description "How many seconds to wait for standard output before giving up.")) + (group (:header "CLIPPING ONELINERS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol clip [ARGS...]") + (text :contents "Instead of running a oneliner, copy it to your system's clipboard") + (text :contents "ol clip demo-1 foo extra=bar")) + (group (:header "SHOWING INFORMATION ABOUT ONELINERS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol show ") + (text :contents "Print information about a oneliner to the screen.")) + (group (:header "NEW ONELINERS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol new") + (text :contents "Interactively create a new oneliner and upload it to the server.")) + (group (:header "EDITING ONELINERS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol edit ") + (text :contents "Interactively alter a oneliner and uplaod it to the server.")) + (group (:header "FLAGGING AND UNFLAGGING ONELINERS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol ") + (text :contents + "Flag or unflag a oneliner. A flagged oneliner is marked as potentially hazardous and will prompt users before exectuion.") + (text :contents + "Flagged oneliners may also be specifically factor into search using the --all-flagged or --not-flagged search options.")) + (group (:header "LOCKING AND UNLOCKING ONELINERS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol ") + (text :contents "(ADMINS ONLY) Lock or unlock a oneliner. A locked oneliner may not be altered or edited.")) + (group (:header "REDEEMING INVITE TOKENS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol redeem ") + (text :contents "Redeem an invite token, INVITE, and reate a new contributor account on the wiki server with user handle and password.")) + (group (:header "INVITE TOKENS" :hidden t) + (text :contents " ") + (text :contents "Usage: ol invite") + (text :contents "Generate a new invite token if you are allowed to do so.")) + (group (:header "LOGIN AND LOGOUT" :hidden t) + (text :contents " ") + (text :contents "Usage: ol [HANDLE PASWORD]") + (text :contents "Login or logout. If logging in, provide a handle and password.") + (text :contents "Once logged in to your configured server, an API access token will be written to your config file, allowing you to make contributions to the wiki.")) + (group (:header "PASSWORD CHANGES" :hidden t) + (text :contents " ") + (text :contents "Usage: ol password ") + (text :contents "Change your password on the configured server.")) + (group (:header "SIGNATURE CHANGES" :hidden t) + (text :contents " ") + (text :contents "Usage: ol signature") + (text :contents "Interactively update your contributor signature.")) + (group (:header "HELP MENU") (text :contents " ") - (text :contents "Options For Making Invites and Redeeming Tokens") - (flag :long-name "invite" - :description "Request an invite token to send to a friend.") - (flag :long-name "redeem" - :description "Redeem an invite token.") - (text :contents +invite-help-text+))) + (text :contents "Usage: ol help [TOPIC]") + (text :contents "Print a help menu. With no arguments, prints this help.") + (text :contents "Help topics include: search, run, clip, show, new, edit, flag, lock, redeem, invite, login, password, signature"))) ;;; HELPERS @@ -179,7 +183,8 @@ you to go to sleep with it at night is written for the author more than the users." (loop for item in (net.didierverna.clon::items *synopsis*) when (and (typep item 'net.didierverna.clon::group) - (string-equal header (net.didierverna.clon::header item))) + (string-equal header (net.didierverna.clon::header item) + :end2 (length header))) return item)) (defun prepare-oneliner-arguments (arguments) -- cgit v1.2.3 From ebc79c386d4db262ae76bb2ba0386460a35648f9 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 10:17:18 -0500 Subject: tweaks to synopsis definition --- app/app.lisp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index ff8322c..0e8b103 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -101,78 +101,81 @@ export EDITOR=/usr/bin/zile (flag :long-name "all-flagged" :description "Request that only flagged oneliners are returned. Without any TERMS, simply returns all flagged oneliners.") (flag :long-name "not-flagged" - :description "Request that no flagged oneliners are returned with the search results. Does nothing without TERMS") + :description "Request that no flagged oneliners are returned with the search results. Does nothing without TERMS.") (flag :long-name "newest" :description "Return newest oneliners that match. Without any TERMS, simply returns the newest oneliners.")) (group (:header "RUNNING ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol [OPTIONS] run [ARGS...]") - (text :contents "Run the oneliner identified by IDENTIFIER, if it exists, with optionally supplied ARGS") + (text :contents " ") + (text :contents "Run the oneliner identified by IDENTIFIER, if it exists, with any required ARGS.") (text :contents "IDENTIFIER should either be the name or the unique numeric ID of a oneliner.") (text :contents "E.g. `ol run demo foo bar` # run \"demo\" with args \"foo\" and \"bar\"") (text :contents " ") (text :contents "Options include:") (lispobj :long-name "timeout" - :short-name "t" :argument-type :optional :argument-name "SECONDS" :default-value 1 :typespec 'integer :description "How many seconds to wait for standard output before giving up.")) (group (:header "CLIPPING ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol clip [ARGS...]") + (text :contents " ") (text :contents "Instead of running a oneliner, copy it to your system's clipboard") (text :contents "ol clip demo-1 foo extra=bar")) (group (:header "SHOWING INFORMATION ABOUT ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol show ") + (text :contents " ") (text :contents "Print information about a oneliner to the screen.")) (group (:header "NEW ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol new") + (text :contents " ") (text :contents "Interactively create a new oneliner and upload it to the server.")) (group (:header "EDITING ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol edit ") + (text :contents " ") (text :contents "Interactively alter a oneliner and uplaod it to the server.")) (group (:header "FLAGGING AND UNFLAGGING ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol ") + (text :contents " ") (text :contents "Flag or unflag a oneliner. A flagged oneliner is marked as potentially hazardous and will prompt users before exectuion.") (text :contents "Flagged oneliners may also be specifically factor into search using the --all-flagged or --not-flagged search options.")) (group (:header "LOCKING AND UNLOCKING ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol ") + (text :contents " ") (text :contents "(ADMINS ONLY) Lock or unlock a oneliner. A locked oneliner may not be altered or edited.")) (group (:header "REDEEMING INVITE TOKENS" :hidden t) - (text :contents " ") (text :contents "Usage: ol redeem ") + (text :contents " ") (text :contents "Redeem an invite token, INVITE, and reate a new contributor account on the wiki server with user handle and password.")) (group (:header "INVITE TOKENS" :hidden t) - (text :contents " ") (text :contents "Usage: ol invite") + (text :contents " ") (text :contents "Generate a new invite token if you are allowed to do so.")) (group (:header "LOGIN AND LOGOUT" :hidden t) - (text :contents " ") (text :contents "Usage: ol [HANDLE PASWORD]") + (text :contents " ") (text :contents "Login or logout. If logging in, provide a handle and password.") (text :contents "Once logged in to your configured server, an API access token will be written to your config file, allowing you to make contributions to the wiki.")) (group (:header "PASSWORD CHANGES" :hidden t) - (text :contents " ") (text :contents "Usage: ol password ") + (text :contents " ") (text :contents "Change your password on the configured server.")) (group (:header "SIGNATURE CHANGES" :hidden t) - (text :contents " ") (text :contents "Usage: ol signature") + (text :contents " ") (text :contents "Interactively update your contributor signature.")) + (group (:header "WHOIS CONTRIBUTOR" :hidden t) + (text :contents "Usage: ol whois ") + (text :contents " ") + (text :contents "Print information about a contributor.")) (group (:header "HELP MENU") + (text :contents "Usage: ol help [COMMAND TOPIC]") (text :contents " ") - (text :contents "Usage: ol help [TOPIC]") (text :contents "Print a help menu. With no arguments, prints this help.") - (text :contents "Help topics include: search, run, clip, show, new, edit, flag, lock, redeem, invite, login, password, signature"))) + (text :contents "Command topics include: search, run, clip, show, new, edit, flag, lock, redeem, invite, login, password, signature"))) ;;; HELPERS -- cgit v1.2.3 From 82a0911f93760a0059addc056340733f8797ae91 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 10:46:41 -0500 Subject: new main in app.lisp; exports to oneliners.cli package --- app/app.lisp | 238 ++++++++++++++++++++++++++++++++++++------------------- lib/package.lisp | 17 +++- 2 files changed, 172 insertions(+), 83 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 0e8b103..3cfb5cf 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -86,9 +86,9 @@ export EDITOR=/usr/bin/zile (defsynopsis (:postfix "COMMAND [ARGS...]") (group (:header "SEARCHING FOR ONELINERS" :hidden t) - (text :contents " ") (text :contents "Usage: ol [OPTIONS] search [TERMS...]") - (text :contents "Search for oneliners that have been tagged with all of TERMS") + (text :contents " ") + (text :contents "Search for oneliners that have been tagged with all of TERMS.") (text :contents "E.g. `ol search grep awk`") (text :contents " ") (text :contents "Options include:") @@ -201,86 +201,160 @@ than the users." ;;; MAIN ENTRY POINT (defun main () - "Entry point for our standalone application." (make-context) - (cli:with-local-state - (let ((arguments (remainder))) - (cond - ((getopt :long-name "version") - (format t "Oneliner CLI Version: ~a~%" +ol-version+)) - ((getopt :long-name "help") - (if (and arguments (find-group-with-header (first arguments))) - (help :item (find-group-with-header (first arguments))) - (help))) - ((getopt :long-name "whois") - (assert (first arguments) () "--whois requires an argument, a user handle.") - (cli::show-contributor (first arguments))) + (a:if-let (arguments (remainder)) + (destructuring-bind (command . args) arguments + (let ((id-or-name + (when args + (or (parse-integer (first args) :junk-allowed t) + (first args))))) + (cli:with-local-state + (ecase (a:make-keyword (string-upcase command)) + (:help + (princ #\newline) + (help-topic (first args))) + (:search + (cli:search-for-oneliners + args + (getopt :long-name "limit") + (getopt :long-name "not-flagged") + (getopt :long-name "all-flagged") + (getopt :long-name "newest"))) + (:run + (cli:run-item id-or-name (rest args) + :timeout (getopt :long-name "timeout"))) + (:clip + (cli:run-item id-or-name (rest args) + :force-clip t)) + (:show + (cli:print-item-explanation id-or-name)) + (:new + (cli:add-new-oneliner)) + (:edit + (cli:edit-item id-or-name)) + (:flag + (cli:flag-item id-or-name)) + (:unflag + (cli:unflag-item id-or-name)) + (:lock + (cli:lock-item id-or-name)) + (:unlock + (cli:unlock-item id-or-name)) + (:redeem + (unless (= 3 (length args)) + (help-topic "redeem") + (uiop:quit)) + (apply 'cli:redeem-invite args)) + (:invite + (cli:request-invite-code)) + (:login + (unless (= 3 (length args)) + (help-topic "login") + (uiop:quit)) + (apply 'cli:login args)) + (:logout + (cli:revoke-access)) + (:password + (unless (= 3 (length args)) + (help-topic "password") + (uiop:quit)) + (apply 'cli:change-pw args)) + (:signature + (cli:change-signature)) + (:whois + (unless args + (help-topic "whois") + (uiop:quit)) + (cli:show-contributor (first args))))))) + (help)) + (uiop:quit)) + +(defun help-topic (topic) + (a:if-let (group (find-group-with-header topic)) + (help :item group) + (help))) + +;; (defun main () +;; "Entry point for our standalone application." +;; (make-context) +;; (cli:with-local-state +;; (let ((arguments (remainder))) +;; (cond +;; ((getopt :long-name "version") +;; (format t "Oneliner CLI Version: ~a~%" +ol-version+)) +;; ((getopt :long-name "help") +;; (if (and arguments (find-group-with-header (first arguments))) +;; (help :item (find-group-with-header (first arguments))) +;; (help))) +;; ((getopt :long-name "whois") +;; (assert (first arguments) () "--whois requires an argument, a user handle.") +;; (cli::show-contributor (first arguments))) - ((getopt :long-name "redeem") - (assert (= 3 (length arguments)) () "--redeem requires exatly three arguments.") - (destructuring-bind (token name pass) arguments - (cli::redeem-invite token name pass))) - - ((getopt :long-name "login") - (assert (= 2 (length arguments)) () "--login requires exactly two arguments.") - (destructuring-bind (user pass) arguments - (cli::login user pass))) - - ((getopt :long-name "change-password") - (assert (= 3 (length arguments)) () "--change-password requires exactly three arguments." ) - (destructuring-bind (current new repeated) arguments - (cli::change-pw current new repeated))) +;; ((getopt :long-name "redeem") +;; (assert (= 3 (length arguments)) () "--redeem requires exatly three arguments.") +;; (destructuring-bind (token name pass) arguments +;; (cli::redeem-invite token name pass))) + +;; ((getopt :long-name "login") +;; (assert (= 2 (length arguments)) () "--login requires exactly two arguments.") +;; (destructuring-bind (user pass) arguments +;; (cli::login user pass))) + +;; ((getopt :long-name "change-password") +;; (assert (= 3 (length arguments)) () "--change-password requires exactly three arguments." ) +;; (destructuring-bind (current new repeated) arguments +;; (cli::change-pw current new repeated))) - ((getopt :long-name "change-signature") - (cli::change-signature)) - - ((getopt :long-name "invite") - (cli::request-invite-code)) - - ((getopt :long-name "logout") - (cli::revoke-access)) - - ((getopt :long-name "add") - (cli::add-new-oneliner)) - - ((and (null arguments) (getopt :long-name "all-flagged")) - (cli::all-flagged-oneliners (getopt :long-name "limit"))) - - ((and (null arguments) (getopt :long-name "newest")) - (cli::newest-oneliners (getopt :long-name "limit"))) - - ((getopt :long-name "clear-cache") - (cli::wipe-cache)) - - (arguments - (destructuring-bind (id-or-name . args) (prepare-oneliner-arguments arguments) - (cond - ((getopt :long-name "flag") - (cli::flag-item id-or-name )) - ((getopt :long-name "unflag") - (cli::unflag-item id-or-name)) - ((getopt :long-name "lock") - (cli::lock-item id-or-name )) - ((getopt :long-name "unlock") - (cli::unlock-item id-or-name )) - ((getopt :long-name "edit") - (cli::edit-item id-or-name )) - ((getopt :long-name "show") - (cli::print-item-explanation id-or-name)) - ((getopt :long-name "clip") - (cli::run-item id-or-name args - :force-clip t - :timeout (getopt :long-name "timeout"))) - ((getopt :long-name "run") - (cli::run-item id-or-name args - :timeout (getopt :long-name "timeout"))) - - (t ; arguments but no overriding flags, search wiki - (cli::search-for-oneliners arguments - (getopt :long-name "limit") - (getopt :long-name "not-flagged") - (getopt :long-name "all-flagged") - (getopt :long-name "newest")))))) - (t ; no arguments and no options, print help - (help))))) - (uiop:quit)) +;; ((getopt :long-name "change-signature") +;; (cli::change-signature)) + +;; ((getopt :long-name "invite") +;; (cli::request-invite-code)) + +;; ((getopt :long-name "logout") +;; (cli::revoke-access)) + +;; ((getopt :long-name "add") +;; (cli::add-new-oneliner)) + +;; ((and (null arguments) (getopt :long-name "all-flagged")) +;; (cli::all-flagged-oneliners (getopt :long-name "limit"))) + +;; ((and (null arguments) (getopt :long-name "newest")) +;; (cli::newest-oneliners (getopt :long-name "limit"))) + +;; ((getopt :long-name "clear-cache") +;; (cli::wipe-cache)) + +;; (arguments +;; (destructuring-bind (id-or-name . args) (prepare-oneliner-arguments arguments) +;; (cond +;; ((getopt :long-name "flag") +;; (cli::flag-item id-or-name )) +;; ((getopt :long-name "unflag") +;; (cli::unflag-item id-or-name)) +;; ((getopt :long-name "lock") +;; (cli::lock-item id-or-name )) +;; ((getopt :long-name "unlock") +;; (cli::unlock-item id-or-name )) +;; ((getopt :long-name "edit") +;; (cli::edit-item id-or-name )) +;; ((getopt :long-name "show") +;; (cli::print-item-explanation id-or-name)) +;; ((getopt :long-name "clip") +;; (cli::run-item id-or-name args +;; :force-clip t +;; :timeout (getopt :long-name "timeout"))) +;; ((getopt :long-name "run") +;; (cli::run-item id-or-name args +;; :timeout (getopt :long-name "timeout"))) + +;; (t ; arguments but no overriding flags, search wiki +;; (cli::search-for-oneliners arguments +;; (getopt :long-name "limit") +;; (getopt :long-name "not-flagged") +;; (getopt :long-name "all-flagged") +;; (getopt :long-name "newest")))))) +;; (t ; no arguments and no options, print help +;; (help))))) +;; (uiop:quit)) diff --git a/lib/package.lisp b/lib/package.lisp index cf1fbcb..6359b12 100644 --- a/lib/package.lisp +++ b/lib/package.lisp @@ -36,4 +36,19 @@ (#:a #:alexandria)) (:export #:with-local-state #:search-for-oneliners - #:the-oneliner)) + #:the-oneliner + #:run-item + #:print-item-explanation + #:add-new-oneliner + #:edit-item + #:flag-item + #:unflag-item + #:lock-item + #:unlock-item + #:redeem-invite + #:request-invite-code + #:change-pw + #:revoke-access + #:change-signature + #:show-contributor + #:login)) -- cgit v1.2.3 From 3a412cda20b45a2e6617d43e66c6c006924dad88 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 10:57:05 -0500 Subject: cosmetic change to command section printout --- app/app.lisp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 3cfb5cf..316b917 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -172,10 +172,23 @@ export EDITOR=/usr/bin/zile (text :contents " ") (text :contents "Print information about a contributor.")) (group (:header "HELP MENU") - (text :contents "Usage: ol help [COMMAND TOPIC]") + (text :contents "Usage: ol help [COMMAND_SECTION]") (text :contents " ") (text :contents "Print a help menu. With no arguments, prints this help.") - (text :contents "Command topics include: search, run, clip, show, new, edit, flag, lock, redeem, invite, login, password, signature"))) + (text :contents "Command sections include:") + (text :contents "search") + (text :contents "run") + (text :contents "clip") + (text :contents "show") + (text :contents "new") + (text :contents "edit") + (text :contents "flag") + (text :contents "lock") + (text :contents "redeem") + (text :contents "invite") + (text :contents "login") + (text :contents "password") + (text :contents "signature"))) ;;; HELPERS -- cgit v1.2.3 From 3236933be611f91183ea6b61890c7fbd0b892d8b Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 10:57:54 -0500 Subject: removed spurious function --- app/app.lisp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 316b917..affb0b7 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -203,14 +203,6 @@ than the users." :end2 (length header))) return item)) -(defun prepare-oneliner-arguments (arguments) - "Takes a list of arguments, as gathered by (REMAINDER), and returns - a list that looks like (ID-OR-NAME . ARGS) where ID-OR-NAME is - either an integer or a string." - (a:if-let (id (parse-integer (first arguments) :junk-allowed t)) - (cons id (rest arguments)) - arguments)) - ;;; MAIN ENTRY POINT (defun main () -- cgit v1.2.3 From b5b0204d6742c68a90a6388593b980864ae301c3 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 10:58:19 -0500 Subject: removed old main --- app/app.lisp | 84 ------------------------------------------------------------ 1 file changed, 84 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index affb0b7..d2dd902 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -279,87 +279,3 @@ than the users." (help :item group) (help))) -;; (defun main () -;; "Entry point for our standalone application." -;; (make-context) -;; (cli:with-local-state -;; (let ((arguments (remainder))) -;; (cond -;; ((getopt :long-name "version") -;; (format t "Oneliner CLI Version: ~a~%" +ol-version+)) -;; ((getopt :long-name "help") -;; (if (and arguments (find-group-with-header (first arguments))) -;; (help :item (find-group-with-header (first arguments))) -;; (help))) -;; ((getopt :long-name "whois") -;; (assert (first arguments) () "--whois requires an argument, a user handle.") -;; (cli::show-contributor (first arguments))) - -;; ((getopt :long-name "redeem") -;; (assert (= 3 (length arguments)) () "--redeem requires exatly three arguments.") -;; (destructuring-bind (token name pass) arguments -;; (cli::redeem-invite token name pass))) - -;; ((getopt :long-name "login") -;; (assert (= 2 (length arguments)) () "--login requires exactly two arguments.") -;; (destructuring-bind (user pass) arguments -;; (cli::login user pass))) - -;; ((getopt :long-name "change-password") -;; (assert (= 3 (length arguments)) () "--change-password requires exactly three arguments." ) -;; (destructuring-bind (current new repeated) arguments -;; (cli::change-pw current new repeated))) - -;; ((getopt :long-name "change-signature") -;; (cli::change-signature)) - -;; ((getopt :long-name "invite") -;; (cli::request-invite-code)) - -;; ((getopt :long-name "logout") -;; (cli::revoke-access)) - -;; ((getopt :long-name "add") -;; (cli::add-new-oneliner)) - -;; ((and (null arguments) (getopt :long-name "all-flagged")) -;; (cli::all-flagged-oneliners (getopt :long-name "limit"))) - -;; ((and (null arguments) (getopt :long-name "newest")) -;; (cli::newest-oneliners (getopt :long-name "limit"))) - -;; ((getopt :long-name "clear-cache") -;; (cli::wipe-cache)) - -;; (arguments -;; (destructuring-bind (id-or-name . args) (prepare-oneliner-arguments arguments) -;; (cond -;; ((getopt :long-name "flag") -;; (cli::flag-item id-or-name )) -;; ((getopt :long-name "unflag") -;; (cli::unflag-item id-or-name)) -;; ((getopt :long-name "lock") -;; (cli::lock-item id-or-name )) -;; ((getopt :long-name "unlock") -;; (cli::unlock-item id-or-name )) -;; ((getopt :long-name "edit") -;; (cli::edit-item id-or-name )) -;; ((getopt :long-name "show") -;; (cli::print-item-explanation id-or-name)) -;; ((getopt :long-name "clip") -;; (cli::run-item id-or-name args -;; :force-clip t -;; :timeout (getopt :long-name "timeout"))) -;; ((getopt :long-name "run") -;; (cli::run-item id-or-name args -;; :timeout (getopt :long-name "timeout"))) - -;; (t ; arguments but no overriding flags, search wiki -;; (cli::search-for-oneliners arguments -;; (getopt :long-name "limit") -;; (getopt :long-name "not-flagged") -;; (getopt :long-name "all-flagged") -;; (getopt :long-name "newest")))))) -;; (t ; no arguments and no options, print help -;; (help))))) -;; (uiop:quit)) -- cgit v1.2.3 From 80bf9816c6e35bf7ffcc1e4349d5abf056c4df7f Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 11:22:21 -0500 Subject: updating helptexts; drafts-file function --- app/app.lisp | 23 +++++------------------ lib/state.lisp | 4 ++++ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index d2dd902..ea11a5e 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -19,22 +19,9 @@ (in-package :oneliners.cli.app) ;;; VERSION -(defparameter +ol-version+ "0.6.0") +(defparameter +ol-version+ "0.7.0") ;;; HELP TEXTS -(defparameter +invite-help-text+ - " -New contributor accounts are added to the your oneliners server by -redeeming invite tokens. - -When the --redeem option is passed, the ARGS section is expected to be -three items long, and is interpreted as TOKEN USERNAME PASSWORD. E.g.: - - ol --redeem PHONEYTOKEN c00lhacker my1337pw - -Would attempt to make a new user named c00lhacker with password -my1337pw.") - (defparameter +oneliners-variables-help-text+ " Oneliners may contain variables. There are positional variables and @@ -48,7 +35,7 @@ number, which must 1 or greater. For example: The #1 and #2 are a positional variables. You might call the above like - ol --run 8 Doofus Tuesday + ol run 8 Doofus Tuesday Assuming that the above oneliner has ID 8, then \"Hello Doofus, Happy Tuesday\" would print to the console. @@ -61,7 +48,7 @@ letters, numbers, or the symbol _. For example: The #name and #thing are named variables. You might call the above like so: - ol --run 3 name=Goober thing='sock in the nose' + ol run 3 name=Goober thing='sock in the nose' Which should print \"Hello Goober you get a sock in the nose\". @@ -91,7 +78,7 @@ export EDITOR=/usr/bin/zile (text :contents "Search for oneliners that have been tagged with all of TERMS.") (text :contents "E.g. `ol search grep awk`") (text :contents " ") - (text :contents "Options include:") + (text :contents "Options:") (lispobj :long-name "limit" :argument-type :optional :argument-name "NUMBER" @@ -111,7 +98,7 @@ export EDITOR=/usr/bin/zile (text :contents "IDENTIFIER should either be the name or the unique numeric ID of a oneliner.") (text :contents "E.g. `ol run demo foo bar` # run \"demo\" with args \"foo\" and \"bar\"") (text :contents " ") - (text :contents "Options include:") + (text :contents "Options:") (lispobj :long-name "timeout" :argument-type :optional :argument-name "SECONDS" diff --git a/lib/state.lisp b/lib/state.lisp index 0f69ff3..a156d59 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -63,6 +63,10 @@ "Returns the pathname holding the location of the cache." (merge-pathnames ".cache/oneliners.cache" (user-homedir-pathname))) +(defun drafts-file () + "Returns the pathame holding the location of the oneliner drafts file." + (merge-pathnames ".cache/oneliners.drafts" (user-homedir-pathname))) + (defun wipe-cache () "Deletes the cache, if present." (uiop:delete-file-if-exists (cached-oneliners-file))) -- cgit v1.2.3 From 07183b5bbb4d2e65514e3ec3e7cdf7e421f97749 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 11:57:06 -0500 Subject: added intial drafting code to new --- lib/client.lisp | 38 +++++++++++++++++++++++++------ lib/state.lisp | 70 +++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/lib/client.lisp b/lib/client.lisp index fe29932..8d40fd5 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -131,8 +131,18 @@ running the body. If such a oneliner can be found." (prompt "Name (leave blank for none): " :expect 'valid-oneliner-name-p :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 _.")))) + (init-tags (parse-oneliner-tags oneliner-string)) + (brief (prompt "Brief Description: " :expect 'valid-brief-description-p @@ -153,17 +163,31 @@ running the body. If such a oneliner can be found." (when (y-or-n-p "Provide an explanation?") (string-from-editor (format nil "~a~%~%" oneliner-string))))) - (api:request-with - (:body (jonathan:to-json - (list :oneliner oneliner-string - :name (if (plusp (length name)) name :null) + (if draft-name + ;; if this is a draft, save it to disk. + (progn + (put-draft draft-name + (make-oneliner + :oneliner oneliner-string + :name name :tags tags :brief brief :explanation explanation :runstyle runstyle)) - :content-type "application/json") - (api:post--oneliner :token (api-token)) ;TODO: update api to return the instance created. - (format t "Added~%")))) + (format t "Saved draft ~a~%" draft-name)) + ;; otherwise, format the oneliner as json and make a request + ;; to create a new oneliner in the wiki + (api:request-with + (:body (jonathan:to-json + (list :oneliner oneliner-string + :name (if (plusp (length name)) name :null) + :tags tags + :brief brief + :explanation explanation + :runstyle runstyle)) + :content-type "application/json") + (api:post--oneliner :token (api-token)) ;TODO: update api to return the instance created. + (format t "Added Oneliner~%"))))) ;;; EDITING ONELINERS diff --git a/lib/state.lisp b/lib/state.lisp index a156d59..123bd79 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -25,7 +25,7 @@ (host "") (shell "bash")) -;;; DYNAMIC VARS FOR CONFIG AND CACHE, AND SOME GETTERS +;;; CONFIG VAR AND OPERATIONS (defvar *config* nil "Holds a config struct instance.") @@ -50,9 +50,54 @@ (defun shell () (config-shell *config*)) + +;;; CACHE VAR AND OPERATIONS + (defvar *cache* nil "Holds cached oneliners as a list.") +(defun merge-oneliners (new) + "Modifies *CACHE*. Merge updated oneliners into the *cache*, ensuring to remove old versions." + (setf *cache* + (nconc + new + (delete-if + (lambda (old-oneliner) + (find (oneliner-id old-oneliner) + new + :key #'oneliner-id + :test #'equal)) + *cache*)))) + +(defun get-cached (id-or-name) + "Looks up a oneliner instance by ID-OR-NAME using the current binding of *cache*. " + (find id-or-name + *cache* + :key (etypecase id-or-name + (integer #'oneliner-id) + (string #'oneliner-name)) + :test #'equal)) + + +;;; DRAFTS VAR AND OPERATIONS + +(defvar *drafts* nil + "Holds a list of oneliner drafts yet to be sent to the server.") + +(defun fetch-draft (name) + "Fetch a draft by name form the *DRAFTS* association list." + (cdr (assoc name *drafts*))) + +(defun drop-draft (name) + "Drop a draft by NAME from the *DFRAFTS* association list." + (setf *DRAFTS* (delete (assoc name *DRAFTS*) *DRAFTS*))) + +(defun put-draft (name draft) + "Modifies *DRAFTS*, adding a new DRAFT associated with NAME. If NAME +is already associated, that old association is deleted." + (drop-draft name) + (push (cons name draft) *drafts*)) + ;;; LOADING AND SAVING STATE (defun config-file () @@ -105,29 +150,6 @@ user for some input if it does not." (read-config-file) (make-fresh-config))) -;;; GETTING AND SETTING STATE, DYNAMICALLY BOUND - -(defun merge-oneliners (new) - "Modifies *CACHE*. Merge updated oneliners into the *cache*, ensuring to remove old versions." - (setf *cache* - (nconc - new - (delete-if - (lambda (old-oneliner) - (find (oneliner-id old-oneliner) - new - :key #'oneliner-id - :test #'equal)) - *cache*)))) - -(defun get-cached (id-or-name) - "Looks up a oneliner instance by ID-OR-NAME using the current binding of *cache*. " - (find id-or-name - *cache* - :key (etypecase id-or-name - (integer #'oneliner-id) - (string #'oneliner-name)) - :test #'equal)) ;;; STATE LOADING MACRO -- cgit v1.2.3 From 7ae6cbff1875ea271fa1724d6e53bc3d3d48dd26 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 13:56:49 -0500 Subject: support for running drafts; drafts accounted for in with-local-state --- app/app.lisp | 10 +++++++--- lib/client.lisp | 18 +++++++++++++----- lib/state.lisp | 10 +++++++++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index ea11a5e..86c7328 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -104,7 +104,9 @@ export EDITOR=/usr/bin/zile :argument-name "SECONDS" :default-value 1 :typespec 'integer - :description "How many seconds to wait for standard output before giving up.")) + :description "How many seconds to wait for standard output before giving up.") + (flag :long-name "draft" + :description "Indicates that you wish to run a draft of a oneliner identified by IDENTIFIER.")) (group (:header "CLIPPING ONELINERS" :hidden t) (text :contents "Usage: ol clip [ARGS...]") (text :contents " ") @@ -214,10 +216,12 @@ than the users." (getopt :long-name "newest"))) (:run (cli:run-item id-or-name (rest args) - :timeout (getopt :long-name "timeout"))) + :timeout (getopt :long-name "timeout") + :draftp (getopt :long-name "draft"))) (:clip (cli:run-item id-or-name (rest args) - :force-clip t)) + :force-clip t + :draftp (getopt :long-name "draft"))) (:show (cli:print-item-explanation id-or-name)) (:new diff --git a/lib/client.lisp b/lib/client.lisp index 8d40fd5..db19bda 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -45,12 +45,18 @@ not in the local cache, try to fetch from configured server." (defmacro when-oneliner ((var name-or-id) &body body) "Finds the oneliner with name-or-id and binds it to var before running the body. If such a oneliner can be found." - (assert (symbolp var)) (let ((nvar (gensym))) `(let ((,nvar ,name-or-id)) (a:when-let (,var (the-oneliner ,nvar)) ,@body)))) +(defmacro when-draft ((var name) &body body) + "Like when-oneliner but restricts itself to local drafts." + (let ((nvar (gensym))) + `(let ((,nvar ,name)) + (a:when-let (,var (fetch-draft ,nvar)) + ,@body)))) + (defun newest-oneliners (&optional limit) (let ((response (if limit @@ -76,10 +82,12 @@ running the body. If such a oneliner can be found." (defvar *ol-output-timeout* 1) -(defun run-item (ident args &key force-clip (timeout nil timeout-p)) - (when-oneliner (ol ident) - (let ((*ol-output-timeout* (if timeout-p timeout *ol-output-timeout*))) - (bind-vars-and-run-oneliner ol args force-clip)))) +(defun run-item (ident args &key force-clip (timeout nil timeout-p) draftp) + "Runs a oneliner identified by IDENT (if available) with arguments ARGS." + (let ((ol (if draftp (fetch-draft ident) (the-oneliner ident)))) + (when ol + (let ((*ol-output-timeout* (if timeout-p timeout *ol-output-timeout*))) + (bind-vars-and-run-oneliner ol args force-clip))))) (defun bind-vars-and-run-oneliner (ol args &optional force-clip) (let* ((oneliner (oneliner-oneliner ol)) diff --git a/lib/state.lisp b/lib/state.lisp index 123bd79..8ab6c51 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -86,7 +86,7 @@ (defun fetch-draft (name) "Fetch a draft by name form the *DRAFTS* association list." - (cdr (assoc name *drafts*))) + (cdr (assoc name *drafts* :test #'string-equal))) (defun drop-draft (name) "Drop a draft by NAME from the *DFRAFTS* association list." @@ -143,6 +143,12 @@ CACHED-ONELINERS-FILE. NIL if there is no such file." :shell (prompt "With which shell should oneliners be run? " :prefill "bash"))) +(defun read-drafts-file () + (read-from-file (drafts-file))) + +(defun write-drafts-to-disk () + (print-to-file *drafts* (drafts-file))) + (defun ensure-config () "Ensures that a configuration file exists on disk, prompting the user for some input if it does not." @@ -158,6 +164,7 @@ user for some input if it does not." sets the api's *host* variable. If BODY produces no errors, the " `(let* ((*config* (ensure-config)) (*cache* (read-cache-file)) + (*drafts* (read-drafts-file)) (api:*host* (config-host *config*))) (assert api:*host* () "ol must be configured with a server host.") (set-term-width) @@ -165,6 +172,7 @@ sets the api's *host* variable. If BODY produces no errors, the " (progn ,@body ;; only if there is no error do we save the local state. + (write-drafts-to-disk) (write-cache-to-disk) (write-config-to-disk)) (error (e) -- cgit v1.2.3 From 7bcf634c789c00a95237ad74e5f923a4214020c8 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 14:21:33 -0500 Subject: can make, run, and publish drafts --- app/app.lisp | 7 ++++ lib/client.lisp | 106 ++++++++++++++++++++++++++++++++++-------------------- lib/oneliner.lisp | 15 ++++++++ 3 files changed, 89 insertions(+), 39 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 86c7328..8e89a93 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -124,6 +124,10 @@ export EDITOR=/usr/bin/zile (text :contents "Usage: ol edit ") (text :contents " ") (text :contents "Interactively alter a oneliner and uplaod it to the server.")) + (group (:header "PUBLISHING ONELINERS" :hidden t) + (text :contents "Usage: ol publish ") + (text :contents " ") + (text :contents "Submits a draft oneliner to the wiki server, and, when successful, deletes the draft.")) (group (:header "FLAGGING AND UNFLAGGING ONELINERS" :hidden t) (text :contents "Usage: ol ") (text :contents " ") @@ -171,6 +175,7 @@ export EDITOR=/usr/bin/zile (text :contents "show") (text :contents "new") (text :contents "edit") + (text :contents "publish") (text :contents "flag") (text :contents "lock") (text :contents "redeem") @@ -228,6 +233,8 @@ than the users." (cli:add-new-oneliner)) (:edit (cli:edit-item id-or-name)) + (:publish + (cli::publish-draft id-or-name)) (:flag (cli:flag-item id-or-name)) (:unflag diff --git a/lib/client.lisp b/lib/client.lisp index db19bda..a72b991 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -125,7 +125,6 @@ running the body. If such a oneliner can be found." ;;; ADDING ONELINERS - (defun add-new-oneliner () (api-token) ;; fails with error if not set. ;; read each field required to make a onelienr in from a prompt. @@ -171,31 +170,28 @@ running the body. If such a oneliner can be found." (when (y-or-n-p "Provide an explanation?") (string-from-editor (format nil "~a~%~%" oneliner-string))))) - (if draft-name - ;; if this is a draft, save it to disk. - (progn - (put-draft draft-name - (make-oneliner - :oneliner oneliner-string - :name name - :tags tags - :brief brief - :explanation explanation - :runstyle runstyle)) - (format t "Saved draft ~a~%" draft-name)) - ;; otherwise, format the oneliner as json and make a request - ;; to create a new oneliner in the wiki - (api:request-with - (:body (jonathan:to-json - (list :oneliner oneliner-string - :name (if (plusp (length name)) name :null) - :tags tags - :brief brief - :explanation explanation - :runstyle runstyle)) - :content-type "application/json") - (api:post--oneliner :token (api-token)) ;TODO: update api to return the instance created. - (format t "Added Oneliner~%"))))) + (let ((local + (make-oneliner + :oneliner oneliner-string + :name name + :tags tags + :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 local) + :content-type "application/json") + (api:post--oneliner :token (api-token)) ;TODO: update api to return the instance created. + (format t "Added Oneliner~%")))))) ;;; EDITING ONELINERS @@ -216,13 +212,23 @@ running the body. If such a oneliner can be found." :expect 'valid-oneliner-name-p :retry-text "Must begin with a letter contain only letters, numbers, - and _." :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 _.")))) (brief (prompt "Brief Description: " :expect 'valid-brief-description-p :retry-text "Too long. Must be <= 72 characters: " :prefill (oneliner-brief ol))) + (init-tags (parse-oneliner-tags oneliner-string)) + (tags (progn (format t "Tags include: ~{~a ~}~%" init-tags) @@ -240,22 +246,44 @@ running the body. If such a oneliner can be found." :expect 'valid-runstyle-p :retry-text "Must be (auto or manual): " :prefill (oneliner-runstyle ol)))) + (explanation - (when (y-or-n-p "Provide an explanation?") + (when (y-or-n-p "Alter the explanation?") (string-from-editor (oneliner-explanation ol))))) - (let ((new-item - (list :oneliner oneliner-string - :tags tags - :brief brief - :name (if (plusp (length name)) name :null) - :explanation explanation - :runstyle runstyle))) - (api:request-with - (:body (jonathan:to-json new-item) - :content-type "application/json") + + (let ((local + (make-oneliner + :id (oneliner-id ol) + :oneliner oneliner-string + :name (if (plusp (length name)) name :null) + :tags tags + :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") + (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token)) + ;(merge-oneliners (list new-item)) ;;TODO: this is broken, wait for API update. + (format t "Edits accepted~%"))))))) + +(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)) - (merge-oneliners (list new-item)) ;;TODO: this is broken, wait for API update. - (format t "OK~%")))))) + (api:post--oneliner :token (api-token))) + ;; 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)))) ;;; ADMIN OF ONELINER ENTRIES diff --git a/lib/oneliner.lisp b/lib/oneliner.lisp index 4828b2d..668a82c 100644 --- a/lib/oneliner.lisp +++ b/lib/oneliner.lisp @@ -94,3 +94,18 @@ (string-trim '(#\space) (alexandria-2:subseq* (oneliner-brief ol) x (+ x *term-width*))))) (format t "~%~a~%~%" (oneliner-oneliner ol)))) + +;;;; json serialization + +(defun oneliner-to-json-body (ol) + "Takes a oneliner structure and produces some json suitable for +sending to the server. ID and some other fields are omitted." + (jonathan:to-json + (list :oneliner (oneliner-oneliner ol) + :tags (oneliner-tags ol) + :brief (oneliner-brief ol) + :name (if (plusp (length (oneliner-name ol))) + (oneliner-name ol) + :null) + :explanation (oneliner-explanation ol) + :runstyle (oneliner-runstyle ol)))) -- cgit v1.2.3 From 5531288c433641d81d1359e0afa69f86d4bf5d07 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 14:24:16 -0500 Subject: can also edit drafts --- app/app.lisp | 2 +- lib/client.lisp | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 8e89a93..01a88ca 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -232,7 +232,7 @@ than the users." (:new (cli:add-new-oneliner)) (:edit - (cli:edit-item id-or-name)) + (cli:edit-item id-or-name (getopt :long-name "draft"))) (:publish (cli::publish-draft id-or-name)) (:flag diff --git a/lib/client.lisp b/lib/client.lisp index a72b991..6883b20 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -195,11 +195,9 @@ running the body. If such a oneliner can be found." ;;; EDITING ONELINERS -(defun edit-item (ident) +(defun edit-item (ident &optional draftp) (api-token) ;; fails with error if not set. - (when-oneliner (ol ident) - ;; Like adding a oneliner, read each field in from a prompt. - ;; Here, prefil the field with its current value. + (let ((ol (if draftp (fetch-draft ident) (the-oneliner ident)))) (let* ((oneliner-string (prompt "Oneliner: " :expect 'valid-oneliner-string-p @@ -270,7 +268,7 @@ running the body. If such a oneliner can be found." (:body (oneliner-to-json-body local) :content-type "application/json") (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token)) - ;(merge-oneliners (list new-item)) ;;TODO: this is broken, wait for API update. + ;(merge-oneliners (list new-item)) ;;TODO: this is broken, wait for API update. (format t "Edits accepted~%"))))))) (defun publish-draft (name) -- cgit v1.2.3 From 8ba6552132fab6daef1f2b10adf932c87947e2ec Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 14:31:12 -0500 Subject: can run the edit command on drafts with --redraft --- app/app.lisp | 8 ++++++-- lib/client.lisp | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 01a88ca..08e203e 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -123,7 +123,11 @@ export EDITOR=/usr/bin/zile (group (:header "EDITING ONELINERS" :hidden t) (text :contents "Usage: ol edit ") (text :contents " ") - (text :contents "Interactively alter a oneliner and uplaod it to the server.")) + (text :contents "Interactively alter a oneliner and uplaod it to the server.") + (text :contents " ") + (text :contents "Options:") + (flag :long-name "redraft" + :description "Indicates that you wish to edit a draft instead of a published oneliner.")) (group (:header "PUBLISHING ONELINERS" :hidden t) (text :contents "Usage: ol publish ") (text :contents " ") @@ -232,7 +236,7 @@ than the users." (:new (cli:add-new-oneliner)) (:edit - (cli:edit-item id-or-name (getopt :long-name "draft"))) + (cli:edit-item id-or-name (getopt :long-name "redraft"))) (:publish (cli::publish-draft id-or-name)) (:flag diff --git a/lib/client.lisp b/lib/client.lisp index 6883b20..233cc42 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -188,7 +188,7 @@ running the body. If such a oneliner can be found." ;; 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 local) + (: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~%")))))) -- cgit v1.2.3 From 6a6c2ec8e2ef6cc9fa91f769d7dbe79387529619 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 14:39:55 -0500 Subject: printing drafts --- app/app.lisp | 16 +++++++++++++++- lib/client.lisp | 7 ++++++- lib/state.lisp | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 08e203e..bac6628 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -128,10 +128,18 @@ export EDITOR=/usr/bin/zile (text :contents "Options:") (flag :long-name "redraft" :description "Indicates that you wish to edit a draft instead of a published oneliner.")) - (group (:header "PUBLISHING ONELINERS" :hidden t) + (group (:header "PUBLISHING ONELINER DRAFTS" :hidden t) (text :contents "Usage: ol publish ") (text :contents " ") (text :contents "Submits a draft oneliner to the wiki server, and, when successful, deletes the draft.")) + (group (:header "DRAFTS LISTING" :hidden t) + (text :contents "Usage: ol drafts") + (text :contents " ") + (text :contents "Prints a listing of current drafts of oneliners yet to be published.")) + (group (:header "TRASH DRAFT" :hidden t) + (text :contents "Usage: ol trash ") + (text :contents " ") + (text :contents "Trashes a draft.")) (group (:header "FLAGGING AND UNFLAGGING ONELINERS" :hidden t) (text :contents "Usage: ol ") (text :contents " ") @@ -179,6 +187,8 @@ export EDITOR=/usr/bin/zile (text :contents "show") (text :contents "new") (text :contents "edit") + (text :contents "drafts") + (text :contents "trash") (text :contents "publish") (text :contents "flag") (text :contents "lock") @@ -239,6 +249,10 @@ than the users." (cli:edit-item id-or-name (getopt :long-name "redraft"))) (:publish (cli::publish-draft id-or-name)) + (:trash + (cli::drop-draft id-or-name)) + (:drafts + (cli::print-drafts)) (:flag (cli:flag-item id-or-name)) (:unflag diff --git a/lib/client.lisp b/lib/client.lisp index 233cc42..530b454 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -21,7 +21,7 @@ ;; WITH-LOCAL-STATE form. If you are hacking in the REPL, make sure ;; to wrap function calls appropriately. -;;; GETTING ONELINERS & Displaying oneliners +;;; GETTING ONELINERS & DISPLAYING ONELINERS (defun search-for-oneliners (terms limit &optional not-flagged-p all-flagged-p newestp) (assert (loop for term in terms never (find #\, term)) () "Search terms may not contain commas.") @@ -78,6 +78,11 @@ running the body. If such a oneliner can be found." (princ #\newline) (princ (oneliner-explanation ol))))) +(defun print-drafts () + (format t "DRAFTS~%") + (dolist (draft *drafts*) + (print-oneliner-result-for-user (cdr draft)))) + ;;; RUNNING ONELINERS (defvar *ol-output-timeout* 1) diff --git a/lib/state.lisp b/lib/state.lisp index 8ab6c51..9c25ab6 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -90,7 +90,7 @@ (defun drop-draft (name) "Drop a draft by NAME from the *DFRAFTS* association list." - (setf *DRAFTS* (delete (assoc name *DRAFTS*) *DRAFTS*))) + (setf *DRAFTS* (delete (assoc name *DRAFTS* :test #'string-equal) *DRAFTS*))) (defun put-draft (name draft) "Modifies *DRAFTS*, adding a new DRAFT associated with NAME. If NAME -- cgit v1.2.3 From 6890b0349f79c0fbbbe5b8b7b3dbf8c2d2262e79 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 14:43:59 -0500 Subject: better printing of drafts --- lib/client.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/client.lisp b/lib/client.lisp index 530b454..dea6de6 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -79,7 +79,7 @@ running the body. If such a oneliner can be found." (princ (oneliner-explanation ol))))) (defun print-drafts () - (format t "DRAFTS~%") + (format t (concatenate 'string "~%~" (prin1-to-string *term-width*) "< ~;DRAFTS~; ~>~%")) (dolist (draft *drafts*) (print-oneliner-result-for-user (cdr draft)))) -- cgit v1.2.3 From 7a97e9d6ba5737f1088dd3a81b9b16121cf47c39 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 14:45:28 -0500 Subject: only print drafts when *drafts* is non null --- lib/client.lisp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/client.lisp b/lib/client.lisp index dea6de6..aa7e896 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -79,9 +79,10 @@ running the body. If such a oneliner can be found." (princ (oneliner-explanation ol))))) (defun print-drafts () - (format t (concatenate 'string "~%~" (prin1-to-string *term-width*) "< ~;DRAFTS~; ~>~%")) - (dolist (draft *drafts*) - (print-oneliner-result-for-user (cdr draft)))) + (when *drafts* + (format t (concatenate 'string "~%~" (prin1-to-string *term-width*) "< ~;DRAFTS~; ~>~%")) + (dolist (draft *drafts*) + (print-oneliner-result-for-user (cdr draft))))) ;;; RUNNING ONELINERS -- cgit v1.2.3 From 57bae08a8b9accc1d4bfb7165080e7d5a5ef2a30 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 17:40:45 -0500 Subject: deletion support; some cache syncing in client functions; --- app/app.lisp | 171 ++++++++++++++++++++++++++++++++------------------------ lib/client.lisp | 68 ++++++++++++++-------- lib/state.lisp | 4 ++ 3 files changed, 146 insertions(+), 97 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index bac6628..25ac8d7 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -187,6 +187,7 @@ export EDITOR=/usr/bin/zile (text :contents "show") (text :contents "new") (text :contents "edit") + (text :contents "delete") (text :contents "drafts") (text :contents "trash") (text :contents "publish") @@ -195,6 +196,7 @@ export EDITOR=/usr/bin/zile (text :contents "redeem") (text :contents "invite") (text :contents "login") + (text :contents "whois") (text :contents "password") (text :contents "signature"))) @@ -214,80 +216,101 @@ than the users." ;;; MAIN ENTRY POINT (defun main () - (make-context) - (a:if-let (arguments (remainder)) - (destructuring-bind (command . args) arguments - (let ((id-or-name - (when args - (or (parse-integer (first args) :junk-allowed t) - (first args))))) - (cli:with-local-state - (ecase (a:make-keyword (string-upcase command)) - (:help - (princ #\newline) - (help-topic (first args))) - (:search - (cli:search-for-oneliners - args - (getopt :long-name "limit") - (getopt :long-name "not-flagged") - (getopt :long-name "all-flagged") - (getopt :long-name "newest"))) - (:run - (cli:run-item id-or-name (rest args) - :timeout (getopt :long-name "timeout") - :draftp (getopt :long-name "draft"))) - (:clip - (cli:run-item id-or-name (rest args) - :force-clip t - :draftp (getopt :long-name "draft"))) - (:show - (cli:print-item-explanation id-or-name)) - (:new - (cli:add-new-oneliner)) - (:edit - (cli:edit-item id-or-name (getopt :long-name "redraft"))) - (:publish - (cli::publish-draft id-or-name)) - (:trash - (cli::drop-draft id-or-name)) - (:drafts - (cli::print-drafts)) - (:flag - (cli:flag-item id-or-name)) - (:unflag - (cli:unflag-item id-or-name)) - (:lock - (cli:lock-item id-or-name)) - (:unlock - (cli:unlock-item id-or-name)) - (:redeem - (unless (= 3 (length args)) - (help-topic "redeem") - (uiop:quit)) - (apply 'cli:redeem-invite args)) - (:invite - (cli:request-invite-code)) - (:login - (unless (= 3 (length args)) - (help-topic "login") - (uiop:quit)) - (apply 'cli:login args)) - (:logout - (cli:revoke-access)) - (:password - (unless (= 3 (length args)) - (help-topic "password") - (uiop:quit)) - (apply 'cli:change-pw args)) - (:signature - (cli:change-signature)) - (:whois - (unless args - (help-topic "whois") - (uiop:quit)) - (cli:show-contributor (first args))))))) - (help)) + (macrolet ((help-and-quit-unless (topic check) + `(unless ,check + (help-topic ,topic) + (uiop:quit)))) + (make-context) + (a:if-let (arguments (remainder)) + (destructuring-bind (command . args) arguments + (let ((id-or-name + (when args + (or (parse-integer (first args) :junk-allowed t) + (first args))))) + (cli:with-local-state + (ecase (a:make-keyword (string-upcase command)) + (:help + (princ #\newline) + (help-topic (first args))) + (:search + (cond + ;; if there are args, use them as search terms + (args + (cli:search-for-oneliners + args + (getopt :long-name "limit") + (getopt :long-name "not-flagged") + (getopt :long-name "all-flagged") + (getopt :long-name "newest"))) + ;; no args, but a --newest flag, just return newest + ((getopt :long-name "newest") + (cli::newest-oneliners (getopt :long-name "limit"))) + ;; no args, but a --all-falgged + ((getopt :long-name "all-flagged") + (cli::all-flagged-oneliners (getopt :long-name "limit"))) + ;; otherwise, print help for search + (t + (help-topic "search") + (uiop:quit)))) + + (:run + (cli:run-item id-or-name (rest args) + :timeout (getopt :long-name "timeout") + :draftp (getopt :long-name "draft"))) + (:clip + (cli:run-item id-or-name (rest args) + :force-clip t + :draftp (getopt :long-name "draft"))) + (:show + (help-and-quit-unless "show" id-or-name) + (cli:print-item-explanation id-or-name)) + (:new + (cli:add-new-oneliner)) + (:edit + (help-and-quit-unless "edit" id-or-name) + (cli:edit-item id-or-name (getopt :long-name "redraft"))) + (:delete + (help-and-quit-unless "delete" id-or-name) + (cli::delete-item id-or-name)) + (:publish + (help-and-quit-unless "publish" id-or-name) + (cli::publish-draft id-or-name)) + (:trash + (help-and-quit-unless "trash" id-or-name) + (cli::drop-draft id-or-name)) + (:drafts + (cli::print-drafts)) + (:flag + (help-and-quit-unless "flag" id-or-name) + (cli:flag-item id-or-name)) + (:unflag + (help-and-quit-unless "flag" id-or-name) + (cli:unflag-item id-or-name)) + (:lock + (help-and-quit-unless "lock" id-or-name) + (cli:lock-item id-or-name)) + (:unlock + (help-and-quit-unless "lock" id-or-name) + (cli:unlock-item id-or-name)) + (:redeem + (help-and-quit-unless "redeem" (= 3 (length args))) + (apply 'cli:redeem-invite args)) + (:invite + (cli:request-invite-code)) + (:login + (help-and-quit-unless "login" (= 3 (length args))) + (apply 'cli:login args)) + (:logout + (cli:revoke-access)) + (:password + (help-and-quit-unless "password" (= 3 (length args))) + (apply 'cli:change-pw args)) + (:signature + (cli:change-signature)) + (:whois + (help-and-quit-unless "whois" args) + (cli:show-contributor (first args))))))) + (help))) (uiop:quit)) (defun help-topic (topic) diff --git a/lib/client.lisp b/lib/client.lisp index aa7e896..4aff60d 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -16,8 +16,8 @@ ;; along with this program. If not, see . (in-package :oneliners.cli) -;; NOTE WHILE HACKING. Each of the functions below that make HTTP -;; requests is meant to be called within the body of a +;; >>>>>NOTE WHILE HACKING<<<<<. Each of the functions below that make +;; HTTP requests are meant to be called within the body of a ;; WITH-LOCAL-STATE form. If you are hacking in the REPL, make sure ;; to wrap function calls appropriately. @@ -277,6 +277,7 @@ running the body. If such a oneliner can be found." ;(merge-oneliners (list new-item)) ;;TODO: this is broken, wait for API update. (format t "Edits accepted~%"))))))) +;;TODO: need to sync cache here. (defun publish-draft (name) (when-draft (ol name) (api:request-with @@ -292,29 +293,50 @@ running the body. If such a oneliner can be found." ;;; ADMIN OF ONELINER ENTRIES +(defun delete-item (ident) + (when-oneliner (ol ident) + (api:delete--oneliner-oneliner + ident + :token (api-token)) + ;; if we've made it this far no http error has been returned, + ;; hence we can delete it from the cache + (remove-from-cache ident))) + (defun flag-item (ident) + (when-oneliner (ol ident) + (api:put--oneliner-entry-flag + ident + :token (api-token) + :value "true") + ;; no http error, so we flag the cached version, ol. + (setf (oneliner-isflagged ol) t))) + +(defun unflag-item (ident) + (when-oneliner (ol ident) + (api:put--oneliner-entry-flag + ident + :token (api-token) + :value "false") + ;; no http error, so we can unflag the cached version, ol + (setf (oneliner-isflagged ol) nil))) + +(defun lock-item (ident) + (when-oneliner (ol ident) + (api:put--oneliner-oneliner-locked + ident + :token (api-token) + :value "true") + ;; no http error, so we can lock the cached version, ol + (setf (oneliner-islocked ol) t))) + +(defun unlock-item (ident) (when-oneliner (ol ident) - (api:put--oneliner-entry-flag (oneliner-id ol) - :token (api-token) - :value "true"))) - -(defun unflag-item (item-number) - (when-oneliner (ol item-number) - (api:put--oneliner-entry-flag (oneliner-id ol) - :token (api-token) - :value "false"))) - -(defun lock-item (item-number) - (when-oneliner (ol item-number) - (api:put--oneliner-oneliner-locked (oneliner-id ol) - :token (api-token) - :value "true"))) - -(defun unlock-item (item-number) - (when-oneliner (ol item-number) - (api:put--oneliner-oneliner-locked (oneliner-id ol) - :token (api-token) - :value "false"))) + (api:put--oneliner-oneliner-locked + ident + :token (api-token) + :value "false") + ;; no http error, so we can unlock the cached version, ol + (setf (oneliner-islocked ol) nil))) ;;; ACCOUNT AND INVITE STUFF diff --git a/lib/state.lisp b/lib/state.lisp index 9c25ab6..7a9a427 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -78,6 +78,10 @@ (string #'oneliner-name)) :test #'equal)) +(defun remove-from-cache (id-or-name) + "Removes an item from the contents of *cache*." + (a:when-let (found (get-cached id-or-name)) + (setf *cache* (delete found *cache*)))) ;;; DRAFTS VAR AND OPERATIONS -- cgit v1.2.3 From 4b390fcde69013393bae325be2e8d2f5944cd15b Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Mar 2022 22:23:46 -0500 Subject: tabulating help menu command listing --- app/app.lisp | 62 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 25ac8d7..b082dee 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -71,6 +71,27 @@ export EDITOR=/usr/bin/zile ;;; CLON SYNOPSIS DEFINITION +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun group-by (n xs &optional default) + (loop for l on xs by (lambda (l) (nthcdr n l)) + when (<= n (length l)) + collect (subseq l 0 n) + else + collect (append l (loop repeat (- n (length l)) collect default)))) + + (defun tabulate-strings (line-width columns strings) + (let ((row-format + (apply 'concatenate 'string + "~" (prin1-to-string line-width) "<" + (loop for i from 0 below columns + collect "~a" + when (< i (1- columns)) + collect "~;" + else + collect "~>")))) + (loop for group in (group-by columns strings " ") + collect (apply 'format nil row-format group))))) + (defsynopsis (:postfix "COMMAND [ARGS...]") (group (:header "SEARCHING FOR ONELINERS" :hidden t) (text :contents "Usage: ol [OPTIONS] search [TERMS...]") @@ -181,24 +202,29 @@ export EDITOR=/usr/bin/zile (text :contents " ") (text :contents "Print a help menu. With no arguments, prints this help.") (text :contents "Command sections include:") - (text :contents "search") - (text :contents "run") - (text :contents "clip") - (text :contents "show") - (text :contents "new") - (text :contents "edit") - (text :contents "delete") - (text :contents "drafts") - (text :contents "trash") - (text :contents "publish") - (text :contents "flag") - (text :contents "lock") - (text :contents "redeem") - (text :contents "invite") - (text :contents "login") - (text :contents "whois") - (text :contents "password") - (text :contents "signature"))) + (text :contents + (str:join + #\newline + (tabulate-strings + 40 5 + '("search" + "run" + "clip" + "show" + "new" + "edit" + "delete" + "drafts" + "trash" + "publish" + "flag" + "lock" + "redeem" + "invite" + "login" + "whois" + "password" + "signature")))))) ;;; HELPERS -- cgit v1.2.3 From f18dddd766af9e06ba4f66487701322de495de59 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 08:11:58 -0500 Subject: tweaks to help menu printing --- app/app.lisp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index b082dee..69cc42c 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -198,7 +198,7 @@ export EDITOR=/usr/bin/zile (text :contents " ") (text :contents "Print information about a contributor.")) (group (:header "HELP MENU") - (text :contents "Usage: ol help [COMMAND_SECTION]") + (text :contents "Usage: ol help [SECTION]") (text :contents " ") (text :contents "Print a help menu. With no arguments, prints this help.") (text :contents "Command sections include:") @@ -336,7 +336,7 @@ than the users." (:whois (help-and-quit-unless "whois" args) (cli:show-contributor (first args))))))) - (help))) + (help-topic "help"))) (uiop:quit)) (defun help-topic (topic) -- cgit v1.2.3 From 86f7cdb2ce0f99aee0328617999f35b63694b4a6 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 08:15:27 -0500 Subject: argument checking for run and clip --- app/app.lisp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/app.lisp b/app/app.lisp index 69cc42c..3277521 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -280,10 +280,12 @@ than the users." (uiop:quit)))) (:run + (help-and-quit-unless "run" id-or-name) (cli:run-item id-or-name (rest args) :timeout (getopt :long-name "timeout") :draftp (getopt :long-name "draft"))) (:clip + (help-and-quit-unless "clip" id-or-name) (cli:run-item id-or-name (rest args) :force-clip t :draftp (getopt :long-name "draft"))) -- cgit v1.2.3 From e2091250cbc8dce679b52636647949d0b417e6be Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 08:21:12 -0500 Subject: CONTRIBUTING rewording --- CONTRIBUTING.org | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.org b/CONTRIBUTING.org index 9d896ee..2641f74 100644 --- a/CONTRIBUTING.org +++ b/CONTRIBUTING.org @@ -26,15 +26,20 @@ by starting the subject line with one of the following: - [PATCH vN] For patches (use git send-email) - [GENERAL CLI] For anything else -** Branch based collaboration +ADDITIONALLY, you may post general issues and bugreports here: +https://todo.sr.ht/~cbeo/oneliners.wiki + +** Making code contributions If you want to work on a feature, please make a new branch based on the relevant release candidate branch and develop your features there. -If the maintainer (me, Colin) has access to your git repo, simply -request that your branch be merged into the relevant release candidate -branch via the mailing list. +If the maintainer (me, Colin) has access to your git repo, use the +mailing list to request that your branch be merged into the relevant +release candidate branch. -Otherwise submit a patch against the release candidate branch. +If requesting a merge is infeasible because your git repository is +private or local to your machine, you may submit a patch against the +relevant release candidate branch via the mailing list. -- cgit v1.2.3 From 1a1de0bb8c18798064d103b70a1c06d20eb3ad05 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 08:48:50 -0500 Subject: moved host assertion inside handler-case --- lib/state.lisp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/state.lisp b/lib/state.lisp index 7a9a427..5ca5a7b 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -170,10 +170,10 @@ sets the api's *host* variable. If BODY produces no errors, the " (*cache* (read-cache-file)) (*drafts* (read-drafts-file)) (api:*host* (config-host *config*))) - (assert api:*host* () "ol must be configured with a server host.") - (set-term-width) (handler-case (progn + (assert api:*host* () "ol must be configured with a server host.") + (set-term-width) ,@body ;; only if there is no error do we save the local state. (write-drafts-to-disk) -- cgit v1.2.3 From 6dd2563a0f2b848e84f297a0a2296756c65f6246 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 14:22:09 -0500 Subject: made the note while hacking comment more visible --- lib/client.lisp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/client.lisp b/lib/client.lisp index 4aff60d..39d60ec 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -16,10 +16,14 @@ ;; along with this program. If not, see . (in-package :oneliners.cli) -;; >>>>>NOTE WHILE HACKING<<<<<. Each of the functions below that make -;; HTTP requests are meant to be called within the body of a -;; WITH-LOCAL-STATE form. If you are hacking in the REPL, make sure -;; to wrap function calls appropriately. +;;;; >>>>>NOTE WHILE HACKING<<<<<. +;;;; ---------------------------------------------------------------- +;;;; Each of the functions below that make HTTP requests are meant to +;;;; be called within the body of a WITH-LOCAL-STATE form. If you are +;;;; hacking in the REPL, make sure to wrap function calls +;;;; appropriately. +;;;; ---------------------------------------------------------------- + ;;; GETTING ONELINERS & DISPLAYING ONELINERS -- cgit v1.2.3 From 3c8b1804a7e520f465ced563bbf9b416b4abb8ab Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 19:00:54 -0500 Subject: added EDITOR CONFIGURATION help topic --- app/app.lisp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/app.lisp b/app/app.lisp index 3277521..703fd77 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -197,6 +197,9 @@ export EDITOR=/usr/bin/zile (text :contents "Usage: ol whois ") (text :contents " ") (text :contents "Print information about a contributor.")) + (group (:header "EDITOR CONFIGURATION" :hidden t) + (text :contents "Some commands use a system editor to edit long blocks of text. To configure this editor, please set the EDITOR environment variable.") + (text :contents "E.g. export EDITOR=/usr/bin/nano")) (group (:header "HELP MENU") (text :contents "Usage: ol help [SECTION]") (text :contents " ") @@ -224,7 +227,8 @@ export EDITOR=/usr/bin/zile "login" "whois" "password" - "signature")))))) + "signature" + "editor")))))) ;;; HELPERS -- cgit v1.2.3 From 08fd723502bb3ee021911c0c9db0f743b575ad68 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 19:06:36 -0500 Subject: Added variables help topic --- app/app.lisp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 703fd77..677eed4 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -198,12 +198,14 @@ export EDITOR=/usr/bin/zile (text :contents " ") (text :contents "Print information about a contributor.")) (group (:header "EDITOR CONFIGURATION" :hidden t) - (text :contents "Some commands use a system editor to edit long blocks of text. To configure this editor, please set the EDITOR environment variable.") - (text :contents "E.g. export EDITOR=/usr/bin/nano")) + (text :contents +configure-your-edtior+)) + (group (:header "VARIABLES IN ONELINERS") + (text :contents +oneliners-variables-help-text+)) (group (:header "HELP MENU") (text :contents "Usage: ol help [SECTION]") (text :contents " ") (text :contents "Print a help menu. With no arguments, prints this help.") + (text :contents " ") (text :contents "Command sections include:") (text :contents (str:join @@ -227,8 +229,9 @@ export EDITOR=/usr/bin/zile "login" "whois" "password" - "signature" - "editor")))))) + "signature")))) + (text :contents " ") + (text :contents "Additional topics include: editor variables"))) ;;; HELPERS -- cgit v1.2.3 From 67c793633bfcd46997155341dd4b1776fb6a6728 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 19:19:24 -0500 Subject: Added help topic explaining icons in printouts --- app/app.lisp | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 677eed4..9b313db 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -68,6 +68,16 @@ export EDITOR=/usr/bin/zile ") +(defparameter +icons-in-printout-docs+ + "In the printout of oneliners, several unicode \"icons\" appear. +Their meaning is as follows: + +- ⚠ : Indicates that the oneliner is flagged. +- 🔒 : Indicates that the oneliner is locked. +- 📋 : Indicates that the oneliner will be copied to the clipboard. + +") + ;;; CLON SYNOPSIS DEFINITION @@ -201,6 +211,8 @@ export EDITOR=/usr/bin/zile (text :contents +configure-your-edtior+)) (group (:header "VARIABLES IN ONELINERS") (text :contents +oneliners-variables-help-text+)) + (group (:header "ICONS IN PRINTOUT") + (text :contents +icons-in-printout-docs+)) (group (:header "HELP MENU") (text :contents "Usage: ol help [SECTION]") (text :contents " ") @@ -212,26 +224,18 @@ export EDITOR=/usr/bin/zile #\newline (tabulate-strings 40 5 - '("search" - "run" - "clip" - "show" - "new" - "edit" - "delete" - "drafts" - "trash" - "publish" - "flag" - "lock" - "redeem" - "invite" - "login" - "whois" - "password" - "signature")))) + '("search" "run" "clip" "show" "new" "edit" + "delete" "drafts" "trash" "publish" "flag" + "lock" "redeem" "invite" "login" "whois" + "password" "signature")))) (text :contents " ") - (text :contents "Additional topics include: editor variables"))) + (text :contents "Additional topics include:") +(text :contents + (str:join + #\newline + (tabulate-strings + 40 5 + '("variables" "editor" "icons")))))) ;;; HELPERS -- cgit v1.2.3 From 130ae266f51f63ac423a65b17749a4d38dda1018 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Mon, 14 Mar 2022 19:36:18 -0500 Subject: Added a --verbose / -v option to RUN --- app/app.lisp | 4 ++++ lib/client.lisp | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 9b313db..eef9b89 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -136,6 +136,9 @@ Their meaning is as follows: :default-value 1 :typespec 'integer :description "How many seconds to wait for standard output before giving up.") + (flag :long-name "verbose" + :short-name "v" + :description "Prints a message indicating the oneliner text that is about to be run prior to execution.") (flag :long-name "draft" :description "Indicates that you wish to run a draft of a oneliner identified by IDENTIFIER.")) (group (:header "CLIPPING ONELINERS" :hidden t) @@ -293,6 +296,7 @@ than the users." (:run (help-and-quit-unless "run" id-or-name) (cli:run-item id-or-name (rest args) + :verbose (getopt :long-name "verbose") :timeout (getopt :long-name "timeout") :draftp (getopt :long-name "draft"))) (:clip diff --git a/lib/client.lisp b/lib/client.lisp index 39d60ec..9f34bb5 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -92,14 +92,14 @@ running the body. If such a oneliner can be found." (defvar *ol-output-timeout* 1) -(defun run-item (ident args &key force-clip (timeout nil timeout-p) draftp) +(defun run-item (ident args &key force-clip (timeout nil timeout-p) draftp verbose) "Runs a oneliner identified by IDENT (if available) with arguments ARGS." (let ((ol (if draftp (fetch-draft ident) (the-oneliner ident)))) (when ol (let ((*ol-output-timeout* (if timeout-p timeout *ol-output-timeout*))) - (bind-vars-and-run-oneliner ol args force-clip))))) + (bind-vars-and-run-oneliner ol args force-clip verbose))))) -(defun bind-vars-and-run-oneliner (ol args &optional force-clip) +(defun bind-vars-and-run-oneliner (ol args &optional force-clip verbose) (let* ((oneliner (oneliner-oneliner ol)) (runstyle (oneliner-runstyle ol)) (pos-args (get-positional-arguments ol)) @@ -120,17 +120,18 @@ running the body. If such a oneliner can be found." do (setf oneliner (str:replace-all var (second bound) oneliner))) - (handle-run-oneliner oneliner (or force-clip (equalp runstyle "manual")))))) + (handle-run-oneliner oneliner (or force-clip (equalp runstyle "manual")) verbose)))) -(defun handle-run-oneliner (ol &optional clip) +(defun handle-run-oneliner (ol &optional clip (verbose t)) (if clip (progn (trivial-clipboard:text ol) (format t "Copied oneliner to clipboard~%")) (progn - (format t "Attempting to run:~%") - (princ ol) - (princ #\newline) - (princ #\newline) + (when verbose + (format t "Attempting to run:~%") + (princ ol) + (princ #\newline) + (princ #\newline)) (run-with-shell ol :shell-name (or (shell) "bash") :await-output-p *ol-output-timeout*)))) ;;; ADDING ONELINERS -- cgit v1.2.3 From fbce85871c6e995ece00e3136cf7dfdeeeff2bb7 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Tue, 15 Mar 2022 15:45:20 -0500 Subject: bugfix: handle user interrupt in new and edit --- app/app.lisp | 194 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 101 insertions(+), 93 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index eef9b89..5139208 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -261,99 +261,105 @@ than the users." (help-topic ,topic) (uiop:quit)))) (make-context) - (a:if-let (arguments (remainder)) - (destructuring-bind (command . args) arguments - (let ((id-or-name - (when args - (or (parse-integer (first args) :junk-allowed t) - (first args))))) - (cli:with-local-state - (ecase (a:make-keyword (string-upcase command)) - (:help - (princ #\newline) - (help-topic (first args))) - (:search - (cond - ;; if there are args, use them as search terms - (args - (cli:search-for-oneliners - args - (getopt :long-name "limit") - (getopt :long-name "not-flagged") - (getopt :long-name "all-flagged") - (getopt :long-name "newest"))) - ;; no args, but a --newest flag, just return newest - ((getopt :long-name "newest") - (cli::newest-oneliners (getopt :long-name "limit"))) - ;; no args, but a --all-falgged - ((getopt :long-name "all-flagged") - (cli::all-flagged-oneliners (getopt :long-name "limit"))) - ;; otherwise, print help for search - (t - (help-topic "search") - (uiop:quit)))) - - (:run - (help-and-quit-unless "run" id-or-name) - (cli:run-item id-or-name (rest args) - :verbose (getopt :long-name "verbose") - :timeout (getopt :long-name "timeout") - :draftp (getopt :long-name "draft"))) - (:clip - (help-and-quit-unless "clip" id-or-name) - (cli:run-item id-or-name (rest args) - :force-clip t - :draftp (getopt :long-name "draft"))) - (:show - (help-and-quit-unless "show" id-or-name) - (cli:print-item-explanation id-or-name)) - (:new - (cli:add-new-oneliner)) - (:edit - (help-and-quit-unless "edit" id-or-name) - (cli:edit-item id-or-name (getopt :long-name "redraft"))) - (:delete - (help-and-quit-unless "delete" id-or-name) - (cli::delete-item id-or-name)) - (:publish - (help-and-quit-unless "publish" id-or-name) - (cli::publish-draft id-or-name)) - (:trash - (help-and-quit-unless "trash" id-or-name) - (cli::drop-draft id-or-name)) - (:drafts - (cli::print-drafts)) - (:flag - (help-and-quit-unless "flag" id-or-name) - (cli:flag-item id-or-name)) - (:unflag - (help-and-quit-unless "flag" id-or-name) - (cli:unflag-item id-or-name)) - (:lock - (help-and-quit-unless "lock" id-or-name) - (cli:lock-item id-or-name)) - (:unlock - (help-and-quit-unless "lock" id-or-name) - (cli:unlock-item id-or-name)) - (:redeem - (help-and-quit-unless "redeem" (= 3 (length args))) - (apply 'cli:redeem-invite args)) - (:invite - (cli:request-invite-code)) - (:login - (help-and-quit-unless "login" (= 3 (length args))) - (apply 'cli:login args)) - (:logout - (cli:revoke-access)) - (:password - (help-and-quit-unless "password" (= 3 (length args))) - (apply 'cli:change-pw args)) - (:signature - (cli:change-signature)) - (:whois - (help-and-quit-unless "whois" args) - (cli:show-contributor (first args))))))) - (help-topic "help"))) + (handler-case + (a:if-let (arguments (remainder)) + (destructuring-bind (command . args) arguments + (let ((id-or-name + (when args + (or (parse-integer (first args) :junk-allowed t) + (first args))))) + (cli:with-local-state + (ecase (a:make-keyword (string-upcase command)) + (:help + (princ #\newline) + (help-topic (first args))) + (:search + (cond + ;; if there are args, use them as search terms + (args + (cli:search-for-oneliners + args + (getopt :long-name "limit") + (getopt :long-name "not-flagged") + (getopt :long-name "all-flagged") + (getopt :long-name "newest"))) + ;; no args, but a --newest flag, just return newest + ((getopt :long-name "newest") + (cli::newest-oneliners (getopt :long-name "limit"))) + ;; no args, but a --all-falgged + ((getopt :long-name "all-flagged") + (cli::all-flagged-oneliners (getopt :long-name "limit"))) + ;; otherwise, print help for search + (t + (help-topic "search") + (uiop:quit)))) + + (:run + (help-and-quit-unless "run" id-or-name) + (cli:run-item id-or-name (rest args) + :verbose (getopt :long-name "verbose") + :timeout (getopt :long-name "timeout") + :draftp (getopt :long-name "draft"))) + (:clip + (help-and-quit-unless "clip" id-or-name) + (cli:run-item id-or-name (rest args) + :force-clip t + :draftp (getopt :long-name "draft"))) + (:show + (help-and-quit-unless "show" id-or-name) + (cli:print-item-explanation id-or-name)) + (:new + (cli:add-new-oneliner)) + (:edit + (help-and-quit-unless "edit" id-or-name) + (cli:edit-item id-or-name (getopt :long-name "redraft"))) + (:delete + (help-and-quit-unless "delete" id-or-name) + (cli::delete-item id-or-name)) + (:publish + (help-and-quit-unless "publish" id-or-name) + (cli::publish-draft id-or-name)) + (:trash + (help-and-quit-unless "trash" id-or-name) + (cli::drop-draft id-or-name)) + (:drafts + (cli::print-drafts)) + (:flag + (help-and-quit-unless "flag" id-or-name) + (cli:flag-item id-or-name)) + (:unflag + (help-and-quit-unless "flag" id-or-name) + (cli:unflag-item id-or-name)) + (:lock + (help-and-quit-unless "lock" id-or-name) + (cli:lock-item id-or-name)) + (:unlock + (help-and-quit-unless "lock" id-or-name) + (cli:unlock-item id-or-name)) + (:redeem + (help-and-quit-unless "redeem" (= 3 (length args))) + (apply 'cli:redeem-invite args)) + (:invite + (cli:request-invite-code)) + (:login + (help-and-quit-unless "login" (= 3 (length args))) + (apply 'cli:login args)) + (:logout + (cli:revoke-access)) + (:password + (help-and-quit-unless "password" (= 3 (length args))) + (apply 'cli:change-pw args)) + (:signature + (cli:change-signature)) + (:whois + (help-and-quit-unless "whois" args) + (cli:show-contributor (first args))))))) + (help-topic "help")) + (#+sbcl sb-sys:interactive-interrupt + #+ccl ccl:interrupt-signal-condition + () + (format t "Aborted by User Interrupt.~%") + (uiop:quit)))) (uiop:quit)) (defun help-topic (topic) @@ -361,3 +367,5 @@ than the users." (help :item group) (help))) + + -- cgit v1.2.3 From 3a19876d855ec8d2279293892e24716b28c4b48a Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Tue, 15 Mar 2022 16:29:53 -0500 Subject: added --confirm option. refactored run-item & co to accomodate --- app/app.lisp | 4 ++++ lib/client.lisp | 54 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 5139208..93181a8 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -139,6 +139,9 @@ Their meaning is as follows: (flag :long-name "verbose" :short-name "v" :description "Prints a message indicating the oneliner text that is about to be run prior to execution.") + (flag :long-name "confirm" + :short-name "c" + :description "Prompts the user for confirmation before running. Implies --verbose.") (flag :long-name "draft" :description "Indicates that you wish to run a draft of a oneliner identified by IDENTIFIER.")) (group (:header "CLIPPING ONELINERS" :hidden t) @@ -298,6 +301,7 @@ than the users." (help-and-quit-unless "run" id-or-name) (cli:run-item id-or-name (rest args) :verbose (getopt :long-name "verbose") + :confirm (getopt :long-name "confirm") :timeout (getopt :long-name "timeout") :draftp (getopt :long-name "draft"))) (:clip diff --git a/lib/client.lisp b/lib/client.lisp index 9f34bb5..61c3130 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -92,47 +92,49 @@ running the body. If such a oneliner can be found." (defvar *ol-output-timeout* 1) -(defun run-item (ident args &key force-clip (timeout nil timeout-p) draftp verbose) +(defun run-item (ident args &key force-clip (timeout nil timeout-p) draftp verbose confirm) "Runs a oneliner identified by IDENT (if available) with arguments ARGS." (let ((ol (if draftp (fetch-draft ident) (the-oneliner ident)))) (when ol (let ((*ol-output-timeout* (if timeout-p timeout *ol-output-timeout*))) - (bind-vars-and-run-oneliner ol args force-clip verbose))))) + (bind-vars-and-run-oneliner ol args force-clip verbose confirm))))) -(defun bind-vars-and-run-oneliner (ol args &optional force-clip verbose) +(defun bind-vars-and-run-oneliner (ol args &optional force-clip verbose confirm) (let* ((oneliner (oneliner-oneliner ol)) (runstyle (oneliner-runstyle ol)) (pos-args (get-positional-arguments ol)) (named-args (get-named-arguments ol))) + + (loop for param in pos-args + for arg in args + do (setf oneliner (str:replace-all param arg oneliner))) + ;; substitute named args + + (setf args + (mapcar (lambda (s) (str:split "=" s)) + (nthcdr (length pos-args) args))) + (loop for var in named-args + for bound = (assoc (subseq var 1) args :test #'equal) + when bound + do (setf oneliner + (str:replace-all var (second bound) oneliner))) + (when (or (not (oneliner-isflagged ol)) (y-or-n-p "This oneliner is flagged. Are you sure you want to run it?")) + (when (or verbose confirm) + (format t "Attempting to run:~%") + (princ oneliner) + (princ #\newline)) ;; substitute positional args - (loop for param in pos-args - for arg in args - do (setf oneliner (str:replace-all param arg oneliner))) - ;; substitute named args - (setf args - (mapcar (lambda (s) (str:split "=" s)) - (nthcdr (length pos-args) args))) - (loop for var in named-args - for bound = (assoc (subseq var 1) args :test #'equal) - when bound - do (setf oneliner - (str:replace-all var (second bound) oneliner))) - - (handle-run-oneliner oneliner (or force-clip (equalp runstyle "manual")) verbose)))) - -(defun handle-run-oneliner (ol &optional clip (verbose t)) + (when (or (not confirm) + (y-or-n-p "Proceed?")) + (handle-run-oneliner oneliner (or force-clip (equalp runstyle "manual"))))))) + +(defun handle-run-oneliner (ol &optional clip) (if clip (progn (trivial-clipboard:text ol) (format t "Copied oneliner to clipboard~%")) - (progn - (when verbose - (format t "Attempting to run:~%") - (princ ol) - (princ #\newline) - (princ #\newline)) - (run-with-shell ol :shell-name (or (shell) "bash") :await-output-p *ol-output-timeout*)))) + (run-with-shell ol :shell-name (or (shell) "bash") :await-output-p *ol-output-timeout*))) ;;; ADDING ONELINERS -- cgit v1.2.3 From 2cf6a9883b59fe27fc6cd4888261416a2e929be3 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Tue, 15 Mar 2022 16:33:56 -0500 Subject: fixed odd help printout on `ol help` --- app/app.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.lisp b/app/app.lisp index 93181a8..c9372c8 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -275,7 +275,7 @@ than the users." (ecase (a:make-keyword (string-upcase command)) (:help (princ #\newline) - (help-topic (first args))) + (help-topic (or (first args) "help"))) (:search (cond ;; if there are args, use them as search terms -- cgit v1.2.3 From 33e54da2d7c5a012650322d10477154b6a91ba1e Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 20 Mar 2022 07:51:25 -0500 Subject: [bugfix] login argument length check was incorrect. --- app/app.lisp | 4 ++-- oneliners.cli.asd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index c9372c8..0684824 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -19,7 +19,7 @@ (in-package :oneliners.cli.app) ;;; VERSION -(defparameter +ol-version+ "0.7.0") +(defparameter +ol-version+ "0.7.1") ;;; HELP TEXTS (defparameter +oneliners-variables-help-text+ @@ -346,7 +346,7 @@ than the users." (:invite (cli:request-invite-code)) (:login - (help-and-quit-unless "login" (= 3 (length args))) + (help-and-quit-unless "login" (= 2 (length args))) (apply 'cli:login args)) (:logout (cli:revoke-access)) diff --git a/oneliners.cli.asd b/oneliners.cli.asd index 1bc60c8..af94496 100644 --- a/oneliners.cli.asd +++ b/oneliners.cli.asd @@ -1,5 +1,5 @@ (defsystem "oneliners.cli" - :version "alpha-0.6.1" + :version "alpha-0.7.1" :author "Colin Okay" :license "AGPLv3" :depends-on ("trivial-clipboard" @@ -28,7 +28,7 @@ choice.") (defsystem "oneliners.cli/app" - :version "alpha-0.6.1" + :version "alpha-0.7.1" :author "Colin Okay" :license "AGPLv3" :depends-on ("net.didierverna.clon" -- cgit v1.2.3 From 5e18f28cb59154410d4177f75dfbf24382726a24 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Thu, 24 Mar 2022 17:12:48 -0500 Subject: [bugfix] edited oneliners end up in the local cache --- lib/client.lisp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/client.lisp b/lib/client.lisp index 61c3130..b39e0ac 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -280,8 +280,11 @@ running the body. If such a oneliner can be found." (api:request-with (:body (oneliner-to-json-body local) :content-type "application/json") - (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token)) - ;(merge-oneliners (list new-item)) ;;TODO: this is broken, wait for API update. + (let ((updated + (jonathan:parse + (api:patch--oneliner-entry-edit (oneliner-id ol) :token (api-token))))) + (merge-oneliners (list updated))) + (format t "Edits accepted~%"))))))) ;;TODO: need to sync cache here. -- cgit v1.2.3 From c698e20e1a8d0871662413b004a908f20bdb3960 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Fri, 25 Mar 2022 15:17:50 -0500 Subject: [bugfix] ecase error handling on bad ol command --- app/app.lisp | 175 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 89 insertions(+), 86 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index 0684824..b0f845c 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -272,92 +272,95 @@ than the users." (or (parse-integer (first args) :junk-allowed t) (first args))))) (cli:with-local-state - (ecase (a:make-keyword (string-upcase command)) - (:help - (princ #\newline) - (help-topic (or (first args) "help"))) - (:search - (cond - ;; if there are args, use them as search terms - (args - (cli:search-for-oneliners - args - (getopt :long-name "limit") - (getopt :long-name "not-flagged") - (getopt :long-name "all-flagged") - (getopt :long-name "newest"))) - ;; no args, but a --newest flag, just return newest - ((getopt :long-name "newest") - (cli::newest-oneliners (getopt :long-name "limit"))) - ;; no args, but a --all-falgged - ((getopt :long-name "all-flagged") - (cli::all-flagged-oneliners (getopt :long-name "limit"))) - ;; otherwise, print help for search - (t - (help-topic "search") - (uiop:quit)))) - - (:run - (help-and-quit-unless "run" id-or-name) - (cli:run-item id-or-name (rest args) - :verbose (getopt :long-name "verbose") - :confirm (getopt :long-name "confirm") - :timeout (getopt :long-name "timeout") - :draftp (getopt :long-name "draft"))) - (:clip - (help-and-quit-unless "clip" id-or-name) - (cli:run-item id-or-name (rest args) - :force-clip t - :draftp (getopt :long-name "draft"))) - (:show - (help-and-quit-unless "show" id-or-name) - (cli:print-item-explanation id-or-name)) - (:new - (cli:add-new-oneliner)) - (:edit - (help-and-quit-unless "edit" id-or-name) - (cli:edit-item id-or-name (getopt :long-name "redraft"))) - (:delete - (help-and-quit-unless "delete" id-or-name) - (cli::delete-item id-or-name)) - (:publish - (help-and-quit-unless "publish" id-or-name) - (cli::publish-draft id-or-name)) - (:trash - (help-and-quit-unless "trash" id-or-name) - (cli::drop-draft id-or-name)) - (:drafts - (cli::print-drafts)) - (:flag - (help-and-quit-unless "flag" id-or-name) - (cli:flag-item id-or-name)) - (:unflag - (help-and-quit-unless "flag" id-or-name) - (cli:unflag-item id-or-name)) - (:lock - (help-and-quit-unless "lock" id-or-name) - (cli:lock-item id-or-name)) - (:unlock - (help-and-quit-unless "lock" id-or-name) - (cli:unlock-item id-or-name)) - (:redeem - (help-and-quit-unless "redeem" (= 3 (length args))) - (apply 'cli:redeem-invite args)) - (:invite - (cli:request-invite-code)) - (:login - (help-and-quit-unless "login" (= 2 (length args))) - (apply 'cli:login args)) - (:logout - (cli:revoke-access)) - (:password - (help-and-quit-unless "password" (= 3 (length args))) - (apply 'cli:change-pw args)) - (:signature - (cli:change-signature)) - (:whois - (help-and-quit-unless "whois" args) - (cli:show-contributor (first args))))))) + (handler-case + (ecase (a:make-keyword (string-upcase command)) + (:help + (princ #\newline) + (help-topic (or (first args) "help"))) + (:search + (cond + ;; if there are args, use them as search terms + (args + (cli:search-for-oneliners + args + (getopt :long-name "limit") + (getopt :long-name "not-flagged") + (getopt :long-name "all-flagged") + (getopt :long-name "newest"))) + ;; no args, but a --newest flag, just return newest + ((getopt :long-name "newest") + (cli::newest-oneliners (getopt :long-name "limit"))) + ;; no args, but a --all-falgged + ((getopt :long-name "all-flagged") + (cli::all-flagged-oneliners (getopt :long-name "limit"))) + ;; otherwise, print help for search + (t + (help-topic "search") + (uiop:quit)))) + + (:run + (help-and-quit-unless "run" id-or-name) + (cli:run-item id-or-name (rest args) + :verbose (getopt :long-name "verbose") + :confirm (getopt :long-name "confirm") + :timeout (getopt :long-name "timeout") + :draftp (getopt :long-name "draft"))) + (:clip + (help-and-quit-unless "clip" id-or-name) + (cli:run-item id-or-name (rest args) + :force-clip t + :draftp (getopt :long-name "draft"))) + (:show + (help-and-quit-unless "show" id-or-name) + (cli:print-item-explanation id-or-name)) + (:new + (cli:add-new-oneliner)) + (:edit + (help-and-quit-unless "edit" id-or-name) + (cli:edit-item id-or-name (getopt :long-name "redraft"))) + (:delete + (help-and-quit-unless "delete" id-or-name) + (cli::delete-item id-or-name)) + (:publish + (help-and-quit-unless "publish" id-or-name) + (cli::publish-draft id-or-name)) + (:trash + (help-and-quit-unless "trash" id-or-name) + (cli::drop-draft id-or-name)) + (:drafts + (cli::print-drafts)) + (:flag + (help-and-quit-unless "flag" id-or-name) + (cli:flag-item id-or-name)) + (:unflag + (help-and-quit-unless "flag" id-or-name) + (cli:unflag-item id-or-name)) + (:lock + (help-and-quit-unless "lock" id-or-name) + (cli:lock-item id-or-name)) + (:unlock + (help-and-quit-unless "lock" id-or-name) + (cli:unlock-item id-or-name)) + (:redeem + (help-and-quit-unless "redeem" (= 3 (length args))) + (apply 'cli:redeem-invite args)) + (:invite + (cli:request-invite-code)) + (:login + (help-and-quit-unless "login" (= 2 (length args))) + (apply 'cli:login args)) + (:logout + (cli:revoke-access)) + (:password + (help-and-quit-unless "password" (= 3 (length args))) + (apply 'cli:change-pw args)) + (:signature + (cli:change-signature)) + (:whois + (help-and-quit-unless "whois" args) + (cli:show-contributor (first args)))) + (#+sbcl sb-kernel:case-failure () + (help-topic "help")))))) (help-topic "help")) (#+sbcl sb-sys:interactive-interrupt #+ccl ccl:interrupt-signal-condition -- cgit v1.2.3 From 4d65d894419c097aa366bc8798e53d7934ea838e Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Fri, 25 Mar 2022 15:29:00 -0500 Subject: [add] option to show the client version --- app/app.lisp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/app.lisp b/app/app.lisp index b0f845c..784d887 100644 --- a/app/app.lisp +++ b/app/app.lisp @@ -215,10 +215,14 @@ Their meaning is as follows: (text :contents "Print information about a contributor.")) (group (:header "EDITOR CONFIGURATION" :hidden t) (text :contents +configure-your-edtior+)) - (group (:header "VARIABLES IN ONELINERS") + (group (:header "VARIABLES IN ONELINERS" :hidden t) (text :contents +oneliners-variables-help-text+)) - (group (:header "ICONS IN PRINTOUT") + (group (:header "ICONS IN PRINTOUT" :hidden t) (text :contents +icons-in-printout-docs+)) + (group (:header "VERSION" :hidden t) + (text :contents "Usage: ol version") + (text :contents " ") + (text :contents "Prints the version of this client.")) (group (:header "HELP MENU") (text :contents "Usage: ol help [SECTION]") (text :contents " ") @@ -233,10 +237,10 @@ Their meaning is as follows: '("search" "run" "clip" "show" "new" "edit" "delete" "drafts" "trash" "publish" "flag" "lock" "redeem" "invite" "login" "whois" - "password" "signature")))) + "password" "signature" "version")))) (text :contents " ") (text :contents "Additional topics include:") -(text :contents + (text :contents (str:join #\newline (tabulate-strings @@ -277,6 +281,8 @@ than the users." (:help (princ #\newline) (help-topic (or (first args) "help"))) + (:version + (format t "ol v~a~%" +ol-version+ )) (:search (cond ;; if there are args, use them as search terms -- cgit v1.2.3 From e95a60bce9d86ca3b2a7cdf41a0c4df3fc5cb3fd Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Fri, 25 Mar 2022 15:39:27 -0500 Subject: [add] specifically handling dexador's http errors on client --- lib/state.lisp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/state.lisp b/lib/state.lisp index 5ca5a7b..49cd5d8 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -179,5 +179,9 @@ sets the api's *host* variable. If BODY produces no errors, the " (write-drafts-to-disk) (write-cache-to-disk) (write-config-to-disk)) + (dexador.error:http-request-failed (e) + (format *error-output* "Operation failed. The server at ~a returned with ~a~%" + api:*host* + (dexador.error:response-status e))) (error (e) (format *error-output* "~a~%" e))))) -- cgit v1.2.3 From fabc8a7b9027ff9c312ed45591e75dfd67c21f05 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Fri, 25 Mar 2022 15:51:26 -0500 Subject: [add] printing creation date in oneliner printouts --- lib/oneliner.lisp | 5 +++-- lib/util.lisp | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/oneliner.lisp b/lib/oneliner.lisp index 668a82c..8386fa9 100644 --- a/lib/oneliner.lisp +++ b/lib/oneliner.lisp @@ -75,7 +75,7 @@ (let* ((title-line-format-str (concatenate 'string "~" (prin1-to-string *term-width*) "<[~a]~;~a~;~a~>~%")) (tags-line-format-string - (concatenate 'string "~" (prin1-to-string *term-width*) "<~a~;by ~a~>~%"))) + (concatenate 'string "~" (prin1-to-string *term-width*) "<~a~;by ~a ~a~>~%"))) (loop repeat *term-width* do (princ #\_)) (terpri) (format t title-line-format-str @@ -87,7 +87,8 @@ (equalp "manual" (oneliner-runstyle ol)))) (format t tags-line-format-string (format nil "tags: ~{~a~^ ~}" (oneliner-tags ol)) - (oneliner-createdby ol)) + (oneliner-createdby ol) + (datestring-of-universal-time (oneliner-createdat ol))) (loop for x from 0 to (length (oneliner-brief ol)) by *term-width* do (format t "~a~%" diff --git a/lib/util.lisp b/lib/util.lisp index 4b827f1..441b2e0 100644 --- a/lib/util.lisp +++ b/lib/util.lisp @@ -71,6 +71,12 @@ determined by EXECUTABLE-ON-SYSTEM-P." (if what "true" "false")) +(defun datestring-of-universal-time (ut) + (multiple-value-bind + (sec min hour day month year) (decode-universal-time ut) + (declare (ignore sec min hour)) + (format nil "~a-~2,'0d-~2,'0d" year month day))) + (defmacro defplist (name &rest slots) (let* ((slots-names (loop for slot in slots @@ -92,3 +98,4 @@ determined by EXECUTABLE-ON-SYSTEM-P." `(progn ,make-name-defun ,@slot-defuns))) + -- cgit v1.2.3