--- /dev/null
+package main
+
+import (
+ "bufio"
+ "encoding/gob"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "github.com/zyedidia/micro/internal/buffer"
+ "github.com/zyedidia/micro/internal/config"
+)
+
+func shouldContinue() bool {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Print("Continue [Y/n]: ")
+ text, err := reader.ReadString('\n')
+ if err != nil {
+ fmt.Println(err)
+ return false
+ }
+
+ if len(text) <= 1 {
+ // default continue
+ return true
+ }
+
+ return strings.ToLower(text)[0] == 'y'
+}
+
+// CleanConfig performs cleanup in the user's configuration directory
+func CleanConfig() {
+ fmt.Println("Cleaning your configuration directory at", config.ConfigDir)
+ fmt.Printf("Please consider backing up %s before continuing\n", config.ConfigDir)
+
+ if !shouldContinue() {
+ fmt.Println("Stopping early")
+ return
+ }
+
+ // detect unused options
+ var unusedOptions []string
+ defaultSettings := config.DefaultAllSettings()
+ for k := range config.GlobalSettings {
+ if _, ok := defaultSettings[k]; !ok {
+ valid := false
+ for _, p := range config.Plugins {
+ if strings.HasPrefix(k, p.Name+".") || k == p.Name {
+ valid = true
+ }
+ }
+ if !valid {
+ unusedOptions = append(unusedOptions, k)
+ }
+ }
+ }
+
+ if len(unusedOptions) > 0 {
+ fmt.Println("The following options are unused:")
+
+ sort.Strings(unusedOptions)
+
+ for _, s := range unusedOptions {
+ 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"))
+
+ if shouldContinue() {
+ for _, s := range unusedOptions {
+ delete(config.GlobalSettings, s)
+ }
+
+ err := config.OverwriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
+ if err != nil {
+ fmt.Println("Error writing settings.json file: " + err.Error())
+ }
+
+ fmt.Println("Removed unused options")
+ fmt.Print("\n\n")
+ }
+ }
+
+ // detect incorrectly formatted buffer/ files
+ files, err := ioutil.ReadDir(filepath.Join(config.ConfigDir, "buffers"))
+ if err == nil {
+ var badFiles []string
+ var buffer buffer.SerializedBuffer
+ for _, f := range files {
+ fname := filepath.Join(config.ConfigDir, "buffers", f.Name())
+ file, err := os.Open(fname)
+ defer file.Close()
+
+ decoder := gob.NewDecoder(file)
+ err = decoder.Decode(&buffer)
+
+ if err != nil {
+ badFiles = append(badFiles, fname)
+ }
+ }
+
+ if len(badFiles) > 0 {
+ fmt.Printf("Detected %d files with an invalid format in %s\n", len(badFiles), filepath.Join(config.ConfigDir, "buffers"))
+ fmt.Println("These files store cursor and undo history.")
+ fmt.Printf("Removing badly formatted files in %s\n", filepath.Join(config.ConfigDir, "buffers"))
+
+ if shouldContinue() {
+ for _, f := range badFiles {
+ err := os.Remove(f)
+ if err != nil {
+ fmt.Println(err)
+ continue
+ }
+ }
+
+ fmt.Println("Removed badly formatted files")
+ fmt.Print("\n\n")
+ }
+ }
+ }
+
+ // detect plugins/ directory
+ plugins := filepath.Join(config.ConfigDir, "plugins")
+ if stat, err := os.Stat(plugins); err == nil && stat.IsDir() {
+ fmt.Printf("Found directory %s\n", plugins)
+ fmt.Printf("Plugins should now be stored in %s\n", filepath.Join(config.ConfigDir, "plug"))
+ fmt.Printf("Removing %s\n", plugins)
+
+ if shouldContinue() {
+ os.RemoveAll(plugins)
+ }
+
+ fmt.Print("\n\n")
+ }
+
+ fmt.Println("Done cleaning")
+}
flagOptions = flag.Bool("options", false, "Show all option help")
flagDebug = flag.Bool("debug", false, "Enable debug mode (prints debug info to ./log.txt)")
flagPlugin = flag.String("plugin", "", "Plugin command")
+ flagClean = flag.Bool("clean", false, "Clean configuration directory")
optionFlags map[string]*string
)
func InitFlags() {
flag.Usage = func() {
fmt.Println("Usage: micro [OPTIONS] [FILE]...")
+ fmt.Println("-clean")
+ fmt.Println(" \tCleans the configuration directory")
fmt.Println("-config-dir dir")
fmt.Println(" \tSpecify a custom location for the configuration directory")
fmt.Println("[FILE]:LINE:COL")
}
}
-// DoPluginFlags parses and executes any -plugin flags
+// DoPluginFlags parses and executes any flags that require LoadAllPlugins (-plugin and -clean)
func DoPluginFlags() {
- if *flagPlugin != "" {
+ if *flagClean || *flagPlugin != "" {
config.LoadAllPlugins()
- args := flag.Args()
+ if *flagPlugin != "" {
+ args := flag.Args()
- config.PluginCommand(os.Stdout, *flagPlugin, args)
+ config.PluginCommand(os.Stdout, *flagPlugin, args)
+ } else if *flagClean {
+ CleanConfig()
+ }
os.Exit(0)
}
"errors"
"io/ioutil"
"os"
+ "path/filepath"
"reflect"
"strconv"
"strings"
}
func ReadSettings() error {
- filename := ConfigDir + "/settings.json"
+ filename := filepath.Join(ConfigDir, "settings.json")
if _, e := os.Stat(filename); e == nil {
input, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
+func OverwriteSettings(filename string) error {
+ var err error
+ if _, e := os.Stat(ConfigDir); e == nil {
+ txt, _ := json.MarshalIndent(GlobalSettings, "", " ")
+ err = ioutil.WriteFile(filename, append(txt, '\n'), 0644)
+ }
+ return err
+}
+
// RegisterCommonOptionPlug creates a new option (called pl.name). This is meant to be called by plugins to add options.
func RegisterCommonOptionPlug(pl string, name string, defaultvalue interface{}) error {
name = pl + "." + name
if v, ok := GlobalSettings[name]; !ok {
defaultCommonSettings[name] = defaultvalue
GlobalSettings[name] = defaultvalue
- err := WriteSettings(ConfigDir + "/settings.json")
+ err := WriteSettings(filepath.Join(ConfigDir, "/settings.json"))
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
}
if v, ok := GlobalSettings[name]; !ok {
defaultGlobalSettings[name] = defaultvalue
GlobalSettings[name] = defaultvalue
- err := WriteSettings(ConfigDir + "/settings.json")
+ err := WriteSettings(filepath.Join(ConfigDir, "settings.json"))
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
}