Refactor and clean up

This commit puts in place the ability for multiple views (splits).
This commit also removes the editor bindings so that all bindings can be
rebound by the user.
I also added some more comments

This fixes #109
This commit is contained in:
Zachary Yedidia
2016-05-28 11:32:09 -04:00
parent d9d0af4a99
commit e8d8da1443
9 changed files with 311 additions and 248 deletions

View File

@@ -24,10 +24,13 @@ func RunShellCommand(input string) (string, error) {
return outstring, err
}
// HandleShellCommand runs the shell command and outputs to DisplayBlock
func HandleShellCommand(input string, view *View, openTerm bool) {
// HandleShellCommand runs the shell command
// The openTerm argument specifies whether a terminal should be opened (for viewing output
// or interacting with stdin)
func HandleShellCommand(input string, openTerm bool) {
inputCmd := strings.Split(input, " ")[0]
if !openTerm {
// Simply run the command in the background and notify the user when it's done
messenger.Message("Running...")
go func() {
output, err := RunShellCommand(input)
@@ -42,19 +45,24 @@ func HandleShellCommand(input string, view *View, openTerm bool) {
} else {
messenger.Message(output)
}
Redraw(view)
// We have to make sure to redraw
RedrawAll()
}()
} else {
// Shut down the screen because we're going to interact directly with the shell
screen.Fini()
screen = nil
args := strings.Split(input, " ")[1:]
// Set up everything for the command
cmd := exec.Command(inputCmd, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// This is a trap for Ctrl-C so that it doesn't kill micro
// Instead we trap Ctrl-C to kill the program we're running
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
@@ -63,51 +71,52 @@ func HandleShellCommand(input string, view *View, openTerm bool) {
}
}()
// Start the command
cmd.Start()
cmd.Wait()
// This is just so we don't return right away and let the user press enter to return
TermMessage("")
// Start the screen back up
InitScreen()
}
}
// HandleCommand handles input from the user
func HandleCommand(input string, view *View) {
func HandleCommand(input string) {
inputCmd := strings.Split(input, " ")[0]
args := strings.Split(input, " ")[1:]
commands := []string{"set", "quit", "save", "replace", "run"}
i := 0
cmd := inputCmd
for _, c := range commands {
if strings.HasPrefix(c, inputCmd) {
i++
cmd = c
}
}
if i == 1 {
inputCmd = cmd
}
switch inputCmd {
case "set":
SetOption(view, args)
// Set an option and we have to set it for every view
for _, view := range views {
SetOption(view, args)
}
case "run":
HandleShellCommand(strings.Join(args, " "), view, false)
// Run a shell command in the background (openTerm is false)
HandleShellCommand(strings.Join(args, " "), false)
case "quit":
if view.CanClose("Quit anyway? (yes, no, save) ") {
// This is a bit weird because micro only has one view for now so there is no way to close
// a single view
// Currently if multiple views were open, it would close all of them, and not check the non-mainviews
// for unsaved changes. This, and the behavior of Ctrl-Q need to be changed when splits are implemented
if views[mainView].CanClose("Quit anyway? (yes, no, save) ") {
screen.Fini()
os.Exit(0)
}
case "save":
view.Save()
// Save the main view
views[mainView].Save()
case "replace":
// This is a regex to parse the replace expression
// We allow no quotes if there are no spaces, but if you want to search
// for or replace an expression with spaces, you can add double quotes
r := regexp.MustCompile(`"[^"\\]*(?:\\.[^"\\]*)*"|[^\s]*`)
replaceCmd := r.FindAllString(strings.Join(args, " "), -1)
if len(replaceCmd) < 2 {
// We need to find both a search and replace expression
messenger.Error("Invalid replace statement: " + strings.Join(args, " "))
return
}
@@ -121,6 +130,7 @@ func HandleCommand(input string, view *View) {
search := string(replaceCmd[0])
replace := string(replaceCmd[1])
// If the search and replace expressions have quotes, we need to remove those
if strings.HasPrefix(search, `"`) && strings.HasSuffix(search, `"`) {
search = search[1 : len(search)-1]
}
@@ -128,17 +138,19 @@ func HandleCommand(input string, view *View) {
replace = replace[1 : len(replace)-1]
}
// We replace all escaped double quotes to real double quotes
search = strings.Replace(search, `\"`, `"`, -1)
replace = strings.Replace(replace, `\"`, `"`, -1)
// messenger.Error(search + " -> " + replace)
regex, err := regexp.Compile(search)
if err != nil {
// There was an error with the user's regex
messenger.Error(err.Error())
return
}
view := views[mainView]
found := false
for {
match := regex.FindStringIndex(view.Buf.String())
@@ -150,7 +162,7 @@ func HandleCommand(input string, view *View) {
// The 'check' flag was used
Search(search, view, true)
view.Relocate()
Redraw(view)
RedrawAll()
choice, canceled := messenger.YesNoPrompt("Perform replacement? (y,n)")
if canceled {
if view.Cursor.HasSelection() {