mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-29 22:27:13 +09:00
Add search and replace
This commit is contained in:
@@ -552,7 +552,7 @@ func (h *BufHandler) SaveAs() bool {
|
||||
func (h *BufHandler) Find() bool {
|
||||
InfoBar.Prompt("Find: ", "", "Find", func(resp string) {
|
||||
// Event callback
|
||||
match, found, _ := h.Buf.FindNext(resp, h.Cursor.Loc, true)
|
||||
match, found, _ := h.Buf.FindNext(resp, h.Buf.Start(), h.Buf.End(), h.Cursor.Loc, true, true)
|
||||
if found {
|
||||
h.Cursor.SetSelectionStart(match[0])
|
||||
h.Cursor.SetSelectionEnd(match[1])
|
||||
@@ -564,7 +564,7 @@ func (h *BufHandler) Find() bool {
|
||||
}, func(resp string, canceled bool) {
|
||||
// Finished callback
|
||||
if !canceled {
|
||||
match, found, err := h.Buf.FindNext(resp, h.Cursor.Loc, true)
|
||||
match, found, err := h.Buf.FindNext(resp, h.Buf.Start(), h.Buf.End(), h.Cursor.Loc, true, true)
|
||||
if err != nil {
|
||||
InfoBar.Error(err)
|
||||
}
|
||||
@@ -597,7 +597,7 @@ func (h *BufHandler) FindNext() bool {
|
||||
if h.Cursor.HasSelection() {
|
||||
searchLoc = h.Cursor.CurSelection[1]
|
||||
}
|
||||
match, found, err := h.Buf.FindNext(h.lastSearch, searchLoc, true)
|
||||
match, found, err := h.Buf.FindNext(h.lastSearch, h.Buf.Start(), h.Buf.End(), searchLoc, true, true)
|
||||
if err != nil {
|
||||
InfoBar.Error(err)
|
||||
}
|
||||
@@ -623,7 +623,7 @@ func (h *BufHandler) FindPrevious() bool {
|
||||
if h.Cursor.HasSelection() {
|
||||
searchLoc = h.Cursor.CurSelection[0]
|
||||
}
|
||||
match, found, err := h.Buf.FindNext(h.lastSearch, searchLoc, false)
|
||||
match, found, err := h.Buf.FindNext(h.lastSearch, h.Buf.Start(), h.Buf.End(), searchLoc, false, true)
|
||||
if err != nil {
|
||||
InfoBar.Error(err)
|
||||
}
|
||||
@@ -1189,7 +1189,7 @@ func (h *BufHandler) SpawnMultiCursor() bool {
|
||||
if h.multiWord {
|
||||
search = "\\b" + search + "\\b"
|
||||
}
|
||||
match, found, err := h.Buf.FindNext(search, searchStart, true)
|
||||
match, found, err := h.Buf.FindNext(search, h.Buf.Start(), h.Buf.End(), searchStart, true, false)
|
||||
if err != nil {
|
||||
InfoBar.Error(err)
|
||||
}
|
||||
@@ -1262,7 +1262,7 @@ func (h *BufHandler) SkipMultiCursor() bool {
|
||||
sel := lastC.GetSelection()
|
||||
searchStart := lastC.CurSelection[1]
|
||||
|
||||
match, found, err := h.Buf.FindNext(string(sel), searchStart, true)
|
||||
match, found, err := h.Buf.FindNext(string(sel), h.Buf.Start(), h.Buf.End(), searchStart, true, false)
|
||||
if err != nil {
|
||||
InfoBar.Error(err)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/zyedidia/micro/cmd/micro/buffer"
|
||||
"github.com/zyedidia/micro/cmd/micro/config"
|
||||
@@ -540,6 +542,115 @@ func (h *BufHandler) SaveCmd(args []string) {
|
||||
|
||||
// ReplaceCmd runs search and replace
|
||||
func (h *BufHandler) ReplaceCmd(args []string) {
|
||||
if len(args) < 2 || len(args) > 4 {
|
||||
// We need to find both a search and replace expression
|
||||
InfoBar.Error("Invalid replace statement: " + strings.Join(args, " "))
|
||||
return
|
||||
}
|
||||
|
||||
all := false
|
||||
noRegex := false
|
||||
|
||||
if len(args) > 2 {
|
||||
for _, arg := range args[2:] {
|
||||
switch arg {
|
||||
case "-a":
|
||||
all = true
|
||||
case "-l":
|
||||
noRegex = true
|
||||
default:
|
||||
InfoBar.Error("Invalid flag: " + arg)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
search := args[0]
|
||||
|
||||
if noRegex {
|
||||
search = regexp.QuoteMeta(search)
|
||||
}
|
||||
|
||||
replace := []byte(args[1])
|
||||
|
||||
var regex *regexp.Regexp
|
||||
var err error
|
||||
if h.Buf.Settings["ignorecase"].(bool) {
|
||||
regex, err = regexp.Compile("(?im)" + search)
|
||||
} else {
|
||||
regex, err = regexp.Compile("(?m)" + search)
|
||||
}
|
||||
if err != nil {
|
||||
// There was an error with the user's regex
|
||||
InfoBar.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
nreplaced := 0
|
||||
start := h.Buf.Start()
|
||||
end := h.Buf.End()
|
||||
if h.Cursor.HasSelection() {
|
||||
start = h.Cursor.CurSelection[0]
|
||||
end = h.Cursor.CurSelection[1]
|
||||
}
|
||||
if all {
|
||||
nreplaced = h.Buf.ReplaceRegex(start, end, regex, replace)
|
||||
} else {
|
||||
inRange := func(l buffer.Loc) bool {
|
||||
return l.GreaterEqual(start) && l.LessThan(end)
|
||||
}
|
||||
|
||||
searchLoc := start
|
||||
searching := true
|
||||
var doReplacement func()
|
||||
doReplacement = func() {
|
||||
locs, found, err := h.Buf.FindNext(search, start, end, searchLoc, true, !noRegex)
|
||||
if err != nil {
|
||||
InfoBar.Error(err)
|
||||
return
|
||||
}
|
||||
if !found || !inRange(locs[0]) || !inRange(locs[1]) {
|
||||
h.Cursor.ResetSelection()
|
||||
h.Cursor.Relocate()
|
||||
return
|
||||
}
|
||||
|
||||
h.Cursor.SetSelectionStart(locs[0])
|
||||
h.Cursor.SetSelectionEnd(locs[1])
|
||||
|
||||
InfoBar.YNPrompt("Perform replacement (y,n,esc)", func(yes, canceled bool) {
|
||||
if !canceled && yes {
|
||||
h.Buf.Replace(locs[0], locs[1], replace)
|
||||
searchLoc = locs[0]
|
||||
searchLoc.X += utf8.RuneCount(replace)
|
||||
h.Cursor.Loc = searchLoc
|
||||
nreplaced++
|
||||
} else if !canceled && !yes {
|
||||
searchLoc = locs[0]
|
||||
searchLoc.X += utf8.RuneCount(replace)
|
||||
} else if canceled {
|
||||
h.Cursor.ResetSelection()
|
||||
h.Cursor.Relocate()
|
||||
return
|
||||
}
|
||||
if searching {
|
||||
doReplacement()
|
||||
}
|
||||
})
|
||||
}
|
||||
doReplacement()
|
||||
}
|
||||
|
||||
// TODO: relocate all cursors?
|
||||
h.Cursor.Relocate()
|
||||
|
||||
if nreplaced > 1 {
|
||||
InfoBar.Message("Replaced ", nreplaced, " occurrences of ", search)
|
||||
} else if nreplaced == 1 {
|
||||
InfoBar.Message("Replaced ", nreplaced, " occurrence of ", search)
|
||||
} else {
|
||||
InfoBar.Message("Nothing matched ", search)
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceAllCmd replaces search term all at once
|
||||
|
||||
@@ -33,20 +33,21 @@ func (h *InfoHandler) HandleEvent(event tcell.Event) {
|
||||
}
|
||||
|
||||
done := h.DoKeyEvent(ke)
|
||||
if e.Key() == tcell.KeyRune && h.HasYN {
|
||||
if e.Rune() == 'y' && h.HasYN {
|
||||
hasYN := h.HasYN
|
||||
if e.Key() == tcell.KeyRune && hasYN {
|
||||
if e.Rune() == 'y' && hasYN {
|
||||
h.YNResp = true
|
||||
h.DonePrompt(false)
|
||||
} else if e.Rune() == 'n' && h.HasYN {
|
||||
} else if e.Rune() == 'n' && hasYN {
|
||||
h.YNResp = false
|
||||
h.DonePrompt(false)
|
||||
}
|
||||
}
|
||||
if e.Key() == tcell.KeyRune && !done && !h.HasYN {
|
||||
if e.Key() == tcell.KeyRune && !done && !hasYN {
|
||||
h.DoRuneInsert(e.Rune())
|
||||
done = true
|
||||
}
|
||||
if done && h.HasPrompt && !h.HasYN {
|
||||
if done && h.HasPrompt && !hasYN {
|
||||
resp := strings.TrimSpace(string(h.LineBytes(0)))
|
||||
hist := h.History[h.PromptType]
|
||||
hist[h.HistoryNum] = resp
|
||||
|
||||
Reference in New Issue
Block a user