Skip to content

Commit 8eb19b9

Browse files
committed
Add io:fwrite/1,2,3 and io:format/3
Also add few io functions required by remote shell Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent f016904 commit 8eb19b9

File tree

2 files changed

+172
-28
lines changed

2 files changed

+172
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929
- Added `erlang:unique_integer/0` and `erlang:unique_integer/1`
3030
- Added support for 'ets:delete/1'.
3131
- Added `lists:flatmap/2`
32+
- Added `io:fwrite/1,2,3` and `io:format/3` as well as few io functions required by remote shell
3233

3334
### Fixed
3435
- ESP32: improved sntp sync speed from a cold boot.

libs/estdlib/src/io.erl

Lines changed: 171 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,163 @@
2727
%%-----------------------------------------------------------------------------
2828
-module(io).
2929

30-
-export([format/1, format/2, get_line/1, put_chars/1, put_chars/2]).
30+
-export([
31+
requests/1,
32+
format/1,
33+
format/2,
34+
format/3,
35+
fwrite/1,
36+
fwrite/2,
37+
fwrite/3,
38+
get_line/1,
39+
put_chars/1,
40+
put_chars/2,
41+
scan_erl_exprs/4,
42+
columns/0,
43+
columns/1,
44+
getopts/0,
45+
getopts/1,
46+
printable_range/0
47+
]).
48+
49+
-export_type([device/0, format/0, standard_io/0, standard_error/0, user/0]).
50+
51+
-type format() :: atom() | string() | binary().
52+
-type standard_io() :: standard_io.
53+
-type standard_error() :: standard_error.
54+
-type user() :: user.
55+
-type device() :: atom() | pid() | standard_io() | standard_error() | user().
56+
57+
-type getopt() ::
58+
{echo, boolean()}
59+
| {binary, boolean()}
60+
| {encoding, unicode}
61+
| {terminal, boolean()}
62+
| {stdin, boolean()}
63+
| {stdout, boolean()}
64+
| {stderr, boolean()}.
65+
66+
%% @priv
67+
requests(Requests) ->
68+
execute_request(group_leader(), {requests, Requests}).
69+
70+
%%-----------------------------------------------------------------------------
71+
%% @equiv columns(standard_io)
72+
%% @doc Returns the number of columns for standard I/O.
73+
%% @end
74+
%%-----------------------------------------------------------------------------
75+
-spec columns() -> {ok, pos_integer()} | {error, enotsup}.
76+
columns() ->
77+
columns(standard_io).
78+
79+
%%-----------------------------------------------------------------------------
80+
%% @param IODevice IO device to get columns of
81+
%% @doc Returns the number of columns for passed I/O device.
82+
%% @end
83+
%%-----------------------------------------------------------------------------
84+
-spec columns(IODevice :: device()) -> {ok, pos_integer()} | {error, enotsup}.
85+
columns(_IODevice) ->
86+
{ok, 80}.
87+
88+
%%-----------------------------------------------------------------------------
89+
%% @equiv getopts(standard_io)
90+
%% @doc Get all options for standard I/O
91+
%% @end
92+
%%-----------------------------------------------------------------------------
93+
-spec getopts() -> [getopt()] | {error, Reason :: any()}.
94+
getopts() ->
95+
getopts(standard_io).
3196

