diff options
-rw-r--r-- | build-app.lisp | 2 | ||||
-rw-r--r-- | lib/client.lisp | 50 | ||||
-rw-r--r-- | lib/oneliner.lisp | 17 | ||||
-rw-r--r-- | lib/state.lisp | 68 | ||||
-rw-r--r-- | lib/util.lisp | 12 | ||||
-rw-r--r-- | oneliners.cli.asd | 27 |
6 files changed, 119 insertions, 57 deletions
diff --git a/build-app.lisp b/build-app.lisp index 2adc30f..2a6abab 100644 --- a/build-app.lisp +++ b/build-app.lisp @@ -17,7 +17,7 @@ ;; along with this program. If not, see <http://www.gnu.org/licenses/>. -(asdf:load-system "oneliners.cli") +(asdf:load-system "oneliners.cli/app") (in-package :oneliners.cli.app) ;;; DUMP EXECUTABLE (dump "ol" main) ; from clon diff --git a/lib/client.lisp b/lib/client.lisp index f49201a..0c4c362 100644 --- a/lib/client.lisp +++ b/lib/client.lisp @@ -1,4 +1,4 @@ -;;;; main.lisp -- oneliners.cli entrypoint +;;;; main.lisp -- client actions ;; Copyright (C) 2022 Colin Okay @@ -16,7 +16,32 @@ ;; along with this program. If not, see <http://www.gnu.org/licenses/>. (in-package :oneliners.cli) -;;; CONFIG AND RESULTS FILE LOCATIONS +;;; SEARCHING FOR 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.") + (with-local-state () + (api:get--oneliners :tags (str:join "," terms) + :limit limit + :notflagged (true-or-false not-flagged-p) + :newest (true-or-false newestp) + :onlyflagged (true-or-false all-flagged-p)))) + +(defun search-for-oneliners (terms limit not-flagged-p all-flagged-p newestp) + + (set-term-width) + (ensure-config) + (let ((response + (api:request-with + (:host (host)) + (api:get--oneliners :tags (str:join "," terms) + :limit limit + :notflagged (if not-flagged-p "true" "false") + :newest (if newestp "true" "false") + :onlyflagged (if all-flagged-p "true" "false"))))) + (cache-and-print-search-response response))) + + (defvar *ol-output-timeout* 1) @@ -175,6 +200,13 @@ and, failing that, try to fetch from configured server." explanation))) (terpri)))) +(defun tags-from-oneliner (string) + "Splits a string using consequitive whitespace as a separator, +returning a set of tags" + (remove-duplicates + (remove-if-not #'executable-on-system-p (ppcre:split " +" string)) + :test #'equal)) + (defun add-new-oneliner () (ensure-config) @@ -433,19 +465,7 @@ and, failing that, try to fetch from configured server." (api:get--oneliners-all-flagged)))) (cache-and-print-search-response response)))) -(defun search-for-oneliners (terms limit not-flagged-p all-flagged-p newestp) - (assert (loop for term in terms never (find #\, term) )) - (set-term-width) - (ensure-config) - (let ((response - (api:request-with - (:host (host)) - (api:get--oneliners :tags (str:join "," terms) - :limit limit - :notflagged (if not-flagged-p "true" "false") - :newest (if newestp "true" "false") - :onlyflagged (if all-flagged-p "true" "false"))))) - (cache-and-print-search-response response))) + ;;; RUNNING THINGS IN THE SHELL. diff --git a/lib/oneliner.lisp b/lib/oneliner.lisp index e96ec22..48c78f6 100644 --- a/lib/oneliner.lisp +++ b/lib/oneliner.lisp @@ -1,4 +1,4 @@ -;;;; oneliner.lisp -- holds a local representation of onelienrs. +;;;; oneliner.lisp -- defines a oneliner structure and functions for using it ;; Copyright (C) 2022 Colin Okay @@ -32,8 +32,9 @@ isflagged islocked) +;;; SUPPLEMENTARY GETTERS -(defun collect-positional-arguments (ol) +(defun get-positional-arguments (ol) "Collects the names of all positional arguments in the oneliner, prefix included." (remove-duplicates (sort @@ -41,22 +42,12 @@ #'string<) :test #'equal)) -(defun collect-named-arguments (ol) +(defun get-named-arguments (ol) "Collects the names of all named arguments in the oneliner, prefix included" (remove-duplicates (ppcre:all-matches-as-strings "#[A-Za-z][A-Za-z0-9_]*" (oneliner-oneliner ol)) :test #'equal)) -(defun tags-from-oneliner (string) - "Splits a string using consequitive whitespace as a separator, -returning a set of tags" - (remove-duplicates - (remove-if-not #'executable-on-system-p (ppcre:split " +" string)) - :test #'equal)) - - - - ;;; VALIDATION OF ONELINER SLOT VALUES (defun valid-oneliner-string-p (string) diff --git a/lib/state.lisp b/lib/state.lisp index b0be21c..5bab3ed 100644 --- a/lib/state.lisp +++ b/lib/state.lisp @@ -15,7 +15,6 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see <http://www.gnu.org/licenses/>. - (in-package :oneliners.cli) ;;; Config Struct @@ -32,6 +31,36 @@ (defvar *cache* nil "Holds cached oneliners as a list.") +;;; LOADING AND SAVING STATE + +(defun config-file () + "Returns the pahtname holding the location of the config file." + (merge-pathnames ".config/oneliners.config" (user-homedir-pathname))) + +(defun cached-oneliners-file () + "Returns the pathname holding the location of the cache." + (merge-pathnames ".cache/oneliners.cache" (user-homedir-pathname))) + +(defun wipe-cache () + "Deletes the cache, if present." + (uiop:delete-file-if-exists (cached-oneliners-file))) + +(defun write-config-to-disk () + (print-to-file *config* (config-file))) + +(defun write-cache-to-disk () + (print-to-file *cache* (cached-oneliners-file))) + +(defun read-config-file () + "Read a configuration from the location returned by CONFIG-FILE. NIL +if there is no such file" + (read-from-file (config-file))) + +(defun read-cache-file () + "Read the cache from the location returned by +CACHED-ONELINERS-FILE. NIL if there is no such file." + (read-from-file (cached-oneliners-file))) + ;;; GETTING AND SETTING STATE, DYNAMICALLY BOUND (defun merge-oneliners (new) @@ -56,23 +85,20 @@ (string #'oneliner-name)) :test #'equal)) -;;; LOADING AND SAVING STATE - -(defun config-file () - "Returns the pahtname holding the location of the config file." - (merge-pathnames ".config/oneliners.config" (user-homedir-pathname))) - -(defun cached-oneliners-file () - "Returns the pathname holding the location of the cache." - (merge-pathnames ".cache/oneliners.cache" (user-homedir-pathname))) - -(defun wipe-cache () - "Deletes the cache, if present." - (uiop:delete-file-if-exists (cached-oneliners-file))) - -(defun write-config-to-disk () - (print-to-file *config* (config-file))) - -(defun write-cache-to-disk () - (print-to-file *cache* (cached-oneliners-file))) - +;;; STATE LOADING MACRO + +(defmacro with-local-state (&body body) + "Binds the *config* and *cache* dynamic variables from disk, and +sets the api's *host* variable. If BODY produces no errors, the " + `(let* ((*config* (read-config-file)) + (*cache* (read-cache-file)) + (api::*host* (config-host *config*))) + (assert *host* () "ol must be configured with a server host.") + (handler-case + (progn + ,@body + ;; only if there is no error do we save the local state. + (write-cache-to-disk) + (write-config-to-disk))) + (error (e) + (format *error-output* "~a~%" e)))) diff --git a/lib/util.lisp b/lib/util.lisp index 31e1984..2a6d456 100644 --- a/lib/util.lisp +++ b/lib/util.lisp @@ -1,4 +1,4 @@ -;;;; util.lisp +;;;; util.lisp -- bits and bobs ;; Copyright (C) 2022 Colin Okay @@ -51,3 +51,13 @@ the directories that appear in the value of that variable." (ensure-directories-exist pathname) (with-open-file (out pathname :direction :output :if-exists if-exists) (print printable-object out))) + +(defun read-from-file (path) + "Reads one form from the file at PATHNAME, if that file exists. Returns NIL if not." + (when (uiop:file-exists-p path) + (with-open-file (input path) + (read input)))) + +(defun true-or-false (what) + "Returns the strings \"true\" or \"false\" depending on whehter or not WHAT is null" + (if what "true" "false")) diff --git a/oneliners.cli.asd b/oneliners.cli.asd index 688d371..a0d5fb2 100644 --- a/oneliners.cli.asd +++ b/oneliners.cli.asd @@ -13,17 +13,32 @@ :components ((:module "lib" :components ((:file "package") - (:file "running") - (:file "term") - (:file "prompt") + + (:file "running") ; oneliners.cli.running package + (:file "term") ; oneliners.cli.term package + (:file "prompt") ; oneliners.cli.prompt package + + ;; oneliners.cli package (:file "util") (:file "oneliner") (:file "state") - (:file "client"))) - (:module "app" + (:file "client")))) + :description "A Command-Line tool for fetching, running, creating, + and updating unix oneliners from a oneliners wiki server of your + choice.") + +(defsystem "oneliners.cli/app" + :version "alpha-0.6.0" + :author "Colin Okay" + :license "AGPLv3" + :depends-on ("net.didierverna.clon" + "oneliners.cli") + :components ((:module "app" :components ((:file "package") (:file "app")))) - :description "") + :description "A Command-Line tool for fetching, running, creating, + and updating unix oneliners from a oneliners wiki server of your + choice.") |