Skip to content

Commit

Permalink
Add replace in selection; fixes zyedidia#1098
Browse files Browse the repository at this point in the history
  • Loading branch information
supbish committed Aug 28, 2018
1 parent 1a617c6 commit a92b256
Showing 1 changed file with 55 additions and 8 deletions.
63 changes: 55 additions & 8 deletions cmd/micro/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,14 +544,15 @@ func Save(args []string) {

// Replace runs search and replace
func Replace(args []string) {
if len(args) < 2 || len(args) > 4 {
if len(args) < 2 || len(args) > 5 {
// We need to find both a search and replace expression
messenger.Error("Invalid replace statement: " + strings.Join(args, " "))
return
}

all := false
noRegex := false
inSelection := false

if len(args) > 2 {
for _, arg := range args[2:] {
Expand All @@ -560,6 +561,8 @@ func Replace(args []string) {
all = true
case "-l":
noRegex = true
case "-s":
inSelection = true
default:
messenger.Error("Invalid flag: " + arg)
return
Expand All @@ -584,18 +587,43 @@ func Replace(args []string) {
}

view := CurView()
startLine := 0
endLine := view.Buf.LinesNum()
var originalCursor Cursor

if inSelection {
originalCursor = *view.Cursor
if view.Cursor.HasSelection() {
startLine = view.Cursor.CurSelection[0].Y
endLine = view.Cursor.CurSelection[1].Y
} else {
startLine = view.Cursor.Loc.Y
endLine = startLine
}
if startLine > endLine {
startLine, endLine = endLine, startLine
}
endLine++
}

found := 0
replaceAll := func() {
var deltas []Delta
for i := 0; i < view.Buf.LinesNum(); i++ {
previousDelta := Delta{}
offset := 0
for i := startLine; i < endLine; i++ {
for _, submatches := range regex.FindAllSubmatchIndex(view.Buf.lines[i].data, -1) {
newText := regex.Expand([]byte{}, replaceBytes, view.Buf.lines[i].data, submatches)

from := Loc{submatches[0], i}
to := Loc{submatches[1], i}

deltas = append(deltas, Delta{string(newText), from, to})
if previousDelta.Start.Y != i {
offset = 0
}
oldText := string(view.Buf.lines[i].data[submatches[0]:submatches[1]])
newText := string(regex.Expand([]byte{}, replaceBytes, view.Buf.lines[i].data, submatches))
from := Loc{submatches[0] + offset, i}
to := Loc{submatches[1] + offset, i}
d := Delta{newText, from, to}
deltas = append(deltas, d)
previousDelta = d
offset += Count(newText) - Count(oldText)
found++
}
}
Expand All @@ -605,14 +633,33 @@ func Replace(args []string) {
if all {
replaceAll()
} else {
hangCheck := 0
for {
// The 'check' flag was used
Search(search, view, true)
if !view.Cursor.HasSelection() {
break
}

// if searching in a selection, and this result is outside of it,
// start the search over from the beginning of the search selection
if inSelection {
loc := view.Cursor.CurSelection[1]
if (loc.Y < startLine || loc.Y >= endLine) {
hangCheck++
if hangCheck > 1 {
view.Cursor.Goto(originalCursor)
break
}
searchStart = Loc{0, startLine}
continue
}
}
hangCheck = 0

view.Relocate()
RedrawAll()

choice, canceled := messenger.LetterPrompt("Perform replacement? (y,n,a)", 'y', 'n', 'a')
if canceled {
if view.Cursor.HasSelection() {
Expand Down

0 comments on commit a92b256

Please sign in to comment.