3297
%%-----------------------------------------------------------------------------
33-
%% @doc Equivalent to format(Format, []).
98+
%% @param IODevice IO device to get options for
99+
%% @doc Get all options for a given IODevice
34100
%% @end
35101
%%-----------------------------------------------------------------------------
36-
-spec format(Format :: string()) -> string().
37-
format(Format) when is_list(Format) ->
38-
format(Format, []).
102+
-spec getopts(IODevice :: device()) -> [getopt()] | {error, Reason :: any()}.
103+
getopts(standard_io) ->
104+
[
105+
{echo, true},
106+
{binary, false},
107+
{encoding, unicode},
108+
{terminal, true},
109+
{stdout, true},
110+
{stderr, true},
111+
{stdin, true}
112+
].
113+
114+
%%-----------------------------------------------------------------------------
115+
%% @doc Returns the user-requested range of printable Unicode characters.
116+
%% Currently always returns `unicode'
117+
%% @end
118+
%%-----------------------------------------------------------------------------
119+
-spec printable_range() -> unicode | latin1.
120+
printable_range() ->
121+
unicode.
122+
123+
%% @equiv fwrite(Format)
124+
-spec format(Format :: format()) -> ok.
125+
format(Format) ->
126+
fwrite(Format).
127+
128+
%% @equiv fwrite(Format, [])
129+
-spec fwrite(Format :: format()) -> ok.
130+
fwrite(Format) ->
131+
fwrite(Format, []).
132+
133+
%% @equiv fwrite(Format, Data)
134+
-spec format(Format :: format(), Data :: [term()]) -> ok.
135+
format(Format, Data) ->
136+
fwrite(Format, Data).
137+
138+
%% @equiv fwrite(standard_io, Format, Data)
139+
-spec fwrite(Format :: format(), Data :: [term()]) -> ok.
140+
fwrite(Format, Data) ->
141+
fwrite(standard_io, Format, Data).
142+
143+
%% @equiv fwrite(IODevice, Format, Data)
144+
-spec format(IODevice :: device(), Format :: format(), Data :: [term()]) -> ok.
145+
format(IODevice, Format, Data) ->
146+
fwrite(IODevice, Format, Data).
39147

40148
%%-----------------------------------------------------------------------------
41149
%% @param Format format string
42-
%% @param Args format argument
43-
%% @returns string
44-
%% @doc Format string and data to console.
150+
%% @param Data format arguments
151+
%% @param IODevice device to write to
152+
%% @returns ok
153+
%% @doc Format string and data to IO device.
45154
%% See io_lib:format/2 for information about
46155
%% formatting capabilities.
47156
%% @end
48157
%%-----------------------------------------------------------------------------
49-
-spec format(Format :: string(), Args :: list()) -> string().
50-
format(Format, Args) when is_list(Format) andalso is_list(Args) ->
158+
-spec fwrite(IODevice :: device(), Format :: string(), Args :: list()) -> string().
159+
fwrite(IODevice, Format, Args) when is_list(Format) andalso is_list(Args) ->
51160
Msg =
52161
try
53162
io_lib:format(Format, Args)
54163
catch
55164
_:_ ->
56165
io_lib:format("Bad format! Format: ~p Args: ~p~n", [Format, Args])
57166
end,
58-
put_chars(Msg).
167+
put_chars(IODevice, Msg).
168+
169+
%%-----------------------------------------------------------------------------
170+
%% @param IODevice device to read from
171+
%% @param Prompt prompt to print
172+
%% @param StartLocation start location for reading
173+
%% @param Options options for tokenizing
174+
%% @returns read tokens or an error
175+
%% @doc Reads data from IODevice with a given prompt
176+
%% @end
177+
%%-----------------------------------------------------------------------------
178+
-spec scan_erl_exprs(IODevice :: device(), Prompt :: atom() | unicode:chardata(), any(), any()) ->
179+
{ok, Tokens :: any(), EndLocation :: any()}
180+
| {eof, EndLocation :: any()}
181+
| eof
182+
| {error, any()}.
183+
scan_erl_exprs(IODevice, Prompt, StartLocation, Options) when is_pid(IODevice) ->
184+
execute_request(
185+
IODevice, {get_until, unicode, Prompt, erl_scan, tokens, [StartLocation, Options]}
186+
).
59187

60188
%%-----------------------------------------------------------------------------
61189
%% @param Prompt prompt for user input
@@ -78,33 +206,48 @@ get_line(Prompt) ->
78206
end.
79207

80208
%%-----------------------------------------------------------------------------
209+
%% @equiv put_chars(standard_io, Chars)
81210
%% @param Chars character(s) to write to console
82211
%% @returns ok
83212
%% @doc Writes the given character(s) to the console.
84213
%% @end
85214
%%-----------------------------------------------------------------------------
86215
-spec put_chars(Chars :: list() | binary()) -> ok.
87216
put_chars(Chars) ->
88-
Self = self(),
89-
case erlang:group_leader() of
90-
Self ->
91-
console:print(Chars);
92-
Leader ->
93-
Ref = make_ref(),
94-
Leader ! {io_request, self(), Ref, {put_chars, unicode, Chars}},
95-
receive
96-
{io_reply, Ref, Line} -> Line
97-
end
98-
end.
217+
put_chars(standard_io, Chars).
99218

100219
%%-----------------------------------------------------------------------------
101-
%% @param Chars character(s) to write to console
220+
%% @param Device device to send characters to
221+
%% @param Chars character(s) to write to device
102222
%% @returns ok
103-
%% @doc Writes the given character(s) to the console.
223+
%% @doc Writes the given character(s) to the given device.
104224
%% @end
105225
%%-----------------------------------------------------------------------------
106-
-spec put_chars(Device :: any(), Chars :: list() | binary()) -> ok.
226+
-spec put_chars(Device :: device(), Chars :: list() | binary()) -> ok.
227+
put_chars(standard_io, Chars) ->
228+
Self = self(),
229+
case erlang:group_leader() of
230+
Self ->
231+
console:print(Chars);
232+
Leader ->
233+
execute_request(Leader, {put_chars, unicode, Chars})
234+
end;
107235
put_chars(standard_error, Chars) ->
108-
put_chars(Chars);
109-
put_chars(standard_output, Chars) ->
110-
put_chars(Chars).
236+
put_chars(standard_io, Chars).
237+
238+
%% @priv
239+
convert_request({requests, Requests}) ->
240+
{requests, [convert_request(Request) || Request <- Requests]};
241+
convert_request(nl) ->
242+
{put_chars, unicode, "\n"};
243+
convert_request(Other) ->
244+
Other.
245+
246+
%% @priv
247+
execute_request(Device, Request) when is_pid(Device) ->
248+
Converted = convert_request(Request),
249+
Ref = make_ref(),
250+
Device ! {io_request, self(), Ref, Converted},
251+
receive
252+
{io_reply, Ref, Result} -> Result
253+
end.

0 commit comments

Comments
 (0)