]> git.lizzy.rs Git - micro.git/commitdiff
Add autoretab autoretab
authorElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 1 Jul 2022 02:31:52 +0000 (04:31 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 12 Sep 2022 14:49:39 +0000 (16:49 +0200)
internal/buffer/buffer.go
internal/config/settings.go

index 56302e9dc5f3404575400e5d78b1ee4f414ae1f4..92c9c9500c9534b270c3db2e4073c343ae8ac82e 100644 (file)
@@ -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
        }
index 2c23f39b433f970d50654557fa7ac1bea5cea77b..ed4e5a27fdc4b1c71f2ca7fddd91ecb812a20d7b 100644 (file)
@@ -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,