// NewMatcher returns a new Matcher func NewMatcher(patternBuilder func([]rune) *Pattern, sort bool, tac bool, eventBox *util.EventBox) *Matcher { partitions := util.Min(numPartitionsMultiplier*runtime.NumCPU(), maxPartitions) return &Matcher{ patternBuilder: patternBuilder, sort: sort, tac: tac, eventBox: eventBox, reqBox: util.NewEventBox(), partitions: partitions, slab: make([]*util.Slab, partitions), mergerCache: make(map[string]*Merger)} }
func buildResult(item *Item, offsets []Offset, score int, trimLen int) *Result { if len(offsets) > 1 { sort.Sort(ByOrder(offsets)) } result := Result{item: item, rank: rank{index: item.index}} numChars := item.text.Length() minBegin := 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) 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 byLength: // If offsets is empty, trimLen will be 0, but we don't care val = util.AsUint16(trimLen) 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(minBegin - whitePrefixLen) } else { val = util.AsUint16(math.MaxUint16 - math.MaxUint16*(maxEnd-whitePrefixLen)/trimLen) } } } result.rank.points[idx] = val } return &result }
func (t *Terminal) printHighlighted(result *Result, attr tui.Attr, col1 tui.ColorPair, col2 tui.ColorPair, current bool) { item := result.item // Overflow text := make([]rune, item.text.Length()) copy(text, item.text.ToRunes()) matchOffsets := []Offset{} var pos *[]int if t.merger.pattern != nil { _, matchOffsets, pos = t.merger.pattern.MatchItem(item, true, t.slab) } charOffsets := matchOffsets if pos != nil { charOffsets = make([]Offset, len(*pos)) for idx, p := range *pos { offset := Offset{int32(p), int32(p + 1)} charOffsets[idx] = offset } sort.Sort(ByOrder(charOffsets)) } var maxe int for _, offset := range charOffsets { maxe = util.Max(maxe, int(offset[1])) } offsets := result.colorOffsets(charOffsets, t.theme, col2, attr, current) maxWidth := t.window.Width - 3 maxe = util.Constrain(maxe+util.Min(maxWidth/2-2, t.hscrollOff), 0, len(text)) if overflow(text, maxWidth) { if t.hscroll { // Stri.. if !overflow(text[:maxe], maxWidth-2) { text, _ = trimRight(text, maxWidth-2) text = append(text, []rune("..")...) } else { // Stri.. if overflow(text[maxe:], 2) { text = append(text[:maxe], []rune("..")...) } // ..ri.. var diff int32 text, diff = trimLeft(text, maxWidth-2) // Transform offsets for idx, offset := range offsets { b, e := offset.offset[0], offset.offset[1] b += 2 - diff e += 2 - diff b = util.Max32(b, 2) offsets[idx].offset[0] = b offsets[idx].offset[1] = util.Max32(b, e) } text = append([]rune(".."), text...) } } else { text, _ = trimRight(text, maxWidth-2) text = append(text, []rune("..")...) for idx, offset := range offsets { offsets[idx].offset[0] = util.Min32(offset.offset[0], int32(maxWidth-2)) offsets[idx].offset[1] = util.Min32(offset.offset[1], int32(maxWidth)) } } } var index int32 var substr string var prefixWidth int maxOffset := int32(len(text)) for _, offset := range offsets { b := util.Constrain32(offset.offset[0], index, maxOffset) e := util.Constrain32(offset.offset[1], index, maxOffset) substr, prefixWidth = processTabs(text[index:b], prefixWidth) t.window.CPrint(col1, attr, substr) if b < e { substr, prefixWidth = processTabs(text[b:e], prefixWidth) t.window.CPrint(offset.color, offset.attr, substr) } index = e if index >= maxOffset { break } } if index < maxOffset { substr, _ = processTabs(text[index:], prefixWidth) t.window.CPrint(col1, attr, substr) } }
// NewTerminal returns new Terminal object func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { input := []rune(opts.Query) var header []string if opts.Reverse { header = opts.Header } else { header = reverseStringArray(opts.Header) } var delay time.Duration if opts.Tac { delay = initialDelayTac } else { delay = initialDelay } var previewBox *util.EventBox if len(opts.Preview.command) > 0 { previewBox = util.NewEventBox() } strongAttr := tui.Bold if !opts.Bold { strongAttr = tui.AttrRegular } var renderer tui.Renderer if opts.Height.size > 0 { maxHeightFunc := func(termHeight int) int { var maxHeight int if opts.Height.percent { maxHeight = util.Min(termHeight, util.Max(int(opts.Height.size*float64(termHeight)/100.0), opts.MinHeight)) } else { maxHeight = util.Min(termHeight, int(opts.Height.size)) } if opts.InlineInfo { return util.Max(maxHeight, minHeight-1) } return util.Max(maxHeight, minHeight) } renderer = tui.NewLightRenderer(opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, maxHeightFunc) } else { renderer = tui.NewFullscreenRenderer(opts.Theme, opts.Black, opts.Mouse) } wordRubout := "[^[:alnum:]][[:alnum:]]" wordNext := "[[:alnum:]][^[:alnum:]]|(.$)" if opts.FileWord { sep := regexp.QuoteMeta(string(os.PathSeparator)) wordRubout = fmt.Sprintf("%s[^%s]", sep, sep) wordNext = fmt.Sprintf("[^%s]%s|(.$)", sep, sep) } return &Terminal{ initDelay: delay, inlineInfo: opts.InlineInfo, prompt: opts.Prompt, reverse: opts.Reverse, hscroll: opts.Hscroll, hscrollOff: opts.HscrollOff, wordRubout: wordRubout, wordNext: wordNext, cx: len(input), cy: 0, offset: 0, yanked: []rune{}, input: input, multi: opts.Multi, sort: opts.Sort > 0, toggleSort: opts.ToggleSort, delimiter: opts.Delimiter, expect: opts.Expect, keymap: opts.Keymap, execmap: opts.Execmap, pressed: "", printQuery: opts.PrintQuery, history: opts.History, margin: opts.Margin, strong: strongAttr, cycle: opts.Cycle, header: header, header0: header, ansi: opts.Ansi, tabstop: opts.Tabstop, reading: true, jumping: jumpDisabled, jumpLabels: opts.JumpLabels, printer: opts.Printer, merger: EmptyMerger, selected: make(map[int32]selectedItem), reqBox: util.NewEventBox(), preview: opts.Preview, previewer: previewer{"", 0, 0, previewBox != nil && !opts.Preview.hidden}, previewBox: previewBox, eventBox: eventBox, mutex: sync.Mutex{}, suppress: true, slab: util.MakeSlab(slab16Size, slab32Size), theme: opts.Theme, startChan: make(chan bool, 1), tui: renderer, initFunc: func() { renderer.Init() }} }
func (t *Terminal) printHighlighted(item *Item, bold bool, col1 int, col2 int, current bool) { var maxe int for _, offset := range item.offsets { maxe = util.Max(maxe, int(offset[1])) } // Overflow text := make([]rune, len(item.text)) copy(text, item.text) offsets := item.colorOffsets(col2, bold, current) maxWidth := C.MaxX() - 3 - t.marginInt[1] - t.marginInt[3] maxe = util.Constrain(maxe+util.Min(maxWidth/2-2, t.hscrollOff), 0, len(text)) fullWidth := displayWidth(text) if fullWidth > maxWidth { if t.hscroll { // Stri.. matchEndWidth := displayWidth(text[:maxe]) if matchEndWidth <= maxWidth-2 { text, _ = trimRight(text, maxWidth-2) text = append(text, []rune("..")...) } else { // Stri.. if matchEndWidth < fullWidth-2 { text = append(text[:maxe], []rune("..")...) } // ..ri.. var diff int32 text, diff = trimLeft(text, maxWidth-2) // Transform offsets for idx, offset := range offsets { b, e := offset.offset[0], offset.offset[1] b += 2 - diff e += 2 - diff b = util.Max32(b, 2) offsets[idx].offset[0] = b offsets[idx].offset[1] = util.Max32(b, e) } text = append([]rune(".."), text...) } } else { text, _ = trimRight(text, maxWidth-2) text = append(text, []rune("..")...) for idx, offset := range offsets { offsets[idx].offset[0] = util.Min32(offset.offset[0], int32(maxWidth-2)) offsets[idx].offset[1] = util.Min32(offset.offset[1], int32(maxWidth)) } } } var index int32 var substr string var prefixWidth int maxOffset := int32(len(text)) for _, offset := range offsets { b := util.Constrain32(offset.offset[0], index, maxOffset) e := util.Constrain32(offset.offset[1], index, maxOffset) substr, prefixWidth = processTabs(text[index:b], prefixWidth) C.CPrint(col1, bold, substr) if b < e { substr, prefixWidth = processTabs(text[b:e], prefixWidth) C.CPrint(offset.color, offset.bold, substr) } index = e if index >= maxOffset { break } } if index < maxOffset { substr, _ = processTabs(text[index:], prefixWidth) C.CPrint(col1, bold, substr) } }