Updated the corresponding documentation and ideas for how to realize scrollable contents.
180 lines
7.2 KiB
Markdown
180 lines
7.2 KiB
Markdown
# zterm Terminal User Interface Library
|
|
|
|
`zterm` is a terminal user interface library to implement terminal (fullscreen or inline) applications.
|
|
|
|
> [!NOTE]
|
|
> Only builds using the master version are tested to work.
|
|
|
|
## Usage
|
|
|
|
To add or update `zterm` as a dependency in your project run the following command:
|
|
|
|
```sh
|
|
zig fetch --save git+https://gitea.yves-biener.de/yves-biener/zterm
|
|
```
|
|
|
|
Add the dependency to your module as follows in your _build.zig_:
|
|
|
|
```zig
|
|
const zterm: *Dependency = b.dependency("zterm", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
// ...
|
|
exe.root_module.addImport("zterm", zterm.module("zterm"));
|
|
```
|
|
|
|
For an example you can take a look at [build.zig](build.zig) for an example.
|
|
|
|
---
|
|
## Design Goals
|
|
|
|
This project draws heavy inspiration from
|
|
[clay](https://github.com/nicbarker/clay) in the way the layout is declared by
|
|
the user. As terminal applications usually are rendered in intermediate mode,
|
|
the rendering is also part of the event loop. Such that every time an event
|
|
happens a render call will usually be done as well. However this is not strickly
|
|
necessary and can be separated to have a fixed rendering of every 16ms (i.e. for
|
|
60 fps), etc.
|
|
|
|
There is only one generic container which contains properties and elements (or
|
|
children) which can also be containers, such that each layout in the end is
|
|
a tree.
|
|
|
|
The library is designed to be very basic and not to provide any more complex
|
|
elements such as input fields, drop-down menu's, buttons, etc. Some of them are
|
|
either easy to implement yourself, specific for you needs or a too complex to
|
|
be provided by the library effectively. For these use-cases there may be other
|
|
libraries that build on top of this one to provide the complex elements as some
|
|
sort of pre-built elements for you to use in your application (or you create
|
|
them yourself).
|
|
|
|
There are only very few system events, that are used by the built-in containers
|
|
and properties accordingly. For you own widgets (i.e. a collection of elements)
|
|
you can extend the events to include your own events to communicate between
|
|
elements, effect the control flow and the corresponding generated layouts and
|
|
much more.
|
|
|
|
As this is a terminal based layout library it also provides a rendering pipeline
|
|
alongside the event loop implementation. Usually the event loop is waiting
|
|
blocking and will only cause a re-draw (**intermediate mode**) after each event.
|
|
Even though the each frame is regenerated from scratch each render loop, the
|
|
corresponding application is still pretty performant as the renderer uses a
|
|
double buffered intermediate mode implementation to only apply the changes from
|
|
each frame to the next to the terminal.
|
|
|
|
This library is also designed to work accordingly in ssh hosted environments,
|
|
such that an application created using this library can be accessed directly
|
|
via ssh. This provides security through the ssh protocol and can defer the
|
|
synchronization process, as users may access the same running instance. Which is
|
|
the primary use-case for myself to create this library in the first place.
|
|
|
|
---
|
|
## Roadmap
|
|
|
|
- [ ] Container rendering
|
|
- [x] Layout
|
|
- [x] direction
|
|
- [x] vertical
|
|
- [x] horizontal
|
|
- [x] padding
|
|
- [x] gap
|
|
- [x] sizing (removed - for now at least)
|
|
- width
|
|
- height
|
|
- options
|
|
- fit
|
|
- grow
|
|
- fixed
|
|
- percent
|
|
- [x] Border
|
|
- [x] sides
|
|
- [x] corners
|
|
- [x] separators
|
|
- [x] Rectangle
|
|
- [ ] User control
|
|
- [x] event handling
|
|
- [x] user content
|
|
- [ ] Default `Element` implementations
|
|
- [ ] Scrollable
|
|
- [ ] user input handling
|
|
- [ ] vertical
|
|
- [ ] horizontal
|
|
- [ ] scroll bar(s) rendering
|
|
- [ ] vertical
|
|
- [ ] horizontal
|
|
- [ ] Content alignment (i.e. standard calculations done with the provided `Size`)
|
|
- [ ] Text display
|
|
- [ ] User input
|
|
- [ ] single line
|
|
- [ ] multi line
|
|
- [ ] min size? (I don't have access to the `.resize` `Event`..)
|
|
|
|
Decorations should respect the layout and the viewport accordingly. This means
|
|
that scrollbars are always visible (except there is no need to have a scrollbar)
|
|
irrelevant depending on the size of the content. The rectangle apply to all
|
|
cells of the content (and may be overwritten by child elements contents).
|
|
The border of an element should be around independent of the scrolling of the
|
|
contents, just like padding.
|
|
|
|
### Scrollable contents
|
|
|
|
Contents that is scrollable should be done *virtually* through the contents of
|
|
the `Container`. This means each container contents implements scrolling for
|
|
itself if required.
|
|
|
|
This still has one issue: Layout of child elements that are already too large
|
|
(i.e. or become too small). The library could provide automatic rendering of a
|
|
scrollbar given the right parameters however. The scrolling input action would
|
|
then also be implemented by the user.
|
|
|
|
Open questions are regarding the sizing options (i.e. how is the size of a
|
|
`Container` actually controlled?, how should it be controlled?, etc.). There
|
|
should be support for the child elements to provide some kind of 'list'
|
|
functionality built-in.
|
|
|
|
**REMINDER**: (mostly for myself) The library should be and remain simple. This
|
|
means that some code for using the library may be duplicated, but this is not
|
|
the main goal. Others may provide more re-usable code snippets that build on top
|
|
of this library instead.
|
|
|
|
### User specific event handling and content rendering
|
|
|
|
For interactions controlled by the user each container can use an `Element`
|
|
interface which contains functions which are called by the `Container`
|
|
during event handling (i.e. `fn handle(..)`) and during rendering (i.e. `fn
|
|
content(..)`) to provide user specific content and user interaction. The
|
|
`Element` may be stateful, but may also be stateless and then be re-used in
|
|
multiple different `Container`s.
|
|
|
|
Composing multiple `Element`s currently requires the implementation of a wrapper
|
|
which contains the `Element`s that need to be handled (should work pretty well
|
|
for stateless `Element`s). Such *stateless* `Element`s may be provided by this
|
|
library.
|
|
|
|
### Input
|
|
|
|
How is the user input handled in the containers? Should there be active
|
|
containers? Some input may happen for a specific container (i.e. when using
|
|
mouse input). How would I handle scrolling for outer and inner elements of
|
|
a container?
|
|
|
|
### Archive
|
|
|
|
The alignment and sizing options only make sense if both are available. For
|
|
this the current implementation has the viewport size and the content size too
|
|
linked. Therefore they have both been removed (at least for now):
|
|
|
|
- *fit*: adjust virtual space of container by the size of its children (i.e. a
|
|
container needs to be able to get the necessary size of its children)
|
|
- *grow*: use as much space as available (what exactly would be the difference
|
|
between this option and *fit*?)
|
|
- *fixed*: use exactly as much cells (in the specified direction)
|
|
|
|
- *center*: elements should have their anchor be placed accordingly to their
|
|
size and the viewport size.
|
|
- *left*: the anchor remains at zero (relative to the location of the
|
|
container on the screen) -> similar to the current implementation!
|
|
- *right*: the anchor is fixed to the right side (i.e. size of the contents -
|
|
size of the viewport)
|