Skip to content

Commit 33ba259

Browse files
Merge branch 'MoreCharOptions' into dev
2 parents 38183b0 + 4e23c6f commit 33ba259

File tree

2 files changed

+179
-147
lines changed

2 files changed

+179
-147
lines changed

internal/display/bufwindow.go

Lines changed: 157 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -453,28 +453,26 @@ func (w *BufWindow) displayBuffer() {
453453

454454
curStyle := config.DefStyle
455455

456-
// Parse showchars which is in the format of option1=val1,option2=val2,...
456+
// Parse showchars which is in the format of key1=val1,key2=val2,...
457457
spacechars := " "
458458
tabchars := b.Settings["indentchar"].(string)
459-
indentspacechars := " "
460-
indenttabchars := b.Settings["indentchar"].(string)
461-
462-
charsentries := strings.Split(b.Settings["showchars"].(string), ",")
463-
for _, entry := range charsentries {
464-
if !strings.Contains(entry, "=") {
459+
var indentspacechars string
460+
var indenttabchars string
461+
for _, entry := range strings.Split(b.Settings["showchars"].(string), ",") {
462+
split := strings.SplitN(entry, "=", 2)
463+
if len(split) < 2 {
465464
continue
466465
}
467-
entrykey := strings.Split(entry, "=")[0]
468-
entryval := strings.Split(entry, "=")[1]
469-
switch entrykey {
466+
key, val := split[0], split[1]
467+
switch key {
470468
case "space":
471-
spacechars = entryval
469+
spacechars = val
472470
case "tab":
473-
tabchars = entryval
471+
tabchars = val
474472
case "ispace":
475-
indentspacechars = entryval
473+
indentspacechars = val
476474
case "itab":
477-
indenttabchars = entryval
475+
indenttabchars = val
478476
}
479477
}
480478

@@ -522,149 +520,171 @@ func (w *BufWindow) displayBuffer() {
522520
}
523521
bloc.X = bslice
524522

525-
draw := func(r rune, showoffset int, combc []rune, isplaceholder bool, style tcell.Style, highlight bool, showcursor bool) {
526-
if nColsBeforeStart <= 0 && vloc.Y >= 0 {
527-
if highlight {
528-
if w.Buf.HighlightSearch && w.Buf.SearchMatch(bloc) {
529-
style = config.DefStyle.Reverse(true)
530-
if s, ok := config.Colorscheme["hlsearch"]; ok {
531-
style = s
523+
// returns the rune to be drawn, style of it and if the bg should be preserved
524+
getRuneStyle := func(r rune, style tcell.Style, showoffset int, linex int, isplaceholder bool) (rune, tcell.Style, bool) {
525+
if nColsBeforeStart > 0 || vloc.Y < 0 || isplaceholder {
526+
return r, style, false
527+
}
528+
529+
for _, mb := range matchingBraces {
530+
if mb.X == bloc.X && mb.Y == bloc.Y {
531+
if b.Settings["matchbracestyle"].(string) == "highlight" {
532+
if s, ok := config.Colorscheme["match-brace"]; ok {
533+
return r, s, false
534+
} else {
535+
return r, style.Reverse(true), false
532536
}
537+
} else {
538+
return r, style.Underline(true), false
533539
}
540+
}
541+
}
534542

535-
_, origBg, _ := style.Decompose()
536-
_, defBg, _ := config.DefStyle.Decompose()
537-
538-
// syntax or hlsearch highlighting with non-default background takes precedence
539-
// over cursor-line and color-column
540-
dontOverrideBackground := origBg != defBg
541-
542-
if b.Settings["hltaberrors"].(bool) {
543-
if s, ok := config.Colorscheme["tab-error"]; ok {
544-
isTab := (r == '\t') || (r == ' ' && !showcursor)
545-
if (b.Settings["tabstospaces"].(bool) && isTab) ||
546-
(!b.Settings["tabstospaces"].(bool) && bloc.X < leadingwsEnd && r == ' ' && !isTab) {
547-
fg, _, _ := s.Decompose()
548-
style = style.Background(fg)
549-
dontOverrideBackground = true
550-
}
551-
}
543+
if r != '\t' && r != ' ' {
544+
return r, style, false
545+
}
546+
547+
var indentrunes []rune
548+
switch r {
549+
case '\t':
550+
if bloc.X < leadingwsEnd && indenttabchars != "" {
551+
indentrunes = []rune(indenttabchars)
552+
} else {
553+
indentrunes = []rune(tabchars)
554+
}
555+
case ' ':
556+
if linex%tabsize == 0 && bloc.X < leadingwsEnd && indentspacechars != "" {
557+
indentrunes = []rune(indentspacechars)
558+
} else {
559+
indentrunes = []rune(spacechars)
560+
}
561+
}
562+
563+
var drawrune rune
564+
if showoffset < len(indentrunes) {
565+
drawrune = indentrunes[showoffset]
566+
} else {
567+
// use space if no showchars or after we showed showchars
568+
drawrune = ' '
569+
}
570+
571+
if s, ok := config.Colorscheme["indent-char"]; ok {
572+
fg, _, _ := s.Decompose()
573+
style = style.Foreground(fg)
574+
}
575+
576+
preservebg := false
577+
if b.Settings["hltaberrors"].(bool) && bloc.X < leadingwsEnd {
578+
if s, ok := config.Colorscheme["tab-error"]; ok {
579+
if b.Settings["tabstospaces"].(bool) && r == '\t' {
580+
fg, _, _ := s.Decompose()
581+
style = style.Background(fg)
582+
preservebg = true
583+
} else if !b.Settings["tabstospaces"].(bool) && r == ' ' {
584+
fg, _, _ := s.Decompose()
585+
style = style.Background(fg)
586+
preservebg = true
552587
}
588+
}
589+
}
553590

554-
if b.Settings["hltrailingws"].(bool) {
555-
if s, ok := config.Colorscheme["trailingws"]; ok {
556-
if bloc.X >= trailingwsStart && bloc.X < blineLen {
557-
hl := true
558-
for _, c := range cursors {
559-
if c.NewTrailingWsY == bloc.Y {
560-
hl = false
561-
break
562-
}
563-
}
564-
if hl {
565-
fg, _, _ := s.Decompose()
566-
style = style.Background(fg)
567-
dontOverrideBackground = true
568-
}
591+
if b.Settings["hltrailingws"].(bool) {
592+
if s, ok := config.Colorscheme["trailingws"]; ok {
593+
if bloc.X >= trailingwsStart && bloc.X < blineLen {
594+
hl := true
595+
for _, c := range cursors {
596+
if c.NewTrailingWsY == bloc.Y {
597+
hl = false
598+
break
569599
}
570600
}
601+
if hl {
602+
fg, _, _ := s.Decompose()
603+
style = style.Background(fg)
604+
preservebg = true
605+
}
571606
}
607+
}
608+
}
572609

573-
for _, c := range cursors {
574-
if c.HasSelection() &&
575-
(bloc.GreaterEqual(c.CurSelection[0]) && bloc.LessThan(c.CurSelection[1]) ||
576-
bloc.LessThan(c.CurSelection[0]) && bloc.GreaterEqual(c.CurSelection[1])) {
577-
// The current character is selected
578-
style = config.DefStyle.Reverse(true)
610+
return drawrune, style, preservebg
611+
}
579612

580-
if s, ok := config.Colorscheme["selection"]; ok {
581-
style = s
582-
}
583-
}
613+
draw := func(r rune, combc []rune, style tcell.Style, highlight bool, showcursor bool, preservebg bool) {
614+
defer func() {
615+
if nColsBeforeStart <= 0 {
616+
vloc.X++
617+
}
618+
nColsBeforeStart--
619+
}()
584620

585-
if b.Settings["cursorline"].(bool) && w.active && !dontOverrideBackground &&
586-
!c.HasSelection() && c.Y == bloc.Y {
587-
if s, ok := config.Colorscheme["cursor-line"]; ok {
588-
fg, _, _ := s.Decompose()
589-
style = style.Background(fg)
590-
}
591-
}
592-
}
621+
if nColsBeforeStart > 0 || vloc.Y < 0 {
622+
return
623+
}
593624

594-
for _, m := range b.Messages {
595-
if bloc.GreaterEqual(m.Start) && bloc.LessThan(m.End) ||
596-
bloc.LessThan(m.End) && bloc.GreaterEqual(m.Start) {
597-
style = style.Underline(true)
598-
break
599-
}
625+
if highlight {
626+
if w.Buf.HighlightSearch && w.Buf.SearchMatch(bloc) {
627+
style = config.DefStyle.Reverse(true)
628+
if s, ok := config.Colorscheme["hlsearch"]; ok {
629+
style = s
600630
}
631+
}
601632

602-
if (r == '\t' || r == ' ') && !isplaceholder {
603-
var indentrunes []rune
604-
switch r {
605-
case '\t':
606-
if bloc.X < leadingwsEnd && !b.Settings["tabstospaces"].(bool) {
607-
indentrunes = []rune(indenttabchars)
608-
} else {
609-
indentrunes = []rune(tabchars)
610-
}
611-
case ' ':
612-
if bloc.X%tabsize == 0 && bloc.X < leadingwsEnd && b.Settings["tabstospaces"].(bool) {
613-
indentrunes = []rune(indentspacechars)
614-
} else {
615-
indentrunes = []rune(spacechars)
616-
}
617-
}
633+
_, origBg, _ := style.Decompose()
634+
_, defBg, _ := config.DefStyle.Decompose()
618635

619-
if showoffset < len(indentrunes) {
620-
r = indentrunes[showoffset]
621-
} else {
622-
// use space if no showchars or after we showed showchars
623-
r = ' '
624-
}
636+
// syntax or hlsearch highlighting with non-default background takes precedence
637+
// over cursor-line and color-column
638+
if !preservebg && origBg != defBg {
639+
preservebg = true
640+
}
625641

626-
if s, ok := config.Colorscheme["indent-char"]; ok && r != ' ' {
627-
fg, _, _ := s.Decompose()
628-
style = style.Foreground(fg)
642+
for _, c := range cursors {
643+
if c.HasSelection() &&
644+
(bloc.GreaterEqual(c.CurSelection[0]) && bloc.LessThan(c.CurSelection[1]) ||
645+
bloc.LessThan(c.CurSelection[0]) && bloc.GreaterEqual(c.CurSelection[1])) {
646+
// The current character is selected
647+
style = config.DefStyle.Reverse(true)
648+
649+
if s, ok := config.Colorscheme["selection"]; ok {
650+
style = s
629651
}
630652
}
631653

632-
if s, ok := config.Colorscheme["color-column"]; ok {
633-
if colorcolumn != 0 && vloc.X-w.gutterOffset+w.StartCol == colorcolumn && !dontOverrideBackground {
654+
if b.Settings["cursorline"].(bool) && w.active && !preservebg &&
655+
!c.HasSelection() && c.Y == bloc.Y {
656+
if s, ok := config.Colorscheme["cursor-line"]; ok {
634657
fg, _, _ := s.Decompose()
635658
style = style.Background(fg)
636659
}
637660
}
661+
}
638662

639-
for _, mb := range matchingBraces {
640-
if mb.X == bloc.X && mb.Y == bloc.Y {
641-
if b.Settings["matchbracestyle"].(string) == "highlight" {
642-
if s, ok := config.Colorscheme["match-brace"]; ok {
643-
style = s
644-
} else {
645-
style = style.Reverse(true)
646-
}
647-
} else {
648-
style = style.Underline(true)
649-
}
650-
}
663+
for _, m := range b.Messages {
664+
if bloc.GreaterEqual(m.Start) && bloc.LessThan(m.End) ||
665+
bloc.LessThan(m.End) && bloc.GreaterEqual(m.Start) {
666+
style = style.Underline(true)
667+
break
651668
}
652669
}
653670

654-
screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, r, combc, style)
655-
656-
if showcursor {
657-
for _, c := range cursors {
658-
if c.X == bloc.X && c.Y == bloc.Y && !c.HasSelection() {
659-
w.showCursor(w.X+vloc.X, w.Y+vloc.Y, c.Num == 0)
660-
}
671+
if s, ok := config.Colorscheme["color-column"]; ok {
672+
if colorcolumn != 0 && vloc.X-w.gutterOffset+w.StartCol == colorcolumn && !preservebg {
673+
fg, _, _ := s.Decompose()
674+
style = style.Background(fg)
661675
}
662676
}
663677
}
664-
if nColsBeforeStart <= 0 {
665-
vloc.X++
678+
679+
screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, r, combc, style)
680+
681+
if showcursor {
682+
for _, c := range cursors {
683+
if c.X == bloc.X && c.Y == bloc.Y && !c.HasSelection() {
684+
w.showCursor(w.X+vloc.X, w.Y+vloc.Y, c.Num == 0)
685+
}
686+
}
666687
}
667-
nColsBeforeStart--
668688
}
669689

670690
wrap := func() {
@@ -712,6 +732,7 @@ func (w *BufWindow) displayBuffer() {
712732

713733
width := 0
714734

735+
linex := totalwidth
715736
switch r {
716737
case '\t':
717738
ts := tabsize - (totalwidth % tabsize)
@@ -736,7 +757,7 @@ func (w *BufWindow) displayBuffer() {
736757
// If a word (or just a wide rune) does not fit in the window
737758
if vloc.X+wordwidth > maxWidth && vloc.X > w.gutterOffset {
738759
for vloc.X < maxWidth {
739-
draw(' ', 0, nil, true, config.DefStyle, false, false)
760+
draw(' ', nil, config.DefStyle, false, false, true)
740761
}
741762

742763
// We either stop or we wrap to draw the word in the next line
@@ -760,15 +781,17 @@ func (w *BufWindow) displayBuffer() {
760781
}
761782

762783
for _, r := range word {
763-
draw(r.r, 0, r.combc, false, r.style, true, true)
784+
drawrune, drawstyle, preservebg := getRuneStyle(r.r, r.style, 0, linex, false)
785+
draw(drawrune, r.combc, drawstyle, true, true, preservebg)
764786

765-
// Draw any extra characters for tabs
787+
// Draw extra characters for tabs or wide runes
766788
for i := 1; i < r.width; i++ {
767-
if r.r != '\t' {
768-
draw(' ', i, nil, true, r.style, true, false)
789+
if r.r == '\t' {
790+
drawrune, drawstyle, preservebg = getRuneStyle('\t', r.style, i, linex+i, false)
769791
} else {
770-
draw('\t', i, nil, false, r.style, true, false)
792+
drawrune, drawstyle, preservebg = getRuneStyle(' ', r.style, i, linex+i, true)
771793
}
794+
draw(drawrune, nil, drawstyle, true, false, preservebg)
772795
}
773796
bloc.X++
774797
}
@@ -821,7 +844,8 @@ func (w *BufWindow) displayBuffer() {
821844

822845
if vloc.X != maxWidth {
823846
// Display newline within a selection
824-
draw(' ', 0, nil, true, config.DefStyle, true, true)
847+
drawrune, drawstyle, preservebg := getRuneStyle(' ', config.DefStyle, 0, totalwidth, true)
848+
draw(drawrune, nil, drawstyle, true, true, preservebg)
825849
}
826850

827851
bloc.X = w.StartCol

0 commit comments

Comments
 (0)