Expand description
Liso (LEE-soh) is an acronym for Line Input with Simultaneous Output. It is
a library for a particular kind of text-based Rust application; one where
the user is expected to give command input at a prompt, but output can
occur at any time. It provides simple line editing, and prevents input from
clashing with output. It can be used asynchronously (with tokio
) or
synchronously (without).
§Usage
Create an InputOutput
object with
InputOutput::new()
. Liso will automatically configure itself based on how
your program is being used.
Your InputOutput
instance can be used to send output or receive input.
Call clone_output
to create an OutputOnly
instance, which can only be used to send output. You can call
clone_output
as many times as you like, as well as cloning the
OutputOnly
s directly. An unlimited number of threads or tasks can send
output through Liso, but only one thread/task can receive user input:
whichever one currently holds the InputOutput
instance.
If the global
feature is enabled, which it is by default, then you
don’t have to create OutputOnly
instances and keep them around in order
to send output. See the “Global” section for more information.
Liso can work with String
s and &str
s directly. If you want to add style
or color, create a Line
, either manually or using
the convenient liso!
macro. Send output to the
user by calling println()
or
wrapln()
, whichever you prefer. Any
styling and color information is reset after the line is output, so you
don’t have to worry about dangling attributes.
Liso supports a prompt line, which is presented ahead of the user input.
Use prompt()
to set it. Styling and
color information is not reset between the prompt and the current input
text, so you can style/color the input text by having the desired
styles/colors active at the end of the prompt line.
Liso supports an optional status line, which “hangs out” above the input
text. Use status()
to set it. Printed
text appears above the status line, the prompt and any in-progress input
appears below it. Use this to present contextual or frequently-changing
information.
Liso supports “notices”, temporary messages that appear in place of the
prompt and input for a limited time. Use
notice()
to display one. The notice
will disappear when the allotted time elapses, when the user presses any
key, or when another notice is displayed, whichever happens first. You
should only use this in direct response to user input; in fact, the only
legitimate use may be to complain about an unknown control character. (See
Response
for an example of this use.)
§Global
If the global
feature is enabled (which it is by default), you can call
output()
to get a valid OutputOnly
instance any time
that an InputOutput
instance is alive. This will panic if there is not
an InputOutput
instance alive, so you’ll still have to have one.
With global
enabled, you can also use the
println!
or wrapln!
macros
to perform output directly and conveniently. println!(...)
is equivalent
to output().println!(liso!(...))
.
Using the output()
function, or the println!
/wrapln!
macros, is
noticeably less efficient than creating an OutputOnly
instance ahead of
time, whether by calling clone_output()
or by calling output()
and
caching the result. But, it’s probably okay as long as you’re not hoping to
do it hundreds of thousands of times per second.
§History
If the history
feature is enabled (which it is by default), Liso supports
a rudimentary command history. It provides a conservative default that
isn’t backed by any file. Try:
io.swap_history(liso::History::from_file(some_path).unwrap());
to make it backed by a file, and see History
for
more information.
§Completion
If the completion
feature is enabled (which it is by default), Liso
supports tab completion. Implement Completor
,
then use set_completor
to make
your new completor active. See the linked documentation for more
information.
§Pipe mode
If either stdin or stdout is not a tty, or the TERM
environment
variable is set to either dumb
or pipe
, Liso enters “pipe mode”. In
this mode, status lines, notices, and prompts are not outputted, style
information is discarded, and every line of input is passed directly to
your program without any processing of control characters or escape
sequences. This means that a program using Liso will behave nicely when
used in a pipeline, or with a relatively unsophisticated terminal.
TERM=dumb
is respected out of backwards compatibility with old UNIXes and
real terminals that identify this way. TERM=pipe
is present as an
alternative for those who would rather not perpetuate an ableist slur, but
is not compatible with other UNIX utilities and conventions. On UNIX. you
can activate “pipe mode” without running afoul of any of this by piping the
output of the Liso-enabled program to cat
, as in my_liso_program | cat
.
Macros§
- liso
- Constructs a
Line
from pieces. More convenient than creating aLine
and calling its methods. - liso_
add - Add some pieces to a
Line
. More convenient than calling its methods. - println
- If the
global
feature is enabled (which it is by default), you can useprintln!(...)
as convenient shorthand foroutput().println(liso!(...))
. This is less efficient than creating anOutputOnly
withclone_output()
and keeping it around, but it is more convenient. You will have to explicitlyuse liso::println;
, or call it by its full path (liso::println!
) or Rust may be uncertain whether you meant to use this orstd::println!
. Panics if there is noInputOutput
instance alive. - wrapln
- If the
global
andwrap
features are enabled (which they are by default), you can usewrapln!(...)
as convenient shorthand foroutput().println(liso!(...))
. This is less efficient than creating anOutputOnly
withclone_output()
and keeping it around, but it is more convenient. Panics if there is noInputOutput
instance alive.
Structs§
- History
- This keeps track of the most recent command lines entered.
- Input
Output - Receives input from, and sends output to, the terminal. You can send
output from any number of threads
(see
Output::clone_output
), but only one thread at a time may have ownership of the overlyingInputOutput
type and therefore the ability to receive input. - Line
- This is a line of text, with optional styling information, ready for
display. The
liso!
macro is extremely convenient for building these. You can also pass aString
,&str
, orCow<str>
to most Liso functions that accept aLine
. - Line
Char - A single character from a
Line
, along with the byte index it begins at, and theStyle
andColor
s it would be displayed with. This is yielded byLineCharIterator
, which is returned byLine::chars()
. - Line
Char Iterator - Allows you to iterate over the characters in a
Line
, one at a time, along with theirStyle
andColor
information. This is returned byLine::chars()
. - Output
- This struct contains all the methods that the
OutputOnly
andInputOutput
structs have in common. Any method of this struct may be called on either of the other structs. - Output
Only - Sends output to the terminal. You can have more than one of these, shared freely among threads and tasks. Give one to every thread, task, or object that needs to produce output.
- Style
- Styles we support outputting.
Enums§
- Color
- Colors we support outputting. For compatibility, we only support the 3-bit ANSI colors.
- Completion
- Response
- Input received from the user, or a special condition. Returned by any of
the following
InputOutput
methods:
Traits§
- Completor
- Something that may know how to respond to a completion request, i.e. a tab press.
Functions§
- output
- If the
global
feature is enabled (which it is by default), and there is anInputOutput
alive somewhere, you can calloutput()
to get anOutputOnly
struct that you can use to perform output on it. This is less efficient than creating anOutputOnly
directly withclone_output()
and keeping it around, but it is more convenient.