Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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))
}
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
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))
}
Ejemplo n.º 5
0
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
}
Ejemplo n.º 6
0
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
}
Ejemplo n.º 7
0
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
}
Ejemplo n.º 8
0
func makeModeLine(text string, width int) *buffer {
	b := newBuffer(width)
	b.writes(util.TrimWcwidth(text, width), styleForMode)
	b.dot = b.cursor()
	return b
}
Ejemplo n.º 9
0
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))
}