~sircmpwn/hare

c80c71f920b0e94370338341fef35b7f6fd4f07c — Sebastian 3 months ago 7323831
shlex: return number of bytes written for quote

Fixes: https://todo.sr.ht/~sircmpwn/hare/619
Signed-off-by: Sebastian <sebastian@sebsite.pw>
2 files changed, 21 insertions(+), 20 deletions(-)

M shlex/+test.ha
M shlex/escape.ha
M shlex/+test.ha => shlex/+test.ha +13 -11
@@ 1,6 1,8 @@
// License: MPL-2.0
// (c) 2021 Alexey Yerin <yyp@disroot.org>
use io;
use strings;
use strio;

@test fn split() void = {
	const s = split(`hello\ world`)!;


@@ 61,16 63,16 @@ use strings;
	assert(split(`unterminated\ backslash \`) is syntaxerr);
};

@test fn quote() void = {
	const bare = quotestr(`hello`);
	defer free(bare);
	assert(bare == `hello`);

	const spaces = quotestr(`hello world`);
	defer free(spaces);
	assert(spaces == `"hello world"`);
fn testquote(sink: *strio::stream, s: str, expected: str) void = {
	assert(quote(sink, s)! == len(expected));
	assert(strio::string(sink) == expected);
	strio::reset(sink);
};

	const quotes = quotestr(`'hello' "world"`);
	defer free(quotes);
	assert(quotes == `"'hello' "'"'"world"'"'""`);
@test fn quote() void = {
	const sink = strio::dynamic();
	defer io::close(&sink)!;
	testquote(&sink, `hello`, `hello`);
	testquote(&sink, `hello world`, `"hello world"`);
	testquote(&sink, `'hello' "world"`, `"'hello' "'"'"world"'"'""`);
};

M shlex/escape.ha => shlex/escape.ha +8 -9
@@ 28,17 28,15 @@ fn is_safe(s: str) bool = {
};

// Quotes a shell string and writes it to the provided I/O handle.
export fn quote(sink: io::handle, s: str) (void | io::error) = {
export fn quote(sink: io::handle, s: str) (size | io::error) = {
	if (len(s) == 0) {
		io::write(sink, strings::toutf8(`''`))?;
		return;
		return io::writeall(sink, strings::toutf8(`''`))?;
	};
	if (is_safe(s)) {
		io::write(sink, strings::toutf8(s))?;
		return;
		return io::writeall(sink, strings::toutf8(s))?;
	};

	io::write(sink, ['"'])?;
	let z = io::writeall(sink, ['"'])?;

	const iter = strings::iter(s);
	for (true) {


@@ 50,13 48,14 @@ export fn quote(sink: io::handle, s: str) (void | io::error) = {
		};

		if (rn == '"') {
			io::write(sink, strings::toutf8(`"'"'"`))?;
			z += io::writeall(sink, strings::toutf8(`"'"'"`))?;
		} else {
			io::write(sink, utf8::encoderune(rn))?;
			z += io::writeall(sink, utf8::encoderune(rn))?;
		};
	};

	io::write(sink, ['"'])?;
	z += io::writeall(sink, ['"'])?;
	return z;
};

// Quotes a shell string and returns a new string. The caller must free the