abrochard / kubel

Emacs extension for controlling Kubernetes with limited permissions
GNU General Public License v3.0
259 stars 41 forks source link

[Suggested change] mark/unmark resources to not call kubectl and refresh #98

Open sawwheet opened 1 year ago

sawwheet commented 1 year ago

Hey! Great work on this package, its simpler than kubernetes-el and works with all resources which is a must for me.

One thing I don't like is that marking and unmarking calls the kubel command, causing a full refresh. This is very slow when marking multiple pods.

I hacked together a simple solution:


    (defun cq/kubel-mark-item ()
        (interactive)
        (let ((item (kubel--get-resource-under-cursor)))
            (unless (-contains? kubel--selected-items item)
                (progn
                    (push item kubel--selected-items)
                    (forward-line 1)
                    (highlight-regexp item)))))

    (defun cq/kubel-unmark-item ()
        (interactive)
        (let ((item (kubel--get-resource-under-cursor)))
            (when (-contains? kubel--selected-items item)
                (progn
                    (setq kubel--selected-items (delete item kubel--selected-items))
                    (forward-line 1)
                    (unhighlight-regexp item)))))

    (defun cq/kubel-unmark-all-items ()
        (interactive)
        (dolist (item kubel--selected-items)
            (unhighlight-regexp item)
            (setq kubel--selected-items (delete item kubel--selected-items))))

    (defun cq/kubel-delete-marked-items ()
        (interactive)
        (save-excursion
            (goto-char (point-min))
            (while (not (eobp))
                (let ((current-item (kubel--get-resource-under-cursor)))
                    (if (-contains-p kubel--selected-items current-item)
                            (progn (message "Deleting: %s" current-item)
                                         (tabulated-list-delete-entry))
                        (forward-line 1))))))

    (defun cq/kubel--propertize-status (status)
        "Return the status in proper font color.

STATUS is the pod status string."
        (let ((pair (cdr (assoc status kubel--status-colors)))
                    (match (or (equal kubel-resource-filter "") (string-match-p kubel-resource-filter status))))
            ;; (selected (and (kubel--items-selected-p) (-contains? kubel--selected-items status))))
            (cond (pair (propertize status 'font-lock-face `(:foreground ,pair)))
                        ;; (selected (propertize (concat "*" status) 'face 'dired-marked))
                        ((not match) (propertize status 'font-lock-face '(:foreground "darkgrey")))
                        (t status))))

    (advice-add 'kubel--propertize-status :override 'cq/kubel--propertize-status)
    (advice-add 'kubel-mark-item :override 'cq/kubel-mark-item)
    (advice-add 'kubel-unmark-item :override 'cq/kubel-unmark)
    (advice-add 'kubel-unmark-all :override 'cq/kubel-unmark-all-items)

         (add-hook 'kubel-mode-hook (lambda ()
                                               (dolist (item kubel--selected-items)
                                            (highlight-regexp item))))

Which basically uses highlighting as the mark indicator, which is instant and does not require calling propertize status and refreshing kubel.

the delete-marked-items function is just something i wanted for easier visibility of my k8s resources.

I definitley did not look through the entire package, so im not sure if there is some other reason the current implementation

abrochard commented 1 year ago

Thank you for sharing! This could definitely be useful. (When I have time) I will look into why marking/unmarking does a refresh and if possible, see if I can include some of your suggestions.

Uthar commented 1 year ago

I also had this problem

I patched it like this:

@@ -1129,20 +1130,24 @@ 
   "Mark or unmark the item under cursor."
   (interactive)
   (let ((item (kubel--get-resource-under-cursor)))
     (unless (-contains? kubel--selected-items item)
       (progn
         (push item kubel--selected-items)
+        (setf (aref (tabulated-list-get-entry) 0)
+              (kubel--propertize-status item))
         (forward-line 1)
-        (kubel)))))
+        (tabulated-list-print t t)))))

 (defun kubel-unmark-item ()
   "Unmark the item under cursor."
   (interactive)
   (let ((item (kubel--get-resource-under-cursor)))
     (when (-contains? kubel--selected-items item)
       (progn
         (setq kubel--selected-items (delete item kubel--selected-items))
-        (kubel)))))
+        (setf (aref (tabulated-list-get-entry) 0)
+              (substring-no-properties item))
+        (tabulated-list-print t t)))))

 (defun kubel-mark-all ()
   "Mark all items."
@@ -1153,13 +1158,19 @@ 
     (while (not (eobp))
       (push (kubel--get-resource-under-cursor) kubel--selected-items)
       (forward-line 1)))
-  (kubel))
+  (dolist (entry tabulated-list-entries)
+    (cl-destructuring-bind (id descs) entry
+      (setf (aref descs 0) (kubel--propertize-status (aref descs 0)))))
+  (tabulated-list-print t t))

 (defun kubel-unmark-all ()
   "Unmark all items."
   (interactive)
   (setq kubel--selected-items '())
-  (kubel))
+  (dolist (entry tabulated-list-entries)
+    (cl-destructuring-bind (id descs) entry
+      (setf (aref descs 0) (string-remove-prefix "*" (substring-no-properties (aref descs 0))))))
+  (tabulated-list-print t t))

 ;; popups

I thought that maybe setting tabulated-list-entries to a function and only caching the entrylist might be better. (i.e. to separate the kubectl invocation from the generating of tabulated entries)

Hopefully this helps