func (l *listing) ModeLine(width int) *buffer { title := l.provider.ModeTitle(l.selected) // TODO keep it one line. b := newBuffer(width) b.writes(util.TrimWcwidth(title, width), styleForMode) b.writes(" ", "") b.writes(l.filter, styleForFilter) b.dot = b.cursor() return b }
func moveDotUp(ed *Editor) { sol := util.FindLastSOL(ed.line[:ed.dot]) if sol == 0 { ed.flash() return } prevEOL := sol - 1 prevSOL := util.FindLastSOL(ed.line[:prevEOL]) width := util.Wcswidth(ed.line[sol:ed.dot]) ed.dot = prevSOL + len(util.TrimWcwidth(ed.line[prevSOL:prevEOL], width)) }
func (n *navigation) ModeLine(width int) *buffer { s := " NAVIGATING " if n.showHidden { s += "(show hidden) " } b := newBuffer(width) b.writes(util.TrimWcwidth(s, width), styleForMode) b.writes(" ", "") b.writes(n.filter, styleForFilter) b.dot = b.cursor() return b }
func moveDotDown(ed *Editor) { eol := util.FindFirstEOL(ed.line[ed.dot:]) + ed.dot if eol == len(ed.line) { ed.flash() return } nextSOL := eol + 1 nextEOL := util.FindFirstEOL(ed.line[nextSOL:]) + nextSOL sol := util.FindLastSOL(ed.line[:ed.dot]) width := util.Wcswidth(ed.line[sol:ed.dot]) ed.dot = nextSOL + len(util.TrimWcwidth(ed.line[nextSOL:nextEOL], width)) }
func (c *completion) ModeLine(width int) *buffer { b := newBuffer(width) b.writes(" ", "") // Write title title := fmt.Sprintf("COMPLETING %s", c.completer) b.writes(util.TrimWcwidth(title, width), styleForMode.String()) // Write filter if c.filtering { b.writes(" ", "") b.writes(c.filter, styleForFilter.String()) b.dot = b.cursor() } // Write horizontal scrollbar, using the remaining space if c.needScrollbar() { scrollbarWidth := width - lineWidth(b.cells[len(b.cells)-1]) - 2 if scrollbarWidth >= 3 { b.writes(" ", "") writeHorizontalScrollbar(b, len(c.candidates), c.firstShown, c.lastShownInFull+1, scrollbarWidth) } } return b }
func (l *listing) List(width, maxHeight int) *buffer { n := l.provider.Len() b := newBuffer(width) if n == 0 { var ph string if pher, ok := l.provider.(Placeholderer); ok { ph = pher.Placeholder() } else { ph = "(no result)" } b.writes(util.TrimWcwidth(ph, width), "") return b } // Collect the entries to show. We start from the selected entry and extend // in both directions alternatingly. The entries are split into lines and // then collected in a list. low := l.selected if low == -1 { low = 0 } high := low height := 0 var lines list.List getEntry := func(i int) []styled { s := l.provider.Show(i, width) lines := strings.Split(s.text, "\n") style := s.style if i == l.selected { style = joinStyle(style, styleForSelected) } styleds := make([]styled, len(lines)) for i, line := range lines { styleds[i] = styled{line, style} } return styleds } // We start by extending high, so that the first entry to include is // l.selected. extendLow := false lastShownIncomplete := false for height < maxHeight && !(low == 0 && high == n) { var i int if (extendLow && low > 0) || high == n { low-- entry := getEntry(low) // Prepend at most the last (height - maxHeight) lines. for i = len(entry) - 1; i >= 0 && height < maxHeight; i-- { lines.PushFront(entry[i]) height++ } if i >= 0 { lastShownIncomplete = true } } else { entry := getEntry(high) // Append at most the first (height - maxHeight) lines. for i = 0; i < len(entry) && height < maxHeight; i++ { lines.PushBack(entry[i]) height++ } if i < len(entry) { lastShownIncomplete = true } high++ } extendLow = !extendLow } l.pagesize = high - low var scrollbar *buffer if low > 0 || high < n || lastShownIncomplete { scrollbar = renderScrollbar(n, low, high, height) width-- } for p := lines.Front(); p != nil; p = p.Next() { s := p.Value.(styled) if p != lines.Front() { b.newline() } b.writes(s.text, s.style) } if scrollbar != nil { b.extendHorizontal(scrollbar, width) } return b }
func (comp *completion) List(width, maxHeight int) *buffer { b := newBuffer(width) cands := comp.candidates if len(cands) == 0 { b.writes(util.TrimWcwidth("(no result)", width), "") return b } if maxHeight <= 1 || width <= 2 { b.writes(util.TrimWcwidth("(terminal too small)", width), "") return b } // Reserve the leftmost row and the rightmost row as margins. width -= 2 // Determine comp.height and comp.firstShown. // First determine whether all candidates can be fit in the screen, // assuming that they are all of maximum width. If that is the case, we use // the computed height as the height for the listing, and the first // candidate to show is 0. Otherwise, we use min(height, len(cands)) as the // height and find the first candidate to show. perLine := max(1, width/(comp.maxWidth(0, len(cands))+completionColMarginTotal)) heightBound := util.CeilDiv(len(cands), perLine) first := 0 height := 0 if heightBound < maxHeight { height = heightBound } else { height = min(maxHeight, len(cands)) // Determine the first column to show. We start with the column in which the // selected one is found, moving to the left until either the width is // exhausted, or the old value of firstShown has been hit. first = comp.selected / height * height w := comp.maxWidth(first, first+height) + completionColMarginTotal for ; first > comp.firstShown; first -= height { dw := comp.maxWidth(first-height, first) + completionColMarginTotal if w+dw > width { break } w += dw } } comp.height = height comp.firstShown = first var i, j int remainedWidth := width trimmed := false // Show the results in columns, until width is exceeded. for i = first; i < len(cands); i += height { // Determine the width of the column (without the margin) colWidth := comp.maxWidth(i, min(i+height, len(cands))) totalColWidth := colWidth + completionColMarginTotal if totalColWidth > remainedWidth { totalColWidth = remainedWidth colWidth = totalColWidth - completionColMarginTotal trimmed = true } col := newBuffer(totalColWidth) for j = i; j < i+height; j++ { if j > i { col.newline() } if j >= len(cands) { // Write padding to make the listing a rectangle. col.writePadding(totalColWidth, styleForCompletion.String()) } else { col.writePadding(completionColMarginLeft, styleForCompletion.String()) s := joinStyles(styleForCompletion, cands[j].display.styles) if j == comp.selected { s = append(s, styleForSelectedCompletion.String()) } col.writes(util.ForceWcwidth(cands[j].display.text, colWidth), s.String()) col.writePadding(completionColMarginRight, styleForCompletion.String()) if !trimmed { comp.lastShownInFull = j } } } // Set w=1 for the leftmost margin. b.extendHorizontal(col, 1) remainedWidth -= totalColWidth if remainedWidth <= completionColMarginTotal { break } } // When the listing is incomplete, always use up the entire width. if remainedWidth > 0 && comp.needScrollbar() { col := newBuffer(remainedWidth) for i := 0; i < height; i++ { if i > 0 { col.newline() } col.writePadding(remainedWidth, styleForCompletion.String()) } b.extendHorizontal(col, 0) remainedWidth = 0 } return b }
func makeModeLine(text string, width int) *buffer { b := newBuffer(width) b.writes(util.TrimWcwidth(text, width), styleForMode) b.dot = b.cursor() return b }
func (loc *location) Show(i, width int) styled { cand := loc.filtered[i] return unstyled(util.TrimWcwidth(fmt.Sprintf("%4.0f %s", cand.Score, parse.Quote(cand.Path)), width)) }