]> git.eshelyaron.com Git - emacs.git/commitdiff
New command 'kubed-explain'
authorEshel Yaron <me@eshelyaron.com>
Sat, 27 Jul 2024 09:00:06 +0000 (11:00 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sat, 27 Jul 2024 12:03:01 +0000 (14:03 +0200)
lisp/net/kubed-transient.el
lisp/net/kubed.el

index b7f23afbb62341e088fdbdba090a78dc91128c88..d43594eb33d57067494a2b3a71d9c24496f7bd6d 100644 (file)
@@ -47,6 +47,8 @@
    ("r" "Run" kubed-transient-run)
    ("a" "Attach" kubed-transient-attach)
    ("d" "Diff" kubed-transient-diff)
+   ("e" "Exec" kubed-transient-exec)
+   ("E" "Explain" kubed-explain)
    ("!" "Command line" kubed-kubectl-command)])
 
 ;;;###autoload
index 538169da4c84446fb10679248942c7b8a841c956..356061e0af6d3277efbcb6e9545e441befae774b 100644 (file)
@@ -118,6 +118,7 @@ interacting with Kubernetes RESOURCEs:
   mode, `kubed-RESOURCEs-mode', which is also defined by this macro.
 - `kubed-update-RESROURCEs': update and repopulate RESOURCEs list.
 - `kubed-create-RESROURCE': create a RESOURCE from a YAML or a JSON file.
+- `kubed-explain-RESROURCEs': show buffer with help about RESOURCEs.
 
 This macro also defines a prefix keymap, `kubed-RESOURCE-prefix-map',
 with bindings for the above commands.
@@ -194,6 +195,7 @@ Other keyword arguments that go between PROPERTIES and COMMANDS are:
         (affx-fun (intern (format "kubed-%Ss-affixation" resource)))
         (updt-cmd (intern (format "kubed-update-%Ss"        resource)))
         (list-cmd (intern (format "kubed-list-%Ss"          resource)))
+        (expl-cmd (intern (format "kubed-explain-%Ss"       resource)))
         (mark-cmd (intern (format "kubed-%Ss-mark-for-deletion" resource)))
         (umrk-cmd (intern (format "kubed-%Ss-unmark"        resource)))
         (exec-cmd (intern (format "kubed-%Ss-execute"       resource)))
@@ -841,6 +843,11 @@ Optional argument DEFAULT is the minibuffer default argument." resource)
          (,sure-fun)
          (pop-to-buffer (,buff-fun ,list-var)))
 
+       (defun ,expl-cmd ()
+         ,(format "Show help buffer with explanation about Kubernetes %Ss." resource)
+         (interactive)
+         (kubed-explain ,(symbol-name plrl-var)))
+
        (defvar-keymap ,map-name
          :doc ,(format "Prefix keymap for Kubed %s commands."
                        (symbol-name resource))
@@ -851,6 +858,7 @@ Optional argument DEFAULT is the minibuffer default argument." resource)
          "d" #',dlt-name
          "g" #',dsp-name
          "u" #',updt-cmd
+         "E" #',expl-cmd
          ,@prf-keys))))
 
 (defvar tramp-kubernetes-namespace)
@@ -1227,7 +1235,7 @@ completion candidates."
 
 Optional argument NAMESPACE is the namespace to use for the created pod,
 defaulting to the current namespace.  PORT is the port to expose,
-defaulting to none.  If ATTACH is non-nil, then attach to the craeted
+defaulting to none.  If ATTACH is non-nil, then attach to the created
 image with a `comint-mode' buffer, and pop to that buffer.  Non-nil
 STDIN says to keep the standard input of the container open; non-nil TTY
 says to allocate a TTY for the container; and non-nil RM says to remove
@@ -1581,6 +1589,92 @@ with \\[universal-argument] \\[universal-argument]; and TTY is t unless\
            (list "--" command)
            args))))
 
