From 0975e7de0c7bfdc6f65bb64537d4eff1aeb09a7e Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 28 May 2026 09:36:06 -0500 Subject: feat(view-sync): pearl-publish-current-source convenience wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is Phase 5 of docs/saved-query-sync-spec.org (ยง New: pearl-publish-current-source). When I'm reading a local saved query rendered in pearl and decide it should be a Linear view, I now have a one-chord publish instead of the M-x round-trip through pearl-sync-saved-query-to-linear with the name lookup. The new command reads the active buffer's #+LINEAR-SOURCE header and dispatches to pearl-sync-saved-query-to-linear with the name pre-filled when the source is a :type filter that matches an entry in pearl-saved-queries. Other shapes refuse with a clear message: no source header at all, the source is already a :type view (no publish needed), the type isn't filter, the source has no usable name (transient ad-hoc filter, or whitespace-only name), or the recorded name doesn't match any local saved query. I bound the command under C-; L f P in pearl-fetch-map. The transient gets ("U" "upload current source") in the Fetch group because P is taken in the transient's flat namespace, and the verb-prefix shape revisit task tracks reshaping that. 7 new tests cover each refusal branch and the dispatch path, including a regression for the whitespace-only :name case the pre-commit review surfaced. The prior check used string-empty-p, which let " " fall through to the no-matching-saved-query branch with a visibly-blank name in the error message. string-blank-p routes it to the cleaner no-name branch. The keymap and transient menu tests gained coverage for the new binding. 660 ert tests total green. make compile and make lint clean. --- pearl.el | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'pearl.el') diff --git a/pearl.el b/pearl.el index 724664b..61c4934 100644 --- a/pearl.el +++ b/pearl.el @@ -4040,6 +4040,39 @@ scope-and-visibility display string for the success message." (message "Failed to sync %s: %s" name (or (plist-get result :error) "Linear refused the create")))))) +;;;###autoload +(defun pearl-publish-current-source () + "Publish the active buffer's local saved query to Linear as a Custom View. +Convenience wrapper. Reads `#+LINEAR-SOURCE' from the current buffer. +When it's a `:type filter' source whose `:name' matches a local saved +query, dispatches to `pearl-sync-saved-query-to-linear' with that name +pre-filled. Otherwise refuses with a clear message: the source is +already a Linear view (no publish needed), the filter is transient (no +name to sync under), or no local saved query matches the recorded name. + +Bound under \\='C-; L f P\\=' inside `pearl-mode' buffers; reachable +through the transient as the `U' (upload) entry in the Fetch group." + (interactive) + (let* ((source (pearl--read-active-source)) + (type (and source (plist-get source :type))) + (name (and source (plist-get source :name)))) + (cond + ((null source) + (user-error "No active source header in this buffer; nothing to publish")) + ((eq type 'view) + (user-error "Source is already a Linear view (%s); no publish needed" + (or name ""))) + ((not (eq type 'filter)) + (user-error "Unsupported source type %s; only filter sources can be published" + type)) + ((or (null name) (and (stringp name) (string-blank-p name))) + (user-error "Source has no name; save it first via pearl-list-issues-filtered then re-publish")) + ((not (assoc name pearl-saved-queries)) + (user-error "No local saved query named %s; save it first via pearl-list-issues-filtered" + name)) + (t + (pearl-sync-saved-query-to-linear name))))) + (defun pearl--sync-saved-query-do-update (name view-id team-id shared filter-data scope-label) "Update an existing Linear view from saved query NAME by VIEW-ID. @@ -5772,7 +5805,8 @@ body stay." ("f" "build a filter" pearl-list-issues-filtered) ("v" "custom view" pearl-run-view) ("Q" "saved query" pearl-run-saved-query) - ("S" "sync saved query" pearl-sync-saved-query-to-linear)] + ("S" "sync saved query" pearl-sync-saved-query-to-linear) + ("U" "upload current source" pearl-publish-current-source)] ["View" ("g" "refresh view" pearl-refresh-current-view) ("r" "refresh issue" pearl-refresh-current-issue) @@ -5816,6 +5850,8 @@ body stay." (define-key map "q" (cons "saved query" #'pearl-run-saved-query)) (define-key map "S" (cons "sync saved query to Linear" #'pearl-sync-saved-query-to-linear)) + (define-key map "P" (cons "publish current source to Linear" + #'pearl-publish-current-source)) map) "Pearl fetch commands; a sub-keymap of `pearl-prefix-map'.") -- cgit v1.2.3