10 "github.com/go-errors/errors"
11 isatty "github.com/mattn/go-isatty"
12 "github.com/zyedidia/micro/cmd/micro/action"
13 "github.com/zyedidia/micro/cmd/micro/buffer"
14 "github.com/zyedidia/micro/cmd/micro/config"
15 "github.com/zyedidia/micro/cmd/micro/screen"
16 "github.com/zyedidia/micro/cmd/micro/util"
17 "github.com/zyedidia/tcell"
21 // These variables should be set by the linker when compiling
23 // Version is the version number or commit hash
24 Version = "0.0.0-unknown"
25 // CommitHash is the commit this version was built on
26 CommitHash = "Unknown"
27 // CompileDate is the date this binary was compiled on
28 CompileDate = "Unknown"
33 events chan tcell.Event
37 flagVersion = flag.Bool("version", false, "Show the version number and information")
38 flagStartPos = flag.String("startpos", "", "LINE,COL to start the cursor at when opening a buffer.")
39 flagConfigDir = flag.String("config-dir", "", "Specify a custom location for the configuration directory")
40 flagOptions = flag.Bool("options", false, "Show all option help")
45 fmt.Println("Usage: micro [OPTIONS] [FILE]...")
46 fmt.Println("-config-dir dir")
47 fmt.Println(" \tSpecify a custom location for the configuration directory")
48 fmt.Println("-startpos LINE,COL")
49 fmt.Println("+LINE:COL")
50 fmt.Println(" \tSpecify a line and column to start the cursor at when opening a buffer")
51 fmt.Println(" \tThis can also be done by opening file:LINE:COL")
52 fmt.Println("-options")
53 fmt.Println(" \tShow all option help")
54 fmt.Println("-version")
55 fmt.Println(" \tShow the version number and information")
57 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")
58 fmt.Println("-option value")
59 fmt.Println(" \tSet `option` to `value` for this session")
60 fmt.Println(" \tFor example: `micro -syntax off file.c`")
61 fmt.Println("\nUse `micro -options` to see the full list of configuration options")
64 optionFlags := make(map[string]*string)
66 for k, v := range config.DefaultGlobalSettings() {
67 optionFlags[k] = flag.String(k, "", fmt.Sprintf("The %s option. Default value: '%v'", k, v))
73 // If -version was passed
74 fmt.Println("Version:", Version)
75 fmt.Println("Commit hash:", CommitHash)
76 fmt.Println("Compiled on", CompileDate)
81 // If -options was passed
82 for k, v := range config.DefaultGlobalSettings() {
83 fmt.Printf("-%s value\n", k)
84 fmt.Printf(" \tDefault value: '%v'\n", v)
90 // LoadInput determines which files should be loaded into buffers
91 // based on the input stored in flag.Args()
92 func LoadInput() []*buffer.Buffer {
93 // There are a number of ways micro should start given its input
95 // 1. If it is given a files in flag.Args(), it should open those
97 // 2. If there is no input file and the input is not a terminal, that means
98 // something is being piped in and the stdin should be opened in an
101 // 3. If there is no input file and the input is a terminal, an empty buffer
108 buffers := make([]*buffer.Buffer, 0, len(args))
112 // We go through each file and load it
113 for i := 0; i < len(args); i++ {
114 if strings.HasPrefix(args[i], "+") {
115 if strings.Contains(args[i], ":") {
116 split := strings.Split(args[i], ":")
117 *flagStartPos = split[0][1:] + "," + split[1]
119 *flagStartPos = args[i][1:] + ",0"
124 buf, err := buffer.NewBufferFromFile(args[i], buffer.BTDefault)
126 util.TermMessage(err)
129 // If the file didn't exist, input will be empty, and we'll open an empty buffer
130 buffers = append(buffers, buf)
132 } else if !isatty.IsTerminal(os.Stdin.Fd()) {
134 // The input is not a terminal, so something is being piped in
135 // and we should read from stdin
136 input, err = ioutil.ReadAll(os.Stdin)
138 util.TermMessage("Error reading from stdin: ", err)
141 buffers = append(buffers, buffer.NewBufferFromString(string(input), filename, buffer.BTDefault))
143 // Option 3, just open an empty buffer
144 buffers = append(buffers, buffer.NewBufferFromString(string(input), filename, buffer.BTDefault))
155 err = config.InitConfigDir(*flagConfigDir)
157 util.TermMessage(err)
159 config.InitRuntimeFiles()
160 err = config.ReadSettings()
162 util.TermMessage(err)
164 config.InitGlobalSettings()
165 action.InitBindings()
166 action.InitCommands()
168 err = config.InitColorscheme()
170 util.TermMessage(err)
175 // If we have an error, we can exit cleanly and not completely
176 // mess up the terminal being worked in
177 // In other words we need to shut down tcell before the program crashes
179 if err := recover(); err != nil {
181 fmt.Println("Micro encountered an error:", err)
182 // Print the stack trace too
183 fmt.Print(errors.Wrap(err, 2).ErrorStack())
192 // Here is the event loop which runs in a separate thread
194 events = make(chan tcell.Event)
197 e := screen.Screen.PollEvent()
206 // Display everything
207 screen.Screen.Fill(' ', config.DefStyle)
208 screen.Screen.HideCursor()
209 action.Tabs.Display()
210 for _, ep := range action.MainTab().Panes {
213 action.MainTab().Display()
214 action.InfoBar.Display()
217 var event tcell.Event
219 // Check for new events
221 case event = <-events:
222 case <-screen.DrawChan:
226 if action.InfoBar.HasPrompt {
227 action.InfoBar.HandleEvent(event)
229 action.Tabs.HandleEvent(event)