#Listen on input

1 messages · Page 1 of 1 (latest)

whole sable
#

I wanna implement history into REPL, but would need to listen to the input of symbol of up arrow or down arrow. Is there any way to do so?

stone pike
#

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

whole sable
#

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?

stone pike
#

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

stone pike
whole sable
#

Ok, thank you. Will try it

stone pike
#

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

whole sable
whole sable
stone pike
#

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

lost cairn
#

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.

whole sable
lost cairn
#

I can look when im home

whole sable
#

std.os.tcsetattr is there, although im unsure what params does it use

whole sable
lost cairn
#

where stdin is std.io.getStdIn();

#

hope that helps @whole sable

whole sable
#

Thanks a lot!

#

Will try asap

lost cairn
#

k

#

sorry I couldn't response sooner

whole sable
#

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

whole sable
lost cairn
#

I think it’s one of the flags

#

try to remove ISIG

whole sable
#

So either add support for it or allow it along the other flags?

lost cairn
#

remove ISIG or manually add support for it

#

Yeah

#

I think it was 23?

whole sable
#

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?

lost cairn
#

you then also need to reset the cursor

stone pike
#

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)

whole sable
#

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? )

vocal adder
#

i'd reccomend go reading its docs and examples

#

it will handle things like history, display, and such

whole sable
vocal adder
stone pike
#

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)

whole sable
stone pike
#

would be nice to have a pure zig version tbh, maybe ill tackle it eventually

whole sable
#

what do you think?

stone pike
#

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
  };
}
whole sable
#

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

whole sable
stone pike
whole sable
#

what do you mean?

stone pike
# whole sable 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

whole sable
#

Yeah, makes sense. Will try when I get home

whole sable
#

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

whole sable
#

evidently im stupid, just include readline/history.h

whole sable
#

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