Would it be possible to implement getch using Owl.LiveScreen (or some other method)? The idea would be to trigger on single keypress events, without using the return key.
Ruby has TTY Toolkit. Do you envision Owl to provide similar features?
I don’t understand what use-cases are addressed by the Erlang I/O protocol and Owl.LiveScreen. Can you talk a bit about that? What types of apps would be a good fit for Owl vs ExNcurses?
Would it be possible to implement getch using Owl.LiveScreen (or some other method)?
I don’t think so. At least for now, I don’t see a way how to implement this easily.
Ruby has TTY Toolkit . Do you envision Owl to provide similar features?
Some components can be definitely useful and easily ported. Didn’t know about this project, thank you. I saw GitHub - Shopify/cli-ui: Terminal user interface library and wanted to make something better There is another similar project in JS ecosystem inquirer - npm. Owl doesn’t support getting char as you type, so whistles and bells like in inquirer are not possible.
I don’t understand what use-cases are addressed by the Erlang I/O protocol and Owl.LiveScreen. Can you talk a bit about that
Sure. Logger writes to stdout by default, and when you draw N progress bars, the cursor has to be moved N lines up, and replace these lines with the new content. It is okay if progress bars are rendered there, but if not, then the content will be replaced. It means that Logger has to be synchronized with an engine that is used for drawing bars. This can be achieved by simply using this line:
That’s it. Now when you log something, messages will be rendered ABOVE progress bars or any other dynamic blocks. There is an example with Logger here owl/emulate_compilation.exs at 9390b8f020aa6ef146c0a51af21bef5be911599b · fuelen/owl · GitHub
Let’s say you render progress bars and want to inspect my_variable using IO.inspect. Everything will be messed up if you simply type IO.inspect(my_variable). Because Owl.LiveScreen implements Erlang I/O protocol, my_variable can be easily inspected by IO.inspect(Owl.LiveScreen, my_variable, [])
What types of apps would be a good fit for Owl vs ExNcurses?
Owl doesn’t use nifs and is not for full-screen lazygit-like applications. At least for now. It is for scripts, executing which you can see the log of the program, what was selected, what was typed, etc. If you need full-screen applications, go with ExNcurses or GitHub - ndreynolds/ratatouille: A TUI (terminal UI) kit for Elixir.
@fuelen Hi, I took a look at Owl.Box documentation.
I suggest to add padding, padding_x and padding_y opts:
padding opt:
"Owl" |> Owl.Box.new(padding: 5) |> to_string() |> String.trim_trailing()
# which is the same as:
"Owl" |> Owl.Box.new(padding_bottom: 5, padding_left: 5, padding_right: 5, padding_top: 5) |> to_string() |> String.trim_trailing()
padding_x opt:
"Owl" |> Owl.Box.new(padding_x: 5) |> to_string() |> String.trim_trailing()
# which is the same as:
"Owl" |> Owl.Box.new(padding_left: 5, padding_right: 5) |> to_string() |> String.trim_trailing()
padding_y opt:
"Owl" |> Owl.Box.new(padding_y: 5) |> to_string() |> String.trim_trailing()
# which is the same as:
"Owl" |> Owl.Box.new(padding_bottom: 5, padding_top: 5) |> to_string() |> String.trim_trailing()
Or even change it to keyword for example:
"Owl" |> Owl.Box.new(padding: [x: 1, y: 2]) |> to_string() |> String.trim_trailing()
# which is the same as:
"Owl" |> Owl.Box.new(padding: [bottom: 2, left: 1, right: 1, top: 2]) |> to_string() |> String.trim_trailing()
Also it would be nice to easily create a full height and/or full width boxes … So far I need to calculate it based on :io.columns() - borders - paddings.
iex> Owl.IO.confirm(answers: [false: {"n", "no"}, true: {"y", "yes"}])
Are you sure? [yN]: no
false
Owl.IO.open_in_editor should accept 2nd argument called editor for non-default editors … Think about detecting installed editors and if there are more than one editor displays select for an editor …
Optionally multiselect and select may also support answers for example:
iex> Owl.IO.select(["one", "two", "three"], answers: fn {index, _elem} -> index end)
#=> 1. one
#=> 2. two
#=> 3. three
#=>
#=> > 1
"one"
iex> Owl.IO.select(["one", "forty two", "three"], answers: fn {_index, elem} -> Macro.underscore(elem) end)
#=> one. one
#=> forty_two. forty two
#=> three. three
#=>
#=> > forty_two
"forty two"
answers here would also add ability to easily add answer left or right padding. This would also be useful for i18n (for example converting number to its equivalent in other languages).
@Eiji I’ve implemented almost all your suggestions, except mapping numbers in select and multiselect. For now, I’m not sure if this is really helpful, because the whole idea is in using numbers.
Oh, I gave a bad example … Just think that someone’s prefers other number system like for example Arabic numbers. Also someone may want to use letters like a), b)c) etc.
Per above do you think you can add suffix option, so for example someone would set suffix as empty string (default) or ) character or something else?
The biggest change in this release is an ability to render tables.
Tables are highly customizable, they work with Owl.Data.t() which allows colorizing even different chars inside a cell, not just a whole cell like in other libraries. Input expects a list of maps, and this structure allows autodetection of columns. There is sorting and filtering of columns, ability to specify max width for entire table (I wanted this for iex helpers ) and for individual columns. And other minor but nice things
A question about LiveScreen – is it possible to capture input/confirmation in a LiveScreen block while allowing other various printed messages to continue above? E.g. imagine the dependency compilation demo, but it prompts the user y/n to compile the dependencies one after the other and then shows the individual file compilation above asynchronously.
I’m thinking no, a least not at the moment, since the LiveScreen render has to return Owl.Data.t() and there doesn’t appear to be any way to “direct” an Owl.IO.confirm/etc. to something other than :stdio.
No, it is not possible to type anything and produce output at the same time. We need better control over inputs, and here is a problem. There is a related discussion here Portable getch? · Discussion #5 · fuelen/owl · GitHub
The easiest workaround for now is to handle editing in the editor.