Repository: zyedidia/micro
File: internal/display/bufwindow.go (Go)

Code before:
			}

			if b.Settings["diffgutter"].(bool) {
				w.drawDiffGutter(s, false, &vloc, &bloc)
			}

			if b.Settings["ruler"].(bool) {
				w.drawLineNum(s, false, &vloc, &bloc)
			}
		} else {
			vloc.X = w.gutterOffset
		}

		bline := b.LineBytes(bloc.Y)
		blineLen := util.CharacterCount(bline)

		leadingwsEnd := len(util.GetLeadingWhitespace(bline))
		trailingwsStart := blineLen - util.CharacterCount(util.GetTrailingWhitespace(bline))

		line, nColsBeforeStart, bslice, startStyle := w.getStartInfo(w.StartCol, bloc.Y)
		if startStyle != nil {
			curStyle = *startStyle
		}
		bloc.X = bslice

		draw := func(r rune, showoffset int, combc []rune, isplaceholder bool, style tcell.Style, highlight bool, showcursor bool) {
			if nColsBeforeStart <= 0 && vloc.Y >= 0 {
				if highlight {
					if w.Buf.HighlightSearch && w.Buf.SearchMatch(bloc) {
						style = config.DefStyle.Reverse(true)
						if s, ok := config.Colorscheme["hlsearch"]; ok {
							style = s
						}
					}

					_, origBg, _ := style.Decompose()
					_, defBg, _ := config.DefStyle.Decompose()

					// syntax or hlsearch highlighting with non-default background takes precedence
					// over cursor-line and color-column
					dontOverrideBackground := origBg != defBg

					if b.Settings["hltaberrors"].(bool) {
						if s, ok := config.Colorscheme["tab-error"]; ok {
							isTab := (r == '\t') || (r == ' ' && !showcursor)
							if (b.Settings["tabstospaces"].(bool) && isTab) ||
								(!b.Settings["tabstospaces"].(bool) && bloc.X < leadingwsEnd && r == ' ' && !isTab) {
								fg, _, _ := s.Decompose()
								style = style.Background(fg)
								dontOverrideBackground = true
							}

Review comment (suggestion):
I think it's better to move `isplaceholder` and `showoffset` somewhere close to the end of the list of arguments  (close to other "less important", more "corner-case" arguments `highlight` and `showcursor`).

At least `combc` should be kept after `r` (since `r` and `combc` together represent a displayed visible character).

...But what I'm actually thinking: instead of having these myriads of tricky arguments to `draw()`, it might be much cleaner to let its caller itself determine and pass the exact character to be displayed?

I realize it's not that simple, since `draw()` would also need to know how to highlight this exact character. But... well, the caller itself could pass the needed `style` as well, right?

That would also allow to drop the existing hacky `isTab := (r == '\t') || (r == ' ' && !showcursor)` (which was added, well, by me).

Code after:
			if b.Settings["diffgutter"].(bool) {
				w.drawDiffGutter(s, false, &vloc, &bloc)
			}

			if b.Settings["ruler"].(bool) {
				w.drawLineNum(s, false, &vloc, &bloc)
			}
		} else {
			vloc.X = w.gutterOffset
		}

		bline := b.LineBytes(bloc.Y)
		blineLen := util.CharacterCount(bline)

		leadingwsEnd := len(util.GetLeadingWhitespace(bline))
		trailingwsStart := blineLen - util.CharacterCount(util.GetTrailingWhitespace(bline))

		line, nColsBeforeStart, bslice, startStyle := w.getStartInfo(w.StartCol, bloc.Y)
		if startStyle != nil {
			curStyle = *startStyle
		}
		bloc.X = bslice

		// returns the rune to be drawn, style of it and if the bg should be preserved
		getRuneStyle := func(r rune, style tcell.Style, showoffset int, linex int, isplaceholder bool) (rune, tcell.Style, bool) {
			if nColsBeforeStart > 0 || vloc.Y < 0 || isplaceholder {
				return r, style, false
			}

			for _, mb := range matchingBraces {
				if mb.X == bloc.X && mb.Y == bloc.Y {
					if b.Settings["matchbracestyle"].(string) == "highlight" {
						if s, ok := config.Colorscheme["match-brace"]; ok {
							return r, s, false
						} else {
							return r, style.Reverse(true), false
						}
					} else {
						return r, style.Underline(true), false
					}
				}
			}

			if r != '\t' && r != ' ' {
				return r, style, false
			}

			var indentrunes []rune
			switch r {
			case '\t':
				if bloc.X < leadingwsEnd && indenttabchars != "" {