Skip to content

Commit 509e549

Browse files
committed
modified search and replace methods
process `Deltas` in `ExecuteTextEvent` in reverse order added `util.RangeMap` changed `util.isMark` to public `IsMark` added `Loc.IsValid` added `(*Buffer).Expand`
1 parent 70dfc7f commit 509e549

9 files changed

Lines changed: 366 additions & 194 deletions

File tree

cmd/micro/initlua.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ func luaImportMicroBuffer() *lua.LTable {
141141
ulua.L.SetField(pkg, "ByteOffset", luar.New(ulua.L, buffer.ByteOffset))
142142
ulua.L.SetField(pkg, "Log", luar.New(ulua.L, buffer.WriteLog))
143143
ulua.L.SetField(pkg, "LogBuf", luar.New(ulua.L, buffer.GetLogBuf))
144+
ulua.L.SetField(pkg, "NewRegexpData", luar.New(ulua.L, buffer.NewRegexpData))
144145

145146
return pkg
146147
}

internal/action/command.go

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,17 +1018,8 @@ func (h *BufPane) ReplaceCmd(args []string) {
10181018

10191019
replace := []byte(replaceStr)
10201020

1021-
var regex *regexp.Regexp
1022-
var err error
10231021
if h.Buf.Settings["ignorecase"].(bool) {
1024-
regex, err = regexp.Compile("(?im)" + search)
1025-
} else {
1026-
regex, err = regexp.Compile("(?m)" + search)
1027-
}
1028-
if err != nil {
1029-
// There was an error with the user's regex
1030-
InfoBar.Error(err)
1031-
return
1022+
search = "(?i)" + search
10321023
}
10331024

10341025
nreplaced := 0
@@ -1042,21 +1033,32 @@ func (h *BufPane) ReplaceCmd(args []string) {
10421033
searchLoc = start // otherwise me might start at the end
10431034
}
10441035
if all {
1045-
nreplaced, _ = h.Buf.ReplaceRegex(start, end, regex, replace, !noRegex)
1036+
var err error
1037+
if noRegex {
1038+
nreplaced, _, err = h.Buf.ReplaceAllLiteral(search, start, end, replace)
1039+
} else {
1040+
nreplaced, _, err = h.Buf.ReplaceAll(search, start, end, replace)
1041+
}
1042+
if err != nil {
1043+
InfoBar.Error(err)
1044+
return
1045+
}
10461046
} else {
1047+
redata, err := buffer.NewRegexpData(search)
1048+
if err != nil {
1049+
InfoBar.Error(err)
1050+
return
1051+
}
1052+
10471053
inRange := func(l buffer.Loc) bool {
10481054
return l.GreaterEqual(start) && l.LessEqual(end)
10491055
}
10501056

10511057
lastMatchEnd := buffer.Loc{-1, -1}
10521058
var doReplacement func()
10531059
doReplacement = func() {
1054-
locs, found, err := h.Buf.FindNext(search, start, end, searchLoc, true, true)
1055-
if err != nil {
1056-
InfoBar.Error(err)
1057-
return
1058-
}
1059-
if !found || !inRange(locs[0]) || !inRange(locs[1]) {
1060+
locs := h.Buf.FindRegexpDown(redata, searchLoc, end)
1061+
if locs == nil || !inRange(locs[0]) || !inRange(locs[1]) {
10601062
h.Cursor.ResetSelection()
10611063
h.Buf.RelocateCursors()
10621064

@@ -1084,12 +1086,14 @@ func (h *BufPane) ReplaceCmd(args []string) {
10841086

10851087
InfoBar.YNPrompt("Perform replacement (y,n,esc)", func(yes, canceled bool) {
10861088
if !canceled && yes {
1087-
_, nrunes := h.Buf.ReplaceRegex(locs[0], locs[1], regex, replace, !noRegex)
1089+
if noRegex {
1090+
_, searchLoc, _ = h.Buf.ReplaceAllLiteral(search, locs[0], locs[1], replace)
1091+
} else {
1092+
_, searchLoc, _ = h.Buf.ReplaceAll(search, locs[0], locs[1], replace)
1093+
}
10881094

1089-
searchLoc = locs[0]
1090-
searchLoc.X += nrunes + locs[0].Diff(locs[1], h.Buf)
10911095
if end.Y == locs[1].Y {
1092-
end = end.Move(nrunes, h.Buf)
1096+
end = buffer.Loc{end.X + searchLoc.X - locs[1].X, end.Y}
10931097
}
10941098
h.Cursor.Loc = searchLoc
10951099
nreplaced++

internal/buffer/buffer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,13 @@ type Buffer struct {
269269
}
270270

271271
// NewBufferFromFileWithCommand opens a new buffer with a given command
272-
// If cmd.StartCursor is {-1, -1} the location does not overwrite what the cursor location
272+
// If cmd.StartCursor is invalid, the location does not overwrite what the cursor location
273273
// would otherwise be (start of file, or saved cursor position if `savecursor` is
274274
// enabled)
275275
func NewBufferFromFileWithCommand(path string, btype BufType, cmd Command) (*Buffer, error) {
276276
var err error
277277
filename := path
278-
if config.GetGlobalOption("parsecursor").(bool) && cmd.StartCursor.X == -1 && cmd.StartCursor.Y == -1 {
278+
if config.GetGlobalOption("parsecursor").(bool) && !cmd.StartCursor.IsValid() {
279279
var cursorPos []string
280280
filename, cursorPos = util.GetPathAndCursorPosition(filename)
281281
cmd.StartCursor, err = ParseCursorLocation(cursorPos)

internal/buffer/eventhandler.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ type TextEvent struct {
3030
C Cursor
3131

3232
EventType int
33+
// If there are several deltas for the same line, they must not overlap
34+
// and be ordered by increasing start position
3335
Deltas []Delta
3436
Time time.Time
3537
}
@@ -114,24 +116,24 @@ func (eh *EventHandler) DoTextEvent(t *TextEvent, useUndo bool) {
114116

115117
// ExecuteTextEvent runs a text event
116118
func ExecuteTextEvent(t *TextEvent, buf *SharedBuffer) {
117-
if t.EventType == TextEventInsert {
118-
for _, d := range t.Deltas {
119+
for i := len(t.Deltas) - 1; i >= 0; i-- {
120+
// Processing the deltas in increasing order would require
121+
// to recompute the positions of the later deltas
122+
d := t.Deltas[i]
123+
if t.EventType == TextEventInsert {
119124
buf.insert(d.Start, d.Text)
120-
}
121-
} else if t.EventType == TextEventRemove {
122-
for i, d := range t.Deltas {
125+
} else if t.EventType == TextEventRemove {
123126
t.Deltas[i].Text = buf.remove(d.Start, d.End)
124-
}
125-
} else if t.EventType == TextEventReplace {
126-
for i, d := range t.Deltas {
127+
} else { // TextEventReplace
127128
t.Deltas[i].Text = buf.remove(d.Start, d.End)
128129
buf.insert(d.Start, d.Text)
129130
t.Deltas[i].Start = d.Start
130131
t.Deltas[i].End = Loc{d.Start.X + util.CharacterCount(d.Text), d.Start.Y}
131132
}
132-
for i, j := 0, len(t.Deltas)-1; i < j; i, j = i+1, j-1 {
133-
t.Deltas[i], t.Deltas[j] = t.Deltas[j], t.Deltas[i]
134-
}
133+
}
134+
135+
for i, j := 0, len(t.Deltas)-1; i < j; i, j = i+1, j-1 {
136+
t.Deltas[i], t.Deltas[j] = t.Deltas[j], t.Deltas[i]
135137
}
136138
}
137139

@@ -195,7 +197,7 @@ func (eh *EventHandler) InsertBytes(start Loc, text []byte) {
195197
e := &TextEvent{
196198
C: *eh.cursors[eh.active],
197199
EventType: TextEventInsert,
198-
Deltas: []Delta{{text, start, Loc{0, 0}}},
200+
Deltas: []Delta{{text, start, Loc{-1, -1}}},
199201
Time: time.Now(),
200202
}
201203
eh.DoTextEvent(e, true)

internal/buffer/loc.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ type Loc struct {
99
X, Y int
1010
}
1111

12+
// IsValid returns true if the argument is an actual buffer location
13+
func (l Loc) IsValid() bool {
14+
return l.X >= 0 && l.Y >= 0
15+
}
16+
1217
// LessThan returns true if b is smaller
1318
func (l Loc) LessThan(b Loc) bool {
1419
if l.Y < b.Y {

0 commit comments

Comments
 (0)