diff options
Diffstat (limited to '')
-rw-r--r-- | 2021/captions/ui.md | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/2021/captions/ui.md b/2021/captions/ui.md new file mode 100644 index 00000000..c9991e91 --- /dev/null +++ b/2021/captions/ui.md @@ -0,0 +1,214 @@ +<a name="transcript"></a> +# Transcript + +[[!template text="Hi! I'm Erik Anderson," start="00:00:07.600" video="mainVideo" id=subtitle]] +[[!template text="and I'll be talking about tui," start="00:00:09.120" video="mainVideo" id=subtitle]] +[[!template text="a user interface framework" start="00:00:10.559" video="mainVideo" id=subtitle]] +[[!template text="that I've written in Emacs Lisp." start="00:00:11.840" video="mainVideo" id=subtitle]] +[[!template text="First, I want to talk a bit about" start="00:00:15.040" video="mainVideo" id=subtitle]] +[[!template text="the problem space of" start="00:00:16.196" video="mainVideo" id=subtitle]] +[[!template text="user interface development," start="00:00:17.296" video="mainVideo" id=subtitle]] +[[!template text="specifically, I want to quickly illustrate" start="00:00:18.728" video="mainVideo" id=subtitle]] +[[!template text="some of the complexities involved" start="00:00:20.880" video="mainVideo" id=subtitle]] +[[!template text="with UI implementation in Emacs." start="00:00:22.320" video="mainVideo" id=subtitle]] +[[!template text="In Emacs, we have the ubiquitous" start="00:00:26.480" video="mainVideo" id=subtitle]] +[[!template text="buffer object type that forms the container" start="00:00:27.920" video="mainVideo" id=subtitle]] +[[!template text="for most content in Emacs." start="00:00:29.920" video="mainVideo" id=subtitle]] +[[!template text="Most interfaces we interact with" start="00:00:31.920" video="mainVideo" id=subtitle]] +[[!template text="consist of character based content" start="00:00:34.079" video="mainVideo" id=subtitle]] +[[!template text="in a buffer that's presented" start="00:00:36.239" video="mainVideo" id=subtitle]] +[[!template text="in a window in frame." start="00:00:38.239" video="mainVideo" id=subtitle]] +[[!template text="Although the underlying content" start="00:00:40.079" video="mainVideo" id=subtitle]] +[[!template text="may be textual, Emacs has capable APIs" start="00:00:41.520" video="mainVideo" id=subtitle]] +[[!template text="to present rich content." start="00:00:44.320" video="mainVideo" id=subtitle]] +[[!template text="The pervasiveness of buffers" start="00:00:47.680" video="mainVideo" id=subtitle]] +[[!template text="affords us wonderful flexibility." start="00:00:49.200" video="mainVideo" id=subtitle]] +[[!template text="This presentation, for instance," start="00:00:50.879" video="mainVideo" id=subtitle]] +[[!template text="is running in an Emacs buffer." start="00:00:52.559" video="mainVideo" id=subtitle]] +[[!template text="Using Emacs's built-in basic" start="00:00:55.520" video="mainVideo" id=subtitle]] +[[!template text="button library, we can insert" start="00:00:57.420" video="mainVideo" id=subtitle]] +[[!template text="an interactive button" start="00:00:59.199" video="mainVideo" id=subtitle]] +[[!template text="that shows a message" start="00:01:00.884" video="mainVideo" id=subtitle]] +[[!template text="in the minibuffer when clicked." start="00:01:01.760" video="mainVideo" id=subtitle]] +[[!template text="What about UIs that express application state?" start="00:01:06.080" video="mainVideo" id=subtitle]] +[[!template text="Most applications don't have a static UI." start="00:01:09.200" video="mainVideo" id=subtitle]] +[[!template text="As application state changes," start="00:01:11.439" video="mainVideo" id=subtitle]] +[[!template text="the UI should change" start="00:01:13.280" video="mainVideo" id=subtitle]] +[[!template text="to display the desired content." start="00:01:14.320" video="mainVideo" id=subtitle]] +[[!template text="One simplifying strategy is to simply" start="00:01:18.479" video="mainVideo" id=subtitle]] +[[!template text="re-render the entire UI upon any change." start="00:01:20.320" video="mainVideo" id=subtitle]] +[[!template text="First erase the contents of the buffer," start="00:01:23.600" video="mainVideo" id=subtitle]] +[[!template text="and then reinsert your UI again" start="00:01:25.680" video="mainVideo" id=subtitle]] +[[!template text="with desired changes," start="00:01:27.600" video="mainVideo" id=subtitle]] +[[!template text="and restore things like point and region." start="00:01:29.040" video="mainVideo" id=subtitle]] +[[!template text="Basic composition is possible" start="00:01:33.040" video="mainVideo" id=subtitle]] +[[!template text="with this approach." start="00:01:34.560" video="mainVideo" id=subtitle]] +[[!template text="Simply insert the elements" start="00:01:35.759" video="mainVideo" id=subtitle]] +[[!template text="of the UI in sequence." start="00:01:37.200" video="mainVideo" id=subtitle]] +[[!template text="Complex elements can be" start="00:01:39.280" video="mainVideo" id=subtitle]] +[[!template text="composed of multiple sub-elements." start="00:01:40.640" video="mainVideo" id=subtitle]] +[[!template text="UIs can be made extensible," start="00:01:44.320" video="mainVideo" id=subtitle]] +[[!template text="and expose this composition," start="00:01:45.840" video="mainVideo" id=subtitle]] +[[!template text="for example, with insertion hooks" start="00:01:47.040" video="mainVideo" id=subtitle]] +[[!template text="like magit's status sections hook." start="00:01:49.360" video="mainVideo" id=subtitle]] +[[!template text="This generally relies on elements" start="00:01:52.320" video="mainVideo" id=subtitle]] +[[!template text="being well-behaved inserting themselves," start="00:01:54.159" video="mainVideo" id=subtitle]] +[[!template text="not affecting the rest of the buffer." start="00:01:56.640" video="mainVideo" id=subtitle]] +[[!template text="If we find ourselves with complex UIs," start="00:02:00.399" video="mainVideo" id=subtitle]] +[[!template text="large buffers, long lines," start="00:02:02.960" video="mainVideo" id=subtitle]] +[[!template text="or poor rendering performance," start="00:02:04.640" video="mainVideo" id=subtitle]] +[[!template text="we might consider partial UI updates" start="00:02:06.320" video="mainVideo" id=subtitle]] +[[!template text="rather than re-rendering completely." start="00:02:09.039" video="mainVideo" id=subtitle]] +[[!template text="In that case, the complexity" start="00:02:11.360" video="mainVideo" id=subtitle]] +[[!template text="for maintaining the UI quickly increases." start="00:02:12.800" video="mainVideo" id=subtitle]] +[[!template text="As accessible as buffers are," start="00:02:15.840" video="mainVideo" id=subtitle]] +[[!template text="we don't have high level abstractions" start="00:02:17.360" video="mainVideo" id=subtitle]] +[[!template text="for managing portions of a UI" start="00:02:19.120" video="mainVideo" id=subtitle]] +[[!template text="rendered to a buffer." start="00:02:20.879" video="mainVideo" id=subtitle]] +[[!template text="(It) is left up to the programmers" start="00:02:22.160" video="mainVideo" id=subtitle]] +[[!template text="to track and update UI state." start="00:02:23.520" video="mainVideo" id=subtitle]] +[[!template text="This is generally done by" start="00:02:25.440" video="mainVideo" id=subtitle]] +[[!template text="one of two methods, reflection," start="00:02:26.540" video="mainVideo" id=subtitle]] +[[!template text="searching for strings or text properties" start="00:02:28.959" video="mainVideo" id=subtitle]] +[[!template text="within the buffer, or tracking segments" start="00:02:30.800" video="mainVideo" id=subtitle]] +[[!template text="of a UI buffer manually" start="00:02:34.239" video="mainVideo" id=subtitle]] +[[!template text="using numeric offsets, or marker," start="00:02:36.080" video="mainVideo" id=subtitle]] +[[!template text="or overlay objects." start="00:02:38.959" video="mainVideo" id=subtitle]] +[[!template text="Here we have a basic timer component" start="00:02:45.280" video="mainVideo" id=subtitle]] +[[!template text="that shows elapsed time" start="00:02:47.280" video="mainVideo" id=subtitle]] +[[!template text="after it's inserted." start="00:02:48.720" video="mainVideo" id=subtitle]] +[[!template text="It works, but has several problems." start="00:02:50.319" video="mainVideo" id=subtitle]] +[[!template text="It doesn't restore the user's point or mark," start="00:02:52.160" video="mainVideo" id=subtitle]] +[[!template text="so it snaps back after every render," start="00:02:55.519" video="mainVideo" id=subtitle]] +[[!template text="after every update." start="00:02:59.120" video="mainVideo" id=subtitle]] +[[!template text="It relies on singleton global state," start="00:03:01.040" video="mainVideo" id=subtitle]] +[[!template text="so isn't designed to coexist" start="00:03:03.360" video="mainVideo" id=subtitle]] +[[!template text="with other instances of itself." start="00:03:05.124" video="mainVideo" id=subtitle]] +[[!template text="It doesn't use a marker," start="00:03:12.000" video="mainVideo" id=subtitle]] +[[!template text="so it's sensitive to content" start="00:03:13.200" video="mainVideo" id=subtitle]] +[[!template text="proceeding it, that's following it," start="00:03:14.640" video="mainVideo" id=subtitle]] +[[!template text="changing in the buffer." start="00:03:16.239" video="mainVideo" id=subtitle]] +[[!template text="The update logic doesn't even consider" start="00:03:23.519" video="mainVideo" id=subtitle]] +[[!template text="which buffer it's trying to update." start="00:03:25.120" video="mainVideo" id=subtitle]] +[[!template text="If I switch buffers," start="00:03:26.799" video="mainVideo" id=subtitle]] +[[!template text="it will insert into another buffer," start="00:03:27.840" video="mainVideo" id=subtitle]] +[[!template text="or even the minibuffer." start="00:03:29.360" video="mainVideo" id=subtitle]] +[[!template text="It can't remove itself, or re-render" start="00:03:31.519" video="mainVideo" id=subtitle]] +[[!template text="if it gets corrupted, as you see." start="00:03:33.360" video="mainVideo" id=subtitle]] +[[!template text="All in all, it's not" start="00:03:34.879" video="mainVideo" id=subtitle]] +[[!template text="a readily composable component." start="00:03:35.920" video="mainVideo" id=subtitle]] +[[!template text="Addressing these components" start="00:03:38.400" video="mainVideo" id=subtitle]] +[[!template text="within this logic further increases" start="00:03:39.519" video="mainVideo" id=subtitle]] +[[!template text="the implementation complexity" start="00:03:41.920" video="mainVideo" id=subtitle]] +[[!template text="of this component," start="00:03:43.936" video="mainVideo" id=subtitle]] +[[!template text="and still this component" start="00:03:45.680" video="mainVideo" id=subtitle]] +[[!template text="would likely have" start="00:03:46.640" video="mainVideo" id=subtitle]] +[[!template text="various subtle differences" start="00:03:47.280" video="mainVideo" id=subtitle]] +[[!template text="with other components" start="00:03:49.120" video="mainVideo" id=subtitle]] +[[!template text="implemented by other authors." start="00:03:52.480" video="mainVideo" id=subtitle]] +[[!template text="For those of you unfamiliar" start="00:03:58.959" video="mainVideo" id=subtitle]] +[[!template text="with this term Yak Shaving," start="00:04:00.319" video="mainVideo" id=subtitle]] +[[!template text="that is a quite technical term" start="00:04:02.159" video="mainVideo" id=subtitle]] +[[!template text="for any seemingly pointless activity," start="00:04:04.080" video="mainVideo" id=subtitle]] +[[!template text="which is actually necessary" start="00:04:07.599" video="mainVideo" id=subtitle]] +[[!template text="to solve a problem," start="00:04:09.680" video="mainVideo" id=subtitle]] +[[!template text="which solves a problem," start="00:04:10.879" video="mainVideo" id=subtitle]] +[[!template text="which, several levels of recursion later," start="00:04:11.920" video="mainVideo" id=subtitle]] +[[!template text="solves the real problem you're working on." start="00:04:14.799" video="mainVideo" id=subtitle]] +[[!template text="The itch that led to this project" start="00:04:18.239" video="mainVideo" id=subtitle]] +[[!template text="was the desire to display a dense summary" start="00:04:19.943" video="mainVideo" id=subtitle]] +[[!template text="of local Git repository statuses." start="00:04:21.840" video="mainVideo" id=subtitle]] +[[!template text="Encountering various implementation" start="00:04:24.400" video="mainVideo" id=subtitle]] +[[!template text="complexity for building UI elements," start="00:04:26.560" video="mainVideo" id=subtitle]] +[[!template text="it led to the yak shaving endeavor" start="00:04:30.080" video="mainVideo" id=subtitle]] +[[!template text="that produced tui." start="00:04:31.680" video="mainVideo" id=subtitle]] +[[!template text="When I wrote the library," start="00:04:33.680" video="mainVideo" id=subtitle]] +[[!template text="I had recently played with" start="00:04:35.440" video="mainVideo" id=subtitle]] +[[!template text="a popular UI framework called React," start="00:04:36.479" video="mainVideo" id=subtitle]] +[[!template text="and had an interest in learning" start="00:04:39.360" video="mainVideo" id=subtitle]] +[[!template text="about the internal architecture of React." start="00:04:41.840" video="mainVideo" id=subtitle]] +[[!template text="So, rather than implement" start="00:04:44.080" video="mainVideo" id=subtitle]] +[[!template text="a string caching layer" start="00:04:45.680" video="mainVideo" id=subtitle]] +[[!template text="on top of tabulated list mode," start="00:04:46.960" video="mainVideo" id=subtitle]] +[[!template text="I was rather inclined" start="00:04:49.280" video="mainVideo" id=subtitle]] +[[!template text="to go down the path of implementing" start="00:04:50.360" video="mainVideo" id=subtitle]] +[[!template text="the React API for Emacs Lisp." start="00:04:52.400" video="mainVideo" id=subtitle]] +[[!template text="I'll offer a brief view of" start="00:04:58.960" video="mainVideo" id=subtitle]] +[[!template text="the tui Emacs Lisp API." start="00:05:00.896" video="mainVideo" id=subtitle]] +[[!template text="Inserting component content" start="00:05:05.120" video="mainVideo" id=subtitle]] +[[!template text="is pretty straightforward." start="00:05:07.360" video="mainVideo" id=subtitle]] +[[!template text="You take a component tree" start="00:05:08.320" video="mainVideo" id=subtitle]] +[[!template text="and render it in an Emacs buffer." start="00:05:10.160" video="mainVideo" id=subtitle]] +[[!template text="If any elements in that tree are updated," start="00:05:16.240" video="mainVideo" id=subtitle]] +[[!template text="their respective content on the tree" start="00:05:18.639" video="mainVideo" id=subtitle]] +[[!template text="is updated automatically." start="00:05:21.039" video="mainVideo" id=subtitle]] +[[!template text="Here's a basic re-implementation" start="00:05:26.320" video="mainVideo" id=subtitle]] +[[!template text="of the straw man timer from earlier," start="00:05:27.919" video="mainVideo" id=subtitle]] +[[!template text="using a macro for syntactic trigger." start="00:05:29.919" video="mainVideo" id=subtitle]] +[[!template text="You'll notice that" start="00:05:32.400" video="mainVideo" id=subtitle]] +[[!template text="the signature includes its own" start="00:05:34.404" video="mainVideo" id=subtitle]] +[[!template text="object reference, arguments, and state." start="00:05:36.164" video="mainVideo" id=subtitle]] +[[!template text="Associating arguments in the state" start="00:05:44.560" video="mainVideo" id=subtitle]] +[[!template text="with a component instance out of the box," start="00:05:46.400" video="mainVideo" id=subtitle]] +[[!template text="makes it easy to design reusable components," start="00:05:51.360" video="mainVideo" id=subtitle]] +[[!template text="and forms the basis for partial UI updates." start="00:05:54.400" video="mainVideo" id=subtitle]] +[[!template text="The component rendering anchors" start="00:06:06.080" video="mainVideo" id=subtitle]] +[[!template text="are durable, so content can be" start="00:06:07.840" video="mainVideo" id=subtitle]] +[[!template text="added and removed surrounding content," start="00:06:09.199" video="mainVideo" id=subtitle]] +[[!template text="or even within the region" start="00:06:11.360" video="mainVideo" id=subtitle]] +[[!template text="of the component," start="00:06:12.479" video="mainVideo" id=subtitle]] +[[!template text="and replaced when it re-renders." start="00:06:13.280" video="mainVideo" id=subtitle]] +[[!template text="Components will also" start="00:06:16.319" video="mainVideo" id=subtitle]] +[[!template text="cleanly remove themselves from a buffer" start="00:06:17.600" video="mainVideo" id=subtitle]] +[[!template text="when instructed to." start="00:06:20.880" video="mainVideo" id=subtitle]] +[[!template text="tui contains the core implementation" start="00:06:28.400" video="mainVideo" id=subtitle]] +[[!template text="of the React API, so components," start="00:06:30.160" video="mainVideo" id=subtitle]] +[[!template text="their constituent props, state," start="00:06:33.440" video="mainVideo" id=subtitle]] +[[!template text="and all of the lifecycle methods" start="00:06:35.840" video="mainVideo" id=subtitle]] +[[!template text="associated with them," start="00:06:38.000" video="mainVideo" id=subtitle]] +[[!template text="as well as keys, refs," start="00:06:39.440" video="mainVideo" id=subtitle]] +[[!template text="and the fundamental" start="00:06:41.120" video="mainVideo" id=subtitle]] +[[!template text="reconciliation algorithm of React." start="00:06:43.228" video="mainVideo" id=subtitle]] +[[!template text="A variety of other React APIs" start="00:06:47.520" video="mainVideo" id=subtitle]] +[[!template text="that haven't been implemented yet." start="00:06:52.188" video="mainVideo" id=subtitle]] +[[!template text="It contains some useful features so far," start="00:06:58.080" video="mainVideo" id=subtitle]] +[[!template text="such as hot reloading, reflection," start="00:07:00.080" video="mainVideo" id=subtitle]] +[[!template text="and various debugging tools," start="00:07:02.639" video="mainVideo" id=subtitle]] +[[!template text="and some reconciliation logging." start="00:07:06.164" video="mainVideo" id=subtitle]] +[[!template text="Lastly, I'd like to give you some quick" start="00:07:12.639" video="mainVideo" id=subtitle]] +[[!template text="visual taste of components built with tui." start="00:07:14.880" video="mainVideo" id=subtitle]] +[[!template text="The grid view that motivated" start="00:07:19.039" video="mainVideo" id=subtitle]] +[[!template text="my development of this package" start="00:07:20.240" video="mainVideo" id=subtitle]] +[[!template text="is very similar to Magit's" start="00:07:21.520" video="mainVideo" id=subtitle]] +[[!template text="list repositories functionality." start="00:07:23.039" video="mainVideo" id=subtitle]] +[[!template text="Essentially, tabulated list mode" start="00:07:30.720" video="mainVideo" id=subtitle]] +[[!template text="but portable and has a separated model" start="00:07:36.080" video="mainVideo" id=subtitle]] +[[!template text="and presentation layers." start="00:07:39.440" video="mainVideo" id=subtitle]] +[[!template text="Here's a basic xkcd comic viewer" start="00:07:49.360" video="mainVideo" id=subtitle]] +[[!template text="showing a couple classics." start="00:07:51.840" video="mainVideo" id=subtitle]] +[[!template text="A long-standing React tutorial is" start="00:08:07.360" video="mainVideo" id=subtitle]] +[[!template text="building a tic-tac-toe game" start="00:08:10.080" video="mainVideo" id=subtitle]] +[[!template text="as a bit of a gimmick," start="00:08:13.280" video="mainVideo" id=subtitle]] +[[!template text="and I'm not quite satisfied with" start="00:08:14.879" video="mainVideo" id=subtitle]] +[[!template text="the buffering direction," start="00:08:17.039" video="mainVideo" id=subtitle]] +[[!template text="but it got me thinking about" start="00:08:25.599" video="mainVideo" id=subtitle]] +[[!template text="layout engines with text," start="00:08:27.120" video="mainVideo" id=subtitle]] +[[!template text="so it was interesting." start="00:08:28.639" video="mainVideo" id=subtitle]] +[[!template text="And here's a small" start="00:08:35.120" video="mainVideo" id=subtitle]] +[[!template text="Unicode character viewer" start="00:08:38.560" video="mainVideo" id=subtitle]] +[[!template text="capable of showing a bunch of characters." start="00:08:46.080" video="mainVideo" id=subtitle]] +[[!template text="If this piques your interest," start="00:08:55.279" video="mainVideo" id=subtitle]] +[[!template text="I would encourage you to check it out." start="00:08:57.279" video="mainVideo" id=subtitle]] +[[!template text="tui should be usable by anyone" start="00:08:59.200" video="mainVideo" id=subtitle]] +[[!template text="with some basic Elisp familiarity," start="00:09:01.440" video="mainVideo" id=subtitle]] +[[!template text="no prior knowledge about JavaScript" start="00:09:04.640" video="mainVideo" id=subtitle]] +[[!template text="or React is necessary." start="00:09:09.680" video="mainVideo" id=subtitle]] +[[!template text="I'd absolutely love to talk with people" start="00:09:12.080" video="mainVideo" id=subtitle]] +[[!template text="about the tui package," start="00:09:13.732" video="mainVideo" id=subtitle]] +[[!template text="textual user interfaces in general," start="00:09:14.880" video="mainVideo" id=subtitle]] +[[!template text="and really anything in Emacs." start="00:09:17.440" video="mainVideo" id=subtitle]] +[[!template text="If you have any ideas, feedback," start="00:09:19.040" video="mainVideo" id=subtitle]] +[[!template text="or want to contribute," start="00:09:20.693" video="mainVideo" id=subtitle]] +[[!template text="please reach out." start="00:09:21.680" video="mainVideo" id=subtitle]] +[[!template text="Thank you all for listening." start="00:09:23.360" video="mainVideo" id=subtitle]] +[[!template text="captions by bhavin192 (Bhavin Gandhi)" start="00:09:24.360" video="mainVideo" id=subtitle]] |