X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=cmd%2Fmicro%2Fmicro.go;h=f6360255fa46d9f91c90895a20db5a343ee94363;hb=69b6c724fc6403ee28eadd53e16a9eb08b40fb51;hp=06e1f968ebd41c3b2ad789a4894afd855f275291;hpb=e7e02729685de27429e220f38250065e2f80ec87;p=micro.git diff --git a/cmd/micro/micro.go b/cmd/micro/micro.go index 06e1f968..f6360255 100644 --- a/cmd/micro/micro.go +++ b/cmd/micro/micro.go @@ -5,7 +5,9 @@ import ( "fmt" "io/ioutil" "os" + "runtime" "sort" + "time" "github.com/go-errors/errors" isatty "github.com/mattn/go-isatty" @@ -27,22 +29,42 @@ var ( flagVersion = flag.Bool("version", false, "Show the version number and information") flagConfigDir = flag.String("config-dir", "", "Specify a custom location for the configuration directory") 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") fmt.Println(" \tSpecify a line and column to start the cursor at when opening a buffer") - fmt.Println(" \tThis can also be done by opening file:LINE:COL") fmt.Println("-options") fmt.Println(" \tShow all option help") + fmt.Println("-debug") + fmt.Println(" \tEnable debug mode (enables logging to ./log.txt)") fmt.Println("-version") fmt.Println(" \tShow the version number and information") + fmt.Print("\nMicro's plugin's can be managed at the command line with the following commands.\n") + fmt.Println("-plugin install [PLUGIN]...") + fmt.Println(" \tInstall plugin(s)") + fmt.Println("-plugin remove [PLUGIN]...") + fmt.Println(" \tRemove plugin(s)") + fmt.Println("-plugin update [PLUGIN]...") + fmt.Println(" \tUpdate plugin(s) (if no argument is given, updates all plugins)") + fmt.Println("-plugin search [PLUGIN]...") + fmt.Println(" \tSearch for a plugin") + fmt.Println("-plugin list") + fmt.Println(" \tList installed plugins") + fmt.Println("-plugin available") + fmt.Println(" \tList available plugins") + fmt.Print("\nMicro's options can also be set via command line arguments for quick\nadjustments. For real configuration, please use the settings.json\nfile (see 'help options').\n\n") fmt.Println("-option value") fmt.Println(" \tSet `option` to `value` for this session") @@ -70,7 +92,7 @@ func InitFlags() { // If -options was passed var keys []string m := config.DefaultAllSettings() - for k, _ := range m { + for k := range m { keys = append(keys, k) } sort.Strings(keys) @@ -81,6 +103,27 @@ func InitFlags() { } os.Exit(0) } + + if util.Debug == "OFF" && *flagDebug { + util.Debug = "ON" + } +} + +// DoPluginFlags parses and executes any flags that require LoadAllPlugins (-plugin and -clean) +func DoPluginFlags() { + if *flagClean || *flagPlugin != "" { + config.LoadAllPlugins() + + if *flagPlugin != "" { + args := flag.Args() + + config.PluginCommand(os.Stdout, *flagPlugin, args) + } else if *flagClean { + CleanConfig() + } + + os.Exit(0) + } } // LoadInput determines which files should be loaded into buffers @@ -134,12 +177,19 @@ func LoadInput() []*buffer.Buffer { } func main() { - var err error + defer os.Exit(0) - InitLog() + // runtime.SetCPUProfileRate(400) + // f, _ := os.Create("micro.prof") + // pprof.StartCPUProfile(f) + // defer pprof.StopCPUProfile() + + var err error InitFlags() + InitLog() + err = config.InitConfigDir(*flagConfigDir) if err != nil { screen.TermMessage(err) @@ -164,19 +214,7 @@ func main() { } } - action.InitBindings() - action.InitCommands() - - err = config.InitColorscheme() - if err != nil { - screen.TermMessage(err) - } - - config.LoadAllPlugins() - err = config.RunPluginFn("init") - if err != nil { - screen.TermMessage(err) - } + DoPluginFlags() screen.Init() @@ -187,25 +225,49 @@ func main() { if err := recover(); err != nil { screen.Screen.Fini() fmt.Println("Micro encountered an error:", err) + // backup all open buffers + for _, b := range buffer.OpenBuffers { + b.Backup(false) + } // Print the stack trace too fmt.Print(errors.Wrap(err, 2).ErrorStack()) os.Exit(1) } }() + err = config.LoadAllPlugins() + if err != nil { + screen.TermMessage(err) + } + + action.InitBindings() + action.InitCommands() + + err = config.InitColorscheme() + if err != nil { + screen.TermMessage(err) + } + b := LoadInput() + + if len(b) == 0 { + // No buffers to open + screen.Screen.Fini() + runtime.Goexit() + } + action.InitTabs(b) action.InitGlobals() - for _, s := range config.LocalSettings { - if _, ok := config.GlobalSettings[s]; ok { - delete(config.GlobalSettings, s) - } + err = config.RunPluginFn("init") + if err != nil { + screen.TermMessage(err) } + events = make(chan tcell.Event) + // Here is the event loop which runs in a separate thread go func() { - events = make(chan tcell.Event) for { screen.Lock() e := screen.Screen.PollEvent() @@ -216,6 +278,22 @@ func main() { } }() + // clear the drawchan so we don't redraw excessively + // if someone requested a redraw before we started displaying + for len(screen.DrawChan) > 0 { + <-screen.DrawChan + } + + var event tcell.Event + + // wait for initial resize event + select { + case event = <-events: + action.Tabs.HandleEvent(event) + case <-time.After(10 * time.Millisecond): + // time out after 10ms + } + for { // Display everything screen.Screen.Fill(' ', config.DefStyle) @@ -228,23 +306,26 @@ func main() { action.InfoBar.Display() screen.Screen.Show() - var event tcell.Event + event = nil // Check for new events select { case f := <-shell.Jobs: // If a new job has finished while running in the background we should execute the callback f.Function(f.Output, f.Args...) + case <-config.Autosave: + for _, b := range buffer.OpenBuffers { + b.Save() + } + case <-shell.CloseTerms: case event = <-events: case <-screen.DrawChan: } - if event != nil { - if action.InfoBar.HasPrompt { - action.InfoBar.HandleEvent(event) - } else { - action.Tabs.HandleEvent(event) - } + if action.InfoBar.HasPrompt { + action.InfoBar.HandleEvent(event) + } else { + action.Tabs.HandleEvent(event) } } }