Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5c21241
actions: SaveAs: Print the error of `os.Stat()` to the `InfoBar`
JoeKar Apr 29, 2024
3fcaf16
actions: SaveCmd: Print the error of `SaveAs` to the `InfoBar`
JoeKar Dec 28, 2024
edc5ff7
save: Convert `os.IsNotExist()` into `errors.Is()`
JoeKar May 1, 2024
6bcec21
open & write: Process regular files only
JoeKar May 12, 2024
6066c1a
buffer: Convert `os.Is()` into `errors.Is()`
JoeKar May 29, 2024
7c659d1
backup: Convert `os.IsNotExist()` into `errors.Is()`
JoeKar May 12, 2024
0b871e1
backup: Store the file with the endings of the buffer
JoeKar May 23, 2024
42ae05b
backup: Lock the buffer lines in `Backup()`
JoeKar May 24, 2024
5aac42d
bindings: Convert `os.IsNotExist()` into `errors.Is()`
JoeKar May 12, 2024
c2bc468
clean: Inform about all failed write steps
JoeKar May 12, 2024
e828027
clean: Remove some unneeded `filepath.Join()` calls
JoeKar May 12, 2024
69064cf
util: Improve and rename `EscapePath()` to `DetermineEscapePath()`
JoeKar May 24, 2024
18a81f0
util: Generalize the file mode of 0666 with `util.FileMode`
JoeKar May 30, 2024
6e8daa1
ioutil: Remove deprecated functions where possible
JoeKar May 30, 2024
9b53257
save: Perform write process safe
JoeKar May 29, 2024
1663a1a
actions: Don't overwrite the buffers `Path`
JoeKar Oct 1, 2024
21b7080
util: Provide `AppendBackupSuffix()` for further transformations
JoeKar Sep 3, 2024
4ac8c78
backup: Perform write process safe
JoeKar May 31, 2024
022ec02
util: Provide `SafeWrite()` to generalize the internal file write pro…
JoeKar Aug 29, 2024
c972360
serialize: Perform write process safe
JoeKar Jun 1, 2024
63d68ec
bindings: Perform write process safe
JoeKar Jun 1, 2024
c926649
settings: Perform write process safe
JoeKar Jun 1, 2024
f8d9855
save: Merge `overwrite()` into `overwriteFile()` and extract `writeFi…
JoeKar Oct 2, 2024
9592bb1
save: Further rework of `overwriteFile()`
JoeKar Nov 19, 2024
e15bb88
micro: Generalize exit behavior
JoeKar Sep 8, 2024
c4dcef3
micro: Provide recovery of `settings.json` & `bindings.json`
JoeKar Sep 8, 2024
8c883c6
backup: Rearrange and extend `BackupMsg`
JoeKar Oct 30, 2024
35d295d
buffer: Remove superfluous `backupTime`
JoeKar Oct 12, 2024
771aab2
save+backup: Process the `save` & `backup` with a sequential channel
JoeKar Oct 1, 2024
79ce93f
backup: Clear the requested backup upon completion notification
JoeKar Oct 12, 2024
49aebe8
save+util: Provide a meaningful error message for safe (over-)write f…
JoeKar Nov 5, 2024
6164050
save: Update the modification time of the buffer only in case of file…
JoeKar Jan 19, 2025
fe134b9
history: Perform write process safe
JoeKar Jan 9, 2025
8b21724
buffer: Store the `encoding` inside the `buffer`
JoeKar Feb 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions cmd/micro/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package main
import (
"bufio"
"encoding/gob"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"

"github.com/zyedidia/micro/v2/internal/buffer"
"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/util"
)

func shouldContinue() bool {
Expand Down Expand Up @@ -39,7 +40,16 @@ func CleanConfig() {
}

fmt.Println("Cleaning default settings")
config.WriteSettings(filepath.Join(config.ConfigDir, "settings.json"))

settingsFile := filepath.Join(config.ConfigDir, "settings.json")
err := config.WriteSettings(settingsFile)
if err != nil {
if errors.Is(err, util.ErrOverwrite) {
fmt.Println(err.Error())
} else {
fmt.Println("Error writing settings.json file: " + err.Error())
}
}

// detect unused options
var unusedOptions []string
Expand Down Expand Up @@ -67,16 +77,20 @@ func CleanConfig() {
fmt.Printf("%s (value: %v)\n", s, config.GlobalSettings[s])
}

fmt.Printf("These options will be removed from %s\n", filepath.Join(config.ConfigDir, "settings.json"))
fmt.Printf("These options will be removed from %s\n", settingsFile)

if shouldContinue() {
for _, s := range unusedOptions {
delete(config.GlobalSettings, s)
}

err := config.OverwriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
err := config.OverwriteSettings(settingsFile)
if err != nil {
fmt.Println("Error writing settings.json file: " + err.Error())
if errors.Is(err, util.ErrOverwrite) {
fmt.Println(err.Error())
} else {
fmt.Println("Error overwriting settings.json file: " + err.Error())
}
}

fmt.Println("Removed unused options")
Expand All @@ -85,12 +99,13 @@ func CleanConfig() {
}

// detect incorrectly formatted buffer/ files
files, err := ioutil.ReadDir(filepath.Join(config.ConfigDir, "buffers"))
buffersPath := filepath.Join(config.ConfigDir, "buffers")
files, err := os.ReadDir(buffersPath)
if err == nil {
var badFiles []string
var buffer buffer.SerializedBuffer
for _, f := range files {
fname := filepath.Join(config.ConfigDir, "buffers", f.Name())
fname := filepath.Join(buffersPath, f.Name())
file, e := os.Open(fname)

if e == nil {
Expand All @@ -105,9 +120,9 @@ func CleanConfig() {
}

if len(badFiles) > 0 {
fmt.Printf("Detected %d files with an invalid format in %s\n", len(badFiles), filepath.Join(config.ConfigDir, "buffers"))
fmt.Printf("Detected %d files with an invalid format in %s\n", len(badFiles), buffersPath)
fmt.Println("These files store cursor and undo history.")
fmt.Printf("Removing badly formatted files in %s\n", filepath.Join(config.ConfigDir, "buffers"))
fmt.Printf("Removing badly formatted files in %s\n", buffersPath)

if shouldContinue() {
removed := 0
Expand Down
2 changes: 1 addition & 1 deletion cmd/micro/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (NullWriter) Write(data []byte) (n int, err error) {
// InitLog sets up the debug log system for micro if it has been enabled by compile-time variables
func InitLog() {
if util.Debug == "ON" {
f, err := os.OpenFile("log.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
f, err := os.OpenFile("log.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, util.FileMode)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
Expand Down
102 changes: 68 additions & 34 deletions cmd/micro/micro.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/signal"
"path/filepath"
"regexp"
"runtime"
"runtime/pprof"
Expand Down Expand Up @@ -99,7 +99,7 @@ func InitFlags() {
fmt.Println("Version:", util.Version)
fmt.Println("Commit hash:", util.CommitHash)
fmt.Println("Compiled on", util.CompileDate)
os.Exit(0)
exit(0)
}

if *flagOptions {
Expand All @@ -115,7 +115,7 @@ func InitFlags() {
fmt.Printf("-%s value\n", k)
fmt.Printf(" \tDefault value: '%v'\n", v)
}
os.Exit(0)
exit(0)
}

if util.Debug == "OFF" && *flagDebug {
Expand All @@ -136,7 +136,7 @@ func DoPluginFlags() {
CleanConfig()
}

os.Exit(0)
exit(0)
}
}

Expand Down Expand Up @@ -209,7 +209,7 @@ func LoadInput(args []string) []*buffer.Buffer {
// Option 2
// The input is not a terminal, so something is being piped in
// and we should read from stdin
input, err = ioutil.ReadAll(os.Stdin)
input, err = io.ReadAll(os.Stdin)
if err != nil {
screen.TermMessage("Error reading from stdin: ", err)
input = []byte{}
Expand All @@ -223,12 +223,55 @@ func LoadInput(args []string) []*buffer.Buffer {
return buffers
}

func checkBackup(name string) error {
target := filepath.Join(config.ConfigDir, name)
backup := util.AppendBackupSuffix(target)
if info, err := os.Stat(backup); err == nil {
input, err := os.ReadFile(backup)
if err == nil {
t := info.ModTime()
msg := fmt.Sprintf(buffer.BackupMsg, target, t.Format("Mon Jan _2 at 15:04, 2006"), backup)
choice := screen.TermPrompt(msg, []string{"r", "i", "a", "recover", "ignore", "abort"}, true)

if choice%3 == 0 {
// recover
err := os.WriteFile(target, input, util.FileMode)
if err != nil {
return err
}
return os.Remove(backup)
} else if choice%3 == 1 {
// delete
return os.Remove(backup)
} else if choice%3 == 2 {
// abort
return errors.New("Aborted")
}
}
}
return nil
}

func exit(rc int) {
for _, b := range buffer.OpenBuffers {
if !b.Modified() {
b.Fini()
}
}

if screen.Screen != nil {
screen.Screen.Fini()
}

os.Exit(rc)
}

func main() {
defer func() {
if util.Stdout.Len() > 0 {
fmt.Fprint(os.Stdout, util.Stdout.String())
}
os.Exit(0)
exit(0)
}()

var err error
Expand Down Expand Up @@ -256,6 +299,12 @@ func main() {
config.InitRuntimeFiles(true)
config.InitPlugins()

err = checkBackup("settings.json")
if err != nil {
screen.TermMessage(err)
exit(1)
}

err = config.ReadSettings()
if err != nil {
screen.TermMessage(err)
Expand Down Expand Up @@ -288,7 +337,7 @@ func main() {
if err != nil {
fmt.Println(err)
fmt.Println("Fatal: Micro could not initialize a Screen.")
os.Exit(1)
exit(1)
}
m := clipboard.SetMethod(config.GetGlobalOption("clipboard").(string))
clipErr := clipboard.Initialize(m)
Expand All @@ -307,7 +356,7 @@ func main() {
for _, b := range buffer.OpenBuffers {
b.Backup()
}
os.Exit(1)
exit(1)
}
}()

Expand All @@ -316,6 +365,12 @@ func main() {
screen.TermMessage(err)
}

err = checkBackup("bindings.json")
if err != nil {
screen.TermMessage(err)
exit(1)
}

action.InitBindings()
action.InitCommands()

Expand Down Expand Up @@ -434,41 +489,20 @@ func DoEvent() {
}
case f := <-timerChan:
f()
case b := <-buffer.BackupCompleteChan:
b.RequestedBackup = false
case <-sighup:
for _, b := range buffer.OpenBuffers {
if !b.Modified() {
b.Fini()
}
}
os.Exit(0)
exit(0)
case <-util.Sigterm:
for _, b := range buffer.OpenBuffers {
if !b.Modified() {
b.Fini()
}
}

if screen.Screen != nil {
screen.Screen.Fini()
}
os.Exit(0)
exit(0)
}

if e, ok := event.(*tcell.EventError); ok {
log.Println("tcell event error: ", e.Error())

if e.Err() == io.EOF {
// shutdown due to terminal closing/becoming inaccessible
for _, b := range buffer.OpenBuffers {
if !b.Modified() {
b.Fini()
}
}

if screen.Screen != nil {
screen.Screen.Fini()
}
os.Exit(0)
exit(0)
}
return
}
Expand Down
5 changes: 3 additions & 2 deletions internal/action/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,9 @@ func (h *BufPane) SaveAsCB(action string, callback func()) bool {
h.completeAction(action)
return
}
} else {
InfoBar.Error(err)
return
}
} else {
InfoBar.YNPrompt(
Expand Down Expand Up @@ -1039,7 +1042,6 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
if err != nil {
InfoBar.Error(err)
} else {
h.Buf.Path = filename
h.Buf.SetName(filename)
InfoBar.Message("Saved " + filename)
if callback != nil {
Expand All @@ -1065,7 +1067,6 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
InfoBar.Error(err)
}
} else {
h.Buf.Path = filename
h.Buf.SetName(filename)
InfoBar.Message("Saved " + filename)
if callback != nil {
Expand Down
23 changes: 15 additions & 8 deletions internal/action/bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"io/fs"
"os"
"path/filepath"
"regexp"
Expand All @@ -14,6 +14,7 @@ import (
"github.com/micro-editor/json5"
"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/screen"
"github.com/zyedidia/micro/v2/internal/util"
"github.com/micro-editor/tcell/v2"
)

Expand All @@ -23,9 +24,13 @@ var Binder = map[string]func(e Event, action string){
"terminal": TermMapEvent,
}

func writeFile(name string, txt []byte) error {
return util.SafeWrite(name, txt, false)
}

func createBindingsIfNotExist(fname string) {
if _, e := os.Stat(fname); os.IsNotExist(e) {
ioutil.WriteFile(fname, []byte("{}"), 0644)
if _, e := os.Stat(fname); errors.Is(e, fs.ErrNotExist) {
writeFile(fname, []byte("{}"))
}
}

Expand All @@ -37,7 +42,7 @@ func InitBindings() {
createBindingsIfNotExist(filename)

if _, e := os.Stat(filename); e == nil {
input, err := ioutil.ReadFile(filename)
input, err := os.ReadFile(filename)
if err != nil {
screen.TermMessage("Error reading bindings.json file: " + err.Error())
return
Expand Down Expand Up @@ -265,7 +270,7 @@ func TryBindKey(k, v string, overwrite bool) (bool, error) {
filename := filepath.Join(config.ConfigDir, "bindings.json")
createBindingsIfNotExist(filename)
if _, e = os.Stat(filename); e == nil {
input, err := ioutil.ReadFile(filename)
input, err := os.ReadFile(filename)
if err != nil {
return false, errors.New("Error reading bindings.json file: " + err.Error())
}
Expand Down Expand Up @@ -304,7 +309,8 @@ func TryBindKey(k, v string, overwrite bool) (bool, error) {
BindKey(k, v, Binder["buffer"])

txt, _ := json.MarshalIndent(parsed, "", " ")
return true, ioutil.WriteFile(filename, append(txt, '\n'), 0644)
txt = append(txt, '\n')
return true, writeFile(filename, txt)
}
return false, e
}
Expand All @@ -317,7 +323,7 @@ func UnbindKey(k string) error {
filename := filepath.Join(config.ConfigDir, "bindings.json")
createBindingsIfNotExist(filename)
if _, e = os.Stat(filename); e == nil {
input, err := ioutil.ReadFile(filename)
input, err := os.ReadFile(filename)
if err != nil {
return errors.New("Error reading bindings.json file: " + err.Error())
}
Expand Down Expand Up @@ -354,7 +360,8 @@ func UnbindKey(k string) error {
}

txt, _ := json.MarshalIndent(parsed, "", " ")
return ioutil.WriteFile(filename, append(txt, '\n'), 0644)
txt = append(txt, '\n')
return writeFile(filename, txt)
}
return e
}
Expand Down
Loading