list.go
func (l *List) Display(where Location) {
	if len(l.content) == 0 || l.visibility == VisibilityHide {
		return
	}

	c := l.content

	// XXX this isn't 100% correct since it doesn't handle wrapping lines.
	switch where {
	case Current:
	case Top:
		if len(c) > l.trueH {
			l.at = 0
			l.paging = true
		}
	case Bottom:
		l.at = len(c) - l.trueH
		if l.at < 0 {
			l.at = 0
		}
		l.paging = false

	case Up:
		l.at = l.at - l.trueH + 1
		if l.at < 0 {
			l.at = 0
		}
		l.paging = true

	case Down:
		y := l.at + l.trueH - 1
		if y+l.trueH > len(c) {
			l.Display(Bottom)
			return
		}
		l.at = y
		l.paging = true

	default:
		return
	}

	c = c[l.at : l.at+l.trueH]

	// create a buffer with all lines neatly clipped
	buffer := make([][]rune, 0, l.trueH*2)
	for _, s := range c {
		printWidth := 0
		start := 0
		var lastColor, leftover string
		var cc string // color continuation on next line
		for i := 0; i < len(s); {
			r, width := utf8.DecodeRuneInString(s[i:])
			if r == '\x1b' {
				_, skip, err := DecodeColor(s[i:])
				if err == nil {
					lastColor = s[i : i+skip]
					i += skip
					leftover = s[start:i]
					continue
				}
			}
			i += width
			printWidth++
			if printWidth > l.trueW-1 {
				// clip, so reset start and printWidth
				buffer = append(buffer,
					[]rune(lastColor+s[start:i]))
				start = i
				printWidth = 0
				cc = lastColor
				if start == len(s) {
					// we ended exactly with a color on
					// term boundary, clear out leftover
					// that was set in lastColor check
					leftover = ""
					break
				}
				continue
			} else if i < len(s) {
				// we do this unecessary song and dance to only
				// assign leftover once
				continue
			}
			leftover = s[start:i]
			break // will always break but do it anyway for clarity
		}
		if leftover != "" {
			// done clipping, next line
			filler := strings.Repeat(" ", l.trueW-printWidth)
			buffer = append(buffer, []rune(cc+leftover+filler))
		}
	}

	// now clip buffer to widget l.trueH; we only want to show bottom
	// l.trueH lines
	if len(buffer) > l.trueH {
		buffer = buffer[len(buffer)-l.trueH:]
	}
	x := 0
	for i, v := range buffer {
		l.w.printf(x, l.trueY+i, l.attr, "%v", string(v))
	}
}
func (l *List) Display(where Location) {
	if len(l.content) == 0 || l.visibility == VisibilityHide {
		return
	}

	c := l.content

	// XXX this isn't 100% correct since it doesn't handle wrapping lines.
	switch where {
	case Current:
	case Top:
		if len(c) > l.trueH {
			l.at = 0
			l.paging = true
		}
	case Bottom:
		l.at = len(c) - l.trueH
		if l.at < 0 {
			l.at = 0
		}
		l.paging = false

	case Up:
		l.at = l.at - l.trueH + 1
		if l.at < 0 {
			l.at = 0
		}
		l.paging = true

	case Down:
		y := l.at + l.trueH - 1
		if y+l.trueH > len(c) {
			l.Display(Bottom)
			return
		}
		l.at = y
		l.paging = true

	default:
		return
	}

	c = c[l.at : l.at+l.trueH]

	// create a buffer with all lines neatly clipped
	buffer := make([][]rune, 0, l.trueH*2)
	for _, s := range c {
		printWidth := 0
		start := 0
		var lastColor, leftover string
		var cc string // color continuation on next line
		for i := 0; i < len(s); {
			r, width := utf8.DecodeRuneInString(s[i:])
			if r == '\x1b' {
				_, skip, err := DecodeColor(s[i:])
				if err == nil {
					lastColor = s[i : i+skip]
					i += skip
					leftover = s[start:i]
					continue
				}
			}
			i += width
			printWidth++
			if printWidth > l.trueW-1 {
				// clip, so reset start and printWidth
				buffer = append(buffer,
					[]rune(lastColor+s[start:i]))
				start = i
				printWidth = 0
				cc = lastColor
				if start == len(s) {
					// we ended exactly with a color on
					// term boundary, clear out leftover
					// that was set in lastColor check
					leftover = ""
					break
				}
				continue
			} else if i < len(s) {
				// we do this unecessary song and dance to only
				// assign leftover once
				continue
			}
			leftover = s[start:i]
			break // will always break but do it anyway for clarity
		}
		if leftover != "" {
			// done clipping, next line
			filler := strings.Repeat(" ", l.trueW-printWidth)
			buffer = append(buffer, []rune(cc+leftover+filler))
		}
	}

	// now clip buffer to widget l.trueH; we only want to show bottom
	// l.trueH lines
	if len(buffer) > l.trueH {
		buffer = buffer[len(buffer)-l.trueH:]
	}
	x := 0
	for i, v := range buffer {
		l.w.printf(x, l.trueY+i, l.attr, "%v", string(v))
	}
}
func ( l * List ) Display ( where Location ) { if len ( l . content ) == 0 || l . visibility == VisibilityHide { return } c := l . content // XXX this isn't 100% correct since it doesn't handle wrapping lines. switch where { case Current : case Top : if len ( c ) > l . trueH { l . at = 0 l . paging = true } case Bottom : l . at = len ( c ) - l . trueH if l . at < 0 { l . at = 0 } l . paging = false case Up : l . at = l . at - l . trueH + 1 if l . at < 0 { l . at = 0 } l . paging = true case Down : y := l . at + l . trueH - 1 if y + l . trueH > len ( c ) { l . Display ( Bottom ) return } l . at = y l . paging = true default : return } c = c [ l . at : l . at + l . trueH ] // create a buffer with all lines neatly clipped buffer := make ( [ ] [ ] rune , 0 , l . trueH * 2 ) for _ , s := range c { printWidth := 0 start := 0 var lastColor , leftover string var cc string // color continuation on next line for i := 0 ; i < len ( s ) ; { r , width := utf8 . DecodeRuneInString ( s [ i : ] ) if r == '\x1b' { _ , skip , err := DecodeColor ( s [ i : ] ) if err == nil { lastColor = s [ i : i + skip ] i += skip leftover = s [ start : i ] continue } } i += width printWidth ++ if printWidth > l . trueW - 1 { // clip, so reset start and printWidth buffer = append ( buffer , [ ] rune ( lastColor + s [ start : i ] ) ) start = i printWidth = 0 cc = lastColor if start == len ( s ) { // we ended exactly with a color on // term boundary, clear out leftover // that was set in lastColor check leftover = " " break } continue } else if i < len ( s ) { // we do this unecessary song and dance to only // assign leftover once continue } leftover = s [ start : i ] break // will always break but do it anyway for clarity } if leftover != " " { // done clipping, next line filler := strings . Repeat ( " " , l . trueW - printWidth ) buffer = append ( buffer , [ ] rune ( cc + leftover + filler ) ) } } // now clip buffer to widget l.trueH; we only want to show bottom // l.trueH lines if len ( buffer ) > l . trueH { buffer = buffer [ len ( buffer ) - l . trueH : ] } x := 0 for i , v := range buffer { l . w . printf ( x , l . trueY + i , l . attr , " " , string ( v ) ) } }
// Display renders the widget.  This is called from queue context so be careful
// to not use blocking calls.
Display renders the widget . This is called from queue context so be careful to not use blocking calls .