hi i'm eric anderson and i'll be talking
about tui a user interface framework
that i've written in emacs lisp
first i want to talk a bit about the
problem space of user interface
development specifically i want to
quickly illustrate some of the
complexities involved with ui
implementation in emacs
in emacs we have the ubiquitous buffer
object type that forms the container for
most content in emacs most
interfaces we interact with consist of
character based content in a buffer
that's prevented presented in a window
in frame
although the underlying content may be
textual emacs as capable apis to present
rich content
the pervasiveness of buffers affords us
wonderful flexibility this presentation
for instance is running in an emacs
buffer
using emacs's built-in basic button
library
we can insert an interactive button that
shows a message in the mini buffer when
clicked
what about uis that express application
state
most applications don't have a static ui
as application state changes the ui
should change to display the desired
content
one simplifying strategy is to simply
re-render the entire ui upon any change
first erase the contents of the buffer
and then reinsert your ui again with
desired changes and restore things like
point and region
basic composition is possible with this
approach simply insert the elements of
the ui in sequence
complex elements can be composed of
multiple sub-elements
uis can be made extensible and expose
this composition for example with
insertion hooks like magit status
sections hook
this generally relies on elements being
well behaved inserting themselves not
affecting the rest of the buffer
if we find ourselves with complex uis
large buffers long lines or poor
rendering performance we might consider
partial ui updates rather than
re-rendering completely
in that case the complexity for
maintaining the ui quickly increases as
accessible as buffers are we don't have
high level abstractions for managing
portions of a ui rendered to a buffer is
left up to the programmers to track and
update ui state this is generally done
by one of two methods
reflection searching for strings or text
properties when the butt within the
buffer or tracking segments of a ui
buffer manually using numeric offsets or
marker or overlay objects
here we have a basic timer component
that shows elapsed time after it's
inserted it works but has several
problems it doesn't restore the user's
point or mark
so it snaps back after every render
after every update
it relies on singleton global state so
isn't designed to coexist with other
instances of itself
it doesn't use a marker so it's
sensitive to content proceeding that's
following it changing in the buffer
the update logic doesn't even consider
which buffer it's trying to update if i
switch buffers it will insert into
another buffer or even the mini buffer
it can't remove itself or re-render if
it gets corrupted as you see all in all
it's not a readily composable component
addressing these components within this
logic further increases the
implementation complexity of this
component and still this component would
likely have various subtle differences
with other
components implemented by other other
authors
for those of you unfamiliar with this
term yak shaving is a quote technical
term for any seamingless
seemingly pointless activity which is
actually necessary to solve a problem
which solves a problem which several
levels of recursion later
solves the real problem you're working
on
the itch that led to this project was
the desire to display a dense summary of
local git repository statuses
encountering various implementation
complexity for building ui elements
it led to the yak shaving endeavor that
produced tui
when i wrote the library
i had recently played with a popular ui
framework called react and
had an interest in learning about the
internal architecture of react so rather
than implement a string caching layer on
top of tabulated list mode i was rather
inclined to go down the path of
implementing the react api
for
emacs lisp
i'll offer a brief view of the tui e-max
lisp api
inserting component
content is pretty straightforward you
take a component tree and render it in
an emax buffer
if any elements in that tree are updated
their respective content on the tree is
updated automatically
here's a basic re-implementation of the
straw man timer from earlier using a
macro for syntactic trigger
you'll notice
that the signature includes its own
object reference arguments and state
so associating arguments in the state
with a component instance out of the box
makes it easy to design reusable
components and forms the basis for
partial ui updates
the component rendering anchors are
durable so content can be added and
removed surrounding content or even
within the region of the component and
replaced when it re-renders
components will also cleanly remove
themselves
from a buffer when asked when instructed
to
tui contains the core implementation of
the react api so components
their constituent props state and all of
the life cycle methods associated with
them
as well as keys refs and the fundamental
reconciliation algorithm of react
a variety of react
apis that
other react apis that haven't been
implemented yet
it contains some useful features so far
such as hot reloading
reflection and
various debugging
tools and some reconciliation logging
lastly i'd like to give you some a quick
visual taste of components built with
tui
the grid view that motivated my
development of this package is very
similar to magit's list repositories
functionality
essentially tabulated list mode
but portable and separate has a
separated model and presentation layers
here's a basic xkcd comic viewer showing
a couple classics
a long-standing react tutorial is
building a tic-tac-toe game
as a bit of a gimmick
and i'm not quite satisfied with the
buffering direction but it got me
thinking about leo layout engines with
text so it was interesting
and here's
a small
unicode character viewer
capable of showing
a bunch of characters
so if this piques your interest i would
encourage you to check it out
tui should be usable by anyone with some
basic e-lisp familiarity
no prior knowledge about emacs or sorry
no prior knowledge about javascript or
react is necessary
i'd absolutely love to talk with people
about the tui package textual user
interfaces in general and really
anything in emacs if you have any ideas
feedback or want to contribute please
reach out
thank you all for listening