+(with-eval-after-load 'help-mode
+  ;; Wait for `help-mode' to define `help-xref'.  It's always loaded by
+  ;; the time we actually need it in `kubed-explain'.
+  (define-button-type 'kubed-explain
+    :supertype 'help-xref
+    'help-function 'kubed-explain
+    'help-echo "mouse-2, RET: explain"))
+
+(defvar kubed-resource-field-history nil
+  "Minibuffer history for `kubed-read-resource-field'.")
+
+(defun kubed-read-resource-field (prompt &optional default)
+  "Prompt with PROMPT for Kubernetes resource type or field name.
+
+Optional argument DEFAULT is the minibuffer default argument."
+  (completing-read
+   (format-prompt prompt default)
+   (lambda (s p a)
+     (unless (eq a 'metadata)
+       (let ((start 0))
+         (while (string-match "\\." s start)
+           (setq start (match-end 0)))
+         (if (eq (car-safe a) 'boundaries)
+             `(boundaries ,start . ,(and (string-match "\\." (cdr a))
+                                         (match-beginning 0)))
+           (let ((table
+                  (if (zerop start)
+                      ;; Complete resource type.
+                      (mapcar
+                       (lambda (line)
+                         (car (split-string line)))
+                       (process-lines
+                        kubed-kubectl-program
+                        "api-resources" "--no-headers"))
+                    ;; Complete (sub-)field name.
+                    (with-temp-buffer
+                      (call-process
+                       kubed-kubectl-program nil t nil
+                       "explain" (substring s 0 start))
+                      (goto-char (point-min))
+                      (let ((res nil))
+                        (while (re-search-forward
+                                (rx line-start (+ " ") (group-n 1 (* alnum)) "\t")
+                                nil t)
+                          (push (match-string 1) res))
+                        res)))))
+             (if a (complete-with-action a table (substring s start) p)
+               ;; `try-completion'.
+               (let ((comp (complete-with-action a table (substring s start) p)))
+                 (if (stringp comp) (concat (substring s 0 start) comp) comp))))))))
+   nil 'confirm nil 'kubed-resource-field-history))
+
+;;;###autoload
+(defun kubed-explain (field)
+  "Show help buffer with explanation about Kubernetes resource FIELD."
+  (interactive
+   (list (kubed-read-resource-field "Explain type or field")))
+  (let ((help-buffer-under-preparation t))
+    (help-setup-xref (list #'kubed-explain field)
+                     (called-interactively-p 'interactive))
+    (with-help-window (help-buffer)
+      (with-current-buffer (help-buffer)
+        (insert (substitute-quotes
+                 (concat "`kubed explain " field "' says:\n\n")))
+        (save-excursion
+          ;; Add button that goes to parent.
+          (goto-char (point-min))
+          (when (re-search-forward (rx " "
+                                       (group-n 1 (* graph))
+                                       "."
+                                       (+ (not (any ?.)))
+                                       line-end)
+                                   nil t)
+            (help-xref-button 1 'kubed-explain (match-string 1))))
+
+        (call-process kubed-kubectl-program nil t nil "explain" field)
+        ;; Buttonize references to other fields.
+        (goto-char (point-min))
+        (while (re-search-forward (rx line-start
+                                      (+ " ")
+                                      (group-n 1 (* alnum))
+                                      "\t")
+                                  nil t)
+          (help-xref-button 1 'kubed-explain
+                            (concat field "." (match-string 1))))))))
+
 (defvar kubed-kubectl-command-history nil
   "Minibuffer history for `kubed-kubectl-command'.")
 
@@ -1622,6 +1716,7 @@ Interactively, prompt for COMMAND with completion for `kubectl' arguments."
   "+" #'kubed-create
   "R" #'kubed-run
   "D" #'kubed-diff
+  "E" #'kubed-explain
   "!" #'kubed-kubectl-command)
 
 (provide 'kubed)