Skip to content

Commit 71d5c09

Browse files
Adding showchars option and removing @ for wide rune in bufwindow
1 parent 98ff79d commit 71d5c09

File tree

3 files changed

+76
-26
lines changed

3 files changed

+76
-26
lines changed

internal/config/settings.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ var defaultCommonSettings = map[string]interface{}{
7070
"hltrailingws": false,
7171
"ignorecase": true,
7272
"incsearch": true,
73-
"indentchar": " ",
73+
"indentchar": " ", // Deprecated
7474
"keepautoindent": false,
7575
"matchbrace": true,
7676
"matchbraceleft": true,
@@ -88,6 +88,7 @@ var defaultCommonSettings = map[string]interface{}{
8888
"scrollbar": false,
8989
"scrollmargin": float64(3),
9090
"scrollspeed": float64(2),
91+
"showchars": "",
9192
"smartpaste": true,
9293
"softwrap": false,
9394
"splitbottom": true,
@@ -210,6 +211,7 @@ func validateParsedSettings() error {
210211
}
211212
continue
212213
}
214+
213215
if _, ok := defaults[k]; ok {
214216
if e := verifySetting(k, v, defaults[k]); e != nil {
215217
err = e

internal/display/bufwindow.go

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package display
22

33
import (
44
"strconv"
5+
"strings"
56

67
runewidth "github.com/mattn/go-runewidth"
78
"github.com/micro-editor/tcell/v2"
@@ -450,6 +451,32 @@ 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+
461+
charsentries := strings.Split(b.Settings["showchars"].(string), ",")
462+
for _, entry := range charsentries {
463+
if !strings.Contains(entry, "=") {
464+
continue
465+
}
466+
entrykey := strings.Split(entry, "=")[0]
467+
entryval := strings.Split(entry, "=")[1]
468+
switch entrykey {
469+
case "space":
470+
spacechars = entryval
471+
case "tab":
472+
tabchars = entryval
473+
case "ispace":
474+
indentspacechars = entryval
475+
case "itab":
476+
indenttabchars = entryval
477+
}
478+
}
479+
453480
for ; vloc.Y < w.bufHeight; vloc.Y++ {
454481
vloc.X = 0
455482

@@ -494,7 +521,7 @@ func (w *BufWindow) displayBuffer() {
494521
}
495522
bloc.X = bslice
496523

497-
draw := func(r rune, combc []rune, style tcell.Style, highlight bool, showcursor bool) {
524+
draw := func(r rune, showoffset int, combc []rune, isplaceholder bool, style tcell.Style, highlight bool, showcursor bool) {
498525
if nColsBeforeStart <= 0 && vloc.Y >= 0 {
499526
if highlight {
500527
if w.Buf.HighlightSearch && w.Buf.SearchMatch(bloc) {
@@ -571,14 +598,30 @@ func (w *BufWindow) displayBuffer() {
571598
}
572599
}
573600

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{' '}
601+
if (r == '\t' || r == ' ') && !isplaceholder {
602+
var indentrunes []rune
603+
switch r {
604+
case '\t':
605+
if bloc.X < leadingwsEnd && !b.Settings["tabstospaces"].(bool) {
606+
indentrunes = []rune(indenttabchars)
607+
} else {
608+
indentrunes = []rune(tabchars)
609+
}
610+
case ' ':
611+
if bloc.X%tabsize == 0 && bloc.X < leadingwsEnd && b.Settings["tabstospaces"].(bool) {
612+
indentrunes = []rune(indentspacechars)
613+
} else {
614+
indentrunes = []rune(spacechars)
615+
}
616+
}
617+
618+
if showoffset < len(indentrunes) {
619+
r = indentrunes[showoffset]
620+
} else {
621+
// use space if no showchars or after we showed showchars
622+
r = ' '
579623
}
580624

581-
r = indentrunes[0]
582625
if s, ok := config.Colorscheme["indent-char"]; ok && r != ' ' {
583626
fg, _, _ := s.Decompose()
584627
style = style.Foreground(fg)
@@ -692,7 +735,7 @@ func (w *BufWindow) displayBuffer() {
692735
// If a word (or just a wide rune) does not fit in the window
693736
if vloc.X+wordwidth > maxWidth && vloc.X > w.gutterOffset {
694737
for vloc.X < maxWidth {
695-
draw(' ', nil, config.DefStyle, false, false)
738+
draw(' ', 0, nil, true, config.DefStyle, false, false)
696739
}
697740

698741
// We either stop or we wrap to draw the word in the next line
@@ -708,17 +751,14 @@ func (w *BufWindow) displayBuffer() {
708751
}
709752

710753
for _, r := range word {
711-
draw(r.r, r.combc, r.style, true, true)
754+
draw(r.r, 0, r.combc, false, r.style, true, true)
712755

713-
// Draw any extra characters either spaces for tabs or @ for incomplete wide runes
714-
if r.width > 1 {
715-
char := ' '
756+
// Draw any extra characters for tabs
757+
for i := 1; i < r.width; i++ {
716758
if r.r != '\t' {
717-
char = '@'
718-
}
719-
720-
for i := 1; i < r.width; i++ {
721-
draw(char, nil, r.style, true, false)
759+
draw(' ', i, nil, true, r.style, true, false)
760+
} else {
761+
draw('\t', i, nil, false, r.style, true, false)
722762
}
723763
}
724764
bloc.X++
@@ -764,7 +804,7 @@ func (w *BufWindow) displayBuffer() {
764804

765805
if vloc.X != maxWidth {
766806
// Display newline within a selection
767-
draw(' ', nil, config.DefStyle, true, true)
807+
draw(' ', 0, nil, true, config.DefStyle, true, true)
768808
}
769809

770810
bloc.X = w.StartCol

runtime/help/options.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,21 @@ Here are the available options:
203203

204204
default value: `true`
205205

206-
* `indentchar`: sets the indentation character. This will not be inserted into
207-
files; it is only a visual indicator that whitespace is present. If set to a
208-
printing character, it functions as a subset of the "show invisibles"
209-
setting available in many other text editors. The color of this character is
210-
determined by the `indent-char` field in the current theme rather than the
211-
default text color.
206+
* `showchars`: sets what characters to be shown for various inivisible characters
207+
in the file. This is similar to `listchars` in vim and the characters shown
208+
will not be inserted into files. This option supersedes the `indentchar`
209+
option.
210+
The color of the shown character is determined by the `indent-char`
211+
field in the current theme rather than the default text color.
212+
This field is specified in the form of `option1=value1,option2=value2,...`.
213+
Here are the list of options:
214+
- `ispace`: indent space characters (space before first visible character)
215+
- `itab`: indent tab characters (tab before first visible character)
216+
- `space`: space characters (space after first visible character)
217+
- `tab`: tab characters (tab after first visible character)
218+
An example of this option could be `tab=>,space=.,itab=|>,ispace=|`
212219

213-
default value: ` ` (space)
220+
default value: ``
214221

215222
* `infobar`: enables the line at the bottom of the editor where messages are
216223
printed. This option is `global only`.
@@ -577,6 +584,7 @@ so that you can see what the formatting should look like.
577584
"scrollbarchar": "|",
578585
"scrollmargin": 3,
579586
"scrollspeed": 2,
587+
"showchars": " ",
580588
"smartpaste": true,
581589
"softwrap": false,
582590
"splitbottom": true,

0 commit comments

Comments
 (0)