From 8011e57a7259b8ae0d24e4ad53dee8ab6eec227e Mon Sep 17 00:00:00 2001
From: dd86k
Date: Mon, 4 Mar 2024 15:40:39 -0500
Subject: [PATCH] Replace term_readline to term_readln
---
app/shell.d | 14 +++++++-------
app/term.d | 44 +++++++++++++++++++++++++++++++++++---------
dub.sdl | 7 ++++++-
tests/readln.d | 21 +++++++++++++++++++++
4 files changed, 69 insertions(+), 17 deletions(-)
create mode 100644 tests/readln.d
diff --git a/app/shell.d b/app/shell.d
index 1d277ef8..ff58456d 100644
--- a/app/shell.d
+++ b/app/shell.d
@@ -88,7 +88,7 @@ void registerHelp(void function(ref command2_help_t help)) {
}*/
int shell_loop() {
- // Load process if CLI specified it
+ // Load or attach process if CLI specified it
if (globals.file) {
if (adbg_debugger_spawn(&process, globals.file,
AdbgSpawnOpt.argv, globals.args, 0))
@@ -123,16 +123,17 @@ int shell_loop() {
term_init;
LINPUT:
- printf("(adbg) "); // print prompt
- char* line = term_readline(null); // read line
+ printf("(adbg) ");
+
+ // .ptr is temporary because a slice with a length of 0
+ // also make its pointer null.
+ char* line = term_readln().ptr;
- //TODO: remove once term gets key events
if (line == null) {
- printf("^D");
return 0;
}
- int error = shell_exec(line); // execute line
+ int error = shell_exec(line);
if (error)
printf("error: %s\n", errorstring(cast(ShellError)error));
goto LINPUT;
@@ -156,7 +157,6 @@ int shell_execv(int argc, const(char) **argv) {
serror("unknown command: '%s'", ucommand);
return ShellError.invalidCommand;
}
-
return command.entry(argc, argv);
}
diff --git a/app/term.d b/app/term.d
index 1aaf8697..3b20c5b9 100644
--- a/app/term.d
+++ b/app/term.d
@@ -14,8 +14,8 @@ import core.stdc.stdio;
extern (C):
-private
-int putchar(int);
+private int putchar(int);
+private int getchar();
version (Windows) {
private import core.sys.windows.windows;
@@ -358,17 +358,43 @@ L_END:
}
}
-//TODO: Consider redoing with getchar+fwrite(stdin)
+// onSpecial: tab, ^D, etc.
+// make onError?
+/// Read a line from stdin.
+/// Params:
+/// onSpecial = (Not implemented) Callback on special characters
+/// Returns: Character slice; Or null on error.
+char[] term_readln(void function(int) onSpecial = null) {
+ import core.stdc.ctype : isprint;
+
+ // GNU readline has this set to 512
+ enum BUFFERSIZE = 1024;
+
+ __gshared char* buffer;
+
+ if (buffer == null) {
+ buffer = cast(char*)malloc(BUFFERSIZE);
+ if (buffer == null)
+ return null;
+ }
+
+ // NOTE: stdin is line-buffered by the host console/terminal
+ // Once it sees a newline, it returns, and we copy up until the newline
+ size_t i;
+LFETCHC:
+ int c = getchar();
+ if (c == '\n' || c == EOF) {
+ buffer[i] = 0;
+ return buffer[0..i];
+ }
+ buffer[i++] = cast(char)c;
+ goto LFETCHC;
+}
-//TODO: term_readline_event(Key, void function(Key))
-// or just term_event_ctrld (etc.)
-//TODO: damage-based display (putchar)
-// instead of reprinting the whole string at every stroke
-// yes, it's very noticeable on windows (because of cursor positioning?)
-//TODO: Use realloc with enum INITBSZ = 2048
/// Read a line from input keystrokes
/// Params: length = Pointer that will contain the number of characters in the buffer
/// Returns: Internal buffer pointer
+deprecated("Use term_readln")
char* term_readline(int *length) {
enum BUFFER_SIZE = 1024;
__gshared char[BUFFER_SIZE] buffer;
diff --git a/dub.sdl b/dub.sdl
index 7ed4bc63..95fc196a 100644
--- a/dub.sdl
+++ b/dub.sdl
@@ -123,7 +123,7 @@ buildType "release-nobounds-static" {
}
#
-# ANCHOR Unit tests
+# ANCHOR Integration tests
#
# NOTE: These MUST be ran as "dub test -b TEST"
# NOTE: Dedicated tests must only exist if one of these conditions are met
@@ -145,6 +145,11 @@ buildType "readline" {
sourceFiles "tests/readline.d"
sourcePaths "app" "src"
}
+buildType "readln" {
+ buildOptions "unittests"
+ sourceFiles "tests/readln.d"
+ sourceFiles "app/term.d"
+}
#
# ANCHOR Examples
diff --git a/tests/readln.d b/tests/readln.d
new file mode 100644
index 00000000..21a6873a
--- /dev/null
+++ b/tests/readln.d
@@ -0,0 +1,21 @@
+module tests.readln;
+
+import core.stdc.stdio;
+import core.stdc.ctype : isprint;
+import term;
+
+extern (C) int putchar(int);
+
+unittest {
+ while (true) {
+ printf("prompt: ");
+ char[] input = term_readln();
+ foreach (char c; input)
+ if (isprint(c))
+ putchar(c);
+ else
+ printf("\\x%02x", c);
+ putchar('\n');
+ printf("buffer had %d characters\n", cast(int)input.length);
+ }
+}
\ No newline at end of file