diff --git a/cmd/micro/command.go b/cmd/micro/command.go index 7ef88513..9d691341 100644 --- a/cmd/micro/command.go +++ b/cmd/micro/command.go @@ -35,27 +35,28 @@ var commandActions map[string]func([]string) func init() { commandActions = map[string]func([]string){ - "Set": Set, - "SetLocal": SetLocal, - "Show": Show, - "Run": Run, - "Bind": Bind, - "Quit": Quit, - "Save": Save, - "Replace": Replace, - "VSplit": VSplit, - "HSplit": HSplit, - "Tab": NewTab, - "Help": Help, - "Eval": Eval, - "ToggleLog": ToggleLog, - "Plugin": PluginCmd, - "Reload": Reload, - "Cd": Cd, - "Pwd": Pwd, - "Open": Open, - "TabSwitch": TabSwitch, - "MemUsage": MemUsage, + "Set": Set, + "SetLocal": SetLocal, + "Show": Show, + "Run": Run, + "Bind": Bind, + "Quit": Quit, + "Save": Save, + "Replace": Replace, + "ReplaceAll": ReplaceAll, + "VSplit": VSplit, + "HSplit": HSplit, + "Tab": NewTab, + "Help": Help, + "Eval": Eval, + "ToggleLog": ToggleLog, + "Plugin": PluginCmd, + "Reload": Reload, + "Cd": Cd, + "Pwd": Pwd, + "Open": Open, + "TabSwitch": TabSwitch, + "MemUsage": MemUsage, } } @@ -89,27 +90,28 @@ func MakeCommand(name, function string, completions ...Completion) { // DefaultCommands returns a map containing micro's default commands func DefaultCommands() map[string]StrCommand { return map[string]StrCommand{ - "set": {"Set", []Completion{OptionCompletion, NoCompletion}}, - "setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}}, - "show": {"Show", []Completion{OptionCompletion, NoCompletion}}, - "bind": {"Bind", []Completion{NoCompletion}}, - "run": {"Run", []Completion{NoCompletion}}, - "quit": {"Quit", []Completion{NoCompletion}}, - "save": {"Save", []Completion{NoCompletion}}, - "replace": {"Replace", []Completion{NoCompletion}}, - "vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}}, - "hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}}, - "tab": {"Tab", []Completion{FileCompletion, NoCompletion}}, - "help": {"Help", []Completion{HelpCompletion, NoCompletion}}, - "eval": {"Eval", []Completion{NoCompletion}}, - "log": {"ToggleLog", []Completion{NoCompletion}}, - "plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}}, - "reload": {"Reload", []Completion{NoCompletion}}, - "cd": {"Cd", []Completion{FileCompletion}}, - "pwd": {"Pwd", []Completion{NoCompletion}}, - "open": {"Open", []Completion{FileCompletion}}, - "tabswitch": {"TabSwitch", []Completion{NoCompletion}}, - "memusage": {"MemUsage", []Completion{NoCompletion}}, + "set": {"Set", []Completion{OptionCompletion, NoCompletion}}, + "setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}}, + "show": {"Show", []Completion{OptionCompletion, NoCompletion}}, + "bind": {"Bind", []Completion{NoCompletion}}, + "run": {"Run", []Completion{NoCompletion}}, + "quit": {"Quit", []Completion{NoCompletion}}, + "save": {"Save", []Completion{NoCompletion}}, + "replace": {"Replace", []Completion{NoCompletion}}, + "replaceall": {"ReplaceAll", []Completion{NoCompletion}}, + "vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}}, + "hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}}, + "tab": {"Tab", []Completion{FileCompletion, NoCompletion}}, + "help": {"Help", []Completion{HelpCompletion, NoCompletion}}, + "eval": {"Eval", []Completion{NoCompletion}}, + "log": {"ToggleLog", []Completion{NoCompletion}}, + "plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}}, + "reload": {"Reload", []Completion{NoCompletion}}, + "cd": {"Cd", []Completion{FileCompletion}}, + "pwd": {"Pwd", []Completion{NoCompletion}}, + "open": {"Open", []Completion{FileCompletion}}, + "tabswitch": {"TabSwitch", []Completion{NoCompletion}}, + "memusage": {"MemUsage", []Completion{NoCompletion}}, } } @@ -506,16 +508,21 @@ func Save(args []string) { // Replace runs search and replace func Replace(args []string) { - if len(args) < 2 { + if len(args) < 2 || len(args) > 3 { // We need to find both a search and replace expression messenger.Error("Invalid replace statement: " + strings.Join(args, " ")) return } - var flags string + allAtOnce := false if len(args) == 3 { - // The user included some flags - flags = args[2] + // user added -a flag + if args[2] == "-a" { + allAtOnce = true + } else { + messenger.Error("Invalid replace flag: " + args[2]) + return + } } search := string(args[0]) @@ -531,40 +538,7 @@ func Replace(args []string) { view := CurView() found := 0 - if strings.Contains(flags, "c") { - for { - // The 'check' flag was used - Search(search, view, true) - if !view.Cursor.HasSelection() { - break - } - view.Relocate() - RedrawAll() - choice, canceled := messenger.YesNoPrompt("Perform replacement? (y,n)") - if canceled { - if view.Cursor.HasSelection() { - view.Cursor.Loc = view.Cursor.CurSelection[0] - view.Cursor.ResetSelection() - } - messenger.Reset() - break - } - if choice { - view.Cursor.DeleteSelection() - view.Buf.Insert(view.Cursor.Loc, replace) - view.Cursor.ResetSelection() - messenger.Reset() - found++ - } else { - if view.Cursor.HasSelection() { - searchStart = ToCharPos(view.Cursor.CurSelection[1], view.Buf) - } else { - searchStart = ToCharPos(view.Cursor.Loc, view.Buf) - } - continue - } - } - } else { + if allAtOnce { // var deltas []Delta for i := 0; i < view.Buf.LinesNum(); i++ { // view.Buf.lines[i].data = regex.ReplaceAll(view.Buf.lines[i].data, []byte(replace)) @@ -584,6 +558,38 @@ func Replace(args []string) { } } // view.Buf.MultipleReplace(deltas) + + } else { + for { + // The 'check' flag was used + Search(search, view, true) + if !view.Cursor.HasSelection() { + break + } + view.Relocate() + RedrawAll() + choice, canceled := messenger.YesNoPrompt("Perform replacement? (y,n)") + if canceled { + if view.Cursor.HasSelection() { + view.Cursor.Loc = view.Cursor.CurSelection[0] + view.Cursor.ResetSelection() + } + messenger.Reset() + break + } else if choice { + view.Cursor.DeleteSelection() + view.Buf.Insert(view.Cursor.Loc, replace) + view.Cursor.ResetSelection() + messenger.Reset() + found++ + } else { + if view.Cursor.HasSelection() { + searchStart = ToCharPos(view.Cursor.CurSelection[1], view.Buf) + } else { + searchStart = ToCharPos(view.Cursor.Loc, view.Buf) + } + } + } } view.Cursor.Relocate() @@ -596,6 +602,12 @@ func Replace(args []string) { } } +// ReplaceAll replaces search term all at once +func ReplaceAll(args []string) { + // aliased to Replace command + Replace(append(args, "-a")) +} + // RunShellCommand executes a shell command and returns the output/error func RunShellCommand(input string) (string, error) { inputCmd := SplitCommandArgs(input)[0] diff --git a/runtime/help/commands.md b/runtime/help/commands.md index 13123099..7323873b 100644 --- a/runtime/help/commands.md +++ b/runtime/help/commands.md @@ -10,12 +10,17 @@ Here are the possible commands that you can use. * `replace "search" "value" flags`: This will replace `search` with `value`. The `flags` are optional. - At this point, there is only one flag: `c`, which enables `check` mode - which asks if you'd like to perform the replacement each time. + At this point, there is only one flag: `-a`, which replaces all occurrences + at once. Note that `search` must be a valid regex. If one of the arguments does not have any spaces in it, you may omit the quotes. +* `replaceall "search" "value"`: This will replace `search` with `value` without + user confirmation. + + See `replace` command for more information. + * `set option value`: sets the option to value. See the `options` help topic for a list of options you can set.