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 doubleClickThreshold = 400 // How many milliseconds to wait before a second click is not a double click
22 autosaveTime = 8 // Number of seconds to wait before autosaving
26 // These variables should be set by the linker when compiling
28 // Version is the version number or commit hash
29 Version = "0.0.0-unknown"
30 // CommitHash is the commit this version was built on
31 CommitHash = "Unknown"
32 // CompileDate is the date this binary was compiled on
33 CompileDate = "Unknown"
38 events chan tcell.Event
42 flagVersion = flag.Bool("version", false, "Show the version number and information")
43 flagStartPos = flag.String("startpos", "", "LINE,COL to start the cursor at when opening a buffer.")
44 flagConfigDir = flag.String("config-dir", "", "Specify a custom location for the configuration directory")
45 flagOptions = flag.Bool("options", false, "Show all option help")
50 fmt.Println("Usage: micro [OPTIONS] [FILE]...")
51 fmt.Println("-config-dir dir")
52 fmt.Println(" \tSpecify a custom location for the configuration directory")
53 fmt.Println("-startpos LINE,COL")
54 fmt.Println("+LINE:COL")
55 fmt.Println(" \tSpecify a line and column to start the cursor at when opening a buffer")
56 fmt.Println(" \tThis can also be done by opening file:LINE:COL")
57 fmt.Println("-options")
58 fmt.Println(" \tShow all option help")
59 fmt.Println("-version")
60 fmt.Println(" \tShow the version number and information")
62 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")
63 fmt.Println("-option value")
64 fmt.Println(" \tSet `option` to `value` for this session")
65 fmt.Println(" \tFor example: `micro -syntax off file.c`")
66 fmt.Println("\nUse `micro -options` to see the full list of configuration options")
69 optionFlags := make(map[string]*string)
71 for k, v := range config.DefaultGlobalSettings() {
72 optionFlags[k] = flag.String(k, "", fmt.Sprintf("The %s option. Default value: '%v'", k, v))
78 // If -version was passed
79 fmt.Println("Version:", Version)
80 fmt.Println("Commit hash:", CommitHash)
81 fmt.Println("Compiled on", CompileDate)
86 // If -options was passed
87 for k, v := range config.DefaultGlobalSettings() {
88 fmt.Printf("-%s value\n", k)
89 fmt.Printf(" \tDefault value: '%v'\n", v)
95 // LoadInput determines which files should be loaded into buffers
96 // based on the input stored in flag.Args()
97 func LoadInput() []*buffer.Buffer {
98 // There are a number of ways micro should start given its input
100 // 1. If it is given a files in flag.Args(), it should open those
102 // 2. If there is no input file and the input is not a terminal, that means
103 // something is being piped in and the stdin should be opened in an
106 // 3. If there is no input file and the input is a terminal, an empty buffer
113 buffers := make([]*buffer.Buffer, 0, len(args))
117 // We go through each file and load it
118 for i := 0; i < len(args); i++ {
119 if strings.HasPrefix(args[i], "+") {
120 if strings.Contains(args[i], ":") {
121 split := strings.Split(args[i], ":")
122 *flagStartPos = split[0][1:] + "," + split[1]
124 *flagStartPos = args[i][1:] + ",0"
129 buf, err := buffer.NewBufferFromFile(args[i])
131 util.TermMessage(err)
134 // If the file didn't exist, input will be empty, and we'll open an empty buffer
135 buffers = append(buffers, buf)
137 } else if !isatty.IsTerminal(os.Stdin.Fd()) {
139 // The input is not a terminal, so something is being piped in
140 // and we should read from stdin
141 input, err = ioutil.ReadAll(os.Stdin)
143 util.TermMessage("Error reading from stdin: ", err)
146 buffers = append(buffers, buffer.NewBufferFromString(string(input), filename))
148 // Option 3, just open an empty buffer
149 buffers = append(buffers, buffer.NewBufferFromString(string(input), filename))
160 err = config.InitConfigDir(*flagConfigDir)
162 util.TermMessage(err)
164 config.InitRuntimeFiles()
165 err = config.ReadSettings()
167 util.TermMessage(err)
169 config.InitGlobalSettings()
170 action.InitBindings()
171 err = config.InitColorscheme()
173 util.TermMessage(err)
178 // If we have an error, we can exit cleanly and not completely
179 // mess up the terminal being worked in
180 // In other words we need to shut down tcell before the program crashes
182 if err := recover(); err != nil {
184 fmt.Println("Micro encountered an error:", err)
185 // Print the stack trace too
186 fmt.Print(errors.Wrap(err, 2).ErrorStack())
192 width, height := screen.Screen.Size()
193 ep := NewBufEditPane(0, 0, width, height-1, b)
195 // Here is the event loop which runs in a separate thread
197 events = make(chan tcell.Event)
200 events <- screen.Screen.PollEvent()
206 // Display everything
207 screen.Screen.Fill(' ', config.DefStyle)
211 var event tcell.Event
213 // Check for new events
215 case event = <-events:
219 ep.HandleEvent(event)