@@ -2,6 +2,7 @@ package display
22
33import (
44 "strconv"
5+ "strings"
56
67 runewidth "github.com/mattn/go-runewidth"
78 "github.com/micro-editor/tcell/v2"
@@ -450,6 +451,35 @@ func (w *BufWindow) displayBuffer() {
450451 cursors := b .GetCursors ()
451452
452453 curStyle := config .DefStyle
454+
455+ // Parse showchars which is in the format of option1=val1,option2=val2,...
456+ spacechars := " "
457+ tabchars := b .Settings ["indentchar" ].(string )
458+ indentspacechars := " "
459+ indenttabchars := b .Settings ["indentchar" ].(string )
460+ incompletechars := " "
461+
462+ charsentries := strings .Split (b .Settings ["showchars" ].(string ), "," )
463+ for _ , entry := range charsentries {
464+ if ! strings .Contains (entry , "=" ) {
465+ continue
466+ }
467+ entrykey := strings .Split (entry , "=" )[0 ]
468+ entryval := strings .Split (entry , "=" )[1 ]
469+ switch entrykey {
470+ case "space" :
471+ spacechars = entryval
472+ case "tab" :
473+ tabchars = entryval
474+ case "ispace" :
475+ indentspacechars = entryval
476+ case "itab" :
477+ indenttabchars = entryval
478+ case "incomplete" :
479+ incompletechars = entryval
480+ }
481+ }
482+
453483 for ; vloc .Y < w .bufHeight ; vloc .Y ++ {
454484 vloc .X = 0
455485
@@ -494,7 +524,7 @@ func (w *BufWindow) displayBuffer() {
494524 }
495525 bloc .X = bslice
496526
497- draw := func (r rune , combc []rune , style tcell.Style , highlight bool , showcursor bool ) {
527+ draw := func (r rune , showoffset int , combc []rune , isplaceholder bool , style tcell.Style , highlight bool , showcursor bool ) {
498528 if nColsBeforeStart <= 0 && vloc .Y >= 0 {
499529 if highlight {
500530 if w .Buf .HighlightSearch && w .Buf .SearchMatch (bloc ) {
@@ -571,14 +601,30 @@ func (w *BufWindow) displayBuffer() {
571601 }
572602 }
573603
574- if r == '\t' {
575- indentrunes := []rune (b .Settings ["indentchar" ].(string ))
576- // if empty indentchar settings, use space
577- if len (indentrunes ) == 0 {
578- indentrunes = []rune {' ' }
604+ if (r == '\t' || r == ' ' ) && ! isplaceholder {
605+ var indentrunes []rune
606+ switch r {
607+ case '\t' :
608+ if bloc .X < leadingwsEnd && ! b .Settings ["tabstospaces" ].(bool ) {
609+ indentrunes = []rune (indenttabchars )
610+ } else {
611+ indentrunes = []rune (tabchars )
612+ }
613+ case ' ' :
614+ if bloc .X % tabsize == 0 && bloc .X < leadingwsEnd && b .Settings ["tabstospaces" ].(bool ) {
615+ indentrunes = []rune (indentspacechars )
616+ } else {
617+ indentrunes = []rune (spacechars )
618+ }
619+ }
620+
621+ if showoffset < len (indentrunes ) {
622+ r = indentrunes [showoffset ]
623+ } else {
624+ // use space if no showchars or after we showed showchars
625+ r = ' '
579626 }
580627
581- r = indentrunes [0 ]
582628 if s , ok := config .Colorscheme ["indent-char" ]; ok && r != ' ' {
583629 fg , _ , _ := s .Decompose ()
584630 style = style .Foreground (fg )
@@ -692,7 +738,7 @@ func (w *BufWindow) displayBuffer() {
692738 // If a word (or just a wide rune) does not fit in the window
693739 if vloc .X + wordwidth > maxWidth && vloc .X > w .gutterOffset {
694740 for vloc .X < maxWidth {
695- draw (' ' , nil , config .DefStyle , false , false )
741+ draw (' ' , 0 , nil , true , config .DefStyle , false , false )
696742 }
697743
698744 // We either stop or we wrap to draw the word in the next line
@@ -708,17 +754,20 @@ func (w *BufWindow) displayBuffer() {
708754 }
709755
710756 for _ , r := range word {
711- draw (r .r , r .combc , r .style , true , true )
757+ draw (r .r , 0 , r .combc , false , r .style , true , true )
712758
713- // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
759+ // Draw any extra characters for tabs or incomplete wide runes
714760 if r .width > 1 {
715- char := ' '
716- if r .r != '\t' {
717- char = '@'
718- }
719-
720761 for i := 1 ; i < r .width ; i ++ {
721- draw (char , nil , r .style , true , false )
762+ if r .r != '\t' {
763+ if i < len (incompletechars ) {
764+ draw ([]rune (incompletechars )[i ], i , nil , false , r .style , true , false )
765+ } else {
766+ draw (' ' , i , nil , true , r .style , true , false )
767+ }
768+ } else {
769+ draw ('\t' , i , nil , false , r .style , true , false )
770+ }
722771 }
723772 }
724773 bloc .X ++
@@ -764,7 +813,7 @@ func (w *BufWindow) displayBuffer() {
764813
765814 if vloc .X != maxWidth {
766815 // Display newline within a selection
767- draw (' ' , nil , config .DefStyle , true , true )
816+ draw (' ' , 0 , nil , true , config .DefStyle , true , true )
768817 }
769818
770819 bloc .X = w .StartCol
0 commit comments