glow/ui/stashitem.go

160 lines
4.5 KiB
Go
Raw Normal View History

2020-05-26 15:51:08 +00:00
package ui
import (
"fmt"
"log"
"strings"
2020-05-26 15:51:08 +00:00
"github.com/charmbracelet/lipgloss"
2020-12-14 23:42:33 +00:00
"github.com/muesli/reflow/ansi"
"github.com/muesli/reflow/truncate"
"github.com/sahilm/fuzzy"
2020-05-26 15:51:08 +00:00
)
const (
verticalLine = "│"
noMemoTitle = "No Memo"
fileListingStashIcon = "• "
2020-05-26 15:51:08 +00:00
)
func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
var (
2020-12-14 23:42:33 +00:00
truncateTo = uint(m.common.width - stashViewHorizontalPadding*2)
gutter string
title = md.Note
2020-11-25 16:40:24 +00:00
date = md.relativeTime()
icon = ""
)
2020-05-26 15:51:08 +00:00
switch md.docType {
case NewsDoc:
2020-05-26 15:51:08 +00:00
if title == "" {
title = "News"
} else {
2020-12-14 23:42:33 +00:00
title = truncate.StringWithTail(title, truncateTo, ellipsis)
2020-05-26 15:51:08 +00:00
}
case StashedDoc, ConvertedDoc:
icon = fileListingStashIcon
2020-05-26 15:51:08 +00:00
if title == "" {
title = noMemoTitle
}
2020-12-14 23:42:33 +00:00
title = truncate.StringWithTail(title, truncateTo-uint(ansi.PrintableRuneWidth(icon)), ellipsis)
2020-07-15 00:25:51 +00:00
default:
2020-12-14 23:42:33 +00:00
title = truncate.StringWithTail(title, truncateTo, ellipsis)
2020-05-26 15:51:08 +00:00
}
isSelected := index == m.cursor()
isFiltering := m.filterState == filtering
singleFilteredItem := isFiltering && len(m.getVisibleMarkdowns()) == 1
2024-05-13 21:01:14 +00:00
styles := &m.common.styles
// If there are multiple items being filtered don't highlight a selected
// item in the results. If we've filtered down to one item, however,
// highlight that first item since pressing return will open it.
if isSelected && !isFiltering || singleFilteredItem {
// Selected item
switch m.selectionState {
case selectionPromptingDelete:
2024-05-13 21:01:14 +00:00
gutter = styles.FaintRedFg(verticalLine)
icon = styles.FaintRedFg(icon)
title = styles.RedFg(title)
date = styles.FaintRedFg(date)
case selectionSettingNote:
2024-05-13 21:01:14 +00:00
gutter = styles.DullYellowFg(verticalLine)
2020-07-15 00:25:51 +00:00
icon = ""
2024-05-13 21:01:14 +00:00
title = m.noteInput.View(m.common.ctx)
date = styles.DullYellowFg(date)
2020-05-26 15:51:08 +00:00
default:
if m.common.latestFileStashed == md.stashID &&
m.statusMessage == stashingStatusMessage {
2024-05-13 21:01:14 +00:00
gutter = styles.GreenFg(verticalLine)
icon = styles.DimGreenFg(icon)
title = styles.GreenFg(title)
date = styles.SemiDimGreenFg(date)
} else {
2024-05-13 21:01:14 +00:00
gutter = styles.DullFuchsiaFg(verticalLine)
icon = styles.DullFuchsiaFg(icon)
if m.currentSection().key == filterSection &&
m.filterState == filterApplied || singleFilteredItem {
s := lipgloss.NewStyle().Foreground(fuchsia)
title = styleFilteredText(title, m.filterInput.Value(), s, s.Copy().Underline(true))
} else {
2024-05-13 21:01:14 +00:00
title = styles.FuchsiaFg(title)
}
2024-05-13 21:01:14 +00:00
date = styles.DullFuchsiaFg(date)
}
2020-05-26 15:51:08 +00:00
}
} else {
// Regular (non-selected) items
gutter = " "
if m.common.latestFileStashed == md.stashID &&
m.statusMessage == stashingStatusMessage {
2024-05-13 21:01:14 +00:00
icon = styles.DimGreenFg(icon)
title = styles.GreenFg(title)
date = styles.SemiDimGreenFg(date)
} else if md.docType == NewsDoc {
if isFiltering && m.filterInput.Value() == "" {
2024-05-13 21:01:14 +00:00
title = styles.DimIndigoFg(title)
date = styles.DimSubtleIndigoFg(date)
} else {
s := lipgloss.NewStyle().Foreground(indigo)
title = styleFilteredText(title, m.filterInput.Value(), s, s.Copy().Underline(true))
2024-05-13 21:01:14 +00:00
date = styles.SubtleIndigoFg(date)
}
} else if isFiltering && m.filterInput.Value() == "" {
2024-05-13 21:01:14 +00:00
icon = styles.DimGreenFg(icon)
if title == noMemoTitle {
2024-05-13 21:01:14 +00:00
title = styles.DimBrightGrayFg(title)
2020-10-26 14:52:54 +00:00
} else {
2024-05-13 21:01:14 +00:00
title = styles.DimNormalFg(title)
2020-10-26 14:52:54 +00:00
}
2024-05-13 21:01:14 +00:00
date = styles.DimBrightGrayFg(date)
2020-05-26 15:51:08 +00:00
} else {
2024-05-13 21:01:14 +00:00
icon = styles.GreenFg(icon)
2020-05-26 15:51:08 +00:00
if title == noMemoTitle {
2024-05-13 21:01:14 +00:00
title = styles.BrightGrayFg(title)
} else {
s := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"})
title = styleFilteredText(title, m.filterInput.Value(), s, s.Copy().Underline(true))
2020-05-26 15:51:08 +00:00
}
2024-05-13 21:01:14 +00:00
date = styles.BrightGrayFg(date)
2020-05-26 15:51:08 +00:00
}
}
2020-07-15 00:25:51 +00:00
fmt.Fprintf(b, "%s %s%s\n", gutter, icon, title)
fmt.Fprintf(b, "%s %s", gutter, date)
2020-05-26 15:51:08 +00:00
}
func styleFilteredText(haystack, needles string, defaultStyle, matchedStyle lipgloss.Style) string {
b := strings.Builder{}
normalizedHay, err := normalize(haystack)
if err != nil && debug {
log.Printf("error normalizing '%s': %v", haystack, err)
}
matches := fuzzy.Find(needles, []string{normalizedHay})
if len(matches) == 0 {
return defaultStyle.Render(haystack)
}
m := matches[0] // only one match exists
for i, rune := range []rune(haystack) {
styled := false
for _, mi := range m.MatchedIndexes {
if i == mi {
b.WriteString(matchedStyle.Render(string(rune)))
styled = true
}
}
if !styled {
b.WriteString(defaultStyle.Render(string(rune)))
}
}
return b.String()
}