Owl.IO (Owl v0.13.0)
View SourceA set of functions for handling IO with support of Owl.Data.t/0.
Summary
Functions
Returns a width of a terminal.
Asks user to type a confirmation.
Reads a line from the stdio and casts a value to the given type.
Wrapper around IO.inspect/3 with changed defaults.
Select multiple values from the given nonempty list.
Opens data in editor for editing.
Wrapper around IO.puts/2 that accepts Owl.Data.t/0.
Returns a height of a terminal.
Selects one item from the given nonempty list.
Types
@type cast_input() :: (String.t() | nil -> {:ok, value :: any()} | {:error, reason :: String.Chars.t()})
@type input_option() :: {:label, Owl.Data.t()} | {:cast, atom() | {atom(), Keyword.t()} | cast_input()} | {:optional, boolean()}
@type multiselect_option() :: {:label, Owl.Data.t() | nil} | {:render_as, (any() -> Owl.Data.t())} | {:min, non_neg_integer() | nil} | {:max, non_neg_integer() | nil}
@type select_option() :: {:label, Owl.Data.t() | nil} | {:render_as, (any() -> Owl.Data.t())}
Functions
@spec columns(IO.device()) :: pos_integer() | nil
Returns a width of a terminal.
A wrapper around :io.columns/1, but returns nil if terminal is not found.
This is useful for convenient falling back to other value using ||/2 operator.
Example
Owl.IO.columns() || 80@spec confirm([confirm_option()]) :: boolean()
Asks user to type a confirmation.
Valid inputs are a blank string and values specified in :answers option.
User will be asked to type a confirmation again on invalid input.
Options
- :message- typically a question about performing operation. Defaults to- "Are you sure?".
- :default- a value that is used when user responds with a blank string. Defaults to- false.
- :answers- allows to specify alternative answers. Defaults to- [true: {"y", ["yes"]}, false: {"n", ["no"]}].
Examples
Owl.IO.confirm()
#=> Are you sure? [yN] n
false
Owl.IO.confirm(message: Owl.Data.tag("Really?", :red), default: true)
#=> Really? [Yn]
true
Owl.IO.confirm(
  message: Owl.Data.tag("Справді?", :red),
  answers: [true: {"т", ["так", "y", "yes"]}, false: {"н", ["ні", "n", "no"]}]
)
#=> Справді? [тН] НІ
false@spec input([input_option()]) :: any()
Reads a line from the stdio and casts a value to the given type.
After reading a line from stdio it will be automatically trimmed with String.trim/2.
The end value will be returned when user types a valid value.
Options
- :secret- set to- trueif you want to make input invisible. Defaults to- false.
- :label- a text label. Defaults to- nil(no label).
- :optional- a boolean that sets whether value is optional. Defaults to- false.
- :cast- casts a value after reading it from- stdio. Defaults to- :string. Possible values:- an anonymous function with arity 1 that is described by cast_input/0
- a pair with built-in type represented as atom and a keyword-list with options. Built-in types:- :integer, options:- :min- a minimum allowed value. Defaults to- nil(no lower bound).
- :max- a maximum allowed value. Defaults to- nil(no upper bound).
 
- :string, options:- no options
 
 
- an atom which is simply an alias to {atom(), []}
 
