Repository: zyedidia/micro
File: internal/buffer/search.go (Go)

Code before:
			charpos = start.X-1
			l = util.SliceEnd(l, charpos)
			ri += 1 // rPadNone -> rPadStart, rPadEnd -> rPadBoth
		}
	}

	return l, charpos, rPadded[ri]
}

func (b *Buffer) findDown(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
	lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
	if start.Y > b.LinesNum()-1 {
		start.X = lastcn - 1
	}
	if end.Y > b.LinesNum()-1 {
		end.X = lastcn
	}
	start.Y = util.Clamp(start.Y, 0, b.LinesNum()-1)
	end.Y = util.Clamp(end.Y, 0, b.LinesNum()-1)

	if start.GreaterThan(end) {
		start, end = end, start
	}

	rPadNone, rPadStart, rPadEnd, rPadBoth := padRegexp(r)
	rPadded := [4]*regexp.Regexp{rPadNone, rPadStart, rPadEnd, rPadBoth}

	for i := start.Y; i <= end.Y; i++ {
		l, charpos, r := findLineParams(b, start, end, i, rPadded)

		match := r.FindIndex(l)

		if match != nil {
			start := Loc{charpos + util.RunePos(l, match[0]), i}
			if r == rPadStart || r == rPadBoth {
				start = start.Move(1, b)
			}
			end := Loc{charpos + util.RunePos(l, match[1]), i}
			if r == rPadEnd || r == rPadBoth {
				end = end.Move(-1, b)
			}
			return [2]Loc{start, end}, true
		}
	}
	return [2]Loc{}, false
}

func (b *Buffer) findUp(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
	lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
	if start.Y > b.LinesNum()-1 {
		start.X = lastcn - 1

Review comment (suggestion):
I guess `padRegexp()` could just return the array of 4 regexps so we could just use it, and naturally index with the numeric constants `rPadNone`, `rPadStart`, `rPadEnd`, `rPadBoth` (defined with `iota` as I suggested above) instead of a separate variable for each.

And then, it also seems cleaner to let `findLineParams()` return not the regexp itself but just the numeric constant `rPadNone`, `rPadStart`, `rPadEnd` or `rPadBoth` (let's call it "padding mode"). Then we don't need to pass the array to `findLineParams()`.

Code after:
	if i == start.Y {
		nchars := util.CharacterCount(l)
		start.X = util.Clamp(start.X, 0, nchars)
		if start.X > 0 {
			charpos = start.X - 1
			l = util.SliceEnd(l, charpos)
			padMode |= padStart
		}
	}

	if padMode == padStart {
		r = regexp.MustCompile(".(?:" + r.String() + ")")
	} else if padMode == padEnd {
		r = regexp.MustCompile("(?:" + r.String() + ").")
	} else if padMode == padStart|padEnd {
		r = regexp.MustCompile(".(?:" + r.String() + ").")
	}

	return l, charpos, padMode, r
}

func (b *Buffer) findDown(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
	lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
	if start.Y > b.LinesNum()-1 {
		start.X = lastcn - 1
	}
	if end.Y > b.LinesNum()-1 {
		end.X = lastcn
	}
	start.Y = util.Clamp(start.Y, 0, b.LinesNum()-1)
	end.Y = util.Clamp(end.Y, 0, b.LinesNum()-1)

	if start.GreaterThan(end) {
		start, end = end, start
	}

	for i := start.Y; i <= end.Y; i++ {
		l, charpos, padMode, rPadded := findLineParams(b, start, end, i, r)

		match := rPadded.FindIndex(l)

		if match != nil {
			if padMode&padStart != 0 {
				_, size := utf8.DecodeRune(l[match[0]:])
				match[0] += size
			}
			if padMode&padEnd != 0 {
				_, size := utf8.DecodeLastRune(l[:match[1]])
				match[1] -= size
			}
			start := Loc{charpos + util.RunePos(l, match[0]), i}