From: Elias Fleckenstein Date: Fri, 1 Jul 2022 02:31:52 +0000 (+0200) Subject: Add autoretab X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=HEAD;p=micro.git Add autoretab --- diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 56302e9d..92c9c950 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -25,6 +25,7 @@ import ( "github.com/zyedidia/micro/v2/internal/screen" "github.com/zyedidia/micro/v2/internal/util" "github.com/zyedidia/micro/v2/pkg/highlight" + "golang.org/x/text/encoding" "golang.org/x/text/encoding/htmlindex" "golang.org/x/text/encoding/unicode" "golang.org/x/text/transform" @@ -213,6 +214,66 @@ type Buffer struct { HighlightSearch bool } +type retabReader struct { + scanner *bufio.Scanner + buffer []byte + toSpaces bool + tabsize int +} + +func newRetabReader(from io.Reader, enc encoding.Encoding, autoretab bool, toSpaces bool, tabsize int) io.Reader { + if !autoretab { + return from + } + r := new(retabReader) + r.scanner = bufio.NewScanner(bufio.NewReader(transform.NewReader(from, enc.NewDecoder()))) + r.toSpaces = toSpaces + r.tabsize = tabsize + return r +} + +func (r *retabReader) fillBuffer(required int) error { + for len(r.buffer) < required { + if r.scanner.Scan() { + line := retabLine([]byte(r.scanner.Text()), r.toSpaces, r.tabsize) + + r.buffer = append(r.buffer, line...) + r.buffer = append(r.buffer, "\n"...) + } else { + if err := r.scanner.Err(); err != nil { + return err + } else { + return io.EOF + } + break + } + } + + return nil +} + +func (r *retabReader) Read(into []byte) (n int, err error) { + err = r.fillBuffer(len(into)) + n = copy(into, r.buffer) + + r.buffer = r.buffer[n:] + return +} + +func retabLine(l []byte, toSpaces bool, tabsize int) []byte { + ws := util.GetLeadingWhitespace(l) + if len(ws) != 0 { + if toSpaces { + ws = bytes.ReplaceAll(ws, []byte{'\t'}, bytes.Repeat([]byte{' '}, tabsize)) + } else { + ws = bytes.ReplaceAll(ws, bytes.Repeat([]byte{' '}, tabsize), []byte{'\t'}) + } + } + + l = bytes.TrimLeft(l, " \t") + return append(ws, l...) +} + // NewBufferFromFileAtLoc opens a new buffer with a given cursor location // If cursorLoc is {-1, -1} the location does not overwrite what the cursor location // would otherwise be (start of file, or saved cursor position if `savecursor` is @@ -355,7 +416,11 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT return NewBufferFromString("", "", btype) } if !hasBackup { - reader := bufio.NewReader(transform.NewReader(r, enc.NewDecoder())) + autoretab := b.Settings["autoretab"].(bool) + toSpaces := b.Settings["tabstospaces"].(bool) + tabsize := util.IntOpt(b.Settings["tabsize"]) + + reader := newRetabReader(r, enc, autoretab, toSpaces, tabsize) var ff FileFormat = FFAuto @@ -534,13 +599,17 @@ func (b *Buffer) ReOpen() error { return err } - reader := bufio.NewReader(transform.NewReader(file, enc.NewDecoder())) + autoretab := b.Settings["autoretab"].(bool) + toSpaces := b.Settings["tabstospaces"].(bool) + tabsize := util.IntOpt(b.Settings["tabsize"]) + + reader := newRetabReader(file, enc, autoretab, toSpaces, tabsize) data, err := ioutil.ReadAll(reader) txt := string(data) - if err != nil { return err } + b.EventHandler.ApplyDiff(txt) err = b.UpdateModTime() @@ -1061,19 +1130,7 @@ func (b *Buffer) Retab() { dirty := false for i := 0; i < b.LinesNum(); i++ { - l := b.LineBytes(i) - - ws := util.GetLeadingWhitespace(l) - if len(ws) != 0 { - if toSpaces { - ws = bytes.ReplaceAll(ws, []byte{'\t'}, bytes.Repeat([]byte{' '}, tabsize)) - } else { - ws = bytes.ReplaceAll(ws, bytes.Repeat([]byte{' '}, tabsize), []byte{'\t'}) - } - } - - l = bytes.TrimLeft(l, " \t") - b.lines[i].data = append(ws, l...) + b.lines[i].data = retabLine(b.LineBytes(i), toSpaces, tabsize) b.MarkModified(i, i) dirty = true } diff --git a/internal/config/settings.go b/internal/config/settings.go index 2c23f39b..ed4e5a27 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -258,6 +258,7 @@ func GetGlobalOption(name string) interface{} { var defaultCommonSettings = map[string]interface{}{ "autoindent": true, "autosu": false, + "autoretab": false, "backup": true, "backupdir": "", "basename": false,