From 459c257560b00a969cc4e8a15fe73377d6476683 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Wed, 3 Jun 2026 12:24:58 -0500 Subject: feat(views): add pearl-assignee-tag-short to trim the @-tag to first name The assignee @-tag slugs Linear's full @-mention handle, so a firstname.lastname handle still renders long (:@first_last:). For someone who wants a tighter tag line, I added pearl-assignee-tag-short (default off): when on, the tag keeps only the first segment of the handle (before the first dot or space), so :@first_last: becomes :@first: and a single-token handle like alice is unchanged. It's opt-in because first names collide across teammates, so the default stays the unambiguous full handle. --- pearl.el | 25 ++++++++++++++++++++----- tests/test-pearl-labels.el | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/pearl.el b/pearl.el index bb91f35..e9f1e8b 100644 --- a/pearl.el +++ b/pearl.el @@ -287,6 +287,17 @@ Set to nil to omit the tag." :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 +=:@first_last:'). With this on, only the first segment is kept -- the part +before the first `.' or space -- so the tag becomes =:@first:'. A single-token +handle like `alice' is unchanged. Shorter and more scannable, but first names +can collide across teammates, so it is off by default. Opt in when brevity +matters more than disambiguation." + :type 'boolean + :group 'pearl) + (defconst pearl--title-case-minor-words '("a" "an" "and" "as" "at" "but" "by" "for" "if" "in" "nor" "of" "on" "or" "per" "the" "to" "vs" "via") @@ -2507,12 +2518,16 @@ e.g. \"nerses\") and falls back to `:name' -- so a teammate whose `:name' is a full email gets @nerses, not @nerses_deepsat_com. The slug reuses `pearl--label-name-to-tag'; the `@' prefix keeps the assignee tag in its own namespace, distinct from label tags, so the label-edit path can preserve it (see -`pearl--set-heading-label-tags'). Title-sync-safe: Org strips tags before the -heading title is hashed." +`pearl--set-heading-label-tags'). With `pearl-assignee-tag-short' on, only the +first segment of the handle is kept (see that variable). Title-sync-safe: Org +strips tags before the heading title is hashed." (when (and pearl-show-assignee assignee) - (let ((slug (pearl--label-name-to-tag - (or (plist-get assignee :display-name) - (plist-get assignee :name))))) + (let* ((handle (or (plist-get assignee :display-name) + (plist-get assignee :name))) + (handle (if (and pearl-assignee-tag-short handle) + (car (split-string handle "[.[:space:]]+" t)) + handle)) + (slug (pearl--label-name-to-tag handle))) (unless (string-empty-p slug) (concat "@" slug))))) (defun pearl--derive-todo-line (states) diff --git a/tests/test-pearl-labels.el b/tests/test-pearl-labels.el index 94211b1..febb906 100644 --- a/tests/test-pearl-labels.el +++ b/tests/test-pearl-labels.el @@ -95,6 +95,20 @@ field -- which is the full email for teammates who never set a display name." "With no displayName, the tag slugs the name." (should (string= "@eric_bell" (pearl--assignee-tag '(:name "Eric Bell"))))) +(ert-deftest test-pearl-assignee-tag-short-keeps-first-segment () + "With `pearl-assignee-tag-short' on, only the first name (before the first dot +or space) is kept, so a firstname.lastname handle shortens to just the first." + (let ((pearl-assignee-tag-short t)) + (should (string= "@vrezh" (pearl--assignee-tag '(:display-name "vrezh.mikayelyan")))) + (should (string= "@eric" (pearl--assignee-tag '(:name "Eric Bell")))) + ;; A single-token handle is unchanged. + (should (string= "@nerses" (pearl--assignee-tag '(:display-name "nerses")))))) + +(ert-deftest test-pearl-assignee-tag-short-off-keeps-full-handle () + "Off by default: the full slugified handle is kept." + (should (string= "@vrezh_mikayelyan" + (pearl--assignee-tag '(:display-name "vrezh.mikayelyan"))))) + (ert-deftest test-pearl-normalize-user-captures-display-name () "The normalized user carries Linear's displayName so the @-tag can use the short handle while the drawer keeps the fuller name." -- cgit v1.2.3