#Listen on input
1 messages · Page 1 of 1 (latest)
This isn't at all zig specific, it's just a termios thing
You'll need to enter raw mode using termios (Google it) which allows you to receive input for every key the user presses, instead of only getting input after a newline
And be aware that you have a lot more work ahead of you than you'd think
You'll essentially need to emulate how getting user input already works
You'll need to maintain a text buffer that the user types into, do something special when the user presses an up or down arrow, and then submit it when the user presses enter
Aha, so I get raw input key at a time, allocate it until enter is pressed?
Right, will it work if someone doesnt have raw mode in their console?
id highly recommend just linking against libc (you'll need it for termios stuff anyway) and using a library called GNU readline, virtually every system that will run your program will have it anyway since all shells and most interactive terminal apps use it
All standards abiding terminals will, even ancient teletypes will do their best
Ok, thank you. Will try it
Not only that, but you'll also need to do the work of displaying the text for the terminal
Oh and this only works on Linux and macos and other posix compliant (enough) systems, it wont work on windows since it has nothing like termios or raw mode in general
Thats fine, Windows does it automatically (at least powershell)
Oh, so also display output on terminal and manipulate it with gnu readline
If you're using GNU readline it's all done for you, you don't have to worry about it at all
Literally just call readline() and it'll give you a null terminated string to what the user typed in
And there are functions that let you store stuff in history so the user can use those
it's very nice
Look at the official docs or the man page
you need to use raw mode
using std.os.termios
disable the buffering
so you can listen to EVERY key press
it can give you some references
to save you time for arrows:
Arrow keys, Page Up, Page Down, Home, and End all input 3 or 4 bytes to the terminal: 27, '[', and then one or two other characters. This is known as an escape sequence. All escape sequences start with a 27 byte. Pressing Escape sends a single 27 byte as input.
Can you elaborate please? I found the std.os.termios, but I dont see anything to disable the buffer by
tcsetattr
I can look when im home
std.os.tcsetattr is there, although im unsure what params does it use
That would be great, thanks
that way it does read one char at a time, great work! however 2 notes, I cant exit without closing console and the arrows detection is not working on my ubuntu, somehow it takes the arrows as [[A or something like that
no worries at all m8, im just happy you can help out
you need to manually add support for ctrl + c
I think it’s one of the flags
try to remove ISIG
So either add support for it or allow it along the other flags?
A thought came to mind, how can I manipulate the console? If you read my initial question, I also state I need to remove the input and replace it with proper history
As someone previously mentioned, this can be achieved with the GNU readline library but can it be done without it?
there is a string that clears console
you then also need to reset the cursor
printing “\x1B[2J\x1B[H” (clear the entire screen and move the
cursor to top left) - https://ziggit.dev/t/how-to-clear-terminal/88
You'll want to use a different escape code to clear it up to the current input line, that way stuff in the terminal before it remains untouched
You'll need to save the current cursor position when you begin asking for input, and clear up to that y position
(Both of those actions are also standard escape codes)
Ok, I have implemented some stuff already. Thought to implement it seamlessly will be a lot of work. Will the GNU Readline library you mentioned help me with some work? ( like deleting char thats under the cursor? )
readline will do basically all of the work for you, as stated
i'd reccomend go reading its docs and examples
it will handle things like history, display, and such
Is this the site you are reffering to? https://tiswww.case.edu/php/chet/readline/readline.html
https://tiswww.cwru.edu/php/chet/readline/rltop.html
this is the actual homepage, but yes, that is the documentation/explanation
It will do literally everything someone could ask for
Allow the user to customize how it works, give them keybindings to jump around text, allow them to delete characters, make copy and pasting work slightly nicer, record history, auto complete file paths or if you want, you can add your own auto completion targets and itll also handle that
It's a giant monolithic library that essentially everything that takes user input should use
(that being said, implementing your own subset of readline is a pretty fun challenge if you want to keep going, just be aware that reimplementing all of GNU readline is very difficult, it's well over 100,000 lines of code)
Maybe for the next project, unfortunately no time for that now 😄
would be nice to have a pure zig version tbh, maybe ill tackle it eventually
I seem to struggle a bit with using readline in zig (readline([*c]const u8) for some reason) but found this https://github.com/joachimschmidt557/linenoize
what do you think?
never used it, but feel free to try it
what issue were you having with readline though?
it's just
const c = @cImport({
@cInclude("readline/readline.h");
});
pub fn main() !void {
const line = c.readline(prompt_here) orelse {
// handle the case where the user doesnt enter anything
};
}
error: ld.lld: undefined symbol: readline
note: referenced by main.zig:175
note: /home/raleks/Documents/dev/vyq/zig-cache/o/73c81f7f25afff4077d64ec8138a3553/vyq.o:(main.repl)
note: did you mean: readlink
note: defined in: /lib/x86_64-linux-gnu/libc.so.6
looks good, though I had to write my own function to make completion really work
you need to also link against readline for it to work
what do you mean?
it's a dynamic library, readline.h is just a file that tells the compiler what symbols are defined in the readline object file
to actually be able to use the functions, you need to tell the linker to include the readline object file
you just need to add
exe.linkLibC();
exe.linkSystemLibrary("readline");
to your build.zig
hope that made any sense
Yeah, makes sense. Will try when I get home
Yes, this works. I think I will try the readline after all instead the linenoize lib I found. Theoratically I can still use the function I wrote for completion in readline as well. Just will have to read the docs about the history more, but should be good
Is it normal I dont see any add_history() in it as docs say there should be that function
evidently im stupid, just include readline/history.h
Think I will stick to linenoize for now. Everything works in readline as well, but I cant get the completion to work over there. Throws invalid pointer