-module(etch@erlang@input).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/etch/erlang/input.gleam").
-export([poll/1, read/0, input_loop/1, get_keyboard_enhancement_flags/0, get_cursor_position/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/etch/erlang/input.gleam", 14).
?DOC(
" Checks if there is an [`Event`](https://hexdocs.pm/etch/etch/event.html#Event) available.\n"
" Returns None if no events were received within the timeout.\n"
" See also [`read`](input.html#read).\n"
).
-spec poll(integer()) -> gleam@option:option({ok, etch@event:event()} |
{error, etch@event:event_error()}).
poll(Timeout) ->
input_ffi:poll(Timeout).
-file("src/etch/erlang/input.gleam", 20).
?DOC(
" Checks if there is an [`Event`](https://hexdocs.pm/etch/etch/event.html#Event) available.\n"
" Waits forever for an available event.\n"
" See also [`poll`](input.html#poll).\n"
).
-spec read() -> gleam@option:option({ok, etch@event:event()} |
{error, etch@event:event_error()}).
read() ->
input_ffi:read().
-file("src/etch/erlang/input.gleam", 43).
-spec push_events(
list({ok, etch@event:event()} | {error, etch@event:event_error()})
) -> nil.
push_events(Events) ->
case Events of
[] ->
nil;
[E | Rest] ->
input_ffi:push(E),
push_events(Rest)
end.
-file("src/etch/erlang/input.gleam", 32).
?DOC(false).
-spec input_loop(boolean()) -> any().
input_loop(Is_raw_mode) ->
Str = case Is_raw_mode of
true ->
io:get_chars(<<""/utf8>>, 128);
false ->
io:get_line(<<""/utf8>>)
end,
Str@1 = gleam@string:to_graphemes(Str),
Events = etch@event:parse_events(Str@1, <<""/utf8>>, [], false),
push_events(Events),
input_loop(Is_raw_mode).
-file("src/etch/erlang/input.gleam", 57).
?DOC(
" Get keyboard enhancement flags. See <https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement>\n"
" This function shouldn't be called in a tight loop. It's fine to call it when\n"
" responding to specific user input (e.g., after a key press), but avoid calling\n"
" it on every loop iteration.\n"
).
-spec get_keyboard_enhancement_flags() -> {ok,
list(etch@event:keyboard_enhancement_flag())} |
{error, etch@event:event_error()}.
get_keyboard_enhancement_flags() ->
gleam_stdlib:print(<<"\x{001b}["/utf8, "?u"/utf8>>),
Flags = io:get_chars(<<""/utf8>>, 32),
case Flags of
<<"\x{001b}[?"/utf8, S/binary>> ->
case gleam@string:last(S) of
{ok, <<"u"/utf8>>} ->
{ok, etch@event:parse_keyboard_enhancement_flags(S)};
_ ->
{error,
{failed_to_parse_event,
<<"Could not get enhancment flags"/utf8>>}}
end;
_ ->
{error,
{failed_to_parse_event,
<<"Could not get cursor position"/utf8>>}}
end.
-file("src/etch/erlang/input.gleam", 78).
?DOC(
" Returns cursor position.\n"
" This function shouldn't be called in a tight loop. It's fine to call it when\n"
" responding to specific user input (e.g., after a key press), but avoid calling\n"
" it on every loop iteration.\n"
).
-spec get_cursor_position() -> {ok, {integer(), integer()}} |
{error, etch@event:event_error()}.
get_cursor_position() ->
gleam_stdlib:print(<<"\x{001b}["/utf8, "6n"/utf8>>),
Pos = io:get_chars(<<""/utf8>>, 32),
case Pos of
<<"\x{001b}["/utf8, S/binary>> ->
case gleam@string:last(S) of
{ok, <<"R"/utf8>>} ->
etch@event:parse_cursor_position(S);
_ ->
{error,
{failed_to_parse_event,
<<"Could not get cursor position"/utf8>>}}
end;
_ ->
{error,
{failed_to_parse_event,
<<"Could not get cursor position"/utf8>>}}
end.