fix(tui): expose gitcrawl link actions

This commit is contained in:
Vincent Koc 2026-05-03 03:52:17 -07:00
parent 227cc9a1fc
commit 9e964bd8f2
No known key found for this signature in database
2 changed files with 45 additions and 8 deletions

View File

@ -539,6 +539,7 @@ const (
actionCycleGroup
actionOpenURL
actionCopyURL
actionCopyMarkdownLink
actionCopyTitle
actionCopyDetail
actionOpenLinkMenu
@ -1066,6 +1067,7 @@ func (m *model) openActionMenuFor(context paneFocus) {
selectedItems = append([]menuItem{
{label: "Open selected URL", action: actionOpenURL},
{label: "Copy selected URL", action: actionCopyURL},
{label: "Copy markdown link", action: actionCopyMarkdownLink},
}, selectedItems...)
}
items := []menuItem{
@ -1075,12 +1077,16 @@ func (m *model) openActionMenuFor(context paneFocus) {
if links := m.selectedReferenceLinks(); len(links) > 0 {
items = append(items,
menuSection("Links"),
menuItem{label: "Open first body link", action: actionOpenFirstLink},
menuItem{label: "Copy first body link", action: actionCopyFirstLink},
)
}
if links := m.selectedReferenceLinks(); len(links) > 1 {
items = append(items,
menuItem{label: "Open body link...", action: actionOpenLinkMenu},
menuItem{label: "Copy body link...", action: actionCopyLinkMenu},
menuItem{label: "Copy all body links", action: actionCopyAllLinks},
)
if len(links) > 1 {
items = append(items, menuItem{label: "Copy all body links", action: actionCopyAllLinks})
}
}
items = append(items, []menuItem{
menuSection("Pane"),
@ -1270,6 +1276,9 @@ func (m *model) runMenuItem(item menuItem) tea.Cmd {
case actionCopyURL:
m.copySelectedURL()
m.closeMenu()
case actionCopyMarkdownLink:
m.copySelectedMarkdownLink()
m.closeMenu()
case actionCopyTitle:
m.copySelectedTitle()
m.closeMenu()
@ -1415,6 +1424,31 @@ func (m *model) copySelectedURL() {
m.status = "Copied selected URL"
}
func (m *model) copySelectedMarkdownLink() {
item, ok := m.selectedItem()
if !ok || strings.TrimSpace(item.URL) == "" {
m.status = "No URL for selected row"
return
}
url := strings.TrimSpace(item.URL)
title := strings.TrimSpace(item.Title)
if title == "" {
title = url
}
if err := copyText("[" + escapeMarkdownLinkLabel(title) + "](" + url + ")"); err != nil {
m.status = err.Error()
return
}
m.status = "Copied markdown link"
}
func escapeMarkdownLinkLabel(value string) string {
value = strings.ReplaceAll(value, `\`, `\\`)
value = strings.ReplaceAll(value, `[`, `\[`)
value = strings.ReplaceAll(value, `]`, `\]`)
return value
}
func (m *model) copySelectedTitle() {
item, ok := m.selectedItem()
if !ok || strings.TrimSpace(item.Title) == "" {

View File

@ -835,7 +835,7 @@ func TestRightClickOpensSharedActionMenu(t *testing.T) {
if !strings.Contains(view, "Open selected URL") || !strings.Contains(view, "Copy selected detail") || !strings.Contains(view, "Links") {
t.Fatalf("action menu missing expected commands:\n%s", view)
}
for _, want := range []string{"Open body link...", "Copy body link...", "Focus detail pane", "Sort focused pane", "Jump to row..."} {
for _, want := range []string{"Copy markdown link", "Open first body link", "Copy first body link", "Focus detail pane", "Sort focused pane", "Jump to row..."} {
if !menuContainsLabel(m.menuItems, want) {
t.Fatalf("action menu items missing %q: %#v", want, m.menuItems)
}
@ -853,8 +853,10 @@ func TestActionMenuUsesGitcrawlStyleLinkPicker(t *testing.T) {
m.height = 16
m.openActionMenuFor(focusRows)
if !menuContainsLabel(m.menuItems, "Open body link...") {
t.Fatalf("action menu missing link picker: %#v", m.menuItems)
for _, want := range []string{"Open first body link", "Copy first body link", "Open body link...", "Copy body link...", "Copy all body links"} {
if !menuContainsLabel(m.menuItems, want) {
t.Fatalf("action menu missing %q: %#v", want, m.menuItems)
}
}
m.openReferenceLinkMenu("open")
if m.menuTitle != "Open Link" {
@ -996,12 +998,13 @@ func TestActionMenuCopyAndOpenSelectedRow(t *testing.T) {
t.Fatalf("open action opened=%v status=%q", opened, m.status)
}
m.copySelectedURL()
m.copySelectedMarkdownLink()
m.copySelectedTitle()
m.copySelectedDetail()
if len(copied) != 3 {
if len(copied) != 4 {
t.Fatalf("copied = %#v", copied)
}
if copied[0] != "https://example.com/launch" || copied[1] != "Launch Plan" || !strings.Contains(copied[2], "Ship the TUI.") {
if copied[0] != "https://example.com/launch" || copied[1] != "[Launch Plan](https://example.com/launch)" || copied[2] != "Launch Plan" || !strings.Contains(copied[3], "Ship the TUI.") {
t.Fatalf("copied values = %#v", copied)
}
}