diff options
Diffstat (limited to 'elisp/cmk.el')
-rw-r--r-- | elisp/cmk.el | 108 |
1 files changed, 84 insertions, 24 deletions
diff --git a/elisp/cmk.el b/elisp/cmk.el index 61b71df..6023cf0 100644 --- a/elisp/cmk.el +++ b/elisp/cmk.el @@ -21,6 +21,8 @@ (require 'subr-x) (require 'cl-lib) (require 'dash) +(require 'company) +(require 'csv-mode) (defun cmk-state-coloring (state) "Font color for numeric STATE input as string." @@ -67,41 +69,49 @@ Default is \"%Y-%m-%d %H:%M\"." " "))) (defconst cmk-problem-col-spec - '(("STATE" 5 t :column "service_state" :parser cmk-state-coloring ) + `(("STATE" 5 t :column "service_state" :parser cmk-state-coloring ) ("Host" 9 t :column "host_name") ("Service" 20 t :column "service_description") - ("Since" 16 nil :column "service_last_state_change" :parser cmk-timestamp-to-date) + ("Since" 16 ,(lambda (a b) + (time-less-p + (encode-time (parse-time-string (elt (cadr a) 3))) + (encode-time (parse-time-string (elt (cadr b) 3))))) + :column "service_last_state_change" :parser cmk-timestamp-to-date) ("Check output" 18 t :column "service_plugin_output" :parser cmk-purge-bangs))) (defconst cmk-log-col-spec - '(("host_state" 5 t :column "host_state" :parser cmk-state-coloring) + '(;("host_state" 5 t :column "host_state" :parser cmk-state-coloring) + ("STATE" 5 t :column "log_state" :parser cmk-state-coloring) + ;; ("lsttype" 8 t :column "log_state_type") ("Host" 9 t :column "host_name") ("Service" 12 t :column "service_description") ("log_time" 16 t :column "log_time" :parser cmk-timestamp-to-date) - ("log_command_name" 10 t :column "log_command_name") - ("log_comment" 15 t :column "log_comment") - ("lineno" 8 t :column "log_lineno") - ("lstate" 8 t :column "log_state") - ("lsttype" 8 t :column "log_state_type") - ("log_type" 8 t :column "log_type") - ("host_scheduled_downtime_depth" 5 t :column "host_scheduled_downtime_depth") - ("host_has_been_checked" 5 t :column "host_has_been_checked") + ;; ("log_command_name" 10 t :column "log_command_name") + ;; ("log_comment" 15 t :column "log_comment") + ;; ("lineno" 8 t :column "log_lineno") + ("log_type" 16 t :column "log_type") + ;; ("host_scheduled_downtime_depth" 5 t :column "host_scheduled_downtime_depth") + ;; ("host_has_been_checked" 5 t :column "host_has_been_checked") ("log_plugin_output" 5 t :column "log_plugin_output"))) (defun cmk-parse-rows (buffer column-spec) "Return tabulated entries from BUFFER according to COLUMN-SPEC." (with-current-buffer buffer (goto-char (point-min)) - (cl-loop until (eobp) - collect - (list (count-lines 1 (point)) - (cl-map 'vector - (lambda (entry spec) - (let ((parser (or (plist-get (cdddr spec) :parser) #'identity))) - (funcall parser entry))) - (split-string (buffer-substring-no-properties (point) (line-end-position)) ";") - column-spec)) - do (forward-line)))) + (let (rows + (parsers (mapcar (lambda (spec) + (or (plist-get (cdddr spec) :parser) #'identity)) + column-spec))) + (while (not (eobp)) + (push + (list (count-lines 1 (point)) + (cl-map 'vector + (lambda (parser entry) (funcall parser entry)) + parsers + (split-string (thing-at-point 'line t) ";" nil "\n"))) + rows) + (forward-line)) + (nreverse rows)))) (defun cmk-livestatus-query (query) "One shot livestatus QUERY, return network process." @@ -120,14 +130,63 @@ Default is \"%Y-%m-%d %H:%M\"." (setq tabulated-list-entries (cmk-parse-rows (process-buffer cmks) tabulated-list-format)) (tabulated-list-print 'remember))) +(defun cmk-timestamp-eldoc-documentation () + (when-let ((number (thing-at-point 'number))) + (format-time-string "%Y-%m-%d %H:%M" (seconds-to-time number)))) + +(defconst cmk-livestatus-headers + '("Filter" "Columns" "Stats" "Limit" "ColumnHeaders" "OutputFormat")) + (define-derived-mode cmk-livestatus-mode prog-mode "livestatus" "Major mode for viewing journalctl output." + (add-function :before-until (local 'eldoc-documentation-function) + #'cmk-timestamp-eldoc-documentation) + ;; (setq-local company-backends (cons 'company-cmk-lq company-backends)) + ;; (setq-local completion-at-point-functions '(cmk-lq-capf)) + (add-hook 'completion-at-point-functions 'cmk-lq-capf nil 'local) ;; code for syntax highlighting (setq font-lock-defaults `(((,(rx bol "GET" eow) . font-lock-keyword-face) (,(rx word-start (or "hosts" "services") word-end) . font-lock-constant-face) - (,(rx bol (or "Filter" "Columns" "Stats" "Limit") ":" whitespace) . font-lock-function-name-face) + (,(concat "^" (regexp-opt cmk-livestatus-headers 'words) ":[[:space:]]") . font-lock-function-name-face) (,(rx bol (or "And" "Or" "Negate") ":" whitespace) . font-lock-keyword-face) (,(rx whitespace (or "~" "=" "=~" "~~" "<" ">" "<=" ">=") whitespace) . font-lock-keyword-face))))) +(defun cmk-custom-livestatus-query () + (interactive) + (let ((query cmk-livestatus-query) + (edit-buffer (get-buffer-create "*LQ*"))) + (with-current-buffer edit-buffer + (cmk-livestatus-mode) + (if (string-blank-p query) (insert "GET ") (insert query)) + (local-set-key "\C-c\C-c" + (lambda () + (interactive) + (let ((new-query (-> (buffer-string) (string-trim) (concat "\n\n")))) + (kill-buffer) + (let ((cmk (cmk-livestatus-query new-query))) + (switch-to-buffer (process-buffer cmk)) + (setq csv-separators '(";") + csv-separator-regexp "[;]" + csv-separator-chars '(59)) + (csv-align-mode) + (setq-local cmk-livestatus-query new-query)))))) + (switch-to-buffer edit-buffer))) + +(defun company-cmk-lq (command &optional arg &rest ignored) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-cmk-lq)) + (prefix (company-grab-word)) + (candidates (cl-loop for header in cmk-livestatus-headers + when (string-prefix-p arg header t) collect header)) + (meta (format "This value is named %s" arg)))) + +(defun cmk-lq-capf () + (when (looking-back (rx bol (+ alpha)) 1) + (list (match-beginning 0) + (match-end 0) + (cl-loop for header in cmk-livestatus-headers + when (string-prefix-p (match-string-no-properties 0) header t) + collect (concat header ": "))))) (defun cmk-edit-lq (buffer) "Open window to edit the livestatus query of current BUFFER." @@ -195,10 +254,11 @@ Negate:")) Filter: class = 1 Filter: class = 3 Filter: class = 8 -Or: 3" +Or: 3 +Filter: log_state_type = HARD" (floor (- (time-to-seconds (current-time)) - (* 4 3600)))))) + (* 24 3600)))))) ;;; Get a different csv |