ed

[hare] The standard editor
Log | Files | Refs | README | LICENSE

commit 718d4ae9c7a5a520f58c2155a6c7b64e1a68a30a
parent 35b39978e5ad17722d20594e66d9157c19f5077f
Author: Byron Torres <b@torresjrjr.com>
Date:   Sat, 17 Dec 2022 01:36:46 +0000

add cmd_list(), printer functions

Diffstat:
Mcommand.ha | 22+++++++++++++++-------
Mparse.ha | 2+-
Mutil.ha | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 8 deletions(-)

diff --git a/command.ha b/command.ha @@ -293,7 +293,19 @@ fn cmd_mark(s: *session, cmd: *command) (void | error) = { s.buf.lines[n].mark = mark; }; -fn cmd_list(s: *session, cmd: *command) (void | error) = void; +fn cmd_list(s: *session, cmd: *command) (void | error) = { + const (a, b) = get_range( + s, + &cmd.linenums, + s.buf.cursor, + s.buf.cursor, + )?; + assert_nonzero(s, a)?; + debug("cmd_list(): (a, b)=({}, {})", a, b); + + printlistlns(&s.buf, a, b)?; + s.buf.cursor = b; +}; fn cmd_move(s: *session, cmd: *command) (void | error) = { const (a, b) = get_range( @@ -351,9 +363,7 @@ fn cmd_number(s: *session, cmd: *command) (void | error) = { assert_nonzero(s, a)?; debug("cmd_number(): (a, b)=({}, {})", a, b); - for (let n = a; n <= b; n += 1) { - fmt::printfln("{}\t{}", n, s.buf.lines[n].text)!; - }; + printnumberlns(&s.buf, a, b)?; s.buf.cursor = b; }; @@ -366,9 +376,7 @@ fn cmd_print(s: *session, cmd: *command) (void | error) = { )?; assert_nonzero(s, a)?; - for (let n = a; n <= b; n += 1) { - fmt::println(s.buf.lines[n].text)!; - }; + printlns(&s.buf, a, b)?; s.buf.cursor = b; }; diff --git a/parse.ha b/parse.ha @@ -223,7 +223,7 @@ fn scan_cmdfn(iter: *strings::iterator) commandfn = { // case 'i' => return &cmd_insert; case 'j' => return &cmd_join; case 'k' => return &cmd_mark; -// case 'l' => return &cmd_list; + case 'l' => return &cmd_list; case 'm' => return &cmd_move; case 'n' => return &cmd_number; case 'p' => return &cmd_print; diff --git a/util.ha b/util.ha @@ -1,4 +1,6 @@ use fmt; +use io; +use strings; fn cmd_dumpbuffer(s: *session, cmd: *command) (void | error) = { return dumpbuffer(&s.buf); @@ -15,3 +17,68 @@ fn debug(fmtstr: str, args: fmt::field...) void = { fmt::errorf(fmtstr, args...)!; fmt::errorln("\x1b[m")!; }; + +type printer = *fn(_: *buffer, _: size, _: size) (size | io::error); + +fn printlns(buf: *buffer, a: size, b: size) (size | io::error) = { + let sz = 0z; + for (let n = a; n <= b; n += 1) { + sz += fmt::println(buf.lines[n].text)?; + }; + return sz; +}; + +fn printnumberlns(buf: *buffer, a: size, b: size) (size | io::error) = { + let sz = 0z; + for (let n = a; n <= b; n += 1) { + sz += fmt::printfln("{}\t{}", n, buf.lines[n].text)?; + }; + return sz; +}; + +fn printlistlns(buf: *buffer, a: size, b: size) (size | io::error) = { + let sz = 0z; + for (let n = a; n <= b; n += 1) { + sz += printlistln(buf.lines[n].text)?; + }; + return sz; +}; + +fn printlistln(text: str) (size | io::error) = { + // TODO: handle wrapping (see ed(1) > list command) + const iter = strings::iter(text); + let sz = 0z; + + for (true) { + const r = match (strings::next(&iter)) { + case void => + break; + case let r: rune => + yield r; + }; + + sz += switch (r) { + case '\\' => + yield fmt::print("\\\\")?; + case '\a' => + yield fmt::print("\\a")?; + case '\b' => + yield fmt::print("\\b")?; + case '\f' => + yield fmt::print("\\f")?; + case '\r' => + yield fmt::print("\\r")?; + case '\t' => + yield fmt::print("\\t")?; + case '\v' => + yield fmt::print("\\v")?; + case '$' => + yield fmt::print("\\$")?; + case => + yield fmt::print(r)?; + }; + }; + + sz += fmt::println('$')?; + return sz; +};