Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FindNextSubmatch: return submatches when searching #3552

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 47 additions & 23 deletions internal/buffer/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/zyedidia/micro/v2/internal/util"
)

func (b *Buffer) findDown(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
func (b *Buffer) findDown(r *regexp.Regexp, start, end Loc) ([]Loc, bool) {
lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
if start.Y > b.LinesNum()-1 {
start.X = lastcn - 1
Expand Down Expand Up @@ -43,18 +43,24 @@ func (b *Buffer) findDown(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
l = util.SliceStart(l, end.X)
}

match := r.FindIndex(l)
match := r.FindSubmatchIndex(l)

if match != nil {
start := Loc{charpos + util.RunePos(l, match[0]), i}
end := Loc{charpos + util.RunePos(l, match[1]), i}
return [2]Loc{start, end}, true
loc := make([]Loc, len(match))
for j, x := range match {
if x == -1 { // submatch doesn't occur in match
loc[j] = Loc{-1, -1}
} else {
loc[j] = Loc{charpos + util.RunePos(l, x), i}
}
}
return loc, true
}
}
return [2]Loc{}, false
return []Loc{}, false
}

func (b *Buffer) findUp(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
func (b *Buffer) findUp(r *regexp.Regexp, start, end Loc) ([]Loc, bool) {
lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
if start.Y > b.LinesNum()-1 {
start.X = lastcn - 1
Expand Down Expand Up @@ -91,46 +97,48 @@ func (b *Buffer) findUp(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
l = util.SliceStart(l, end.X)
}

allMatches := r.FindAllIndex(l, -1)
allMatches := r.FindAllSubmatchIndex(l, -1)

if allMatches != nil {
match := allMatches[len(allMatches)-1]
start := Loc{charpos + util.RunePos(l, match[0]), i}
end := Loc{charpos + util.RunePos(l, match[1]), i}
return [2]Loc{start, end}, true
loc := make([]Loc, len(match))
for j, x := range match {
if x == -1 { // submatch doesn't occur in match
loc[j] = Loc{-1, -1}
} else {
loc[j] = Loc{charpos + util.RunePos(l, x), i}
}
}
return loc, true
}
}
return [2]Loc{}, false
return []Loc{}, false
}

// FindNext finds the next occurrence of a given string in the buffer
// It returns the start and end location of the match (if found) and
// a boolean indicating if it was found
// FindNextSubmatch finds the next occurrence of a given string in the
// buffer. It returns the start and end location of the match and of
// all submatches (if found) and a boolean indicating if it was found.
// May also return an error if the search regex is invalid
func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bool) ([2]Loc, bool, error) {
func (b *Buffer) FindNextSubmatch(s string, start, end, from Loc, down bool) ([]Loc, bool, error) {
if s == "" {
return [2]Loc{}, false, nil
return []Loc{}, false, nil
}

var r *regexp.Regexp
var err error

if !useRegex {
s = regexp.QuoteMeta(s)
}

if b.Settings["ignorecase"].(bool) {
r, err = regexp.Compile("(?i)" + s)
} else {
r, err = regexp.Compile(s)
}

if err != nil {
return [2]Loc{}, false, err
return []Loc{}, false, err
}

var found bool
var l [2]Loc
var l []Loc
if down {
l, found = b.findDown(r, from, end)
if !found {
Expand All @@ -145,6 +153,22 @@ func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bo
return l, found, nil
}

// FindNext finds the next occurrence of a given string in the buffer
// It returns the start and end location of the match (if found) and
// a boolean indicating if it was found
// May also return an error if the search regex is invalid
func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bool) ([2]Loc, bool, error) {
if !useRegex {
s = regexp.QuoteMeta(s)
}
l, found, err := b.FindNextSubmatch(s, start, end, from, down)
if found {
return [2]Loc{l[0], l[1]}, found, err
} else {
return [2]Loc{}, found, err
}
}

// ReplaceRegex replaces all occurrences of 'search' with 'replace' in the given area
// and returns the number of replacements made and the number of runes
// added or removed on the last line of the range
Expand Down
Loading