Measure the width of text in the terminal and build simple layouts!
0

Configure Feed

Select the types of activity you want to include in your feed.

string_width / test / tui_ffi.erl
2.8 kB 91 lines
1-module(tui_ffi). 2-export([tui_app/4]). 3 4-behaviour(gen_event). 5-export([init/1, handle_event/2, handle_info/2, handle_call/2, terminate/2]). 6-export([run_read_loop/1]). 7 8%% This implements tui_app using the new OTP 28 features. 9%% To try this out, build erlang from this branch (or what until the PR is merged): 10%% 11%% Branch: https://github.com/garazdawi/otp/blob/lukas/kernel/shell-improvements 12%% PR: https://github.com/erlang/otp/pull/8962 13%% 14%% Also, please heart the PR <3 15%% 16%% To be able to exit properly on CTRL+C, you have to invoke erlang with the +Bc flag: 17%% 18%% ERL_FLAGS="+Bc" gleam run -m human_rights 19%% 20%% Just `gleam run` also works, but will bring up the break handler menu on CTRL+C. 21%% If you abort, your terminal will still be somewhat broken; a `reset` fixes that. 22 23tui_app(State, OnResize, OnData, View) -> 24 io:setopts(standard_io, [binary, {encoding, utf8}]), 25 ok = shell:start_interactive({noshell, raw}), 26 io:put_chars(<<"\e[?1049h\e[?25l"/utf8>>), 27 28 ok = gen_event:swap_sup_handler( 29 erl_signal_server, 30 {erl_signal_handler, []}, 31 {tui_ffi, [self()]}), 32 os:set_signal(sigwinch, handle), 33 %% os:set_signal(sigterm, handle), 34 35 spawn_link(tui_ffi, run_read_loop, [self()]), 36 37 loop(State, OnResize, OnData, View), 38 io:put_chars(<<"\e[?25h\e[?1049l"/utf8>>), 39 init:stop(), 40 nil. 41 42loop(State, OnResize, OnData, View) -> 43 %% io:put_chars(<<"\e[0;0H"/utf8>>), 44 io:put_chars(string:replace(View(State), <<"\n"/utf8>>, <<"\r\n"/utf8>>, all)), 45 %% io:put_chars(unicode:characters_to_binary(integer_to_list(os:system_time()))), 46 receive 47 { data, Chars } -> 48 case handle_input(Chars, State, OnData) of 49 stop -> stop; 50 NewState -> 51 loop(NewState, OnResize, OnData, View) 52 end; 53 54 { signal, sigint } -> stop; 55 { signal, sigterm } -> stop; 56 57 { signal, sigwinch } -> 58 {ok, Rows} = io:rows(), 59 {ok, Cols} = io:columns(), 60 NewState = OnResize(State, Rows, Cols), 61 loop(NewState, OnResize, OnData, View) 62 end. 63 64handle_input(<<>>, State, _OnData) -> State; 65handle_input(<<3, _rest/bits>>, _State, _OnData) -> stop; 66handle_input(<<"q"/utf8, _rest/bits>>, _State, _OnData) -> stop; 67handle_input(Rest, State, OnData) -> OnData(State, Rest). 68 69%% input handler 70 71run_read_loop(Pid) -> 72 Chars = io:get_chars("", 64), 73 Pid ! { data, Chars }, 74 run_read_loop(Pid). 75 76%% signal handler 77 78init({[Pid], _}) -> {ok, {Pid}}. 79 80handle_event(Signal, {Pid} = State) -> 81 Pid ! { signal, Signal }, 82 {ok, State}. 83 84handle_info(_, State) -> 85 {ok, State}. 86 87handle_call(_Request, State) -> 88 {ok, ok, State}. 89 90terminate(_Args, _State) -> 91 ok.