diff --git a/internal/action/bufpane.go b/internal/action/bufpane.go index 9df8779e..5941a509 100644 --- a/internal/action/bufpane.go +++ b/internal/action/bufpane.go @@ -249,6 +249,17 @@ func (h *BufPane) Name() string { // HandleEvent executes the tcell event properly func (h *BufPane) HandleEvent(event tcell.Event) { + if h.Buf.ExternallyModified() { + InfoBar.YNPrompt("The file on disk has changed. Reload file? (y,n)", func(yes, canceled bool) { + if !yes || canceled { + h.Buf.UpdateModTime() + } else { + h.Buf.ReOpen() + } + }) + + } + switch e := event.(type) { case *tcell.EventRaw: re := RawEvent{ diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index dd7d0950..8d418cd3 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -18,7 +18,7 @@ import ( "github.com/zyedidia/micro/internal/config" ulua "github.com/zyedidia/micro/internal/lua" "github.com/zyedidia/micro/internal/screen" - . "github.com/zyedidia/micro/internal/util" + "github.com/zyedidia/micro/internal/util" "github.com/zyedidia/micro/pkg/highlight" "golang.org/x/text/encoding/htmlindex" "golang.org/x/text/encoding/unicode" @@ -123,8 +123,8 @@ type Buffer struct { // and an error if the file is a directory func NewBufferFromFile(path string, btype BufType) (*Buffer, error) { var err error - filename, cursorPos := GetPathAndCursorPosition(path) - filename, err = ReplaceHome(filename) + filename, cursorPos := util.GetPathAndCursorPosition(path) + filename, err = util.ReplaceHome(filename) if err != nil { return nil, err } @@ -148,7 +148,7 @@ func NewBufferFromFile(path string, btype BufType) (*Buffer, error) { // File does not exist -- create an empty buffer with that name buf = NewBufferFromString("", filename, btype) } else { - buf = NewBuffer(file, FSize(file), filename, cursorLoc, btype) + buf = NewBuffer(file, util.FSize(file), filename, cursorLoc, btype) } return buf, nil @@ -216,7 +216,7 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT } // The last time this file was modified - b.ModTime, _ = GetModTime(b.Path) + b.UpdateModTime() switch b.Endings { case FFUnix: @@ -329,6 +329,22 @@ func (b *Buffer) FileType() string { return b.Settings["filetype"].(string) } +// ExternallyModified returns whether the file being edited has +// been modified by some external process +func (b *Buffer) ExternallyModified() bool { + modTime, err := util.GetModTime(b.Path) + if err == nil { + return modTime != b.ModTime + } + return false +} + +// UpdateModTime updates the modtime of this file +func (b *Buffer) UpdateModTime() (err error) { + b.ModTime, err = util.GetModTime(b.Path) + return +} + // ReOpen reloads the current buffer from disk func (b *Buffer) ReOpen() error { file, err := os.Open(b.Path) @@ -350,7 +366,7 @@ func (b *Buffer) ReOpen() error { } b.EventHandler.ApplyDiff(txt) - b.ModTime, err = GetModTime(b.Path) + err = b.UpdateModTime() b.isModified = false b.RelocateCursors() return err @@ -512,7 +528,7 @@ func (b *Buffer) ClearMatches() { // depending on the settings) func (b *Buffer) IndentString(tabsize int) string { if b.Settings["tabstospaces"].(bool) { - return Spaces(tabsize) + return util.Spaces(tabsize) } return "\t" } @@ -600,7 +616,7 @@ func (b *Buffer) RemoveCursor(i int) { copy(b.cursors[i:], b.cursors[i+1:]) b.cursors[len(b.cursors)-1] = nil b.cursors = b.cursors[:len(b.cursors)-1] - b.curCursor = Clamp(b.curCursor, 0, len(b.cursors)-1) + b.curCursor = util.Clamp(b.curCursor, 0, len(b.cursors)-1) b.UpdateCursors() } @@ -741,13 +757,13 @@ func (b *Buffer) FindMatchingBrace(braceType [2]rune, start Loc) (Loc, bool) { // Retab changes all tabs to spaces or vice versa func (b *Buffer) Retab() { toSpaces := b.Settings["tabstospaces"].(bool) - tabsize := IntOpt(b.Settings["tabsize"]) + tabsize := util.IntOpt(b.Settings["tabsize"]) dirty := false for i := 0; i < b.LinesNum(); i++ { l := b.LineBytes(i) - ws := GetLeadingWhitespace(l) + ws := util.GetLeadingWhitespace(l) if len(ws) != 0 { if toSpaces { ws = bytes.Replace(ws, []byte{'\t'}, bytes.Repeat([]byte{' '}, tabsize), -1) @@ -789,10 +805,12 @@ func ParseCursorLocation(cursorPositions []string) (Loc, error) { return startpos, err } +// Line returns the string representation of the given line number func (b *Buffer) Line(i int) string { return string(b.LineBytes(i)) } +// WriteLog writes a string to the log buffer func WriteLog(s string) { LogBuf.EventHandler.Insert(LogBuf.End(), s) } diff --git a/internal/buffer/save.go b/internal/buffer/save.go index 240526e8..5b23cb3b 100644 --- a/internal/buffer/save.go +++ b/internal/buffer/save.go @@ -13,7 +13,7 @@ import ( "github.com/zyedidia/micro/internal/config" "github.com/zyedidia/micro/internal/screen" - . "github.com/zyedidia/micro/internal/util" + "github.com/zyedidia/micro/internal/util" "golang.org/x/text/encoding" "golang.org/x/text/encoding/htmlindex" "golang.org/x/text/transform" @@ -140,12 +140,12 @@ func (b *Buffer) saveToFile(filename string, withSudo bool) error { // Update the last time this file was updated after saving defer func() { - b.ModTime, _ = GetModTime(filename) + b.ModTime, _ = util.GetModTime(filename) err = b.Serialize() }() // Removes any tilde and replaces with the absolute path to home - absFilename, _ := ReplaceHome(filename) + absFilename, _ := util.ReplaceHome(filename) // Get the leading path to the file | "." is returned if there's no leading path provided if dirname := filepath.Dir(absFilename); dirname != "." { diff --git a/internal/buffer/serialize.go b/internal/buffer/serialize.go index 2cadcc77..16c4b6bf 100644 --- a/internal/buffer/serialize.go +++ b/internal/buffer/serialize.go @@ -10,7 +10,7 @@ import ( "golang.org/x/text/encoding" "github.com/zyedidia/micro/internal/config" - . "github.com/zyedidia/micro/internal/util" + "github.com/zyedidia/micro/internal/util" ) // The SerializedBuffer holds the types that get serialized when a buffer is saved @@ -30,7 +30,7 @@ func (b *Buffer) Serialize() error { return nil } - name := config.ConfigDir + "/buffers/" + EscapePath(b.AbsPath) + name := config.ConfigDir + "/buffers/" + util.EscapePath(b.AbsPath) return overwriteFile(name, encoding.Nop, func(file io.Writer) error { err := gob.NewEncoder(file).Encode(SerializedBuffer{ @@ -48,7 +48,7 @@ func (b *Buffer) Unserialize() error { if b.Path == "" { return nil } - file, err := os.Open(config.ConfigDir + "/buffers/" + EscapePath(b.AbsPath)) + file, err := os.Open(config.ConfigDir + "/buffers/" + util.EscapePath(b.AbsPath)) defer file.Close() if err == nil { var buffer SerializedBuffer