unibilium
Unibilium.cr
Crystal bindings for unibilium, a terminfo library.
Unibilium supports:
- Parsing terminfo files with standard and extended sections
- Parsing terminfo files with 16-bit and 32-bit numeric format
- Formatting/executing/running terminfo format strings
- Creating and modifying terminfo databases and dumping them in terminfo file format
Installation
Add this to your application's shard.yml
:
dependencies:
unibilium:
github: crystallabs/unibilium.cr
version: ~> 1.1
You must have libunibilium
installed in order to use these bindings. For compilation you also need development headers.
Most distributions have packages named unibilium
/unibilium-dev
or libunibilium
/libunibilium-dev
.
Usage
Usage in a nutshell:
Here is a copy of examples/main.cr
:
require "../src/unibilium"
# Loading a terminfo
ENV["TERM"] = "linux"
terminfo = Unibilium::Terminfo.from_env
# terminfo = Unibilium::Terminfo.from_io(io)
# terminfo = Unibilium::Terminfo.from_bytes(bytes)
# terminfo = Unibilium::Terminfo.from_file(path)
# terminfo = Unibilium::Terminfo.from_terminal(name)
cls = terminfo.get(Unibilium::Entry::String::Clear_screen)
terminfo.format STDOUT, cls
# Querying basic information
p terminfo.name
p terminfo.aliases
p terminfo.name_for(Unibilium::Entry::Boolean::Has_meta_key)
p terminfo.short_name_for(Unibilium::Entry::Boolean::Has_meta_key)
# Retrieving capabilities with get, get?
p bool = terminfo.get(Unibilium::Entry::Boolean::Has_meta_key)
p num = terminfo.get?(Unibilium::Entry::Numeric::Lines)
p str = terminfo.get(Unibilium::Entry::String::Cursor_address)
p String.new str
# Interpreting/executing string capabilities
STDOUT.write terminfo.run(str, 10, 10)
# # Or:
# cmd = String.new terminfo.run(str, 10, 10)
# print cmd
puts "Cursor at 10,10"
# Accessing extended section:
p terminfo.extensions.count_bool
p terminfo.extensions.count_num
p terminfo.extensions.count_str
# has?, [], []?
terminfo.extensions["U8"] # => CapabilityExtension
p terminfo.extensions["U8"]? # =? CapabilityExtension?
if terminfo.extensions.has?("U8") # => true | false
u8 = terminfo.extensions.get_num("U8")
puts "Extended numeric value U8 = #{u8}"
end
# Rarely used:
# get_{bool,num,str}_name(id)
p terminfo.extensions.get_bool_name(0)
# get_X, get_X?
p terminfo.extensions.get_bool("AX")
p terminfo.extensions.get_num("U8")
p terminfo.extensions.get_str("E3")
pos = terminfo.run(str, 25, 10)
p String.new pos
STDOUT.write pos
STDOUT.puts "Cursor at 25,10"
STDOUT.flush
terminfo.format(STDOUT, str, 28, 10)
puts "Cursor at 28,10"
terminfo.destroy
p terminfo.destroyed?
Creating a new or modified terminfo db:
require "unibilium"
terminfo = Unibilium::Terminfo.dummy
terminfo.aliases = ["test", "new test terminal"]
terminfo.set(Unibilium::Entry::Numeric::Lines, 100)
terminfo.extensions.add("U8", 1)
terminfo.extensions.set("U8", -1)
terminfo.extensions.rename("U8", "U9")
terminfo.extensions.delete("U9")
File.write "test.terminfo", terminfo.dump
For more detailed examples, refer to directories examples/
and spec/
.
Argument Types
For the non-extended section, #get
/#get?
accept fixed enum values which are pre-defined and
categorized into Entry::Boolean
, Entry::Numeric
, and Entry::String
.
For the extended section, capabilities are always accessed as strings. Because type cannot be
determined from a string, there is no single #get
/#get?
metod; instead there are the individual
get methods for the three possible types -- #get_{bool,num,str}[?]
.
Testing for an extended capability with #extensions.has?(X)
will return a boolean, specifying
whether the capability exists at all.
Testing with #extensions[X]?
will return Nil | CapabilityExtension
instance from which the type
and terminfo id can be read.
Return Values
The return values are coming directly from terminfo-encoded data as follows:
- Boolean - Bool. (False is also returned if a value is unset)
- Numeric - Int32. (-1 is returned if a value is unset, -2 if disabled)
- String - String | Nil. (Nil is returned if a value is unset)
Accessing an existing extended capability can return the same data types as the standard section.
This library does not interpret return values. I.e. the special return values which indicate a missing capability (the indistinguishable boolean false, numeric -1 and -2, and string nil) are just returned as-is.
More Usability
This library is low-level.
You may be interested in an add-on library unibilium-shim.cr which implements the following additions:
- Accessing and running standard capabilities using long string names, short string names, and methods
- Interpreting return values (testing for
false
,<0
, andnil
values to indicate missing/disabled capabilities)
Notes
Currently using the Crystal API is not possible to have an extended capability of the same name existing in multiple sections.
Testing
Run crystal spec
as usual.
Documentation
Run crystal docs
as usual.
Thanks
-
All the fine folks on Libera.Chat IRC channel #crystal-lang and on Crystal's Gitter channel https://gitter.im/crystal-lang/crystal
-
Blacksmoke16
-
HertzDevil