diff options
| author | Thanos Apollo <public@thanosapollo.org> | 2026-04-25 10:46:37 +0300 |
|---|---|---|
| committer | Thanos Apollo <public@thanosapollo.org> | 2026-04-25 10:46:37 +0300 |
| commit | 246d83c548da6b113c92f5bcd3d6083456944a02 (patch) | |
| tree | b80f92c546344ba396c73489c2601a16dfb65c38 | |
| parent | ec8676e149998707696516e1b3b7b16399b84e38 (diff) | |
buffer: Remove DB dependency, move CAPF to utils and routing to view
Move CAPF completion functions (issue-capf, mention-capf) from buffer.el
to utils.el where the DB dependency already exists. Move view-item
routing to view.el. buffer.el is now a pure rendering library with no
forgejo-db references. Re-render helper also moved to view.el.
| -rw-r--r-- | lisp/forgejo-buffer.el | 117 | ||||
| -rw-r--r-- | lisp/forgejo-issue.el | 4 | ||||
| -rw-r--r-- | lisp/forgejo-pull.el | 8 | ||||
| -rw-r--r-- | lisp/forgejo-utils.el | 87 | ||||
| -rw-r--r-- | lisp/forgejo-view.el | 39 |
5 files changed, 128 insertions, 127 deletions
diff --git a/lisp/forgejo-buffer.el b/lisp/forgejo-buffer.el index ed439e4..de00701 100644 --- a/lisp/forgejo-buffer.el +++ b/lisp/forgejo-buffer.el @@ -31,7 +31,6 @@ (require 'dom) (require 'diff-mode) (require 'forgejo) -(require 'forgejo-db) (defvar forgejo-repo--host) (defvar forgejo-repo--owner) @@ -193,7 +192,7 @@ Returns nil if BODY is :null, nil, or empty." (defun forgejo-buffer--browse-url (url &rest _args) "Open URL in forgejo.el if it's a Forgejo issue/PR, else in browser." (if-let* ((parsed (forgejo-buffer--parse-forgejo-url url))) - (forgejo-buffer-view-item (nth 0 parsed) (nth 1 parsed) (nth 2 parsed)) + (forgejo-view-item (nth 0 parsed) (nth 1 parsed) (nth 2 parsed)) (browse-url-default-browser url))) (defun forgejo-buffer--insert-html (html) @@ -327,20 +326,8 @@ NODE-DATA is a plist with :type and type-specific keys." map) "Keymap for reference links in event lines.") -(declare-function forgejo-issue-view "forgejo-issue.el" +(declare-function forgejo-view-item "forgejo-view.el" (owner repo number)) -(declare-function forgejo-pull-view "forgejo-pull.el" - (owner repo number)) - -(defun forgejo-buffer-view-item (owner repo number) - "View issue or PR NUMBER in OWNER/REPO. -Checks the DB to determine if it's a PR, falls back to issue view." - (let ((cached (forgejo-db-get-issue - (url-host (url-generic-parse-url forgejo-repo--host)) - owner repo number))) - (if (and cached (alist-get 'pull_request cached)) - (forgejo-pull-view owner repo number) - (forgejo-issue-view owner repo number)))) (defun forgejo-buffer-follow-ref () "Follow the reference link at point. @@ -351,7 +338,7 @@ Uses the ref-repo text property for cross-repo references." (parts (when full-name (split-string full-name "/"))) (owner (or (nth 0 parts) forgejo-repo--owner)) (repo (or (nth 1 parts) forgejo-repo--name))) - (forgejo-buffer-view-item owner repo number)))) + (forgejo-view-item owner repo number)))) (defvar forgejo-buffer-commit-map (let ((map (make-sparse-keymap))) @@ -812,86 +799,6 @@ Both should be alists with `body_html' pre-populated from the DB." (push result nodes))))) (nreverse nodes))) -;;; Issue/PR # completion - -(defvar-local forgejo-buffer--capf-candidates nil - "Cached completion candidates for # references.") - -(defun forgejo-buffer--issue-capf () - "Completion-at-point function for #N issue/PR references." - (when-let* ((bounds (forgejo-buffer--capf-bounds))) - (let ((start (car bounds)) - (end (cdr bounds))) - (list start end - (forgejo-buffer--capf-collection) - :annotation-function #'forgejo-buffer--capf-annotate - :exclusive 'no)))) - -(defun forgejo-buffer--capf-bounds () - "Return (START . END) for the # reference at point, or nil." - (save-excursion - (let ((end (point))) - (when (re-search-backward "#" (line-beginning-position) t) - (cons (point) end))))) - -(defun forgejo-buffer--capf-collection () - "Return completion candidates for # references." - (or forgejo-buffer--capf-candidates - (setq forgejo-buffer--capf-candidates - (mapcar (lambda (pair) - (format "#%d" (car pair))) - (forgejo-buffer--capf-load-candidates))))) - -(defun forgejo-buffer--capf-load-candidates () - "Load issue/PR candidates from the DB for the current repo context." - (when-let* ((host (and (boundp 'forgejo-repo--host) - (url-host (url-generic-parse-url forgejo-repo--host)))) - (owner (and (boundp 'forgejo-repo--owner) forgejo-repo--owner)) - (repo (and (boundp 'forgejo-repo--name) forgejo-repo--name))) - (forgejo-db-get-issue-titles host owner repo))) - -(defun forgejo-buffer--capf-annotate (candidate) - "Return the title annotation for CANDIDATE (#N)." - (when (string-match "#\\([0-9]+\\)" candidate) - (let* ((number (string-to-number (match-string 1 candidate))) - (titles (forgejo-buffer--capf-load-candidates)) - (title (alist-get number titles))) - (when title (concat " " title))))) - -;;; @mention completion - -(defvar-local forgejo-buffer--mention-candidates nil - "Cached completion candidates for @ mentions.") - -(defun forgejo-buffer--mention-capf () - "Completion-at-point function for @user mentions." - (when-let* ((bounds (forgejo-buffer--mention-bounds))) - (list (car bounds) (cdr bounds) - (forgejo-buffer--mention-collection) - :exclusive 'no))) - -(defun forgejo-buffer--mention-bounds () - "Return (START . END) for the @ mention at point, or nil." - (save-excursion - (let ((end (point))) - (when (re-search-backward "@" (line-beginning-position) t) - (cons (point) end))))) - -(defun forgejo-buffer--mention-collection () - "Return completion candidates for @ mentions." - (or forgejo-buffer--mention-candidates - (setq forgejo-buffer--mention-candidates - (mapcar (lambda (login) (concat "@" login)) - (forgejo-buffer--mention-load-users))))) - -(defun forgejo-buffer--mention-load-users () - "Load usernames from the DB for the current repo context." - (when-let* ((host (and (boundp 'forgejo-repo--host) - (url-host (url-generic-parse-url forgejo-repo--host)))) - (owner (and (boundp 'forgejo-repo--owner) forgejo-repo--owner)) - (repo (and (boundp 'forgejo-repo--name) forgejo-repo--name))) - (forgejo-db-get-authors host owner repo))) - ;;; Utilities for detail views (defun forgejo-buffer--node-at-point (ewoc) @@ -921,24 +828,6 @@ Both should be alists with `body_html' pre-populated from the DB." (when (and assignees (not (string-empty-p assignees))) (concat " " (propertize assignees 'face 'shadow))))))) -;;; Re-render helper - -(defun forgejo-buffer--re-render (buf-name host owner repo number - render-fn &optional restore-line) - "Re-render detail buffer BUF-NAME from fresh DB data. -RENDER-FN is called with (BUF-NAME HOST-URL OWNER REPO ISSUE-ALIST -TIMELINE-ALISTS)." - (when (buffer-live-p (get-buffer buf-name)) - (let* ((host-url (forgejo--host-url-for-hostname host)) - (issue (forgejo-db-get-issue host owner repo number)) - (tl-rows (forgejo-db-get-timeline host owner repo number)) - (tl-alists (mapcar #'forgejo-db--row-to-timeline-alist tl-rows))) - (funcall render-fn buf-name host-url owner repo issue tl-alists) - (when restore-line - (with-current-buffer buf-name - (goto-char (point-min)) - (forward-line (1- restore-line))))))) - ;;; Diff hunk rendering (defun forgejo-buffer--insert-diff-hunk (hunk-text) diff --git a/lisp/forgejo-issue.el b/lisp/forgejo-issue.el index c9e1900..2337bcf 100644 --- a/lisp/forgejo-issue.el +++ b/lisp/forgejo-issue.el @@ -345,8 +345,8 @@ When RESTORE-LINE is non-nil, go to that line after re-rendering." (lambda (timeline _tl-headers) (forgejo-db-save-timeline host owner repo number timeline) ;; First render with whatever we have - (forgejo-buffer--re-render - buf-name host owner repo number + (forgejo-view--re-render + buf-name host-url host owner repo number #'forgejo-issue--render-detail restore-line) ;; Then render missing HTML and re-render (forgejo-view--render-missing-html diff --git a/lisp/forgejo-pull.el b/lisp/forgejo-pull.el index d84e829..4932242 100644 --- a/lisp/forgejo-pull.el +++ b/lisp/forgejo-pull.el @@ -310,8 +310,8 @@ When RESTORE-LINE is non-nil, go to that line after re-rendering." (lambda (timeline _tl-headers) (forgejo-db-save-timeline host owner repo number timeline) ;; First render with whatever we have - (forgejo-buffer--re-render - buf-name host owner repo number + (forgejo-view--re-render + buf-name host-url host owner repo number #'forgejo-pull--render-detail restore-line) ;; Fetch review comments, then render missing HTML (let ((tl-alists (mapcar #'forgejo-db--row-to-timeline-alist @@ -319,8 +319,8 @@ When RESTORE-LINE is non-nil, go to that line after re-rendering." (forgejo-review-sync-comments host-url host owner repo number tl-alists (lambda () - (forgejo-buffer--re-render - buf-name host owner repo number + (forgejo-view--re-render + buf-name host-url host owner repo number #'forgejo-pull--render-detail restore-line) (forgejo-view--render-missing-html host-url host owner repo number buf-name restore-line diff --git a/lisp/forgejo-utils.el b/lisp/forgejo-utils.el index 83ae3a5..1752946 100644 --- a/lisp/forgejo-utils.el +++ b/lisp/forgejo-utils.el @@ -73,10 +73,87 @@ CALLBACK is called on success." (message "%sd %s/%s#%d" action owner repo number) (when callback (funcall callback))))))) -;;; Comment +;;; Issue/PR # completion + +(defvar-local forgejo-utils--capf-candidates nil + "Cached completion candidates for # references.") + +(defun forgejo-utils-issue-capf () + "Completion-at-point function for #N issue/PR references." + (when-let* ((bounds (forgejo-utils--capf-bounds))) + (let ((start (car bounds)) + (end (cdr bounds))) + (list start end + (forgejo-utils--capf-collection) + :annotation-function #'forgejo-utils--capf-annotate + :exclusive 'no)))) + +(defun forgejo-utils--capf-bounds () + "Return (START . END) for the # reference at point, or nil." + (save-excursion + (let ((end (point))) + (when (re-search-backward "#" (line-beginning-position) t) + (cons (point) end))))) + +(defun forgejo-utils--capf-collection () + "Return completion candidates for # references." + (or forgejo-utils--capf-candidates + (setq forgejo-utils--capf-candidates + (mapcar (lambda (pair) + (format "#%d" (car pair))) + (forgejo-utils--capf-load-candidates))))) + +(defun forgejo-utils--capf-load-candidates () + "Load issue/PR candidates from the DB for the current repo context." + (when-let* ((host (and (boundp 'forgejo-repo--host) + (url-host (url-generic-parse-url forgejo-repo--host)))) + (owner (and (boundp 'forgejo-repo--owner) forgejo-repo--owner)) + (repo (and (boundp 'forgejo-repo--name) forgejo-repo--name))) + (forgejo-db-get-issue-titles host owner repo))) + +(defun forgejo-utils--capf-annotate (candidate) + "Return the title annotation for CANDIDATE (#N)." + (when (string-match "#\\([0-9]+\\)" candidate) + (let* ((number (string-to-number (match-string 1 candidate))) + (titles (forgejo-utils--capf-load-candidates)) + (title (alist-get number titles))) + (when title (concat " " title))))) + +;;; @mention completion + +(defvar-local forgejo-utils--mention-candidates nil + "Cached completion candidates for @ mentions.") + +(defun forgejo-utils-mention-capf () + "Completion-at-point function for @user mentions." + (when-let* ((bounds (forgejo-utils--mention-bounds))) + (list (car bounds) (cdr bounds) + (forgejo-utils--mention-collection) + :exclusive 'no))) + +(defun forgejo-utils--mention-bounds () + "Return (START . END) for the @ mention at point, or nil." + (save-excursion + (let ((end (point))) + (when (re-search-backward "@" (line-beginning-position) t) + (cons (point) end))))) + +(defun forgejo-utils--mention-collection () + "Return completion candidates for @ mentions." + (or forgejo-utils--mention-candidates + (setq forgejo-utils--mention-candidates + (mapcar (lambda (login) (concat "@" login)) + (forgejo-utils--mention-load-users))))) + +(defun forgejo-utils--mention-load-users () + "Load usernames from the DB for the current repo context." + (when-let* ((host (and (boundp 'forgejo-repo--host) + (url-host (url-generic-parse-url forgejo-repo--host)))) + (owner (and (boundp 'forgejo-repo--owner) forgejo-repo--owner)) + (repo (and (boundp 'forgejo-repo--name) forgejo-repo--name))) + (forgejo-db-get-authors host owner repo))) -(declare-function forgejo-buffer--issue-capf "forgejo-buffer.el" ()) -(declare-function forgejo-buffer--mention-capf "forgejo-buffer.el" ()) +;;; Comment (defun forgejo-utils-read-body (prompt &optional initial) "Read multi-line text with # issue/PR completion. @@ -89,8 +166,8 @@ Like `read-string-from-buffer' but with # completion for issue references." forgejo-repo--owner owner forgejo-repo--name repo) (setq-local completion-at-point-functions - (list #'forgejo-buffer--issue-capf - #'forgejo-buffer--mention-capf)) + (list #'forgejo-utils-issue-capf + #'forgejo-utils-mention-capf)) (run-hooks 'forgejo-compose-hook)))) (unwind-protect (progn diff --git a/lisp/forgejo-view.el b/lisp/forgejo-view.el index b1e6044..dc4f893 100644 --- a/lisp/forgejo-view.el +++ b/lisp/forgejo-view.el @@ -64,6 +64,23 @@ Called with (HOST-URL OWNER REPO NUMBER).") "Return the data plist of the EWOC node at point, or nil." (forgejo-buffer--node-at-point forgejo-view--ewoc)) +;;; Item routing + +(declare-function forgejo-issue-view "forgejo-issue.el" + (owner repo number)) +(declare-function forgejo-pull-view "forgejo-pull.el" + (owner repo number)) + +(defun forgejo-view-item (owner repo number) + "View issue or PR NUMBER in OWNER/REPO. +Checks the DB to determine if it's a PR, falls back to issue view." + (let ((cached (forgejo-db-get-issue + (url-host (url-generic-parse-url forgejo-repo--host)) + owner repo number))) + (if (and cached (alist-get 'pull_request cached)) + (forgejo-pull-view owner repo number) + (forgejo-issue-view owner repo number)))) + ;;; List-view rendering (defun forgejo-view--render-from-db (buf-name host-url host owner repo @@ -120,6 +137,24 @@ SYNC-FN and BROWSE-FN are stored as buffer-locals for action commands." (set-buffer-modified-p nil) (current-buffer)))) +;;; Re-render from DB + +(defun forgejo-view--re-render (buf-name host-url host owner repo number + render-fn &optional restore-line) + "Re-render detail buffer BUF-NAME from fresh DB data. +HOST-URL is the instance. HOST is the hostname. +RENDER-FN is called with (BUF-NAME HOST-URL OWNER REPO ITEM TIMELINE). +Restores point to RESTORE-LINE if given." + (when (buffer-live-p (get-buffer buf-name)) + (let* ((issue (forgejo-db-get-issue host owner repo number)) + (tl-rows (forgejo-db-get-timeline host owner repo number)) + (tl-alists (mapcar #'forgejo-db--row-to-timeline-alist tl-rows))) + (funcall render-fn buf-name host-url owner repo issue tl-alists) + (when restore-line + (with-current-buffer buf-name + (goto-char (point-min)) + (forward-line (1- restore-line))))))) + ;;; Markdown rendering for missing HTML (defun forgejo-view--render-missing-html (host-url host owner repo number @@ -138,8 +173,8 @@ restore RESTORE-LINE." (lambda () (cl-decf pending) (when (<= pending 0) - (forgejo-buffer--re-render - buf-name host owner repo number + (forgejo-view--re-render + buf-name host-url host owner repo number render-detail-fn restore-line))))) ;; Item body (when (and item |
