]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/buffer.go
Merge pull request #507 from NicolaiSoeborg/master
[micro.git] / cmd / micro / buffer.go
index d9d78fda527cfbfbe94c9f74efcc4ff3f42352ea..fdcc37ad2d43cf3f8e71773c43d749b174f48165 100644 (file)
@@ -3,15 +3,19 @@ package main
 import (
        "bytes"
        "encoding/gob"
+       "io"
        "io/ioutil"
        "os"
        "os/exec"
        "os/signal"
        "path/filepath"
+       "regexp"
        "strconv"
        "strings"
        "time"
        "unicode/utf8"
+
+       "github.com/mitchellh/go-homedir"
 )
 
 // Buffer stores the text for files that are loaded into the text editor
@@ -27,8 +31,10 @@ type Buffer struct {
 
        // Path to the file on disk
        Path string
+       // Absolute path to the file on disk
+       AbsPath string
        // Name of the buffer on the status line
-       Name string
+       name string
 
        // Whether or not the buffer has been modified since it was opened
        IsModified bool
@@ -53,8 +59,12 @@ type SerializedBuffer struct {
        ModTime      time.Time
 }
 
-// NewBuffer creates a new buffer from `txt` with path and name `path`
-func NewBuffer(txt []byte, path string) *Buffer {
+func NewBufferFromString(text, path string) *Buffer {
+       return NewBuffer(strings.NewReader(text), path)
+}
+
+// NewBuffer creates a new buffer from a given reader with a given path
+func NewBuffer(reader io.Reader, path string) *Buffer {
        if path != "" {
                for _, tab := range tabs {
                        for _, view := range tab.views {
@@ -66,7 +76,7 @@ func NewBuffer(txt []byte, path string) *Buffer {
        }
 
        b := new(Buffer)
-       b.LineArray = NewLineArray(txt)
+       b.LineArray = NewLineArray(reader)
 
        b.Settings = DefaultLocalSettings()
        for k, v := range globalSettings {
@@ -75,13 +85,10 @@ func NewBuffer(txt []byte, path string) *Buffer {
                }
        }
 
-       b.Path = path
-       b.Name = path
+       absPath, _ := filepath.Abs(path)
 
-       // If the file doesn't have a path to disk then we give it no name
-       if path == "" {
-               b.Name = "No name"
-       }
+       b.Path = path
+       b.AbsPath = absPath
 
        // The last time this file was modified
        b.ModTime, _ = GetModTime(b.Path)
@@ -136,8 +143,7 @@ func NewBuffer(txt []byte, path string) *Buffer {
        if b.Settings["savecursor"].(bool) || b.Settings["saveundo"].(bool) {
                // If either savecursor or saveundo is turned on, we need to load the serialized information
                // from ~/.config/micro/buffers
-               absPath, _ := filepath.Abs(b.Path)
-               file, err := os.Open(configDir + "/buffers/" + EscapePath(absPath))
+               file, err := os.Open(configDir + "/buffers/" + EscapePath(b.AbsPath))
                if err == nil {
                        var buffer SerializedBuffer
                        decoder := gob.NewDecoder(file)
@@ -166,6 +172,16 @@ func NewBuffer(txt []byte, path string) *Buffer {
        return b
 }
 
+func (b *Buffer) GetName() string {
+       if b.name == "" {
+               if b.Path == "" {
+                       return "No name"
+               }
+               return b.Path
+       }
+       return b.name
+}
+
 // UpdateRules updates the syntax rules and filetype for this buffer
 // This is called when the colorscheme changes
 func (b *Buffer) UpdateRules() {
@@ -246,8 +262,7 @@ func (b *Buffer) SaveWithSudo() error {
 // Serialize serializes the buffer to configDir/buffers
 func (b *Buffer) Serialize() error {
        if b.Settings["savecursor"].(bool) || b.Settings["saveundo"].(bool) {
-               absPath, _ := filepath.Abs(b.Path)
-               file, err := os.Create(configDir + "/buffers/" + EscapePath(absPath))
+               file, err := os.Create(configDir + "/buffers/" + EscapePath(b.AbsPath))
                if err == nil {
                        enc := gob.NewEncoder(file)
                        gob.Register(TextEvent{})
@@ -267,15 +282,27 @@ func (b *Buffer) Serialize() error {
 func (b *Buffer) SaveAs(filename string) error {
        b.FindFileType()
        b.UpdateRules()
-       b.Name = filename
-       b.Path = filename
-       str := b.String()
+       dir, _ := homedir.Dir()
+       b.Path = strings.Replace(filename, "~", dir, 1)
+       if b.Settings["rmtrailingws"].(bool) {
+               r, _ := regexp.Compile(`[ \t]+$`)
+               for lineNum, line := range b.Lines(0, b.NumLines) {
+                       indices := r.FindStringIndex(line)
+                       if indices == nil {
+                               continue
+                       }
+                       startLoc := Loc{indices[0], lineNum}
+                       b.deleteToEnd(startLoc)
+               }
+               b.Cursor.Relocate()
+       }
        if b.Settings["eofnewline"].(bool) {
                end := b.End()
                if b.RuneAt(Loc{end.X - 1, end.Y}) != '\n' {
                        b.Insert(end, "\n")
                }
        }
+       str := b.String()
        data := []byte(str)
        err := ioutil.WriteFile(filename, data, 0644)
        if err == nil {
@@ -283,6 +310,7 @@ func (b *Buffer) SaveAs(filename string) error {
                b.ModTime, _ = GetModTime(filename)
                return b.Serialize()
        }
+       b.ModTime, _ = GetModTime(filename)
        return err
 }
 
@@ -291,7 +319,6 @@ func (b *Buffer) SaveAs(filename string) error {
 func (b *Buffer) SaveAsWithSudo(filename string) error {
        b.FindFileType()
        b.UpdateRules()
-       b.Name = filename
        b.Path = filename
 
        // The user may have already used sudo in which case we won't need the password
@@ -348,6 +375,11 @@ func (b *Buffer) remove(start, end Loc) string {
        b.Update()
        return sub
 }
+func (b *Buffer) deleteToEnd(start Loc) {
+       b.IsModified = true
+       b.LineArray.DeleteToEnd(start)
+       b.Update()
+}
 
 // Start returns the location of the first character in the buffer
 func (b *Buffer) Start() Loc {