ppq: Display Opencode releases
This commit is contained in:
parent
81fbe9ed45
commit
a88e8fe7d6
1 changed files with 148 additions and 21 deletions
169
ppq-status.el
169
ppq-status.el
|
|
@ -77,25 +77,144 @@
|
|||
(when secret
|
||||
(funcall (plist-get (car secret) :secret)))))
|
||||
|
||||
;; --- Table 1: Fruits ---
|
||||
;; --- Table 1: Releases ---
|
||||
|
||||
(defvar ppq-fruits-mode-map
|
||||
(defvar ppq--releases-data nil
|
||||
"Cached releases data from GitHub.")
|
||||
|
||||
(defvar ppq--releases-projects
|
||||
'(("Opencode" . "anomalyco/opencode"))
|
||||
"List of projects to fetch releases for.
|
||||
Each element is a cons cell (DISPLAY-NAME . REPO-STRING).")
|
||||
|
||||
(defun ppq--releases-get-buffer-name ()
|
||||
"Get the releases buffer name."
|
||||
"*Dashboard:Releases*")
|
||||
|
||||
(defvar ppq--releases-active-processes nil
|
||||
"List of active release fetch processes.")
|
||||
|
||||
(defun ppq--releases-process-sentinel (process _event)
|
||||
"Process sentinel for gh release list.
|
||||
PROCESS is the process object, _EVENT is the status change string."
|
||||
(setq ppq--releases-active-processes
|
||||
(delq process ppq--releases-active-processes))
|
||||
(when (memq (process-status process) '(exit signal))
|
||||
(let ((stdout-buf (process-buffer process))
|
||||
(stderr-buf (process-get process 'ppq-stderr-buffer))
|
||||
(exit-code (process-exit-status process))
|
||||
(project-name (process-get process 'ppq-project-name)))
|
||||
(if (zerop exit-code)
|
||||
(let ((output (with-current-buffer stdout-buf
|
||||
(buffer-string))))
|
||||
(condition-case nil
|
||||
(let* ((json (json-parse-string (string-trim output) :object-type 'alist))
|
||||
(releases (if (vectorp json) (append json nil) json)))
|
||||
(push (cons project-name releases) ppq--releases-data)
|
||||
(ppq--releases-refresh-buffer))
|
||||
(error nil)))
|
||||
(let ((stderr-output (with-current-buffer stderr-buf
|
||||
(buffer-string))))
|
||||
(message "ppq releases: failed for %s: %s"
|
||||
project-name (string-trim stderr-output))))
|
||||
(when (buffer-live-p stdout-buf)
|
||||
(kill-buffer stdout-buf))
|
||||
(when (buffer-live-p stderr-buf)
|
||||
(kill-buffer stderr-buf)))))
|
||||
|
||||
(defun ppq--releases-fetch-async (project-name repo)
|
||||
"Fetch releases for REPO asynchronously using gh CLI.
|
||||
PROJECT-NAME is the display name for the project."
|
||||
(let* ((stdout-buf (generate-new-buffer " *gh-releases-stdout*"))
|
||||
(stderr-buf (generate-new-buffer " *gh-releases-stderr*"))
|
||||
(process-environment (append '("PAGER=cat" "GH_PAGER=cat" "GIT_PAGER=cat" "NO_COLOR=1")
|
||||
process-environment))
|
||||
(process (make-process
|
||||
:name "gh-releases"
|
||||
:buffer stdout-buf
|
||||
:command (list "gh" "api"
|
||||
(format "repos/%s/releases?per_page=5" repo))
|
||||
:stderr stderr-buf
|
||||
:sentinel #'ppq--releases-process-sentinel
|
||||
:noquery t)))
|
||||
(process-put process 'ppq-project-name project-name)
|
||||
(process-put process 'ppq-stderr-buffer stderr-buf)
|
||||
(push process ppq--releases-active-processes)))
|
||||
|
||||
(defun ppq--releases-fetch-all-async ()
|
||||
"Fetch releases for all configured projects."
|
||||
(setq ppq--releases-data nil)
|
||||
(dolist (project ppq--releases-projects)
|
||||
(ppq--releases-fetch-async (car project) (cdr project))))
|
||||
|
||||
(defun ppq--releases-format-date (iso-date)
|
||||
"Format ISO-DATE string to human-readable date."
|
||||
(when iso-date
|
||||
(condition-case nil
|
||||
(format-time-string
|
||||
"%Y-%m-%d"
|
||||
(encode-time (parse-time-string iso-date)))
|
||||
(error iso-date))))
|
||||
|
||||
(defun ppq--releases-insert-content ()
|
||||
"Insert releases content into current buffer."
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(insert "* Software Releases\n\n")
|
||||
(if ppq--releases-data
|
||||
(dolist (project-data ppq--releases-data)
|
||||
(let ((project-name (car project-data))
|
||||
(releases (cdr project-data)))
|
||||
(insert (format "** %s\n" project-name))
|
||||
(if releases
|
||||
(dolist (release releases)
|
||||
(let* ((tag (cdr (assq 'tag_name release)))
|
||||
(name (cdr (assq 'name release)))
|
||||
(published (cdr (assq 'published_at release)))
|
||||
(body (cdr (assq 'body release)))
|
||||
(display-name (if (and name (not (string= name "")))
|
||||
name
|
||||
tag)))
|
||||
(insert (format "*** %s (%s)\n"
|
||||
display-name
|
||||
(ppq--releases-format-date published)))
|
||||
;; Insert changelog body if present
|
||||
(when (and body (not (eq body :null)) (not (string= body "")))
|
||||
(insert "\n#+begin_src markdown\n")
|
||||
(insert body)
|
||||
(insert "\n#+end_src\n"))))
|
||||
(insert "- No releases found\n"))
|
||||
(insert "\n")))
|
||||
(insert "Loading releases...\n"))
|
||||
(goto-char (point-min))
|
||||
;; Fold to show release versions (level 3) but hide changelog content
|
||||
(org-content 3)))
|
||||
|
||||
(defun ppq--releases-refresh-buffer ()
|
||||
"Refresh the releases buffer if it exists."
|
||||
(when-let ((buf (get-buffer (ppq--releases-get-buffer-name))))
|
||||
(with-current-buffer buf
|
||||
(ppq--releases-insert-content))))
|
||||
|
||||
(defun ppq-releases-mode ()
|
||||
"Major mode for displaying GitHub releases."
|
||||
(interactive)
|
||||
(kill-all-local-variables)
|
||||
(org-mode)
|
||||
(org-indent-mode 1)
|
||||
(setq major-mode 'ppq-releases-mode
|
||||
mode-name "Releases")
|
||||
(use-local-map (let ((map (copy-keymap org-mode-map)))
|
||||
(define-key map "q" #'ppq-quit)
|
||||
map))
|
||||
(setq buffer-read-only t)
|
||||
(ppq--releases-insert-content))
|
||||
|
||||
(defvar ppq-releases-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map tabulated-list-mode-map)
|
||||
(define-key map "q" #'ppq-quit)
|
||||
map))
|
||||
|
||||
(define-derived-mode ppq-fruits-mode tabulated-list-mode "Fruits"
|
||||
"A table of fruits."
|
||||
(setq tabulated-list-format [("Fruit" 15 t) ("Color" 10 t) ("Taste" 10 t)])
|
||||
(setq tabulated-list-entries
|
||||
'((1 ["Apple" "Red" "Sweet"])
|
||||
(2 ["Banana" "Yellow" "Sweet"])
|
||||
(3 ["Lemon" "Yellow" "Sour"])
|
||||
(4 ["Grape" "Purple" "Sweet"])))
|
||||
(tabulated-list-init-header)
|
||||
(tabulated-list-print))
|
||||
|
||||
;; --- Table 2: Models ---
|
||||
|
||||
(defvar ppq--models-data nil
|
||||
|
|
@ -301,11 +420,18 @@
|
|||
(defun ppq-quit ()
|
||||
"Quit the dashboard, restore previous window configuration, and kill buffers."
|
||||
(interactive)
|
||||
(dolist (buf (list (get-buffer "*Dashboard:Fruits*")
|
||||
;; Kill any active release fetch processes
|
||||
(dolist (proc ppq--releases-active-processes)
|
||||
(when (process-live-p proc)
|
||||
(delete-process proc)))
|
||||
(setq ppq--releases-active-processes nil)
|
||||
;; Kill buffers
|
||||
(dolist (buf (list (get-buffer "*Dashboard:Releases*")
|
||||
(get-buffer "*Dashboard:Models*")
|
||||
(get-buffer "*Dashboard:Info*")))
|
||||
(when buf (kill-buffer buf)))
|
||||
(setq ppq--models-data nil)
|
||||
(setq ppq--releases-data nil)
|
||||
(when ppq--window-config
|
||||
(set-window-configuration ppq--window-config)
|
||||
(setq ppq--window-config nil)))
|
||||
|
|
@ -318,12 +444,12 @@
|
|||
(interactive)
|
||||
(setq ppq--window-config (current-window-configuration))
|
||||
|
||||
(let ((fruits-buf (get-buffer-create "*Dashboard:Fruits*"))
|
||||
(let ((releases-buf (get-buffer-create "*Dashboard:Releases*"))
|
||||
(models-buf (get-buffer-create "*Dashboard:Models*"))
|
||||
(org-buf (get-buffer-create "*Dashboard:Info*")))
|
||||
|
||||
(with-current-buffer fruits-buf
|
||||
(ppq-fruits-mode))
|
||||
(with-current-buffer releases-buf
|
||||
(ppq-releases-mode))
|
||||
|
||||
(with-current-buffer models-buf
|
||||
(ppq-models-mode))
|
||||
|
|
@ -337,7 +463,7 @@
|
|||
(insert "Welcome to the *PayPerQ* dashboard!\n\n")
|
||||
(insert "** Notes\n")
|
||||
(insert "- Press ~q~ in any table to quit\n")
|
||||
(insert "- Table 1 :: Fruits of the world\n")
|
||||
(insert "- Table 1 :: Recent Releases (loading...)\n")
|
||||
(insert "- Table 2 :: PayPerQ Models (loading...)\n\n")
|
||||
(insert "** Balance\n\n")
|
||||
(insert "** Topup (BTC-LN)\n")
|
||||
|
|
@ -352,12 +478,13 @@
|
|||
(let* ((top-left (selected-window))
|
||||
(top-right (split-window-right))
|
||||
(bottom (split-window-below (/ (window-height) 2))))
|
||||
(set-window-buffer top-left fruits-buf)
|
||||
(set-window-buffer top-left releases-buf)
|
||||
(set-window-buffer top-right models-buf)
|
||||
(set-window-buffer bottom org-buf))
|
||||
|
||||
(select-window (get-buffer-window fruits-buf)))
|
||||
(select-window (get-buffer-window releases-buf)))
|
||||
|
||||
(ppq--releases-fetch-all-async)
|
||||
(ppq--fetch-models-async)
|
||||
(ppq--fetch-balance-async))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue