From: Eshel Yaron Date: Sat, 27 Jul 2024 09:00:06 +0000 (+0200) Subject: New command 'kubed-explain' X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=9816d357e6399b3b74dc62fde3b9ee90064fd203;p=emacs.git New command 'kubed-explain' --- diff --git a/lisp/net/kubed-transient.el b/lisp/net/kubed-transient.el index b7f23afbb62..d43594eb33d 100644 --- a/lisp/net/kubed-transient.el +++ b/lisp/net/kubed-transient.el @@ -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 diff --git a/lisp/net/kubed.el b/lisp/net/kubed.el index 538169da4c8..356061e0af6 100644 --- a/lisp/net/kubed.el +++ b/lisp/net/kubed.el @@ -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)