diff options
Diffstat (limited to 'pearl.el')
| -rw-r--r-- | pearl.el | 77 |
1 files changed, 71 insertions, 6 deletions
@@ -287,6 +287,18 @@ Set to nil to omit the tag." :type 'boolean :group 'pearl) +(defcustom pearl-show-glyphs t + "When non-nil, overlay a content glyph on the leading stars of Linear headings. +An issue heading (one carrying a `LINEAR-ID') shows a ticket glyph; a comment +heading (`LINEAR-COMMENT-ID') shows a speech glyph. The glyph rides a `display' +overlay on the space after the stars, so it sits ahead of the TODO keyword -- +where a literal text prefix can't go, since Org needs the keyword first. +Display-only: the buffer text is untouched, so parsing, sync, and merge keep +working. The overlay goes stale after a manual heading edit until the next +fetch/refresh. Set to nil to omit the glyphs." + :type 'boolean + :group 'pearl) + (defcustom pearl-assignee-tag-short nil "When non-nil, shorten the assignee @-tag to the first name only. The default slugs Linear's full @-mention handle (e.g. `first.last' becomes @@ -7127,6 +7139,50 @@ unlike `issueDelete' this is not a recoverable soft delete." (list :success (eq t (cdr (assoc 'success payload))))))) (lambda (_error _response _data) (funcall callback '(:success nil)))))) +(defconst pearl--ticket-glyph "🎫" + "Glyph overlaid on issue headings (those carrying a `LINEAR-ID').") + +(defconst pearl--comment-glyph "💬" + "Glyph overlaid on comment headings (those carrying a `LINEAR-COMMENT-ID').") + +(defun pearl--heading-glyph (comment-id issue-id) + "Return the content glyph for a heading, or nil when it carries no Linear id. +COMMENT-ID wins over ISSUE-ID so a comment heading shows the speech glyph; the +two ids are disjoint in practice, but the order makes the precedence explicit." + (cond (comment-id pearl--comment-glyph) + (issue-id pearl--ticket-glyph) + (t nil))) + +(defun pearl--apply-heading-glyphs (&optional buffer) + "Overlay a content glyph on the leading stars of Linear headings in BUFFER. +An issue heading (`LINEAR-ID') gets `pearl--ticket-glyph'; a comment heading +(`LINEAR-COMMENT-ID') gets `pearl--comment-glyph', chosen per heading from its +drawer rather than per outline level. The glyph rides a `display' overlay on +the space after the leading stars, so it renders ahead of the TODO keyword and +leaves the stars (and any `org-superstar' / `org-modern' bullet composed from +them) untouched. Buffer text is unchanged, so parsing and the merge rewrites +keep working. Idempotent: clears prior glyph overlays first; with +`pearl-show-glyphs' nil it just clears. Overlays go stale after a manual +heading edit until the next fetch/refresh re-applies them." + (with-current-buffer (or buffer (current-buffer)) + (save-excursion + (remove-overlays (point-min) (point-max) 'pearl-glyph t) + (when pearl-show-glyphs + (goto-char (point-min)) + ;; Match the leading-star run; point lands on the char after it. A real + ;; heading has a space there -- the `char-after' guard skips body lines + ;; that merely begin with asterisks (e.g. inline `**bold**'). + (while (re-search-forward "^\\*+" nil t) + (let ((stars-end (point)) + (glyph (pearl--heading-glyph + (org-entry-get nil "LINEAR-COMMENT-ID") + (org-entry-get nil "LINEAR-ID")))) + (when (and glyph (eq (char-after) ?\s)) + (let ((ov (make-overlay stars-end (1+ stars-end)))) + (overlay-put ov 'pearl-glyph t) + (overlay-put ov 'evaporate t) + (overlay-put ov 'display (concat " " glyph " ")))))))))) + (defun pearl--apply-comment-highlights (viewer-id) "Color every comment heading in the buffer by editability for VIEWER-ID. The viewer's own comments get `pearl-editable-comment' on the heading line; all @@ -7160,11 +7216,18 @@ highlights first." ;;;###autoload (defun pearl-highlight-comments () - "Color comment headings in the current buffer by who can edit them. -The viewer's own comments render green (editable); others render greyed. Runs -after a fetch/refresh, and is safe to invoke by hand." + "Redecorate the current buffer's headings: content glyphs and comment colors. +First lays the heading glyphs (see `pearl--apply-heading-glyphs'), then colors +comment headings by who can edit them -- the viewer's own comments render green +(editable), others render greyed. Runs after a fetch/refresh, and is safe to +invoke by hand." (interactive) (let ((buffer (current-buffer))) + ;; Heading glyphs are drawer-driven, not viewer-driven, so apply them + ;; synchronously here -- they ride the same redecoration trigger as comment + ;; coloring but must show even when the viewer can't be resolved (offline, + ;; missing key). + (pearl--apply-heading-glyphs buffer) ;; Best-effort: highlighting is a display nicety and must never abort the ;; operation that triggered it (e.g. a missing API key errors in the ;; request layer), so a failure to resolve the viewer just skips coloring. @@ -7488,12 +7551,14 @@ reachable from the keyboard. Turns on automatically in any buffer Pearl rendered (one carrying a `#+LINEAR-SOURCE' header); see `pearl--maybe-enable-mode' on `org-mode-hook'. On enable it also collapses the `#+' keyword preamble (see -`pearl--hide-preamble'), so opening a Linear file hides it the same way a fresh -fetch does." +`pearl--hide-preamble') and overlays the heading content glyphs (see +`pearl--apply-heading-glyphs'), so opening a Linear file decorates it the same +way a fresh fetch does." :lighter (:eval (pearl--mode-line-lighter)) :keymap pearl-mode-map (when pearl-mode - (pearl--hide-preamble))) + (pearl--hide-preamble) + (pearl--apply-heading-glyphs))) (defun pearl--buffer-is-pearl-p () "Non-nil when the current buffer is a Pearl-rendered Linear file. |
