commit 3b7f8d3a4fe2b5c0c259d3604572bf213f92e75e
parent 3c9de16b8ac47fbda677d1b9c52faac470f405ef
Author: Byron Torres <b@torresjrjr.com>
Date: Tue, 9 Jan 2024 11:33:07 +0000
add regex search pattern memory
Diffstat:
5 files changed, 37 insertions(+), 10 deletions(-)
diff --git a/address.ha b/address.ha
@@ -1,4 +1,5 @@
use regex;
+use strings;
type Address = struct{
addrform: AddressForm,
@@ -26,6 +27,9 @@ type InvalidAddress = !void;
// A regular expression search found no match.
type NoMatch = !void;
+// There is no previously used regex search pattern.
+type NoPrevRegex = !void;
+
fn addr_nextline(buf: *Buffer, n: size) size = {
if (len(buf.lines) - 1 == n)
return n;
@@ -65,10 +69,10 @@ fn addr_regex(
buf: *Buffer,
rad: RegexAddr,
start: size,
-) (size | NoMatch | regex::error) = {
+ s: *Session,
+) (size | NoPrevRegex | NoMatch | regex::error) = {
const length = len(buf.lines);
- // TODO: use BRE, not ERE.
- const re = regex::compile(rad.expr)?; defer regex::finish(&re);
+ const re = newregex(s, rad.expr)?; defer regex::finish(&re);
for (let x = 1z; x <= length; x += 1) {
const n =
@@ -86,3 +90,21 @@ fn addr_regex(
return NoMatch;
};
+
+fn newregex(s: *Session, expr: str) (regex::regex | NoPrevRegex | regex::error) = {
+ debug("expr=<{}>", expr);
+ debug("s.lastregex=<{}>", s.lastregex);
+
+ const newexpr =
+ if (expr != "")
+ expr
+ else if (s.lastregex is str)
+ s.lastregex as str
+ else
+ return NoPrevRegex;
+
+ // TODO: use BRE, not ERE.
+ const re = regex::compile(newexpr)?;
+ s.lastregex = strings::dup(newexpr);
+ yield re;
+};
diff --git a/command.ha b/command.ha
@@ -36,6 +36,7 @@ type CmdError = !(
| NoFilename
| WarnBufferModified
| NoMatch
+ | NoPrevRegex
| NoPrevShCmd
| NoPrevGlobalSubCmd
| InvalidGlobalSubCmd
@@ -456,7 +457,7 @@ fn cmd_substitute(s: *Session, cmd: *Command) (void | Error) = {
)?;
assert_nonzero(s, a)?;
- const regex = regex::compile(cmd.arg1)?; defer regex::finish(®ex);
+ const re = newregex(s, cmd.arg1)?; defer regex::finish(&re);
const replacement = cmd.arg2;
const flags = cmd.arg3;
// TODO: parse and use substitution flags `cmd.arg3`
@@ -465,7 +466,7 @@ fn cmd_substitute(s: *Session, cmd: *Command) (void | Error) = {
for (let i = a; i <= b; i += 1) {
const old = s.buf.lines[i].text;
- const results = regex::findall(®ex, old);
+ const results = regex::findall(&re, old);
defer regex::result_freeall(results);
if (len(results) == 0)
diff --git a/execute.ha b/execute.ha
@@ -37,7 +37,7 @@ fn exec_addr(s: *Session, addr: Address) (size | CmdError) = {
case let mark: rune =>
return addr_mark(s.buf, mark)?;
case let rad: RegexAddr =>
- return addr_regex(s.buf, rad, s.buf.cursor)?;
+ return addr_regex(s.buf, rad, s.buf.cursor, s)?;
};
};
diff --git a/global.ha b/global.ha
@@ -17,12 +17,12 @@ fn global(s: *Session, cmd: *Command, matched: bool) (void | Error) = {
)?;
assert_nonzero(s, a)?;
- const regex = regex::compile(cmd.arg1)?; defer regex::finish(®ex);
+ const re = newregex(s, cmd.arg1)?; defer regex::finish(&re);
for (let i = a; i <= b; i += 1) {
const line = s.buf.lines[i];
line.globalmark = false; // TODO: is this necessary?
- if (matched == regex::test(®ex, line.text))
+ if (matched == regex::test(&re, line.text))
line.globalmark = true;
};
@@ -116,12 +116,12 @@ fn global_interactive(s: *Session, cmd: *Command, matched: bool) (void | Error)
)?;
assert_nonzero(s, a)?;
- const regex = regex::compile(cmd.arg1)?; defer regex::finish(®ex);
+ const re = newregex(s, cmd.arg1)?; defer regex::finish(&re);
for (let i = a; i <= b; i += 1) {
const line = s.buf.lines[i];
line.globalmark = false; // TODO: is this necessary?
- if (matched == regex::test(®ex, line.text))
+ if (matched == regex::test(&re, line.text))
line.globalmark = true;
};
diff --git a/main.ha b/main.ha
@@ -21,6 +21,7 @@ type Session = struct{
prompt: str,
warned: bool,
prev_shcmd: (str | void),
+ lastregex: (void | str),
};
type Error = !(...InteractionError | ...ParseError | ...CmdError);
@@ -52,6 +53,7 @@ export fn main() void = {
prompt = "*",
prev_shcmd = void,
lasterror = void,
+ lastregex = void,
...
};
@@ -160,6 +162,8 @@ fn strerror(err: Error) str = {
return "Invalid destination";
case NoMatch =>
return "No match";
+ case NoPrevRegex =>
+ return "No previous search pattern";
case NoPrevShCmd =>
return "No previous shell command";
case NoPrevGlobalSubCmd =>