From 57bae08a8b9accc1d4bfb7165080e7d5a5ef2a30 Mon Sep 17 00:00:00 2001
From: Colin Okay <okay@toyful.space>
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 <http://www.gnu.org/licenses/>.
 (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