@@ -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"
@@ -451,6 +452,32 @@ func (w *BufWindow) displayBuffer() {
451452 cursors := b .GetCursors ()
452453
453454 curStyle := config .DefStyle
455+
456+ // Parse showchars which is in the format of option1=val1,option2=val2,...
457+ spacechars := " "
458+ 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 , "=" ) {
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+ }
479+ }
480+
454481 for ; vloc .Y < w .bufHeight ; vloc .Y ++ {
455482 vloc .X = 0
456483
@@ -495,7 +522,7 @@ func (w *BufWindow) displayBuffer() {
495522 }
496523 bloc .X = bslice
497524
498- draw := func (r rune , combc []rune , validrune bool , style tcell.Style , highlight bool , showcursor bool ) {
525+ draw := func (r rune , showoffset int , combc []rune , isplaceholder bool , style tcell.Style , highlight bool , showcursor bool ) {
499526 if nColsBeforeStart <= 0 && vloc .Y >= 0 {
500527 if highlight {
501528 if w .Buf .HighlightSearch && w .Buf .SearchMatch (bloc ) {
@@ -572,25 +599,30 @@ func (w *BufWindow) displayBuffer() {
572599 }
573600 }
574601
575- if r == '\t' || ( r == ' ' && bloc . X < blineLen && validrune ) {
602+ if ( r == '\t' || r == ' ' ) && ! isplaceholder {
576603 var indentrunes []rune
577604 switch r {
578605 case '\t' :
579- indentrunes = []rune (b .Settings ["indenttabchar" ].(string ))
606+ if bloc .X < leadingwsEnd && ! b .Settings ["tabstospaces" ].(bool ) {
607+ indentrunes = []rune (indenttabchars )
608+ } else {
609+ indentrunes = []rune (tabchars )
610+ }
580611 case ' ' :
581- if bloc .X % tabsize == 0 && bloc .X < leadingwsEnd {
582- indentrunes = []rune (b . Settings [ "indentspacechar" ].( string ) )
612+ if bloc .X % tabsize == 0 && bloc .X < leadingwsEnd && b . Settings [ "tabstospaces" ].( bool ) {
613+ indentrunes = []rune (indentspacechars )
583614 } else {
584- indentrunes = []rune (b . Settings [ "spacechar" ].( string ) )
615+ indentrunes = []rune (spacechars )
585616 }
586617 }
587618
588- // if no override for current character, use space
589- if len (indentrunes ) == 0 {
590- indentrunes = []rune {' ' }
619+ if showoffset < len (indentrunes ) {
620+ r = indentrunes [showoffset ]
621+ } else {
622+ // use space if no showchars or after we showed showchars
623+ r = ' '
591624 }
592625
593- r = indentrunes [0 ]
594626 if s , ok := config .Colorscheme ["indent-char" ]; ok && r != ' ' {
595627 fg , _ , _ := s .Decompose ()
596628 style = style .Foreground (fg )
@@ -704,7 +736,7 @@ func (w *BufWindow) displayBuffer() {
704736 // If a word (or just a wide rune) does not fit in the window
705737 if vloc .X + wordwidth > maxWidth && vloc .X > w .gutterOffset {
706738 for vloc .X < maxWidth {
707- draw (' ' , nil , false , config .DefStyle , false , false )
739+ draw (' ' , 0 , nil , true , config .DefStyle , false , false )
708740 }
709741
710742 // We either stop or we wrap to draw the word in the next line
@@ -728,17 +760,14 @@ func (w *BufWindow) displayBuffer() {
728760 }
729761
730762 for _ , r := range word {
731- draw (r .r , r .combc , true , r .style , true , true )
763+ draw (r .r , 0 , r .combc , false , r .style , true , true )
732764
733- // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
734- if r .width > 1 {
735- char := ' '
765+ // Draw any extra characters for tabs
766+ for i := 1 ; i < r .width ; i ++ {
736767 if r .r != '\t' {
737- char = '@'
738- }
739-
740- for i := 1 ; i < r .width ; i ++ {
741- draw (char , nil , false , r .style , true , false )
768+ draw (' ' , i , nil , true , r .style , true , false )
769+ } else {
770+ draw ('\t' , i , nil , false , r .style , true , false )
742771 }
743772 }
744773 bloc .X ++
@@ -792,7 +821,7 @@ func (w *BufWindow) displayBuffer() {
792821
793822 if vloc .X != maxWidth {
794823 // Display newline within a selection
795- draw (' ' , nil , false , config .DefStyle , true , true )
824+ draw (' ' , 0 , nil , true , config .DefStyle , true , true )
796825 }
797826
798827 bloc .X = w .StartCol
0 commit comments