Change replace command default behaviour to confirm replacement for each occurrences

This commit is contained in:
ali
2017-05-26 03:43:57 +04:30
parent 6cf6857602
commit 480a220fda
2 changed files with 99 additions and 82 deletions

View File

@@ -35,27 +35,28 @@ var commandActions map[string]func([]string)
func init() { func init() {
commandActions = map[string]func([]string){ commandActions = map[string]func([]string){
"Set": Set, "Set": Set,
"SetLocal": SetLocal, "SetLocal": SetLocal,
"Show": Show, "Show": Show,
"Run": Run, "Run": Run,
"Bind": Bind, "Bind": Bind,
"Quit": Quit, "Quit": Quit,
"Save": Save, "Save": Save,
"Replace": Replace, "Replace": Replace,
"VSplit": VSplit, "ReplaceAll": ReplaceAll,
"HSplit": HSplit, "VSplit": VSplit,
"Tab": NewTab, "HSplit": HSplit,
"Help": Help, "Tab": NewTab,
"Eval": Eval, "Help": Help,
"ToggleLog": ToggleLog, "Eval": Eval,
"Plugin": PluginCmd, "ToggleLog": ToggleLog,
"Reload": Reload, "Plugin": PluginCmd,
"Cd": Cd, "Reload": Reload,
"Pwd": Pwd, "Cd": Cd,
"Open": Open, "Pwd": Pwd,
"TabSwitch": TabSwitch, "Open": Open,
"MemUsage": MemUsage, "TabSwitch": TabSwitch,
"MemUsage": MemUsage,
} }
} }
@@ -89,27 +90,28 @@ func MakeCommand(name, function string, completions ...Completion) {
// DefaultCommands returns a map containing micro's default commands // DefaultCommands returns a map containing micro's default commands
func DefaultCommands() map[string]StrCommand { func DefaultCommands() map[string]StrCommand {
return map[string]StrCommand{ return map[string]StrCommand{
"set": {"Set", []Completion{OptionCompletion, NoCompletion}}, "set": {"Set", []Completion{OptionCompletion, NoCompletion}},
"setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}}, "setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}},
"show": {"Show", []Completion{OptionCompletion, NoCompletion}}, "show": {"Show", []Completion{OptionCompletion, NoCompletion}},
"bind": {"Bind", []Completion{NoCompletion}}, "bind": {"Bind", []Completion{NoCompletion}},
"run": {"Run", []Completion{NoCompletion}}, "run": {"Run", []Completion{NoCompletion}},
"quit": {"Quit", []Completion{NoCompletion}}, "quit": {"Quit", []Completion{NoCompletion}},
"save": {"Save", []Completion{NoCompletion}}, "save": {"Save", []Completion{NoCompletion}},
"replace": {"Replace", []Completion{NoCompletion}}, "replace": {"Replace", []Completion{NoCompletion}},
"vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}}, "replaceall": {"ReplaceAll", []Completion{NoCompletion}},
"hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}}, "vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}},
"tab": {"Tab", []Completion{FileCompletion, NoCompletion}}, "hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}},
"help": {"Help", []Completion{HelpCompletion, NoCompletion}}, "tab": {"Tab", []Completion{FileCompletion, NoCompletion}},
"eval": {"Eval", []Completion{NoCompletion}}, "help": {"Help", []Completion{HelpCompletion, NoCompletion}},
"log": {"ToggleLog", []Completion{NoCompletion}}, "eval": {"Eval", []Completion{NoCompletion}},
"plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}}, "log": {"ToggleLog", []Completion{NoCompletion}},
"reload": {"Reload", []Completion{NoCompletion}}, "plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}},
"cd": {"Cd", []Completion{FileCompletion}}, "reload": {"Reload", []Completion{NoCompletion}},
"pwd": {"Pwd", []Completion{NoCompletion}}, "cd": {"Cd", []Completion{FileCompletion}},
"open": {"Open", []Completion{FileCompletion}}, "pwd": {"Pwd", []Completion{NoCompletion}},
"tabswitch": {"TabSwitch", []Completion{NoCompletion}}, "open": {"Open", []Completion{FileCompletion}},
"memusage": {"MemUsage", []Completion{NoCompletion}}, "tabswitch": {"TabSwitch", []Completion{NoCompletion}},
"memusage": {"MemUsage", []Completion{NoCompletion}},
} }
} }
@@ -506,16 +508,21 @@ func Save(args []string) {
// Replace runs search and replace // Replace runs search and replace
func Replace(args []string) { 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 // We need to find both a search and replace expression
messenger.Error("Invalid replace statement: " + strings.Join(args, " ")) messenger.Error("Invalid replace statement: " + strings.Join(args, " "))
return return
} }
var flags string allAtOnce := false
if len(args) == 3 { if len(args) == 3 {
// The user included some flags // user added -a flag
flags = args[2] if args[2] == "-a" {
allAtOnce = true
} else {
messenger.Error("Invalid replace flag: " + args[2])
return
}
} }
search := string(args[0]) search := string(args[0])
@@ -531,40 +538,7 @@ func Replace(args []string) {
view := CurView() view := CurView()
found := 0 found := 0
if strings.Contains(flags, "c") { if allAtOnce {
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 {
// var deltas []Delta // var deltas []Delta
for i := 0; i < view.Buf.LinesNum(); i++ { for i := 0; i < view.Buf.LinesNum(); i++ {
// view.Buf.lines[i].data = regex.ReplaceAll(view.Buf.lines[i].data, []byte(replace)) // 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) // 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() 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 // RunShellCommand executes a shell command and returns the output/error
func RunShellCommand(input string) (string, error) { func RunShellCommand(input string) (string, error) {
inputCmd := SplitCommandArgs(input)[0] inputCmd := SplitCommandArgs(input)[0]

View File

@@ -10,12 +10,17 @@ Here are the possible commands that you can use.
* `replace "search" "value" flags`: This will replace `search` with `value`. * `replace "search" "value" flags`: This will replace `search` with `value`.
The `flags` are optional. The `flags` are optional.
At this point, there is only one flag: `c`, which enables `check` mode At this point, there is only one flag: `-a`, which replaces all occurrences
which asks if you'd like to perform the replacement each time. at once.
Note that `search` must be a valid regex. If one of the arguments 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. 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 * `set option value`: sets the option to value. See the `options` help topic
for a list of options you can set. for a list of options you can set.