summaryrefslogtreecommitdiff
path: root/dot-oh-my-zsh/custom/plugins/fzf/src/result.go
diff options
context:
space:
mode:
Diffstat (limited to 'dot-oh-my-zsh/custom/plugins/fzf/src/result.go')
-rw-r--r--dot-oh-my-zsh/custom/plugins/fzf/src/result.go258
1 files changed, 258 insertions, 0 deletions
diff --git a/dot-oh-my-zsh/custom/plugins/fzf/src/result.go b/dot-oh-my-zsh/custom/plugins/fzf/src/result.go
new file mode 100644
index 00000000..c4acb5fa
--- /dev/null
+++ b/dot-oh-my-zsh/custom/plugins/fzf/src/result.go
@@ -0,0 +1,258 @@
+package fzf
+
+import (
+ "math"
+ "sort"
+ "unicode"
+
+ "github.com/junegunn/fzf/src/tui"
+ "github.com/junegunn/fzf/src/util"
+)
+
+// Offset holds two 32-bit integers denoting the offsets of a matched substring
+type Offset [2]int32
+
+type colorOffset struct {
+ offset [2]int32
+ color tui.ColorPair
+}
+
+type Result struct {
+ item *Item
+ points [4]uint16
+}
+
+func buildResult(item *Item, offsets []Offset, score int) Result {
+ if len(offsets) > 1 {
+ sort.Sort(ByOrder(offsets))
+ }
+
+ result := Result{item: item}
+ numChars := item.text.Length()
+ minBegin := math.MaxUint16
+ minEnd := math.MaxUint16
+ maxEnd := 0
+ validOffsetFound := false
+ for _, offset := range offsets {
+ b, e := int(offset[0]), int(offset[1])
+ if b < e {
+ minBegin = util.Min(b, minBegin)
+ minEnd = util.Min(e, minEnd)
+ maxEnd = util.Max(e, maxEnd)
+ validOffsetFound = true
+ }
+ }
+
+ for idx, criterion := range sortCriteria {
+ val := uint16(math.MaxUint16)
+ switch criterion {
+ case byScore:
+ // Higher is better
+ val = math.MaxUint16 - util.AsUint16(score)
+ case byChunk:
+ b := minBegin
+ e := maxEnd
+ l := item.text.Length()
+ for ; b >= 1; b-- {
+ if unicode.IsSpace(item.text.Get(b - 1)) {
+ break
+ }
+ }
+ for ; e < l; e++ {
+ if unicode.IsSpace(item.text.Get(e)) {
+ break
+ }
+ }
+ val = util.AsUint16(e - b)
+ case byLength:
+ val = item.TrimLength()
+ case byBegin, byEnd:
+ if validOffsetFound {
+ whitePrefixLen := 0
+ for idx := 0; idx < numChars; idx++ {
+ r := item.text.Get(idx)
+ whitePrefixLen = idx
+ if idx == minBegin || !unicode.IsSpace(r) {
+ break
+ }
+ }
+ if criterion == byBegin {
+ val = util.AsUint16(minEnd - whitePrefixLen)
+ } else {
+ val = util.AsUint16(math.MaxUint16 - math.MaxUint16*(maxEnd-whitePrefixLen)/int(item.TrimLength()))
+ }
+ }
+ }
+ result.points[3-idx] = val
+ }
+
+ return result
+}
+
+// Sort criteria to use. Never changes once fzf is started.
+var sortCriteria []criterion
+
+// Index returns ordinal index of the Item
+func (result *Result) Index() int32 {
+ return result.item.Index()
+}
+
+func minRank() Result {
+ return Result{item: &minItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
+}
+
+func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme, colBase tui.ColorPair, colMatch tui.ColorPair, current bool) []colorOffset {
+ itemColors := result.item.Colors()
+
+ // No ANSI codes
+ if len(itemColors) == 0 {
+ var offsets []colorOffset
+ for _, off := range matchOffsets {
+ offsets = append(offsets, colorOffset{offset: [2]int32{off[0], off[1]}, color: colMatch})
+ }
+ return offsets
+ }
+
+ // Find max column
+ var maxCol int32
+ for _, off := range matchOffsets {
+ if off[1] > maxCol {
+ maxCol = off[1]
+ }
+ }
+ for _, ansi := range itemColors {
+ if ansi.offset[1] > maxCol {
+ maxCol = ansi.offset[1]
+ }
+ }
+
+ cols := make([]int, maxCol)
+ for colorIndex, ansi := range itemColors {
+ for i := ansi.offset[0]; i < ansi.offset[1]; i++ {
+ cols[i] = colorIndex + 1 // 1-based index of itemColors
+ }
+ }
+
+ for _, off := range matchOffsets {
+ for i := off[0]; i < off[1]; i++ {
+ // Negative of 1-based index of itemColors
+ // - The extra -1 means highlighted
+ cols[i] = cols[i]*-1 - 1
+ }
+ }
+
+ // sort.Sort(ByOrder(offsets))
+
+ // Merge offsets
+ // ------------ ---- -- ----
+ // ++++++++ ++++++++++
+ // --++++++++-- --++++++++++---
+ curr := 0
+ start := 0
+ ansiToColorPair := func(ansi ansiOffset, base tui.ColorPair) tui.ColorPair {
+ fg := ansi.color.fg
+ bg := ansi.color.bg
+ if fg == -1 {
+ if current {
+ fg = theme.Current.Color
+ } else {
+ fg = theme.Fg.Color
+ }
+ }
+ if bg == -1 {
+ if current {
+ bg = theme.DarkBg.Color
+ } else {
+ bg = theme.Bg.Color
+ }
+ }
+ return tui.NewColorPair(fg, bg, ansi.color.attr).MergeAttr(base)
+ }
+ var colors []colorOffset
+ add := func(idx int) {
+ if curr != 0 && idx > start {
+ if curr < 0 {
+ color := colMatch
+ if curr < -1 && theme.Colored {
+ origColor := ansiToColorPair(itemColors[-curr-2], colMatch)
+ // hl or hl+ only sets the foreground color, so colMatch is the
+ // combination of either [hl and bg] or [hl+ and bg+].
+ //
+ // If the original text already has background color, and the
+ // foreground color of colMatch is -1, we shouldn't only apply the
+ // background color of colMatch.
+ // e.g. echo -e "\x1b[32;7mfoo\x1b[mbar" | fzf --ansi --color bg+:1,hl+:-1:underline
+ // echo -e "\x1b[42mfoo\x1b[mbar" | fzf --ansi --color bg+:1,hl+:-1:underline
+ if color.Fg().IsDefault() && origColor.HasBg() {
+ color = origColor
+ } else {
+ color = origColor.MergeNonDefault(color)
+ }
+ }
+ colors = append(colors, colorOffset{
+ offset: [2]int32{int32(start), int32(idx)}, color: color})
+ } else {
+ ansi := itemColors[curr-1]
+ colors = append(colors, colorOffset{
+ offset: [2]int32{int32(start), int32(idx)},
+ color: ansiToColorPair(ansi, colBase)})
+ }
+ }
+ }
+ for idx, col := range cols {
+ if col != curr {
+ add(idx)
+ start = idx
+ curr = col
+ }
+ }
+ add(int(maxCol))
+ return colors
+}
+
+// ByOrder is for sorting substring offsets
+type ByOrder []Offset
+
+func (a ByOrder) Len() int {
+ return len(a)
+}
+
+func (a ByOrder) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
+func (a ByOrder) Less(i, j int) bool {
+ ioff := a[i]
+ joff := a[j]
+ return (ioff[0] < joff[0]) || (ioff[0] == joff[0]) && (ioff[1] <= joff[1])
+}
+
+// ByRelevance is for sorting Items
+type ByRelevance []Result
+
+func (a ByRelevance) Len() int {
+ return len(a)
+}
+
+func (a ByRelevance) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
+func (a ByRelevance) Less(i, j int) bool {
+ return compareRanks(a[i], a[j], false)
+}
+
+// ByRelevanceTac is for sorting Items
+type ByRelevanceTac []Result
+
+func (a ByRelevanceTac) Len() int {
+ return len(a)
+}
+
+func (a ByRelevanceTac) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
+func (a ByRelevanceTac) Less(i, j int) bool {
+ return compareRanks(a[i], a[j], true)
+}