- an anonymous function with arity 1 that is described by 
Examples
Owl.IO.input()
#=> > hello world
"hello world"
Owl.IO.input(secret: true)
#=> >
"password"
Owl.IO.input(optional: true)
#=> >
nil
Owl.IO.input(label: "Your age", cast: {:integer, min: 18, max: 100})
#=> Your age
#=> > 12
#=> must be greater than or equal to 18
#=> Your age
#=> > 102
#=> must be less than or equal to 100
#=> Your age
#=> > 18
18
Owl.IO.input(label: "Birth date in ISO 8601 format:", cast: &Date.from_iso8601/1)
#=> Birth date in ISO 8601 format:
#=> > 1 January
#=> invalid_format
#=> Birth date in ISO 8601 format:
#=> > 2021-01-01
~D[2021-01-01]Wrapper around IO.inspect/3 with changed defaults.
As in puts/2, device argument is moved to the end.
Options are the same as for IO.inspect/3 with small changes:
- :prettyis- trueby default.
- :syntax_colorsuses color schema from- IExby default.
- :labelis extended and accepts- Owl.Data.t/0.
Examples
"Hello"
|> Owl.IO.inspect(label: "Greeting")
|> String.upcase()
|> Owl.IO.inspect(label: Owl.Data.tag("GREETING", :cyan))
#=> Greeting: "Hello"
#=> GREETING: "HELLO"
# inspect data above rendered live blocks
Owl.IO.inspect("Hello", [], Owl.LiveScreen)
#=> "Hello"@spec multiselect([item, ...], [multiselect_option()]) :: [item] when item: any()
Select multiple values from the given nonempty list.
Input item numbers must be separated by any non-digit character. Most likely you'd want to use spaces or commas. It is possible to specify a range of numbers using hyphen.
Options
- :label- a text label. Defaults to- nil(no label).
- :render_as- a function that renders given item. Defaults to- Function.identity/1.
- :min- a minimum output list length. Defaults to- nil(no lower bound).
- :max- a maximum output list length. Defaults to- nil(no upper bound).
Examples
Owl.IO.multiselect(["one", "two", "three"], min: 2, label: "Select 2 numbers:", render_as: &String.upcase/1)
#=> 1. ONE
#=> 2. TWO
#=> 3. THREE
#=>
#=> Select 2 numbers:
#=> > 1
#=> the number of elements must be greater than or equal to 2
#=> Select 2 numbers:
#=> > 1 3
#=>
["one", "three"]
Owl.IO.multiselect(Enum.to_list(1..5), render_as: &to_string/1)
#=> 1. 1
#=> 2. 2
#=> 3. 3
#=> 4. 4
#=> 5. 5
#=>
#=> > 1-3 5
#=>
[1, 2, 3, 5]Opens data in editor for editing.
Returns updated data when file is saved and editor is closed.
Similarly to IEx.Helpers.open/1, this function uses ELIXIR_EDITOR environment variable by default.
__FILE__ notation is supported as well.
Example
# use neovim in alacritty terminal emulator as an editor
$ export ELIXIR_EDITOR="alacritty -e nvim"
# open editor from Elixir code
Owl.IO.open_in_editor("hello\nworld")
# specify editor explicitly
Owl.IO.open_in_editor("hello\nworld", "alacritty -e nvim")@spec puts(Owl.Data.t(), device :: IO.device()) :: :ok
Wrapper around IO.puts/2 that accepts Owl.Data.t/0.
The other difference is that device argument is moved to second argument.
Examples
Owl.IO.puts(["Hello ", Owl.Data.tag("world", :green)])
#=> Hello world
# specify Owl.LiveScreen as a device in order to print data above rendered live blocks
Owl.IO.puts(["Hello ", Owl.Data.tag("world", :green)], Owl.LiveScreen)
#=> Hello world@spec rows(IO.device()) :: pos_integer() | nil
Returns a height of a terminal.
A wrapper around :io.rows/1, but returns nil if terminal is not found.
This is useful for convenient falling back to other value using ||/2 operator.
Example
Owl.IO.rows() || 20@spec select([item, ...], [select_option()]) :: item when item: any()
Selects one item from the given nonempty list.
Returns value immediately if list contains only 1 element.
Options
- :label- a text label. Defaults to- nil(no label).
- :render_as- a function that renders given item. Defaults to- Function.identity/1.
Examples
Owl.IO.select(["one", "two", "three"])
#=> 1. one
#=> 2. two
#=> 3. three
#=>
#=> > 1
#=>
"one"
~D[2001-01-01]
|> Date.range(~D[2001-01-03])
|> Enum.to_list()
|> Owl.IO.select(render_as: &Date.to_iso8601/1, label: "Please select a date")
#=> 1. 2001-01-01
#=> 2. 2001-01-02
#=> 3. 2001-01-03
#=>
#=> Please select a date
#=> > 2
#=>
~D[2001-01-02]
packages = [
  %{name: "elixir", description: "programming language"},
  %{name: "asdf", description: "version manager"},
  %{name: "neovim", description: "fork of vim"}
]
Owl.IO.select(packages,
  render_as: fn %{name: name, description: description} ->
    [Owl.Data.tag(name, :cyan), "\n  ", Owl.Data.tag(description, :light_black)]
  end
)
#=> 1. elixir
#=>      programming language
#=> 2. asdf
#=>      version manager
#=> 3. neovim
#=>      fork of vim
#=>
#=> > 3
#=>
%{description: "fork of vim", name: "neovim"}