mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-30 06:37:14 +09:00
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:
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user