WEBVTT

00:00:00.020 --> 00:00:06.720
In this episode, we welcome back Will McGugan, the creator of the wildly popular Rich Library and the founder of Textualize.

00:00:07.380 --> 00:00:11.700
We'll dive into Will's latest article on algorithms for high-performance terminal apps

00:00:12.400 --> 00:00:16.480
and explore how he's quietly revolutionizing what's possible in the terminal.

00:00:17.080 --> 00:00:22.860
From smooth animations to dynamic widgets and full-fledged TUI, or should we say GUI, frameworks.

00:00:23.480 --> 00:00:27.779
Whether you're looking to supercharge your command line tools or just curious about how Python

00:00:28.160 --> 00:00:32.599
can push the limits of text-based UIs. You'll love hearing how Will's taking a modern,

00:00:32.780 --> 00:00:36.900
web-inspired approach to old-school terminals. This is Talk Python To Me,

00:00:37.040 --> 00:00:41.020
episode 498, recorded February 4th, 2025.

00:00:42.160 --> 00:00:42.860
Are you ready for your

00:00:42.860 --> 00:00:43.220
host,

00:00:43.580 --> 00:00:43.720
please?

00:00:44.560 --> 00:00:47.480
You're listening to Michael Kennedy on Talk Python To Me.

00:00:48.020 --> 00:00:51.120
Live from Portland, Oregon, and this segment was made with Python.

00:00:54.280 --> 00:00:59.480
Welcome to Talk Python To Me, a weekly podcast on Python. This is your host, Michael Kennedy.

00:00:59.860 --> 00:01:04.739
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython,

00:01:05.400 --> 00:01:10.760
both accounts over at fosstodon.org, and keep up with the show and listen to over nine years of

00:01:11.060 --> 00:01:12.720
episodes at talkpython.fm.

00:01:12.980 --> 00:01:13.460
If

00:01:13.460 --> 00:01:16.500
you want to be part of our live episodes, you can find the live streams

00:01:16.640 --> 00:01:21.939
over on YouTube. Subscribe to our YouTube channel over at talkpython.fm/youtube and get

00:01:21.960 --> 00:01:27.100
notified about upcoming shows. This episode is sponsored by Posit Connect from the makers of

00:01:27.240 --> 00:01:31.760
Shiny. Publish, share, and deploy all of your data projects that you're creating using Python.

00:01:32.560 --> 00:01:38.420
Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quarto, Reports, Dashboards, and APIs.

00:01:39.360 --> 00:01:44.200
Posit Connect supports all of them. Try Posit Connect for free by going to talkpython.fm

00:01:44.420 --> 00:01:49.660
slash posit, P-O-S-I-T. Will, welcome back to Talk Python To Me. It's great to talk with you.

00:01:49.960 --> 00:01:51.020
Thank you. It's good to be here again.

00:01:51.420 --> 00:01:52.080
It's going to be really fun.

00:01:52.960 --> 00:01:56.060
You know, I've built some really cool apps with Rich,

00:01:56.600 --> 00:01:58.600
and we're going to talk about Rich and Textual.

00:01:58.880 --> 00:02:01.540
Probably a little more on the Textual side this time around,

00:02:01.780 --> 00:02:06.820
but still a very, very cool revolution you're bringing to the terminal.

00:02:07.280 --> 00:02:09.360
Yeah, a very quiet but pretty revolution.

00:02:10.110 --> 00:02:10.640
I like it.

00:02:11.300 --> 00:02:11.520
Indeed.

00:02:12.560 --> 00:02:15.080
Okay, so we want to talk about Textual.

00:02:15.130 --> 00:02:19.300
You wrote a cool article called Algorithms for High-Performance Terminal Apps,

00:02:19.640 --> 00:02:21.220
which I thought would be fun to dive in,

00:02:21.250 --> 00:02:24.200
but we're going to also keep it more of a broad-ranging conversation.

00:02:24.560 --> 00:02:25.860
At the start of all that, you know,

00:02:26.200 --> 00:02:29.400
it's been a little while since I've had you on the show.

00:02:29.800 --> 00:02:32.660
Again, tell people who maybe haven't listened to that episode

00:02:33.120 --> 00:02:33.860
or episodes

00:02:33.860 --> 00:02:34.480
who

00:02:34.480 --> 00:02:34.780
you are.

00:02:35.040 --> 00:02:36.500
Sure. My name is Will McGugan.

00:02:36.900 --> 00:02:38.760
I'm a software developer, Python developer,

00:02:38.840 --> 00:02:40.780
probably like most of your listeners.

00:02:41.820 --> 00:02:44.120
I achieved a certain amount of infamy

00:02:45.260 --> 00:02:47.520
when I built this library called Rich,

00:02:47.580 --> 00:02:49.040
which a lot of people use.

00:02:49.380 --> 00:02:50.820
If you see some fancy output in a terminal,

00:02:51.500 --> 00:02:52.240
that might have been me.

00:02:53.200 --> 00:02:55.740
And I founded a startup called Textualize,

00:02:56.100 --> 00:02:58.760
which is all about improving the developer experience

00:02:59.400 --> 00:02:59.920
in the terminal.

00:03:00.600 --> 00:03:02.400
And I'm sure we'll discuss Textual,

00:03:02.460 --> 00:03:05.060
which is my other Python library in this show.

00:03:05.320 --> 00:03:05.980
Yeah, absolutely.

00:03:06.500 --> 00:03:08.000
I'm super excited for it.

00:03:08.160 --> 00:03:12.300
And is this close to the one-year anniversary for Textual?

00:03:13.160 --> 00:03:14.680
It was an anniversary of some sort

00:03:14.720 --> 00:03:17.200
because we're going to talk about one of your,

00:03:17.620 --> 00:03:18.500
one of your articles.

00:03:19.740 --> 00:03:20.200
It's actually

00:03:20.200 --> 00:03:21.800
closer to three years

00:03:22.220 --> 00:03:23.860
since I founded Textualize.

00:03:23.930 --> 00:03:24.660
Oh, no, you know, it's not,

00:03:25.020 --> 00:03:26.240
it's the 1.0 miles.

00:03:26.660 --> 00:03:27.060
Oh, right, yeah.

00:03:27.340 --> 00:03:29.540
1.0 year, the 1.0 version.

00:03:29.880 --> 00:03:30.280
There we go.

00:03:30.640 --> 00:03:31.220
That's what I was thinking.

00:03:32.000 --> 00:03:34.700
Yeah, so Textual follows Semver,

00:03:35.120 --> 00:03:36.700
which I imagine people are familiar with.

00:03:37.500 --> 00:03:38.660
When you're on the zero version,

00:03:39.180 --> 00:03:40.220
you have a bit of flexibility

00:03:40.580 --> 00:03:41.680
and you can make breaking changes.

00:03:42.090 --> 00:03:42.780
We try not to,

00:03:43.620 --> 00:03:44.660
but you can make breaking changes

00:03:44.750 --> 00:03:45.659
and it gives you a bit of freedom

00:03:45.680 --> 00:03:47.820
early on to play around with things.

00:03:48.600 --> 00:03:50.080
But some people stick to

00:03:50.540 --> 00:03:52.280
ZeroVer just forever,

00:03:52.700 --> 00:03:53.700
which is fine if that's what you do.

00:03:54.080 --> 00:03:55.700
But when you go to 1.0,

00:03:55.760 --> 00:03:58.000
it advertises to people that this is stable.

00:03:58.460 --> 00:03:59.740
You can rely on the interface

00:04:00.220 --> 00:04:02.240
not changing too quickly.

00:04:04.320 --> 00:04:05.700
And if there are any changes,

00:04:05.880 --> 00:04:06.700
it's well documented.

00:04:07.160 --> 00:04:08.040
If you followed along,

00:04:08.360 --> 00:04:09.300
it's a very modest release

00:04:09.720 --> 00:04:11.300
from the last zero version

00:04:11.800 --> 00:04:13.040
to the 1.0 version.

00:04:13.820 --> 00:04:14.620
But it says to the world,

00:04:14.840 --> 00:04:16.739
hey, everything textualized is ready.

00:04:16.950 --> 00:04:18.200
You can start using it in production,

00:04:18.970 --> 00:04:21.799
even though you could probably have been using it in production for a year.

00:04:22.019 --> 00:04:22.860
I'm sure that you

00:04:22.860 --> 00:04:23.220
could have.

00:04:23.320 --> 00:04:23.960
I'm sure you could have.

00:04:24.640 --> 00:04:27.580
Are you familiar with zerover.org,

00:04:27.860 --> 00:04:31.060
the numeral zerover.org?

00:04:31.420 --> 00:04:32.040
Have you seen this?

00:04:32.640 --> 00:04:33.300
No, I didn't.

00:04:33.600 --> 00:04:35.780
I thought it was just an aspect of Semver.

00:04:35.850 --> 00:04:36.520
I didn't realize it was.

00:04:36.820 --> 00:04:39.100
It is absolutely an aspect of Semver.

00:04:39.620 --> 00:04:41.660
But this, I can't remember who put this together.

00:04:41.830 --> 00:04:42.680
Does it say at the bottom?

00:04:43.040 --> 00:04:44.300
Let's see about the About page.

00:04:45.660 --> 00:04:50.720
published yeah that's what i thought i thought it was Mahmoud Hashemi amazing yeah so Mahmoud put

00:04:50.720 --> 00:04:53.440
this together and basically it calls out

00:04:53.440 --> 00:04:54.880
i

00:04:54.880 --> 00:04:57.680
think it's it's a little contrarian to you know there's

00:04:57.680 --> 00:05:03.240
a lot of especially larger companies that have rules about what version you're allowed to use

00:05:03.240 --> 00:05:09.400
and is software ready enough if it's a 0.3 we can't use it it's not ready not until it's a 1.0 or a 2.0

00:05:09.340 --> 00:05:10.960
or something along those lines, right?

00:05:11.650 --> 00:05:12.560
And so this is

00:05:12.560 --> 00:05:14.620
the

00:05:14.620 --> 00:05:16.700
popular projects

00:05:16.990 --> 00:05:19.400
that are still really, really low in their versions.

00:05:19.960 --> 00:05:22.260
It says, welcome to Zerover 0.0.1.

00:05:23.420 --> 00:05:27.500
And if you go down here, it says, like, look, React Native is 0.78.

00:05:27.800 --> 00:05:28.640
Right, right, yeah.

00:05:28.760 --> 00:05:29.040
Even though

00:05:29.040 --> 00:05:29.800
it's 10 years old.

00:05:30.820 --> 00:05:32.920
Hugo, which I use for my blog and love it,

00:05:33.070 --> 00:05:34.980
it's got 77,000 GitHub stars.

00:05:35.070 --> 00:05:37.340
It was first released 12 years ago.

00:05:38.020 --> 00:05:39.700
More than a decade long.

00:05:40.500 --> 00:05:42.840
It's still zero dot something.

00:05:43.520 --> 00:05:45.680
Let's see if there's some that are really extreme here.

00:05:45.900 --> 00:05:47.180
I think the problem is that

00:05:47.180 --> 00:05:48.920
non

00:05:48.920 --> 00:05:49.560
-software developers

00:05:49.670 --> 00:05:51.220
have a different idea of what versions mean.

00:05:52.720 --> 00:05:53.160
We

00:05:53.160 --> 00:05:54.400
know that they're about compatibility.

00:05:56.060 --> 00:05:59.760
But when you're marketing it, 1.0 is like you advertise it,

00:05:59.760 --> 00:06:00.800
you make a splash about it.

00:06:01.020 --> 00:06:01.720
That's when it's actually

00:06:01.720 --> 00:06:02.040
out.

00:06:02.070 --> 00:06:02.620
You can use it.

00:06:02.820 --> 00:06:04.440
Otherwise, it's just like a toy, right?

00:06:05.380 --> 00:06:06.700
And then, boom, 2.0.

00:06:07.440 --> 00:06:07.620
Yeah.

00:06:07.680 --> 00:06:08.320
Yeah, let's see.

00:06:09.280 --> 00:06:10.560
NeoVim, 0.10.

00:06:11.940 --> 00:06:14.640
scikit-learn, it's 15 years old, it's 0.17.

00:06:15.160 --> 00:06:22.840
So I think I totally hear what you're saying, right, about like, yes, this, and I think we both agree, like, what this should mean.

00:06:22.980 --> 00:06:30.980
If your thing is 0.17, probably that means there's a good chance that there might be some adaptations to the API.

00:06:31.540 --> 00:06:37.660
at the same time if you're scikit-learn and you've had you've been around for 15 years yeah it might

00:06:37.810 --> 00:06:41.640
be time to bump that to something over 0.17 you know what i mean

00:06:41.640 --> 00:06:42.420
what

00:06:42.420 --> 00:06:42.980
do you think it's

00:06:42.980 --> 00:06:43.700
i

00:06:43.700 --> 00:06:44.080
think it's

00:06:44.180 --> 00:06:48.660
it's the um developer-led projects the ones which are just a bunch of developers releasing

00:06:49.240 --> 00:06:55.500
at open source uh we developers don't like to make too much promises exactly if we were to put a 1.0

00:06:55.530 --> 00:06:56.060
on it who's

00:06:56.060 --> 00:06:59.419
going to be on the hook for making that 1.0 and then they're stuck with it right

00:06:59.440 --> 00:07:04.220
Exactly. We know that 1.0 is not going to be perfect and bug-free.

00:07:05.460 --> 00:07:09.900
So we don't necessarily want to be on the hook for it not being perfect.

00:07:10.700 --> 00:07:15.560
Yeah, I know. At the same time, you're on the hook to not change scikit-learn at this point anyway.

00:07:16.000 --> 00:07:16.660
You know what I mean?

00:07:16.920 --> 00:07:21.900
And I'm only picking on them because I know they're so well-loved in the community and they're very, very common.

00:07:22.120 --> 00:07:25.300
Unlike, say, Ruff, which is on this list, but Ruff is pretty new.

00:07:26.540 --> 00:07:29.000
Anyway, I think I'll put this in the show notes.

00:07:29.280 --> 00:07:29.640
Zerover.

00:07:30.460 --> 00:07:30.800
Thanks, 

00:07:30.880 --> 00:07:31.720
That was really fun.

00:07:32.440 --> 00:07:34.260
So let's talk about terminals.

00:07:35.020 --> 00:07:35.600
Terminal revolution.

00:07:36.180 --> 00:07:39.580
I think it's a pretty interesting time for terminals,

00:07:40.340 --> 00:07:43.440
both the application that runs your terminal

00:07:44.180 --> 00:07:46.600
as well as closer to what you're doing,

00:07:47.320 --> 00:07:51.700
building applications that are like CLI apps or TUI apps,

00:07:52.240 --> 00:07:54.220
as we'll coin the term.

00:07:54.400 --> 00:07:55.160
No, you've coined the term.

00:07:55.460 --> 00:07:57.920
We'll tell people about the term if they don't know, right?

00:07:58.360 --> 00:08:01.480
I mean, we've got Warp, we've got Ghostty,

00:08:02.170 --> 00:08:04.180
I don't know how you say, Ghostty, whatever.

00:08:04.780 --> 00:08:07.640
A bunch of other options coming along for terminals

00:08:07.940 --> 00:08:10.300
that make being in the terminal nicer.

00:08:10.800 --> 00:08:14.640
And I think also draw people into wanting to build apps

00:08:14.780 --> 00:08:17.340
that run in that space rather than try to get away from it, right?

00:08:17.840 --> 00:08:22.979
It's not macOS where it's just the default Z shell

00:08:23.580 --> 00:08:26.120
with no history and it's like white with weird fonts

00:08:26.860 --> 00:08:28.740
or CMD on Windows where you're like,

00:08:28.810 --> 00:08:29.860
what is this thing, you know?

00:08:30.380 --> 00:08:31.380
What are your thoughts on this?

00:08:31.390 --> 00:08:33.700
I mean, first of all, like maybe just on the apps that run,

00:08:33.820 --> 00:08:35.880
do you have a favorite terminal app that you run?

00:08:36.720 --> 00:08:39.360
I've been using iTerm for the last few years.

00:08:39.450 --> 00:08:40.400
It's kind of my daily driver.

00:08:41.580 --> 00:08:42.500
But there's a few other good ones.

00:08:42.700 --> 00:08:47.040
There's Alacritty and Kitty and then GhostTTY or GhostTTY.

00:08:47.230 --> 00:08:47.680
I'm not sure.

00:08:47.860 --> 00:08:49.040
That's a new kid on the block.

00:08:50.040 --> 00:08:50.900
And it is very good.

00:08:51.260 --> 00:08:52.260
It is very good indeed.

00:08:52.940 --> 00:08:55.000
but I like ITerms feature set

00:08:55.400 --> 00:08:57.260
it's not the fastest but it's fairly reliable

00:08:57.740 --> 00:08:59.240
and it's got lots of other features

00:08:59.940 --> 00:09:00.980
I played around with

00:09:02.339 --> 00:09:02.779
I

00:09:02.779 --> 00:09:03.480
played around with

00:09:03.610 --> 00:09:04.540
warp.dev as well

00:09:05.460 --> 00:09:07.240
I think that's a little too

00:09:09.040 --> 00:09:09.480
unconventional

00:09:09.860 --> 00:09:10.420
for me at the moment

00:09:11.300 --> 00:09:12.600
they've done some very cool stuff though

00:09:13.200 --> 00:09:14.500
there's lots of innovation there

00:09:14.700 --> 00:09:17.140
it takes some good news to you, that's the one I've been using

00:09:17.300 --> 00:09:18.520
last year or so and I really

00:09:19.160 --> 00:09:20.999
enjoyed it, it does some very cool things like

00:09:21.020 --> 00:09:29.680
For example, if I'm on my computer and then I SSH into another computer and then in that computer I Docker exec something into a Docker

00:09:29.680 --> 00:09:32.020
system,

00:09:32.110 --> 00:09:39.500
a Docker container, Warp will say, would you like to apply the Warp shell to this Docker container instead of whatever does it?

00:09:39.580 --> 00:09:40.840
It might not even have Bash, right?

00:09:40.910 --> 00:09:41.960
It might just be SH.

00:09:42.030 --> 00:09:43.320
You just hit a button and it goes, whoop.

00:09:43.960 --> 00:09:50.020
It adapts and basically become kind of like in memory, installs itself into that container temporarily, right?

00:09:50.120 --> 00:09:50.680
that sets all the

00:09:50.680 --> 00:09:51.800
settings

00:09:51.800 --> 00:09:52.240
and stuff.

00:09:52.440 --> 00:09:54.860
So it's a long ways from cmd.exe.

00:09:55.440 --> 00:09:58.700
I guess it's worth pointing out to people out there on Windows,

00:09:58.920 --> 00:10:01.860
if you're not using Windows Terminal, please,

00:10:02.040 --> 00:10:02.740
right?

00:10:02.980 --> 00:10:04.200
You need to use Windows Terminal.

00:10:05.079 --> 00:10:07.960
It's such an improvement over...

00:10:07.960 --> 00:10:09.260
Massive improvement.

00:10:09.320 --> 00:10:09.580
I mean,

00:10:09.700 --> 00:10:11.380
you probably run into this all the time, right?

00:10:12.060 --> 00:10:12.840
Yeah, and the solution,

00:10:13.040 --> 00:10:15.040
if someone tries something in the terminal

00:10:15.080 --> 00:10:17.000
they use is retro textual and it doesn't work properly,

00:10:18.100 --> 00:10:21.080
I first say, we try downloading Windows Terminal.

00:10:21.600 --> 00:10:24.460
And 99% of the time, it not only fixes it,

00:10:24.460 --> 00:10:26.060
but it makes it look beautiful.

00:10:26.720 --> 00:10:28.340
I mean, hat's off to Microsoft.

00:10:29.660 --> 00:10:31.400
They didn't change the terminal for decades.

00:10:32.180 --> 00:10:34.100
But when they did, they made a very good job of it.

00:10:34.700 --> 00:10:35.600
Yeah, it took a while.

00:10:36.480 --> 00:10:38.380
I don't know if it's the default yet.

00:10:38.540 --> 00:10:38.980
You know what I mean?

00:10:39.780 --> 00:10:41.220
I'm not sure what's actually presented

00:10:41.920 --> 00:10:43.780
if you kind of pull up the start menu.

00:10:44.560 --> 00:10:46.720
It's a very strange architecture.

00:10:47.640 --> 00:10:50.400
You can pull up cmd.exe.

00:10:50.700 --> 00:10:51.640
That's what I've been used to calling it

00:10:51.640 --> 00:10:52.760
because it has it in the title bar.

00:10:53.560 --> 00:10:55.040
If you send it some magic codes,

00:10:56.020 --> 00:10:58.780
you can switch it into essentially Windows Terminal.

00:10:58.880 --> 00:11:04.800
It'll process escape sequences like it does on Mac and Linux.

00:11:05.500 --> 00:11:09.120
So the actual window you see is just kind of like a window

00:11:09.400 --> 00:11:12.100
onto the thing which renders the terminal.

00:11:13.400 --> 00:11:14.040
So you can get Windows.

00:11:14.340 --> 00:11:15.619
You might already have Windows Terminal

00:11:15.640 --> 00:11:17.400
even if you don't get the experience.

00:11:18.060 --> 00:11:20.800
But software can switch it into this mode,

00:11:21.720 --> 00:11:23.320
which makes it work really well.

00:11:23.680 --> 00:11:24.960
I had no idea. That's cool.

00:11:25.370 --> 00:11:25.460
Okay.

00:11:25.850 --> 00:11:28.600
Yeah, it's probably the same core for both of them or something, right?

00:11:28.900 --> 00:11:29.400
Yeah, exactly.

00:11:29.480 --> 00:11:32.340
The architecture is very component-based

00:11:32.560 --> 00:11:34.960
and you can switch it at runtime.

00:11:35.570 --> 00:11:36.820
Yeah, that sounds very Microsoft.

00:11:37.820 --> 00:11:39.460
Is there a code that you can put to embed?

00:11:39.800 --> 00:11:41.360
Like if you can split the panes

00:11:41.460 --> 00:11:43.280
and then you can embed Excel on one side maybe

00:11:43.570 --> 00:11:44.600
and then SharePoint on the other?

00:11:44.900 --> 00:11:45.660
I haven't found it.

00:11:45.820 --> 00:11:46.300
I'm just kidding.

00:11:47.540 --> 00:11:48.360
I wouldn't be

00:11:48.360 --> 00:11:49.180
surprised, yeah.

00:11:49.480 --> 00:11:50.100
I wouldn't either.

00:11:50.820 --> 00:11:51.420
I wouldn't either.

00:11:52.000 --> 00:11:56.260
Are you a fan of modifying your shell, I guess?

00:11:56.560 --> 00:11:59.960
You know, like, oh my ZSH or

00:11:59.960 --> 00:12:02.740
oh My Posh or Starship or any of these?

00:12:03.140 --> 00:12:04.400
Yeah, to change the prompt.

00:12:05.020 --> 00:12:07.360
Yeah, I do have, I can't remember which one I use now.

00:12:08.200 --> 00:12:09.500
It's not, is it Starship?

00:12:09.820 --> 00:12:09.960
Yeah.

00:12:11.280 --> 00:12:12.540
Yeah, it's fairly minimal.

00:12:12.940 --> 00:12:16.080
It tells me the branch, the Git branch I'm working on,

00:12:16.200 --> 00:12:17.480
the version of Python that's running,

00:12:18.220 --> 00:12:20.280
and the version of the application I'm working on.

00:12:20.540 --> 00:12:21.880
So that's really nice.

00:12:22.120 --> 00:12:24.240
Oh, it'll tell you the version of the application you're working on?

00:12:24.680 --> 00:12:26.400
Yeah, it says v1.0.0,

00:12:26.400 --> 00:12:29.500
so it's somehow pulled out the version from Textual, I guess.

00:12:29.780 --> 00:12:29.920
Oh,

00:12:30.020 --> 00:12:31.040
wow. That's pretty cool.

00:12:31.200 --> 00:12:33.660
I guess if it's in a repo and knows that repo is a package,

00:12:33.800 --> 00:12:36.320
it can figure out what version it is, but that's still pretty neat.

00:12:36.660 --> 00:12:38.120
I guess. I must go on the spec.

00:12:38.940 --> 00:12:40.060
PyProject.toml, I'm guessing.

00:12:40.540 --> 00:12:40.660
Yeah.

00:12:41.580 --> 00:12:42.640
Yeah, I don't know. It's magic.

00:12:42.780 --> 00:12:43.260
and it works.

00:12:43.640 --> 00:12:45.720
So don't delve too deeply.

00:12:46.980 --> 00:12:48.720
Yeah, the whole reason I'm bringing this up,

00:12:48.720 --> 00:12:50.360
it might feel like a little bit of a diversion,

00:12:50.600 --> 00:12:52.600
but when people think about terminal apps

00:12:52.920 --> 00:12:53.980
and just being in the terminal

00:12:54.360 --> 00:12:55.100
and somebody says,

00:12:55.180 --> 00:12:56.920
oh God, I hate the terminal.

00:12:57.120 --> 00:12:58.580
It's so bad.

00:12:59.020 --> 00:12:59.880
I can't stand it.

00:13:00.120 --> 00:13:02.400
It usually means they're not adopting

00:13:02.860 --> 00:13:04.740
some of these really magical tools.

00:13:05.400 --> 00:13:05.940
Regardless of which one,

00:13:06.500 --> 00:13:08.800
regardless of whether you adopt Starship

00:13:08.980 --> 00:13:11.420
or Oh My ZSH or Warp or whatever,

00:13:11.980 --> 00:13:14.720
you get a dramatically different experience, right?

00:13:15.060 --> 00:13:17.140
Yeah, it's infinitely customizable,

00:13:17.860 --> 00:13:20.660
the terminal and the shell and various other software.

00:13:22.060 --> 00:13:24.900
So you can get the kind of experience that you want out of a terminal.

00:13:25.040 --> 00:13:28.260
People get very comfortable with their terminal environment.

00:13:29.660 --> 00:13:32.880
It feels like an old pair of shoes.

00:13:34.340 --> 00:13:36.280
It's just that comfortable.

00:13:36.600 --> 00:13:38.520
I guess it depends what tools you use as well.

00:13:38.940 --> 00:13:42.820
For example, if you're a NeoVim or an Emacs type person,

00:13:43.300 --> 00:13:47.120
you're in the terminal even way, way more than, say, for me, for example,

00:13:47.320 --> 00:13:51.020
use PyCharm and other tools that I only dip in and out

00:13:52.279 --> 00:13:54.220
when I'm working on code for that kind of stuff.

00:13:54.460 --> 00:13:58.860
Yeah, for me, I'm switching between terminal and VS Code most of the day.

00:13:58.960 --> 00:13:59.020
So

00:13:59.020 --> 00:13:59.560
I've got both

00:13:59.560 --> 00:14:00.540
open.

00:14:00.660 --> 00:14:04.260
I write some code and I switch back to terminal and run said code.

00:14:04.620 --> 00:14:06.060
So I'm in both.

00:14:06.520 --> 00:14:11.140
Yeah, but funnily enough, I never got into editors that run inside the terminal.

00:14:12.180 --> 00:14:16.340
I do like all the fancy graphics that VS Code can give you that terminal couldn't.

00:14:17.160 --> 00:14:17.300
Yeah.

00:14:17.980 --> 00:14:19.860
That matters less to other people, but I like it.

00:14:20.280 --> 00:14:20.680
You know what?

00:14:21.840 --> 00:14:25.660
When I started out doing programming, I started out doing a lot of work on silicon graphics,

00:14:26.339 --> 00:14:30.920
mainframes, doing Emacs on Onyx workstations and stuff like that.

00:14:31.280 --> 00:14:34.860
And I was happy as a clam to get out of there as quick as possible.

00:14:35.440 --> 00:14:42.000
get out of. I'm like, can I get some better tools than this? And yeah, I don't know. I'm on the GUI

00:14:42.120 --> 00:14:47.200
side as well, but I feel like kind of like the terminal. If you don't customize your terminal,

00:14:47.340 --> 00:14:53.440
it's not a great experience. If you don't really commit to learning all the hotkeys of your GUI app,

00:14:53.780 --> 00:14:56.720
well, it feels like, well, I got to use this mouse. It's all clunky, but like I almost never

00:14:56.880 --> 00:15:01.079
use the mouse. You know what I mean? Even though I'm in a GUI app, right? They just customize the

00:15:01.100 --> 00:15:01.840
keys? I

00:15:01.840 --> 00:15:02.900
think you can get very

00:15:03.120 --> 00:15:04.320
proficient in both.

00:15:05.320 --> 00:15:06.980
You know, I've seen people using a terminal and they

00:15:07.060 --> 00:15:08.480
use Emacs or Vim

00:15:09.160 --> 00:15:11.140
and their fingers just fly

00:15:11.360 --> 00:15:12.640
through it and they're very proficient.

00:15:13.380 --> 00:15:14.940
But the same thing in VS Code.

00:15:15.080 --> 00:15:16.580
If you know your editor

00:15:17.280 --> 00:15:19.000
and you know the shortcut keys and you don't reach

00:15:19.000 --> 00:15:20.960
for the mouse very often, you can be just

00:15:21.030 --> 00:15:22.460
as proficient, really.

00:15:23.220 --> 00:15:24.940
At Textualize, we had a policy if you use whatever

00:15:24.970 --> 00:15:25.860
you want to use to

00:15:25.860 --> 00:15:26.760
edit

00:15:27.080 --> 00:15:28.620
code. If you take a developer

00:15:29.040 --> 00:15:31.060
who uses Vim

00:15:31.080 --> 00:15:32.020
and then force

00:15:32.020 --> 00:15:32.700
them to Vs code,

00:15:32.700 --> 00:15:33.580
they will not be happy.

00:15:33.820 --> 00:15:35.780
And they will not be as

00:15:35.780 --> 00:15:36.100
efficient

00:15:36.100 --> 00:15:37.200
at

00:15:37.200 --> 00:15:37.360
all.

00:15:38.699 --> 00:15:40.680
Yeah, that's a really tricky balance, right?

00:15:40.680 --> 00:15:43.400
You want to let people work where they're comfortable, for sure.

00:15:45.500 --> 00:15:46.780
This portion of Talk Python To Me

00:15:46.820 --> 00:15:48.280
is brought to you by the folks at Posit.

00:15:48.720 --> 00:15:50.320
Posit has made a huge investment

00:15:50.420 --> 00:15:51.600
in the Python community lately.

00:15:52.220 --> 00:15:53.640
Known originally for RStudio,

00:15:54.020 --> 00:15:55.780
they've been building out a suite of tools

00:15:56.000 --> 00:15:57.420
and services for Team Python.

00:15:58.120 --> 00:15:59.100
Over the past few years,

00:15:59.300 --> 00:16:01.380
we've all learned some pretty scary terms.

00:16:02.020 --> 00:16:06.340
Hypersquatting, supply chain attack, obfuscated code, and more.

00:16:06.940 --> 00:16:10.680
These all orbit around the idea that when you install Python packages,

00:16:11.300 --> 00:16:14.740
you're effectively running arbitrary code off the internet on your dev machine,

00:16:15.460 --> 00:16:17.180
and usually even on your servers.

00:16:17.940 --> 00:16:19.180
But thought alone makes me shudder,

00:16:19.500 --> 00:16:23.340
and this doesn't even touch the reproducibility issues surrounding external packages.

00:16:24.120 --> 00:16:25.360
But there are tools to help.

00:16:25.900 --> 00:16:28.840
Posit Package Manager can solve both problems for you.

00:16:29.640 --> 00:16:32.940
Think of Posit Package Manager as your personal package concierge.

00:16:33.300 --> 00:16:37.680
You use it to build your own package repositories within your firewall that keep your project safe.

00:16:37.880 --> 00:16:42.920
You can upload your own internal packages to share or import packages directly from PyPI.

00:16:43.580 --> 00:16:48.940
Your team members can install from these repos in normal ways using tools like pip, Poetry, and uv.

00:16:49.580 --> 00:16:55.940
Posit Package Manager can help you manage updates, ensuring you're using the latest, most secure versions of your packages.

00:16:56.540 --> 00:16:59.840
but it also takes point-in-time snapshots of your repos,

00:17:00.020 --> 00:17:03.740
which you can use to rerun your code reproducibly in the future.

00:17:04.319 --> 00:17:07.500
Posit Package Manager reports on packages with known CVEs

00:17:07.579 --> 00:17:10.360
and other vulnerabilities so you can keep ahead of threats.

00:17:10.980 --> 00:17:12.819
And if you need the highest level of security,

00:17:13.000 --> 00:17:16.339
you can even run Posit Package Manager in air-gapped environments.

00:17:16.980 --> 00:17:19.360
If you work on a data science team where security matters,

00:17:19.600 --> 00:17:22.920
you owe it to you and your org to check out Posit Package Manager.

00:17:23.000 --> 00:17:29.360
visit talkpython.fm/ppm today and get a three-month free trial to see if it's a good fit

00:17:29.560 --> 00:17:35.140
that's talkpython.fm/ppm the link is in your podcast player show notes thank you deposit

00:17:35.340 --> 00:17:36.060
for supporting the show

00:17:36.060 --> 00:17:37.860
all

00:17:37.860 --> 00:17:43.440
right well i think that's a good transition to tui what is what are

00:17:43.560 --> 00:17:47.920
tuis why do people build them i know we talked about this in the last episode we won't totally

00:17:48.060 --> 00:17:51.839
necessarily rehash it but there are some people haven't seen it there are some incredible

00:17:51.860 --> 00:17:57.320
applications and we will see some built in textual that run in the terminal yeah

00:17:57.320 --> 00:17:58.940
sure so TUI stands

00:17:59.200 --> 00:18:06.460
for Text User Interface um i don't actually like that term anymore okay um and the reason is well

00:18:06.580 --> 00:18:11.680
the thing is um the TUI's that you build with textual are also GUI's um it's a very simplified

00:18:11.840 --> 00:18:17.760
form of graphics but we've got we've got lines um and and corners and you've got like a mouse that

00:18:17.780 --> 00:18:21.620
can move around. So it is rounded with text, but

00:18:22.020 --> 00:18:25.780
it works just like a GUI. I guess it's a little bit like

00:18:25.880 --> 00:18:29.360
saying a web browser is a document-based UI.

00:18:30.920 --> 00:18:33.740
It's technically correct, but no. We're having this whole video

00:18:34.240 --> 00:18:37.400
live stream recording across the internet,

00:18:38.220 --> 00:18:41.800
across the world in a web browser, and there's only a little text on the

00:18:41.880 --> 00:18:42.260
screen, right?

00:18:42.380 --> 00:18:45.899
Yeah, exactly. So the term TUI is stuck, but

00:18:45.980 --> 00:18:48.440
It's a GUI that runs in your terminal.

00:18:49.060 --> 00:18:51.660
Well, I think originally it was pretty text-based.

00:18:52.300 --> 00:18:52.740
It was.

00:18:52.770 --> 00:18:54.800
The advanced version might be a progress bar, right?

00:18:55.140 --> 00:18:56.340
Or emojis or color.

00:18:56.560 --> 00:18:56.680
Yeah,

00:18:57.250 --> 00:18:57.380
exactly.

00:18:57.570 --> 00:19:01.220
So those are technically text, but it looks like images.

00:19:01.480 --> 00:19:02.760
So you've got emoji.

00:19:02.830 --> 00:19:06.100
You can have lots of, like, I'm looking at my Starship prompt,

00:19:06.150 --> 00:19:08.920
and it's got a little snake because it's in Python and that kind of stuff.

00:19:09.000 --> 00:19:12.100
That is technically text, but it is graphical.

00:19:12.420 --> 00:19:13.480
and progress bars.

00:19:14.680 --> 00:19:17.200
You create a bar using characters,

00:19:17.840 --> 00:19:19.240
but essentially you're creating an image.

00:19:20.280 --> 00:19:21.140
So I think the distinction between

00:19:21.140 --> 00:19:22.260
text

00:19:22.260 --> 00:19:22.760
user interface

00:19:23.020 --> 00:19:26.120
and graphical user interface is fuzzy now.

00:19:27.120 --> 00:19:29.260
If you say TUI, I'll know what you're talking about,

00:19:29.720 --> 00:19:31.920
but I just don't like the term.

00:19:31.950 --> 00:19:33.280
I don't think it's as clear.

00:19:33.500 --> 00:19:35.520
I'm not sure we even need the distinction.

00:19:35.860 --> 00:19:36.820
Yeah, I hear you.

00:19:37.240 --> 00:19:38.140
Are you familiar with Btop?

00:19:38.360 --> 00:19:39.180
Have you seen this app?

00:19:39.960 --> 00:19:41.340
Yeah, that's really, really pretty.

00:19:41.640 --> 00:19:42.700
I like the fading effect.

00:19:43.160 --> 00:19:49.260
I mean, this app has just crazy amounts of graphics

00:19:49.620 --> 00:19:52.140
and it's all written in the terminal with live updating.

00:19:52.540 --> 00:19:54.460
I don't know how many graphs, but many, many graphs.

00:19:55.040 --> 00:19:56.660
Interesting thing about Btop,

00:19:57.620 --> 00:19:59.840
I think most people who run it don't run it

00:20:00.040 --> 00:20:01.820
because they really need to keep an eye

00:20:02.140 --> 00:20:05.440
on the performance of their course and file system, etc.

00:20:06.200 --> 00:20:09.000
I think a lot of them run it because it's retro cool.

00:20:09.540 --> 00:20:10.520
It's retro cool.

00:20:11.260 --> 00:20:12.180
It looks cool.

00:20:12.220 --> 00:20:16.640
It looks like how you thought computers were going to look.

00:20:17.680 --> 00:20:17.920
I'm going to be

00:20:17.920 --> 00:20:19.080
a programmer and a hacker.

00:20:19.240 --> 00:20:20.540
I'm going to be a super tech guy.

00:20:21.399 --> 00:20:22.540
This, yeah, you know what?

00:20:22.540 --> 00:20:24.180
It could be, this could be a movie UI.

00:20:24.640 --> 00:20:26.420
You know how when you're watching a movie,

00:20:26.640 --> 00:20:29.160
they're like, they fucked for whatever reason,

00:20:29.340 --> 00:20:31.600
won't run macOS or Windows.

00:20:32.100 --> 00:20:36.420
They come up with some weird variation that's got weird graphics.

00:20:36.420 --> 00:20:37.100
Yeah, and have some dialogue

00:20:37.100 --> 00:20:37.620
like,

00:20:38.220 --> 00:20:39.180
I've got to hack the Gibson.

00:20:39.420 --> 00:20:39.740
Okay, done.

00:20:40.520 --> 00:20:40.920
Exactly.

00:20:41.160 --> 00:20:42.640
I need to fill up something computer.

00:20:43.020 --> 00:20:44.080
This is Visual Basic.

00:20:44.380 --> 00:20:45.100
I know Visual Basic.

00:20:45.240 --> 00:20:45.920
I know this, yeah.

00:20:45.920 --> 00:20:46.260
I'm going to get his IP address.

00:20:46.320 --> 00:20:47.100
It's like, what?

00:20:47.320 --> 00:20:47.400
Yeah.

00:20:47.980 --> 00:20:48.300
I don't know.

00:20:49.320 --> 00:20:49.760
Oh, boy.

00:20:49.980 --> 00:20:54.940
Anyway, I think this is a really, really cool example of pushing way, way, way beyond.

00:20:55.060 --> 00:20:57.200
This is a graphical user interface.

00:20:57.420 --> 00:20:59.260
This is not a textual user interface, right?

00:20:59.840 --> 00:21:00.160
Exactly.

00:21:00.580 --> 00:21:03.320
I mean, technically it is text, but it's also graphical.

00:21:03.780 --> 00:21:03.880
Yeah.

00:21:04.100 --> 00:21:04.280
Yeah.

00:21:04.540 --> 00:21:04.660
Yeah.

00:21:05.440 --> 00:21:07.560
So we have two things that you guys make.

00:21:08.060 --> 00:21:09.900
We've got textual and rich.

00:21:10.300 --> 00:21:12.040
And maybe it's worth talking about Rich for a moment

00:21:12.080 --> 00:21:13.080
since that's the foundation.

00:21:13.960 --> 00:21:14.160
Sure.

00:21:14.740 --> 00:21:17.760
Okay, so Rich basically formats data

00:21:18.020 --> 00:21:20.120
in a very pleasing-to-the-eye way.

00:21:21.340 --> 00:21:24.180
You can print, say, a Python dict,

00:21:24.600 --> 00:21:26.720
and it'll format with an indentation.

00:21:26.900 --> 00:21:28.260
It'll colorize strings and things.

00:21:29.160 --> 00:21:32.360
And you can print things like tables quite effortlessly,

00:21:33.020 --> 00:21:34.920
syntax-highlighted code,

00:21:35.720 --> 00:21:38.980
and you can use up to 16.7 million colors.

00:21:40.020 --> 00:21:43.320
Essentially, it was a toolkit to prettify terminal output

00:21:43.640 --> 00:21:46.660
with as little effort as possible.

00:21:47.220 --> 00:21:48.380
And it's all kind of

00:21:48.380 --> 00:21:49.640
integrated.

00:21:50.150 --> 00:21:53.800
So you can put syntax-highlighted text inside a table

00:21:54.220 --> 00:21:56.680
or a progress bar inside a cell.

00:21:56.870 --> 00:21:58.680
And everything kind of works together.

00:21:58.750 --> 00:22:00.420
So it's a single coherent system.

00:22:00.470 --> 00:22:03.240
Because some of this stuff existed prior to Rich.

00:22:04.000 --> 00:22:05.820
But they were written by different authors.

00:22:06.740 --> 00:22:08.340
And they weren't designed to work together.

00:22:09.300 --> 00:22:09.860
Maybe there's a

00:22:09.860 --> 00:22:11.900
table

00:22:11.900 --> 00:22:13.740
one by one person

00:22:13.960 --> 00:22:15.800
and then a progress bar by another,

00:22:15.980 --> 00:22:17.740
and they didn't really work the same or integrate

00:22:17.800 --> 00:22:18.640
or things like that, yeah?

00:22:19.400 --> 00:22:20.260
Exactly, exactly.

00:22:20.540 --> 00:22:25.720
So it meant that terminal output was still quite basic.

00:22:26.460 --> 00:22:29.380
When color was used, it would colorize a single line

00:22:29.800 --> 00:22:30.780
or something like that.

00:22:31.380 --> 00:22:31.740
And it still,

00:22:31.980 --> 00:22:32.780
it

00:22:32.780 --> 00:22:33.300
helped,

00:22:34.280 --> 00:22:36.840
but it wasn't great for parsing,

00:22:37.240 --> 00:22:38.280
visually parsing that information.

00:22:38.980 --> 00:22:41.240
but Rich gave you that ability

00:22:41.700 --> 00:22:42.640
that when you write output

00:22:43.060 --> 00:22:43.660
it is readable

00:22:44.580 --> 00:22:46.580
I think prior to that we developers

00:22:47.220 --> 00:22:48.920
kind of built up this skill

00:22:49.100 --> 00:22:50.880
of staring at monochrome

00:22:51.380 --> 00:22:52.740
text with funny characters

00:22:53.020 --> 00:22:54.860
and numbers and somehow

00:22:55.120 --> 00:22:56.880
pulling out meaningful information

00:22:57.380 --> 00:22:58.860
out of that and it took years to

00:22:59.260 --> 00:22:59.520
develop

00:23:00.659 --> 00:23:02.400
but hopefully now we don't need to

00:23:02.820 --> 00:23:04.960
because you can write things to the terminal

00:23:05.060 --> 00:23:06.899
that looks much like the output

00:23:06.920 --> 00:23:07.640
you'd get in a browser.

00:23:08.280 --> 00:23:10.680
It's formatted and readable and colorful.

00:23:11.060 --> 00:23:11.220
Yeah.

00:23:11.980 --> 00:23:13.860
You know, one thing that might be worth talking about

00:23:14.020 --> 00:23:17.720
is the live updates, like live tables and stuff.

00:23:18.160 --> 00:23:18.460
Yes.

00:23:18.920 --> 00:23:22.280
So in Rich you can create a live object.

00:23:22.520 --> 00:23:23.580
That's what the class is called.

00:23:23.670 --> 00:23:26.040
And basically it clears the screen

00:23:26.650 --> 00:23:27.660
and it writes that output

00:23:28.390 --> 00:23:29.940
and then you can refresh it.

00:23:30.660 --> 00:23:31.640
It can do that quickly,

00:23:32.390 --> 00:23:34.380
like 20 times a second or less,

00:23:35.240 --> 00:23:36.800
depending on how much data you've got.

00:23:36.860 --> 00:23:40.300
So you can create animations, you can create dashboards,

00:23:40.490 --> 00:23:41.460
you can create like

00:23:41.460 --> 00:23:42.660
a

00:23:42.660 --> 00:23:44.120
scrolling list of text.

00:23:44.510 --> 00:23:45.800
But it was kind of, it was limited.

00:23:46.700 --> 00:23:49.500
Because all it could do is update information regularly.

00:23:49.500 --> 00:23:50.300
It wasn't interactive.

00:23:50.820 --> 00:23:55.560
You couldn't click or scroll or even detect key presses.

00:23:55.860 --> 00:23:58.020
It was purely for updating information.

00:23:58.120 --> 00:24:00.900
It's kind of like a very rudimentary predecessor

00:24:00.900 --> 00:24:01.900
textual.

00:24:02.600 --> 00:24:06.180
Another thing that's interesting is what's the frame rate?

00:24:06.480 --> 00:24:08.180
of a terminal.

00:24:08.800 --> 00:24:11.260
People think of it just kind of scrolling text

00:24:11.500 --> 00:24:13.860
and printing out text, and you see it kind of going by,

00:24:13.980 --> 00:24:17.020
and you're like, well, that's kind of how the UIs must be.

00:24:17.200 --> 00:24:19.620
But you can actually push these things pretty far, right?

00:24:19.840 --> 00:24:20.940
You can.

00:24:21.640 --> 00:24:23.360
The interesting thing is I don't think anyone

00:24:24.100 --> 00:24:25.680
who sat down to develop a terminal

00:24:26.500 --> 00:24:29.360
was thinking in terms of frames per second.

00:24:30.880 --> 00:24:34.979
They were just, they want to optimize the text output

00:24:35.000 --> 00:24:39.300
So that if you cut a large file, it didn't take forever to scroll through.

00:24:39.720 --> 00:24:41.860
Right, or didn't flicker around or something, yeah.

00:24:42.140 --> 00:24:42.860
Yeah, yeah.

00:24:43.120 --> 00:24:49.220
And later on, people like myself and others were creating animations and things.

00:24:49.680 --> 00:24:51.860
And they're thinking, well, how fast can I push this?

00:24:52.340 --> 00:24:53.540
And it turns out pretty fast.

00:24:54.620 --> 00:24:59.080
Because terminals use your GPU to render the text.

00:25:00.220 --> 00:25:03.940
And if you send a text fast enough, it'll keep up, mostly.

00:25:04.560 --> 00:25:08.140
And I found that 60 frames a second is completely workable

00:25:08.140 --> 00:25:08.900
on

00:25:08.900 --> 00:25:09.740
most terminals.

00:25:11.360 --> 00:25:13.400
You don't really need that for most apps

00:25:14.640 --> 00:25:18.520
because if you're scrolling text, you can only move character at a time.

00:25:18.880 --> 00:25:21.840
It's not pictal perfect because it's kind of like a grid.

00:25:23.360 --> 00:25:25.640
So if you want to scroll at 60 frames a second,

00:25:25.820 --> 00:25:28.120
you'd have to move 60 lines in a second,

00:25:28.860 --> 00:25:29.900
with which text would just kind of

00:25:29.900 --> 00:25:30.760
whiz by.

00:25:31.040 --> 00:25:31.960
Yeah, it gets blurry

00:25:31.960 --> 00:25:32.260
anyway.

00:25:32.800 --> 00:25:35.680
Yeah, so it can do 60 frames a second,

00:25:35.860 --> 00:25:37.980
which is sometimes fun for animation effects,

00:25:39.180 --> 00:25:40.220
but generally you don't need it.

00:25:41.000 --> 00:25:43.200
You can update 10 frames a second,

00:25:43.740 --> 00:25:45.700
and it'll look nice and smooth.

00:25:46.340 --> 00:25:47.360
But it's nice to know that you can.

00:25:47.760 --> 00:25:48.820
We've got a ridiculous demo,

00:25:49.680 --> 00:25:51.820
which creates a really colorful gradient

00:25:52.350 --> 00:25:54.660
and then rotates it at 60 frames a second.

00:25:55.120 --> 00:25:55.380
Wow.

00:25:56.500 --> 00:25:57.220
It looks very cool.

00:25:57.420 --> 00:25:59.220
It would be terrible in an actual app

00:25:59.430 --> 00:26:00.160
because it'd

00:26:00.160 --> 00:26:01.020
just burn your retina,

00:26:01.780 --> 00:26:02.740
but it is possible.

00:26:03.720 --> 00:26:03.920
Yeah.

00:26:04.600 --> 00:26:08.500
Reminds me of the early days when computers just started having VGA and stuff

00:26:08.620 --> 00:26:09.920
and people would come out with amazing

00:26:09.920 --> 00:26:11.340
graphical,

00:26:12.060 --> 00:26:13.000
what do they call them?

00:26:13.080 --> 00:26:14.100
I can't remember what they call them.

00:26:14.660 --> 00:26:15.220
Demos and things?

00:26:15.620 --> 00:26:16.960
I think I was thinking demos as well.

00:26:17.120 --> 00:26:18.200
Yeah, I think that is what they call them.

00:26:18.300 --> 00:26:21.160
And we would download them off of BBSs and watch them.

00:26:21.200 --> 00:26:23.299
We're just like, wow, it's so good on my 486DX.

00:26:23.980 --> 00:26:25.560
I can't believe it could do it.

00:26:25.620 --> 00:26:26.340
It's so smooth.

00:26:27.380 --> 00:26:28.820
They were amazing, right?

00:26:29.180 --> 00:26:29.980
Similar deal with the

00:26:29.980 --> 00:26:30.120
terminals.

00:26:30.440 --> 00:26:39.180
The manufacturer of those devices back then probably didn't have graphical animations or games in mind when they were building

00:26:39.180 --> 00:26:40.280
those

00:26:40.280 --> 00:26:40.700
computers.

00:26:40.780 --> 00:26:45.660
But then you got some interested parties who were willing to experiment and they actually managed to

00:26:45.660 --> 00:26:46.700
make

00:26:46.700 --> 00:26:49.600
it do things, which the manufacturer just never intended.

00:26:49.740 --> 00:26:50.620
The same thing with the terminal.

00:26:51.580 --> 00:26:56.920
No one ever sat down and created a system to display 16.7 million colors at 60 frames a second.

00:26:57.700 --> 00:27:00.980
It was other people that just tried that and got it to work.

00:27:01.080 --> 00:27:05.960
So there's an amazing amount of creativity and freedom in working and stuff like that,

00:27:06.260 --> 00:27:09.100
which I kind of missed from the old days because now computers are so fast and so powerful.

00:27:09.100 --> 00:27:09.440
I know.

00:27:09.740 --> 00:27:11.220
People don't have to even worry about it, do they?

00:27:14.520 --> 00:27:16.140
I want to kind of work through this.

00:27:16.300 --> 00:27:21.780
You have this live demo, the official textual demo, which you can still...

00:27:22.140 --> 00:27:22.500
Let me go.

00:27:22.540 --> 00:27:23.660
I think I have it in the next...

00:27:23.660 --> 00:27:23.700
No.

00:27:24.460 --> 00:27:25.340
If I click on it,

00:27:25.520 --> 00:27:26.520
it

00:27:26.520 --> 00:27:27.280
tells me how to get it.

00:27:28.400 --> 00:27:32.580
props for the install step here, the uvx.

00:27:32.720 --> 00:27:34.060
Are you a uv convert?

00:27:34.160 --> 00:27:35.620
Are you a uv fan these days?

00:27:36.120 --> 00:27:37.360
I am a fan.

00:27:37.680 --> 00:27:40.140
Yeah, I mean, that I think is a killer app

00:27:40.140 --> 00:27:43.000
that you can send someone a fairly short command line

00:27:43.000 --> 00:27:44.580
and they can run your project.

00:27:45.980 --> 00:27:48.920
The Python, it says --Python 3.12.

00:27:50.400 --> 00:27:52.140
That was because at the time,

00:27:52.440 --> 00:27:56.380
it wouldn't install a version of Python that it can run on.

00:27:56.600 --> 00:27:58.220
I think Astro's working on that.

00:27:58.280 --> 00:27:59.560
So I think in the future, maybe now,

00:28:00.100 --> 00:28:02.780
you could just do uvx textual-demo,

00:28:03.340 --> 00:28:05.140
and then it would just run.

00:28:05.860 --> 00:28:08.040
But even so, I think that's a beautiful way

00:28:08.100 --> 00:28:10.700
of allowing people to test your code

00:28:10.840 --> 00:28:11.840
with very little barriers.

00:28:13.120 --> 00:28:13.520
Yeah,

00:28:13.640 --> 00:28:15.080
especially the script stuff now.

00:28:16.000 --> 00:28:17.040
You can just use the script and

00:28:17.040 --> 00:28:17.680
put the dependencies

00:28:17.820 --> 00:28:21.260
at the top and just say uv run.

00:28:21.520 --> 00:28:22.660
I can't remember the exact syntax,

00:28:22.880 --> 00:28:25.199
but basically you can embed what it needs to run

00:28:25.220 --> 00:28:27.020
just as a comment and it'll run.

00:28:27.580 --> 00:28:28.000
That's excellent.

00:28:28.320 --> 00:28:29.720
It's no harder than it needs to be,

00:28:30.030 --> 00:28:31.160
which is great.

00:28:31.480 --> 00:28:32.580
It's very clear what it does

00:28:33.020 --> 00:28:34.420
and it works very well.

00:28:34.540 --> 00:28:35.920
It's the kind of computing that you want.

00:28:36.480 --> 00:28:37.960
You don't want to have to send someone

00:28:38.100 --> 00:28:38.940
a page of instructions

00:28:39.800 --> 00:28:41.440
and say, go and download this software

00:28:41.910 --> 00:28:43.640
and then write this into your configuration file.

00:28:44.020 --> 00:28:45.120
Yeah, that's just a headache.

00:28:45.480 --> 00:28:46.920
I don't want to deal with that ever again.

00:28:47.110 --> 00:28:49.400
I just want to send people what uvx, blah, and then done.

00:28:49.740 --> 00:28:50.160
I agree.

00:28:50.690 --> 00:28:51.060
I agree.

00:28:52.220 --> 00:28:53.160
If you have uvx,

00:28:53.260 --> 00:28:54.200
you're good to go, right?

00:28:55.280 --> 00:28:56.540
and you don't even have to have Python

00:28:56.880 --> 00:28:58.900
and you also don't have to worry about the version of Python.

00:28:59.100 --> 00:28:59.940
So these are all good things.

00:29:00.460 --> 00:29:03.540
So let's run it and let's see what happens here.

00:29:04.180 --> 00:29:05.960
There's a lot going on in this demo.

00:29:06.640 --> 00:29:08.460
Chris May out in the audience gives you props

00:29:08.580 --> 00:29:10.440
for making it so easy to run.

00:29:10.700 --> 00:29:14.660
And Hugo says, I can drop, I can drop the Python.

00:29:15.120 --> 00:29:18.260
As you imagined, I can just say uvx textual demo

00:29:18.380 --> 00:29:19.420
and I'll probably get 13.1.

00:29:19.760 --> 00:29:21.140
Let's see, something's happening.

00:29:21.440 --> 00:29:23.620
I think it worked if you had that version of Python.

00:29:24.240 --> 00:29:27.480
But if you didn't have the correct version of Python, it would sometimes fail.

00:29:28.020 --> 00:29:28.400
Got it.

00:29:28.640 --> 00:29:29.220
Maybe they fixed it.

00:29:29.500 --> 00:29:29.560
Yeah.

00:29:29.920 --> 00:29:30.040
Maybe.

00:29:30.500 --> 00:29:30.640
Maybe.

00:29:31.640 --> 00:29:37.400
So when this thing pulls up, it looks very much like a web browser.

00:29:38.180 --> 00:29:44.680
With the main difference, I think, that there's not a lot of pictures, as in true graphics, right?

00:29:44.900 --> 00:29:54.040
But if you imagine like a really nicely styled website that maybe used color and emoji and CSS, but just white on graphics, right?

00:29:54.160 --> 00:29:56.760
I feel like, would you say that's kind of the extent?

00:29:57.120 --> 00:29:57.520
It is.

00:29:57.620 --> 00:30:01.420
It's kind of like a minimal web interface that focuses on typography.

00:30:02.140 --> 00:30:03.620
That's not a potential because you've only got one

00:30:03.620 --> 00:30:03.980
font.

00:30:04.440 --> 00:30:05.180
Yeah, yeah, yeah.

00:30:05.480 --> 00:30:06.360
Exactly, you can't.

00:30:06.860 --> 00:30:07.000
Yeah.

00:30:07.960 --> 00:30:11.540
But as we'll see, you can actually do graphics pretty well.

00:30:12.460 --> 00:30:15.200
Yeah, if you see the numbers up at the top,

00:30:16.340 --> 00:30:17.720
there's nothing in the terminal that's placed.

00:30:18.060 --> 00:30:19.420
Most people are saying they won't know,

00:30:19.440 --> 00:30:22.240
but at the top it says version, then it says 100,

00:30:22.300 --> 00:30:24.820
GitHub stars 27.2 thousand

00:30:25.460 --> 00:30:26.500
how many forks and so on

00:30:26.500 --> 00:30:28.160
but those are colored differently

00:30:28.240 --> 00:30:28.860
they look different

00:30:29.140 --> 00:30:30.060
okay now tell us about the numbers

00:30:30.400 --> 00:30:32.080
yeah sure so they're taller

00:30:32.520 --> 00:30:34.140
and wider than the rest of the text

00:30:34.380 --> 00:30:37.220
but there is no alternative font

00:30:37.560 --> 00:30:38.040
in the terminal

00:30:38.280 --> 00:30:40.660
those numbers are made up of other characters

00:30:41.360 --> 00:30:42.380
box drawing characters

00:30:42.420 --> 00:30:44.200
so you've got like a vertical line

00:30:44.200 --> 00:30:45.120
a horizontal line

00:30:45.480 --> 00:30:47.400
you've got a curved corner

00:30:47.740 --> 00:30:48.940
you've got like a T section

00:30:49.380 --> 00:30:50.559
and you can assemble that

00:30:50.800 --> 00:30:53.600
and make it display something that looks like numbers.

00:30:53.820 --> 00:30:56.580
It does look like numbers.

00:30:56.620 --> 00:30:57.020
You've got the

00:30:57.020 --> 00:30:58.980
little subscript for the thousands,

00:30:59.380 --> 00:31:00.160
the kilo

00:31:00.160 --> 00:31:02.300
stars, I don't know.

00:31:03.620 --> 00:31:05.600
If I remember correctly, it's a two by three,

00:31:06.020 --> 00:31:08.420
no, sorry, three by three grid of characters.

00:31:09.400 --> 00:31:12.400
And I had to hand edit this in Python

00:31:13.120 --> 00:31:16.060
by cut and pasting the box characters from Wikipedia

00:31:16.680 --> 00:31:18.160
to assemble numbers.

00:31:18.840 --> 00:31:20.300
And I discovered the numbers work quite well.

00:31:20.400 --> 00:31:26.080
numbers look like numbers and i've also got hex digits so a b c d e f

00:31:26.080 --> 00:31:26.820
um

00:31:26.820 --> 00:31:28.240
i tried to keep going

00:31:28.340 --> 00:31:34.400
but i found that some characters didn't work at all um like an x there's no diagonal cross piece

00:31:34.440 --> 00:31:41.240
in these uh unicode characters so it's an x just became impossible with a three by three grid um

00:31:41.760 --> 00:31:44.940
but for numbers it works beautifully yeah yeah very interesting a

00:31:44.940 --> 00:31:46.559
little bit like a classical

00:31:46.580 --> 00:31:48.080
alarm clock where the numbers

00:31:48.820 --> 00:31:50.020
like a seven digit display.

00:31:50.600 --> 00:31:51.180
Yes, exactly.

00:31:51.810 --> 00:31:51.940
Yeah.

00:31:53.890 --> 00:31:54.040
Cool.

00:31:54.800 --> 00:31:55.020
All right.

00:31:55.310 --> 00:31:57.120
So if you run the demo,

00:31:57.590 --> 00:31:59.580
it comes up with comments

00:31:59.750 --> 00:32:01.600
that show you or sort of a

00:32:02.000 --> 00:32:03.160
walkthrough of what's possible

00:32:03.550 --> 00:32:04.260
in these little boxes.

00:32:04.410 --> 00:32:05.400
And it says, look, you can go

00:32:05.820 --> 00:32:06.400
and scroll it.

00:32:06.470 --> 00:32:07.980
You scroll with your mouse.

00:32:08.760 --> 00:32:10.560
You know, it scrolls that section.

00:32:10.980 --> 00:32:12.480
It says you want to go to the next one.

00:32:13.260 --> 00:32:13.720
Hit tab.

00:32:14.040 --> 00:32:15.020
Hit enter to open it up.

00:32:15.680 --> 00:32:18.020
It's, even though, kind of like we were talking,

00:32:18.180 --> 00:32:19.640
even though it's a user interface,

00:32:20.020 --> 00:32:21.960
like with scroll bars and I can grab the scroll bar

00:32:22.160 --> 00:32:24.880
and go to it and I can click on the things and so on,

00:32:25.500 --> 00:32:27.940
it's also very keyboard friendly, right?

00:32:28.040 --> 00:32:29.540
This is probably a super important aspect

00:32:29.920 --> 00:32:33.060
of building these types of applications in the terminal

00:32:33.240 --> 00:32:34.320
because people expect that, right?

00:32:34.520 --> 00:32:35.580
Yeah, very much so.

00:32:35.680 --> 00:32:39.260
So a lot of text was inspired by web development

00:32:39.400 --> 00:32:41.460
because I was a web developer for many years.

00:32:41.860 --> 00:32:42.860
And there's a lot of work being done

00:32:42.860 --> 00:32:44.680
in interfaces in the web world.

00:32:45.580 --> 00:32:48.600
Lots of work, you know, loads of developers working on it for years.

00:32:49.460 --> 00:32:50.920
I wanted to bring some of that to Terminal,

00:32:51.160 --> 00:32:54.480
but I also didn't want to lose what made the Terminal interesting.

00:32:55.900 --> 00:32:58.720
Terminal is a very keyboard-focused thing,

00:32:59.420 --> 00:33:02.640
so I wanted textual apps to also be very keyboard-focused.

00:33:03.300 --> 00:33:05.620
The mouse is terrific for discovering things.

00:33:06.310 --> 00:33:08.440
You know, you can move it around and there's tooltips, etc.

00:33:09.120 --> 00:33:11.200
You can click those links or you can press the key.

00:33:12.200 --> 00:33:14.180
But if you want to, if you use an app regularly,

00:33:14.400 --> 00:33:15.840
you'll want to learn the keys.

00:33:16.680 --> 00:33:17.320
So it is very focused.

00:33:17.470 --> 00:33:19.920
You can use the keyboard for everything.

00:33:21.020 --> 00:33:24.120
In the footer, that displays all the main keys.

00:33:24.640 --> 00:33:26.400
You can also use tab and shift tab

00:33:26.470 --> 00:33:28.120
to move around various elements.

00:33:28.660 --> 00:33:29.700
You can use up, down to scroll.

00:33:31.100 --> 00:33:33.680
So you could get by without ever using the term,

00:33:34.040 --> 00:33:35.500
without ever using the mouse.

00:33:36.780 --> 00:33:38.760
And it's there if you need it,

00:33:38.900 --> 00:33:39.620
but you don't have to.

00:33:39.800 --> 00:33:40.720
Yeah, that's incredible.

00:33:41.460 --> 00:33:42.740
It's got code highlighting.

00:33:43.800 --> 00:33:45.080
It's got a lot of different things.

00:33:46.060 --> 00:33:47.840
For people who maybe want to get started with this,

00:33:48.140 --> 00:33:50.340
I think there's two, let's say three,

00:33:50.940 --> 00:33:52.320
three things that are worth looking at.

00:33:52.400 --> 00:33:55.140
One, you actually, you said you were a web developer,

00:33:55.420 --> 00:33:57.600
so you must have been a fan of View Source, right?

00:33:57.820 --> 00:33:58.160
Oh, yeah.

00:33:58.520 --> 00:34:00.840
So you added, you basically added View Source.

00:34:01.200 --> 00:34:01.780
That's right, yeah.

00:34:01.900 --> 00:34:05.400
You type C, it says so at the bottom,

00:34:05.540 --> 00:34:07.920
and that pulls up the source of the current page,

00:34:08.000 --> 00:34:10.280
just like you would at my website or any website, right?

00:34:10.520 --> 00:34:13.760
Yeah, I want people to realize that the code behind that

00:34:13.899 --> 00:34:18.820
not that complex but textual it looks like complex um what you're viewing at the moment is actually

00:34:19.220 --> 00:34:24.100
markdown um which you might think that's quite hard to render markdown in the terminal and well

00:34:24.100 --> 00:34:29.780
it is but we've done it for you so um you just embed a widget and somewhere in the code it'll

00:34:29.919 --> 00:34:36.040
say yield markdown and then it'll have the contents and it renders markdown you see there's a code

00:34:36.200 --> 00:34:37.520
block there with syntax highlight code

00:34:37.520 --> 00:34:41.100
yeah well that's the magic of of these libraries right it's

00:34:41.060 --> 00:34:43.980
hard once for you and then it's easy for other people.

00:34:44.440 --> 00:34:46.060
Yeah. We suffer so you don't have to.

00:34:46.820 --> 00:34:53.159
Exactly. I feel like the most, the biggest example of that in the Python space is Jupyter Notebooks,

00:34:53.620 --> 00:34:58.020
right? All that interactivity and all that stuff, people are writing TypeScript and JavaScript and

00:34:58.540 --> 00:35:03.900
all these kinds of things, you know, it's for, you know, Plotly and other plotting UI things.

00:35:04.140 --> 00:35:10.180
And that's so Python people can write Python code and not write, you know, they're not creating

00:35:10.200 --> 00:35:12.020
websites are just typing in a notebook and they get

00:35:12.180 --> 00:35:13.780
interactive things, right? But that's

00:35:14.120 --> 00:35:15.820
probably the biggest take one for the team

00:35:16.150 --> 00:35:16.640
sort of deal.

00:35:16.800 --> 00:35:18.140
Yeah, there's a lot of work

00:35:18.620 --> 00:35:19.360
under the hood.

00:35:20.200 --> 00:35:21.180
A lot of people that use

00:35:22.080 --> 00:35:24.120
Jupyter Notebooks, that's their only

00:35:24.460 --> 00:35:26.120
knowledge of Python. They think Python is

00:35:26.240 --> 00:35:27.340
Jupyter and Jupyter is Python.

00:35:28.680 --> 00:35:30.340
And that's fine. It's a tool

00:35:30.720 --> 00:35:32.260
and it gives them access to

00:35:32.580 --> 00:35:34.300
all this stuff which would be very hard

00:35:34.440 --> 00:35:34.540
otherwise.

00:35:35.010 --> 00:35:36.320
So yeah, I think Jupyter

00:35:36.400 --> 00:35:37.600
is a great example of that.

00:35:38.520 --> 00:35:39.380
Out in the audience,

00:35:40.140 --> 00:35:43.960
And we have David points out JPTerm.

00:35:43.980 --> 00:35:45.100
Are you familiar with JPTerm?

00:35:45.460 --> 00:35:45.720
Yes.

00:35:46.120 --> 00:35:47.140
Is that David Brokert?

00:35:47.460 --> 00:35:48.100
Yeah, yeah, yeah.

00:35:48.400 --> 00:35:55.000
The successor of MBTerm, and it's Jupyter, Jupyter Lab in the terminal.

00:35:55.420 --> 00:35:55.700
Yeah.

00:35:56.580 --> 00:35:57.020
It's gone

00:35:57.020 --> 00:35:57.560
full circle.

00:35:59.060 --> 00:36:00.840
It's like the Inception movie.

00:36:02.520 --> 00:36:03.000
It

00:36:03.000 --> 00:36:03.760
really is, right?

00:36:04.060 --> 00:36:06.360
But you can embed the textual app inside Jupyter.

00:36:07.020 --> 00:36:10.880
So you could have Jterm working in a textual app inside Jupyter

00:36:11.420 --> 00:36:12.960
that's also displaying another notebook.

00:36:13.860 --> 00:36:14.000
Yeah.

00:36:16.060 --> 00:36:16.200
Incredible.

00:36:17.480 --> 00:36:17.720
All right.

00:36:18.020 --> 00:36:23.320
So if we go to the terminal where I got this running,

00:36:23.720 --> 00:36:25.640
and anyone else out there listening wants to check this out,

00:36:25.640 --> 00:36:26.440
you just run it.

00:36:26.700 --> 00:36:30.420
And I was starting to say there's three places you should check out

00:36:30.600 --> 00:36:33.520
before I got kind of starstruck with view code.

00:36:34.260 --> 00:36:34.360
Okay.

00:36:34.860 --> 00:36:35.660
So I think there's

00:36:35.660 --> 00:36:36.720
probably

00:36:36.720 --> 00:36:39.120
the best place to get started is to look at the widgets.

00:36:39.600 --> 00:36:44.780
I don't know what you think, but just like, well, what can this framework do in terms of what are the building blocks that you can look at the widgets?

00:36:45.660 --> 00:36:52.520
And then once you decide, okay, this is pretty interesting, I think people should check out the projects because there are some pretty interesting things.

00:36:52.550 --> 00:36:55.680
I know we've covered them on Python bytes that are built on top of textual.

00:36:56.010 --> 00:36:59.960
And then just to talk about the graphics, what is

00:36:59.960 --> 00:37:01.060
this game?

00:37:01.540 --> 00:37:04.100
This is a game in inverted commas.

00:37:05.080 --> 00:37:05.980
it's got different names

00:37:07.300 --> 00:37:08.440
sliding tile puzzle

00:37:08.920 --> 00:37:10.900
I think is the most common thing, you've probably seen it before

00:37:11.900 --> 00:37:12.860
you've got a square

00:37:13.140 --> 00:37:14.820
the square is made up of lots of little tiles

00:37:14.960 --> 00:37:16.620
and there's one space and you can move a

00:37:17.140 --> 00:37:18.500
square into that one space

00:37:19.080 --> 00:37:20.680
and the goal is to reassemble

00:37:21.160 --> 00:37:22.880
the image, but for here

00:37:23.300 --> 00:37:24.700
I've used code

00:37:25.080 --> 00:37:26.900
so you've got all these tiles with code on it

00:37:26.960 --> 00:37:28.240
and you've got to reassemble it

00:37:29.100 --> 00:37:30.840
into actual working code

00:37:31.000 --> 00:37:32.960
which I think is what most people think

00:37:32.980 --> 00:37:35.920
developers do. This is how we make code, just by

00:37:35.920 --> 00:37:36.960
sliding

00:37:36.960 --> 00:37:37.720
these tiles around.

00:37:38.100 --> 00:37:43.380
Yeah. I remember one of my daughters, I can't remember which one, saw me typing out code.

00:37:43.640 --> 00:37:47.560
And she's like, what are you doing? What is that? I'm working on this project, this program,

00:37:47.900 --> 00:37:50.460
this website. That's what websites look like. Okay.

00:37:51.860 --> 00:37:55.800
Yeah. My wife calls it the gibberish. She says, are you working on the gibberish? Yeah, I am.

00:37:57.180 --> 00:37:57.900
That's incredible.

00:37:58.080 --> 00:38:02.940
That's an amazing way to put it. Yeah. You know, I was just thinking the other

00:38:02.960 --> 00:38:05.620
the incredible power of text, right?

00:38:05.840 --> 00:38:08.780
You think of all these systems, the internet, Linux,

00:38:09.400 --> 00:38:11.540
configuration, source code, design,

00:38:11.840 --> 00:38:14.060
all of that is just words, right?

00:38:14.200 --> 00:38:16.780
It's not working with GUIs and all that stuff.

00:38:16.920 --> 00:38:17.780
It's just typing.

00:38:17.900 --> 00:38:18.640
Text is, yeah,

00:38:18.920 --> 00:38:19.400
very important.

00:38:19.520 --> 00:38:22.260
I quite like websites that skew graphics

00:38:22.440 --> 00:38:25.580
and have just kind of like typography-based thing.

00:38:26.680 --> 00:38:29.660
I find you can more easily extract the information you need.

00:38:30.380 --> 00:38:31.900
But most websites these days you go to

00:38:31.980 --> 00:38:34.500
and loads of ads, loads of image,

00:38:34.830 --> 00:38:35.540
they pop in and out.

00:38:35.840 --> 00:38:37.900
The text seems almost secondary.

00:38:39.000 --> 00:38:42.420
So I'm a big fan of just text in general.

00:38:43.000 --> 00:38:43.640
Yeah, same.

00:38:44.740 --> 00:38:45.780
All right, so people can play the game.

00:38:46.260 --> 00:38:47.280
That's kind of interesting, right?

00:38:47.400 --> 00:38:50.080
Like I said, I think where maybe it's more interesting

00:38:50.440 --> 00:38:51.860
is talking about the widgets.

00:38:52.510 --> 00:38:53.760
And when I look at this, you know,

00:38:53.860 --> 00:38:56.280
what this reminds me of is it reminds me of

00:38:56.380 --> 00:38:57.920
if I were to go over here and type Bulma

00:38:58.400 --> 00:39:01.740
and go, which Bulma is very refreshing.

00:39:01.800 --> 00:39:05.180
CSS framework that doesn't require build tools

00:39:05.500 --> 00:39:09.080
and shaking and webpack and all that junk.

00:39:10.100 --> 00:39:11.160
Or like Tailwind.

00:39:11.900 --> 00:39:13.600
Tailwind is kind of a pain to work with,

00:39:13.800 --> 00:39:16.080
but it's also super beautiful, right?

00:39:16.420 --> 00:39:18.900
When I look at this, the widgets,

00:39:19.440 --> 00:39:21.520
it feels very much similar to that, right?

00:39:21.600 --> 00:39:23.200
I'm sure people have checked out CSS frameworks.

00:39:23.780 --> 00:39:24.980
Yeah, that's...

00:39:25.180 --> 00:39:26.240
Yeah, tell us about it.

00:39:26.800 --> 00:39:29.400
Yeah, so I mean, you know, again, coming from the web,

00:39:30.460 --> 00:39:32.860
I want to have a web-like experience.

00:39:33.140 --> 00:39:34.200
Because everybody's familiar with the web.

00:39:34.440 --> 00:39:36.180
It's like you can sit someone down on a website

00:39:36.300 --> 00:39:37.000
and they'll be able to use it.

00:39:37.320 --> 00:39:38.980
I wanted the same thing for terminal apps.

00:39:40.520 --> 00:39:42.640
You know, some terminal apps have a bad reputation

00:39:42.780 --> 00:39:45.020
and have been hard to use, and it's mostly deserved.

00:39:45.580 --> 00:39:47.220
Like, you know, how do you quit Vim?

00:39:48.020 --> 00:39:48.960
It's a running joke.

00:39:50.200 --> 00:39:51.080
I don't know how to quit Vim.

00:39:51.100 --> 00:39:52.080
You reboot your computer.

00:39:52.580 --> 00:39:53.320
Everybody knows that.

00:39:53.620 --> 00:39:53.880
Come on.

00:39:54.560 --> 00:39:54.880
Exactly.

00:39:55.080 --> 00:39:58.920
I wanted, like, an interface that people were very, very familiar with.

00:40:00.660 --> 00:40:01.800
this is actually in alphabetical order

00:40:02.040 --> 00:40:03.920
but I think buttons was actually one of the first

00:40:04.020 --> 00:40:04.580
thing I developed

00:40:05.980 --> 00:40:07.540
because the terminal doesn't give you

00:40:08.140 --> 00:40:09.680
anything for free, the terminal is just

00:40:10.040 --> 00:40:11.780
text with escape sequences

00:40:12.020 --> 00:40:13.960
for colour and style

00:40:14.160 --> 00:40:15.260
like italic, bold etc

00:40:16.340 --> 00:40:18.080
but there's no escape sequence for a button

00:40:18.320 --> 00:40:19.720
the most simplest atomic

00:40:20.280 --> 00:40:21.160
user interface thing

00:40:21.680 --> 00:40:23.800
a button with a bit of text that you click

00:40:23.940 --> 00:40:25.860
there's nothing in the terminal spec

00:40:25.980 --> 00:40:28.319
for that, so you have to start from scratch

00:40:28.340 --> 00:40:32.180
and we built this button that looks buttony.

00:40:32.560 --> 00:40:34.480
It even has a 3D

00:40:34.480 --> 00:40:35.840
sort of raised

00:40:35.840 --> 00:40:36.240
effect

00:40:36.240 --> 00:40:36.700
and stuff.

00:40:37.400 --> 00:40:39.220
Yeah, so there's a lighter color at the top

00:40:39.260 --> 00:40:40.260
and a darker color at the bottom,

00:40:40.700 --> 00:40:44.359
and it looks like a classic Windows raised button.

00:40:45.020 --> 00:40:47.620
Imagine if this light is coming from the top

00:40:47.760 --> 00:40:48.940
and illuminating the top edge.

00:40:50.560 --> 00:40:52.100
Some people don't like them.

00:40:53.120 --> 00:40:55.640
I think one of the reasons is it has to take up three characters.

00:40:55.740 --> 00:40:58.260
In order to get that effect, you have to take up three lines.

00:40:59.460 --> 00:41:01.520
So it creates quite a chunky button.

00:41:01.760 --> 00:41:03.660
It looks like a button, but it's chunky.

00:41:04.320 --> 00:41:07.960
But you can style it very trivially to be one line long,

00:41:08.200 --> 00:41:11.120
so your button can just be as tall as it needs to be.

00:41:11.320 --> 00:41:11.540
Nice.

00:41:12.300 --> 00:41:14.680
Yeah, these are great, and we've got other things.

00:41:14.820 --> 00:41:16.160
I was thinking as you were talking about

00:41:16.160 --> 00:41:17.800
primitives you have to work with,

00:41:17.980 --> 00:41:22.720
I was thinking of pretty much every 3D rendered thing that people see,

00:41:22.880 --> 00:41:25.700
video games and others as well, animations.

00:41:26.180 --> 00:41:26.720
They're just triangles.

00:41:27.640 --> 00:41:30.380
There's just a bunch of triangles, which is so insane that you think,

00:41:30.440 --> 00:41:32.000
that thing that looks like a real forest,

00:41:32.540 --> 00:41:34.780
every single thing on the screen is some weird triangle

00:41:35.280 --> 00:41:37.060
with a texture and stuff applied to it.

00:41:37.320 --> 00:41:38.080
But a lot of triangles.

00:41:38.640 --> 00:41:39.040
Lots.

00:41:39.680 --> 00:41:42.840
You can't think too hard about how fast things are happening

00:41:42.880 --> 00:41:44.700
on graphics cards because your mind will melt.

00:41:44.820 --> 00:41:46.140
It's like there's so much going on.

00:41:47.020 --> 00:41:47.740
You've got check boxes.

00:41:48.180 --> 00:41:48.560
Is it all?

00:41:49.680 --> 00:41:50.240
Radio buttons.

00:41:50.700 --> 00:41:52.560
Radio buttons, which are great.

00:41:52.660 --> 00:42:17.300
A lot of the things that people might think about, data tables, you know, this is, if you're doing data science, I think one of the things worth talking about, because when we talk about some of the performance things, there's a lot of this within that within that, right? Like, like in your data table. So this whole UI, I can scroll up and down and see all the different widgets. But then when I get to the data table section, I can scroll horizontally and vertically within the data table itself,

00:42:18.020 --> 00:42:18.140
right?

00:42:18.200 --> 00:42:21.420
You can also press Control-A, and that'll maximize it.

00:42:21.680 --> 00:42:22.120
Oh, yeah.

00:42:22.540 --> 00:42:22.960
Very cool.

00:42:23.020 --> 00:42:23.920
I didn't even know about that.

00:42:24.140 --> 00:42:25.560
Yeah, this is a nice feature,

00:42:26.160 --> 00:42:28.880
which I think websites should have and GUIs in general.

00:42:29.260 --> 00:42:30.480
I remember Windows used to suffer from this.

00:42:30.580 --> 00:42:32.620
You'd get like a dialog where you had to enter a lot of text,

00:42:32.820 --> 00:42:34.660
but the dialog was this size,

00:42:35.400 --> 00:42:37.160
and you weren't allowed to resize it.

00:42:37.300 --> 00:42:38.180
You can't resize it.

00:42:39.100 --> 00:42:39.200
Yeah.

00:42:39.580 --> 00:42:41.940
Or you tap over and hope you hit the right button that you can't see.

00:42:42.260 --> 00:42:42.560
Yeah.

00:42:42.960 --> 00:42:45.800
So I added a shortcut key,

00:42:45.920 --> 00:42:48.060
which can maximize anything which is focused.

00:42:48.100 --> 00:42:50.280
can make it resize it to the size of the screen.

00:42:51.680 --> 00:42:51.860
Nice.

00:42:52.110 --> 00:42:52.220
Okay.

00:42:52.560 --> 00:42:55.740
In the interest of time, let's go and talk about projects real quick.

00:42:56.360 --> 00:43:01.620
I think one of the things that probably can inspire people a lot is some of these projects

00:43:02.200 --> 00:43:02.320
here.

00:43:02.480 --> 00:43:06.980
If you go to the project section, you've got a couple that are super nice here.

00:43:07.140 --> 00:43:12.580
For example, I would say this posting I know by Darren Burns is pretty interesting.

00:43:13.040 --> 00:43:14.340
This is like postman, right?

00:43:14.440 --> 00:43:16.760
Like an HTTP client, but entirely in your terminal.

00:43:16.930 --> 00:43:17.720
 tell people about this.

00:43:17.880 --> 00:43:18.220
is great.

00:43:18.520 --> 00:43:19.540
Yeah, so this is something that

00:43:19.840 --> 00:43:21.780
Darren Burns built and he's

00:43:21.840 --> 00:43:23.800
a developer of, one of the

00:43:23.860 --> 00:43:25.780
developers, and he made a fantastic job of this.

00:43:25.840 --> 00:43:27.540
This is not a textualized project

00:43:28.050 --> 00:43:29.920
but basically it's Postman

00:43:30.060 --> 00:43:31.040
which is a tool for making

00:43:32.099 --> 00:43:33.840
HTTP requests. You might

00:43:33.960 --> 00:43:35.740
use it if you're developing an API

00:43:35.870 --> 00:43:37.200
and you want to experiment

00:43:37.800 --> 00:43:39.500
and you don't want to have to build all the tooling

00:43:39.880 --> 00:43:41.760
to talk to your API. You can just go straight

00:43:41.880 --> 00:43:43.900
into this interface and experiment

00:43:44.430 --> 00:43:45.340
and play around with it.

00:43:45.640 --> 00:43:46.820
I did that two days ago.

00:43:47.680 --> 00:43:50.280
Yeah, and it's super useful.

00:43:50.660 --> 00:43:51.780
And the fact that it's in the terminal

00:43:51.820 --> 00:43:53.800
is completely appropriate for this kind of application

00:43:54.240 --> 00:43:54.400
because

00:43:54.400 --> 00:43:55.860
that's

00:43:55.860 --> 00:43:58.240
where you're going to be a lot of the time.

00:43:58.500 --> 00:43:59.720
It just seems to be the right place.

00:43:59.720 --> 00:44:02.200
If you have your app in a browser,

00:44:02.600 --> 00:44:05.120
it can take you out of your flow if you're developing

00:44:05.320 --> 00:44:07.000
and having to switch over a window.

00:44:07.900 --> 00:44:11.500
But having it all on the terminal is super useful.

00:44:11.880 --> 00:44:14.919
And this project has sort of grown in feature set

00:44:14.940 --> 00:44:18.200
and I think it's comparable to some much, much larger projects,

00:44:18.400 --> 00:44:19.160
including Postman.

00:44:19.440 --> 00:44:20.000
Yeah, nice.

00:44:20.220 --> 00:44:21.060
And open source,

00:44:21.320 --> 00:44:21.400
right?

00:44:21.780 --> 00:44:22.140
Open

00:44:22.140 --> 00:44:22.680
source, yeah.

00:44:22.940 --> 00:44:23.400
Yeah, cool.

00:44:24.440 --> 00:44:27.080
What other ones do you want to give a quick shout-out to?

00:44:27.500 --> 00:44:28.860
Well, yeah, we'll go through them there.

00:44:28.960 --> 00:44:30.160
We've got Memray

00:44:30.160 --> 00:44:31.740
that was written by Bloomberg.

00:44:32.060 --> 00:44:33.960
They were an early adopter of Textual,

00:44:34.340 --> 00:44:36.160
and it's kind of a memory profiler,

00:44:36.280 --> 00:44:38.340
so it can run your Python application

00:44:39.180 --> 00:44:42.439
and it can pinpoint exactly what's taking up too much memory

00:44:43.060 --> 00:44:45.580
or if you've got a leak, you know, you're in a loop

00:44:45.740 --> 00:44:47.580
and you've been reserving objects, you don't know about it,

00:44:48.400 --> 00:44:49.540
it can alert you to that,

00:44:50.300 --> 00:44:53.840
which is very hard to actually debug without any kind of tool.

00:44:54.960 --> 00:44:56.860
So that's a fantastic project.

00:44:57.820 --> 00:44:58.100
I

00:44:58.100 --> 00:45:00.540
had them on not too long ago to talk about it,

00:45:00.600 --> 00:45:02.120
and yeah, this is a super cool project.

00:45:03.580 --> 00:45:06.620
I think also just graphically, it's pretty neat, right?

00:45:06.940 --> 00:45:10.399
Yeah, it displays all the information that you need

00:45:10.620 --> 00:45:13.280
right there in the terminal in a nice way.

00:45:13.840 --> 00:45:15.920
I mean, I can imagine a previous version

00:45:15.980 --> 00:45:19.260
of something like this writing out a big spew of JSON,

00:45:20.260 --> 00:45:24.320
which you then got to study to figure it out.

00:45:25.220 --> 00:45:26.620
We've saved a CSV file.

00:45:26.760 --> 00:45:27.420
Now you can look at it.

00:45:27.520 --> 00:45:28.060
It's like, oh, great.

00:45:28.120 --> 00:45:29.320
Yeah, exactly.

00:45:29.540 --> 00:45:30.980
But if you can look at it in a graphical form

00:45:30.980 --> 00:45:31.580
in a nice table,

00:45:31.760 --> 00:45:35.460
you can visually parse information much quicker

00:45:35.920 --> 00:45:37.440
so you can pinpoint things.

00:45:38.000 --> 00:45:39.720
We talked a little bit around this,

00:45:40.300 --> 00:45:43.540
But another huge benefit of these types of UIs with Textual

00:45:43.980 --> 00:45:48.520
is the ability to run them remotely on servers and other,

00:45:48.960 --> 00:45:53.660
or on a Raspberry Pi or on things that are embedded types of stuff

00:45:53.800 --> 00:45:56.080
that you just only access through the terminal, right?

00:45:56.680 --> 00:46:00.380
Like if you wanted to do memory on your web server,

00:46:00.940 --> 00:46:03.500
you probably don't want to just open up a bunch of ports

00:46:03.680 --> 00:46:07.820
and start serving, you know, a parallel HTTP request over it, right?

00:46:08.300 --> 00:46:10.820
But if you SSH in and you just run this GUI that's updating,

00:46:10.940 --> 00:46:11.760
it's really nice, right?

00:46:12.120 --> 00:46:12.960
Yeah, exactly.

00:46:14.160 --> 00:46:15.300
You don't even need to have a desktop.

00:46:16.150 --> 00:46:17.740
You don't need to run a server.

00:46:17.850 --> 00:46:19.800
And like I said, you don't need to set your firewall

00:46:19.950 --> 00:46:22.080
to allow a particular port and configure applications.

00:46:22.780 --> 00:46:23.360
All that's gone.

00:46:23.470 --> 00:46:24.580
Because it's a text interface,

00:46:24.870 --> 00:46:28.100
you just need to have a shell SSH into the server

00:46:28.360 --> 00:46:31.060
and then run it, and you can see this nice interface there

00:46:31.760 --> 00:46:33.220
because it is just purely text.

00:46:33.740 --> 00:46:35.100
And there's not much text involved.

00:46:35.380 --> 00:46:38.200
You'd be surprised about text that needs to be sent over the wire.

00:46:38.280 --> 00:46:39.700
is surprisingly minimal.

00:46:40.940 --> 00:46:42.280
If you compared it to a YouTube video

00:46:43.030 --> 00:46:43.920
of the lowest quality,

00:46:44.010 --> 00:46:45.100
I don't know what the lowest quality is,

00:46:45.270 --> 00:46:47.060
like 120p or something.

00:46:47.400 --> 00:46:50.480
Yeah, 360 by 240 or something.

00:46:50.710 --> 00:46:50.940
Who knows?

00:46:51.080 --> 00:46:51.220
Yeah,

00:46:51.260 --> 00:46:53.520
that would be vastly more data

00:46:53.960 --> 00:46:55.640
than a text interface like this.

00:46:55.980 --> 00:46:57.960
Yeah, even if it's madly updating, yeah.

00:46:58.240 --> 00:46:59.020
I mean, you could actually.

00:46:59.220 --> 00:47:00.580
You could if you want to push it.

00:47:00.650 --> 00:47:02.740
Like if I was to run this ridiculous demo

00:47:02.920 --> 00:47:05.059
with a spinning gradient at 60 frames a second

00:47:06.020 --> 00:47:08.180
and setting the screen size to ridiculous.

00:47:09.260 --> 00:47:13.100
It might turn into a video, but for most interfaces.

00:47:14.160 --> 00:47:19.600
But is it probably applicable for like GZip transfer as well?

00:47:19.740 --> 00:47:21.160
You know, text compresses really well.

00:47:21.360 --> 00:47:21.780
I don't know.

00:47:22.140 --> 00:47:22.280
True.

00:47:22.840 --> 00:47:23.780
It depends what you're rendering.

00:47:24.160 --> 00:47:25.100
I don't know if SSH does.

00:47:25.660 --> 00:47:25.900
I don't know.

00:47:26.140 --> 00:47:26.460
Maybe it does.

00:47:26.540 --> 00:47:28.780
I would think it compresses.

00:47:29.880 --> 00:47:31.000
Compresses and encrypts.

00:47:31.340 --> 00:47:31.460
Yeah.

00:47:31.700 --> 00:47:32.020
I would

00:47:32.020 --> 00:47:32.180
hope

00:47:32.180 --> 00:47:32.360
so.

00:47:32.800 --> 00:47:35.220
Yeah, well, compression should be cheaper than the encryption.

00:47:35.460 --> 00:47:37.440
So yeah, why not go ahead and compress it while I'm at it, right?

00:47:37.580 --> 00:47:38.040
Exactly, yeah.

00:47:38.720 --> 00:47:39.280
Yeah, yeah, yeah.

00:47:39.410 --> 00:47:39.520
Okay.

00:47:40.600 --> 00:47:43.300
So somewhere in here, we've pulled up so many things.

00:47:43.720 --> 00:47:46.600
I pulled up your article that I wanted to talk about as well.

00:47:46.690 --> 00:47:48.220
So let's talk about this.

00:47:48.340 --> 00:47:50.720
This was your, you said you wanted to write an article,

00:47:51.510 --> 00:47:54.380
sort of celebrate the 1.0 milestone for Textual.

00:47:54.700 --> 00:47:56.020
And the article was called

00:47:56.100 --> 00:47:58.420
Algorithms for High-Performance Terminal Apps.

00:47:58.580 --> 00:48:00.860
And I thought there was just some fun things to pull out of here.

00:48:01.100 --> 00:48:03.320
So I thought we could maybe talk through some of them.

00:48:03.620 --> 00:48:03.900
Yeah, sure.

00:48:03.980 --> 00:48:07.960
So there's lots of interesting technical problems to solve with Textual

00:48:08.300 --> 00:48:09.840
and lots of cool solutions.

00:48:10.500 --> 00:48:13.940
But I still rarely have the chance to talk to anyone about it

00:48:13.980 --> 00:48:15.480
because it's one of these things that's kind of under the hood.

00:48:15.540 --> 00:48:16.080
It just works.

00:48:16.520 --> 00:48:16.620
Yeah.

00:48:17.060 --> 00:48:18.380
There's nothing to discuss.

00:48:18.620 --> 00:48:22.300
So I wrote this blog post to describe some of the cool things that go on.

00:48:22.560 --> 00:48:25.420
The most core part of Textual is the compositor.

00:48:26.320 --> 00:48:27.800
This takes all the widgets.

00:48:28.540 --> 00:48:33.540
If you've got an interface, it might have data table, button, checkboxes.

00:48:35.160 --> 00:48:38.120
And there might be loads of those, and it might be able to scroll through it.

00:48:38.840 --> 00:48:42.420
And Textual has to take all those widgets and assemble them into a single update.

00:48:43.600 --> 00:48:46.880
Because there's nothing in the terminal that does a kind of a tiling window manager.

00:48:48.220 --> 00:48:49.680
You just write text to the terminal.

00:48:50.460 --> 00:48:56.420
So the software has to create this illusion that you've got windows and things that are overlapping.

00:48:57.000 --> 00:48:58.900
and that's essentially what the compositor does.

00:48:59.680 --> 00:48:59.880
That's

00:48:59.880 --> 00:49:00.140
great.

00:49:00.280 --> 00:49:01.900
And you've got transparency.

00:49:03.800 --> 00:49:04.840
Oh my goodness.

00:49:05.300 --> 00:49:06.540
Yeah, it's kind of magical.

00:49:06.620 --> 00:49:08.000
It shouldn't be possible in the terminal.

00:49:08.740 --> 00:49:09.720
It should not be possible.

00:49:09.860 --> 00:49:10.500
It cheats.

00:49:11.400 --> 00:49:13.640
You're not seeing true transparency

00:49:14.100 --> 00:49:15.720
because the terminal is not capable of it.

00:49:15.720 --> 00:49:18.960
You can't put an X on top of an A

00:49:19.400 --> 00:49:21.340
and then see the X translucently

00:49:21.860 --> 00:49:23.300
with an A in the background.

00:49:24.280 --> 00:49:26.600
But you can change background colors.

00:49:26.910 --> 00:49:28.900
So if you put something on top of background,

00:49:29.330 --> 00:49:34.640
you can calculate the transparency on top of the widget underneath it.

00:49:34.930 --> 00:49:38.380
So you can create the illusion of background of transparency.

00:49:39.480 --> 00:49:42.920
And that's something that the compositor does as well.

00:49:43.980 --> 00:49:45.500
Is textual pure Python?

00:49:45.940 --> 00:49:46.640
Pure Python, yeah.

00:49:47.640 --> 00:49:52.000
I had thought that at some point we would have to write something in Rust.

00:49:52.420 --> 00:49:55.960
And I bought a couple of Rust books, which I haven't read yet.

00:49:56.160 --> 00:49:58.340
But every time I got to a point where this is a bit too slow,

00:49:58.880 --> 00:50:02.180
I found a very good optimization in Python.

00:50:02.720 --> 00:50:04.440
So it turns out that it's just not necessary.

00:50:04.740 --> 00:50:07.820
I mean, if we were to write some core code in Rust,

00:50:08.440 --> 00:50:10.480
I don't think we'd get marvelous speed up.

00:50:10.530 --> 00:50:13.840
We might get 5%, 10% if we're lucky for a lot of effort.

00:50:14.580 --> 00:50:18.460
But since it runs on a lowly Raspberry Pi, it's not been necessary.

00:50:18.560 --> 00:50:20.160
Python's been more than fast enough.

00:50:20.460 --> 00:50:20.640
Yeah.

00:50:21.240 --> 00:50:25.200
And you can just ride on the coattails of the faster CPython team.

00:50:25.600 --> 00:50:25.920
Oh, yeah.

00:50:26.050 --> 00:50:27.140
Yeah, I mean, yeah.

00:50:27.320 --> 00:50:27.740
That helps too.

00:50:27.740 --> 00:50:27.860
A new

00:50:27.860 --> 00:50:29.900
version comes along, we can say Textual just got 10%

00:50:29.900 --> 00:50:30.360
faster.

00:50:31.860 --> 00:50:35.180
Textual has some sort of concurrency framework too, right?

00:50:35.620 --> 00:50:37.400
Yeah, so it's based on asyncio.

00:50:38.260 --> 00:50:45.100
And every widget from a button to a text area to a checkbox runs an asyncio task.

00:50:45.920 --> 00:50:50.000
So all these things are running concurrently, potentially updating the state.

00:50:50.840 --> 00:50:53.880
and Textual will update things

00:50:54.720 --> 00:50:56.080
according to the schedule of the widgets.

00:50:57.020 --> 00:50:58.780
You might have a widget which, say,

00:50:58.890 --> 00:50:59.900
updates 10 times a second,

00:51:00.640 --> 00:51:02.880
another widget which updates when you press a key,

00:51:03.620 --> 00:51:06.660
and another widget which updates infrequently.

00:51:07.360 --> 00:51:10.020
And Textual will combine those updates

00:51:10.210 --> 00:51:13.720
into a single update so that it looks clean,

00:51:13.730 --> 00:51:14.760
it doesn't flicker,

00:51:15.360 --> 00:51:20.380
and it's what does the magic of updating things.

00:51:20.820 --> 00:51:20.860
Yeah,

00:51:21.240 --> 00:51:21.400
awesome.

00:51:21.820 --> 00:51:22.500
That's super neat.

00:51:23.400 --> 00:51:27.180
I think UI frameworks and AsyncIO, Async and Await,

00:51:27.370 --> 00:51:28.340
they make a lot of sense, right?

00:51:28.700 --> 00:51:30.500
It's event-driven stuff, and so you can,

00:51:30.900 --> 00:51:32.600
instead of pulling or whatever, you just say,

00:51:32.600 --> 00:51:33.940
I'm going to wait until this thing

00:51:33.940 --> 00:51:34.540
has

00:51:34.540 --> 00:51:35.260
some kind of event,

00:51:35.350 --> 00:51:37.920
and then I'll work on it, and if that doesn't have an event,

00:51:38.020 --> 00:51:39.120
I'm going to go work on something else.

00:51:39.340 --> 00:51:40.060
Yeah, it's pretty cool.

00:51:40.160 --> 00:51:40.320
Yeah,

00:51:40.380 --> 00:51:40.880
exactly.

00:51:41.740 --> 00:51:44.080
It's funny that AsyncIO was obviously, you can tell by the name,

00:51:44.260 --> 00:51:46.860
it wasn't intended to build user interfaces,

00:51:47.350 --> 00:51:49.920
whether in the terminal or not, it was built for I.O.,

00:51:49.940 --> 00:51:53.200
but it's very good at handling concurrency of any kind,

00:51:55.080 --> 00:51:56.380
including text user interfaces.

00:51:56.980 --> 00:51:58.640
So I'm a big fan of Async.

00:51:58.780 --> 00:52:00.000
It's not perfect.

00:52:00.180 --> 00:52:03.500
There are a bunch of gotchas which come up in our support channels.

00:52:04.880 --> 00:52:07.080
For instance, someone will be playing around with Textual

00:52:07.420 --> 00:52:10.160
and will say, well, I'm going to need some long-running tasks,

00:52:10.580 --> 00:52:12.380
so I'll simulate this by putting a sleep in.

00:52:12.900 --> 00:52:13.840
We'll do like sleep 10.

00:52:14.860 --> 00:52:15.500
The whole app

00:52:15.500 --> 00:52:16.340
just locks up.

00:52:16.340 --> 00:52:16.940
I can't believe it.

00:52:17.020 --> 00:52:17.260
Exactly,

00:52:17.480 --> 00:52:17.980
exactly.

00:52:18.840 --> 00:52:22.380
So it's not perfect, but there is no perfect solution to concurrency.

00:52:23.680 --> 00:52:28.300
But I think it's as good as it can be with the current level of technology, I think.

00:52:28.540 --> 00:52:28.720
Yeah,

00:52:28.990 --> 00:52:29.120
yeah.

00:52:29.880 --> 00:52:29.960
Yeah,

00:52:30.020 --> 00:52:30.340
very neat.

00:52:31.120 --> 00:52:31.860
Free-threaded Python?

00:52:33.539 --> 00:52:34.260
Is it going to

00:52:34.260 --> 00:52:35.020
influence that

00:52:35.020 --> 00:52:35.500
kind of thing?

00:52:36.500 --> 00:52:37.220
I think so.

00:52:37.280 --> 00:52:39.860
There's a whole lot of cool things that free-threaded Python can do.

00:52:40.520 --> 00:52:43.420
We've kind of convinced ourselves that we didn't need that kind of level of concurrency,

00:52:43.910 --> 00:52:48.160
you know, from like a web application or something, because it's really linear.

00:52:49.500 --> 00:52:51.400
and the I.O. gives you concurrency

00:52:52.020 --> 00:52:53.500
in a sense because you're waiting for the I.O.

00:52:54.780 --> 00:52:55.700
But I think

00:52:56.000 --> 00:52:59.400
we need a better abstraction for concurrency

00:53:00.960 --> 00:53:01.700
because having to

00:53:01.960 --> 00:53:03.060
explicitly create a thread

00:53:03.540 --> 00:53:05.520
and run it requires that you think

00:53:05.600 --> 00:53:06.880
in terms of threads

00:53:08.240 --> 00:53:08.960
which is quite challenging.

00:53:10.060 --> 00:53:11.059
I think it should be

00:53:11.760 --> 00:53:12.960
the same as async.io. It

00:53:12.960 --> 00:53:13.500
should be async

00:53:13.620 --> 00:53:13.940
and await.

00:53:14.520 --> 00:53:16.679
I think that would be a marriage

00:53:16.680 --> 00:53:19.900
between them where like you don't really know as you're consuming it you know

00:53:19.900 --> 00:53:20.360
yeah

00:53:20.360 --> 00:53:20.880
unfortunately

00:53:21.720 --> 00:53:28.020
async io is single threaded you can use multiple threads but you've got to consciously write the

00:53:28.140 --> 00:53:29.900
code i would like to see an async io

00:53:29.900 --> 00:53:31.840
where it just distributed work

00:53:31.840 --> 00:53:35.340
across the course if it's if it's

00:53:35.400 --> 00:53:39.460
io based just keep it on the same thread but if it's computational based then like you're going to

00:53:39.560 --> 00:53:43.360
just put it on another thread and give me a future sort of thing to await and we don't care

00:53:43.360 --> 00:53:43.639
yeah

00:53:43.800 --> 00:53:44.020
Absolutely.

00:53:44.500 --> 00:53:44.580
Yeah.

00:53:44.900 --> 00:53:46.980
So I think in the future,

00:53:47.060 --> 00:53:48.520
we're probably going to get something like that

00:53:48.640 --> 00:53:51.100
because I think Python is so valuable

00:53:51.920 --> 00:53:53.400
that people are going to want to use it more

00:53:53.840 --> 00:53:55.820
and they're going to build these better abstractions.

00:53:56.200 --> 00:53:58.780
So I imagine in a year or two,

00:53:59.320 --> 00:54:00.100
maybe less,

00:54:00.780 --> 00:54:03.980
we'll have an asyncio that's rethreaded

00:54:04.020 --> 00:54:04.780
or something like it.

00:54:04.940 --> 00:54:05.040
Yeah.

00:54:05.480 --> 00:54:06.900
We say that we don't need it for web apps

00:54:07.040 --> 00:54:08.560
because we can just scale them out, right?

00:54:08.600 --> 00:54:10.980
We'll just run four of them, four worker processes.

00:54:11.180 --> 00:54:13.740
but there's a big memory cost to running.

00:54:14.160 --> 00:54:15.840
Well, I've got 16 cores,

00:54:16.060 --> 00:54:18.780
so I'm going to run 16 worker processes, right?

00:54:19.400 --> 00:54:20.580
They each take half a gig.

00:54:20.780 --> 00:54:21.620
All of a sudden, you're like,

00:54:21.800 --> 00:54:22.900
eight gigs just for this.

00:54:24.540 --> 00:54:27.060
Just so I can get computational parallelism, right?

00:54:27.660 --> 00:54:27.740
Yeah.

00:54:27.940 --> 00:54:28.440
Exactly.

00:54:28.700 --> 00:54:29.380
I mean, yeah,

00:54:29.540 --> 00:54:32.660
the IO gets you a lot of the way there,

00:54:32.780 --> 00:54:36.280
but sometimes you accidentally create CPU-bound code,

00:54:36.900 --> 00:54:38.680
which would run very poorly.

00:54:39.240 --> 00:54:43.000
But if you're using all our threads efficiently, then that should be easier.

00:54:43.220 --> 00:54:44.100
It should be easier, yeah.

00:54:44.760 --> 00:54:44.940
You know,

00:54:44.960 --> 00:54:45.880
it's super easy.

00:54:46.080 --> 00:54:47.160
Like, oh, I've

00:54:47.160 --> 00:54:52.780
got an ORM and I'm going to return 20,000 things that I'm parsing into Pydantic objects for FastAPI.

00:54:52.840 --> 00:54:56.660
All of a sudden, like, most of the work is the serialization that's computational.

00:54:57.220 --> 00:54:57.580
Anyway, all right.

00:54:57.700 --> 00:54:59.560
So let's get back to this.

00:54:59.680 --> 00:55:01.040
But I think that's super, super interesting.

00:55:01.560 --> 00:55:03.140
We could do a whole other hour on that.

00:55:03.900 --> 00:55:12.040
So one of the things in here you talked about is thinking in segments and not characters or stuff for drawing terminal lines.

00:55:12.080 --> 00:55:17.240
Let's talk about that because I really want to talk about the switching the primitive idea you got, but I think this is a good setup.

00:55:17.640 --> 00:55:18.020
Yeah, sure.

00:55:18.740 --> 00:55:25.540
So people who aren't familiar with inner workings of terminals might look at terminals and think it's like a two-dimensional array of characters.

00:55:26.080 --> 00:55:27.060
It does seem like that.

00:55:27.420 --> 00:55:37.100
And if you're building a textual app, you might think that you could compose a screenful of text like a bitmap, as if the characters were pixels.

00:55:37.740 --> 00:55:40.940
And as developers, that would be like stuff we're very familiar with.

00:55:40.940 --> 00:55:42.360
We could easily build that

00:55:42.360 --> 00:55:43.620
and

00:55:43.620 --> 00:55:45.340
create stuff with it.

00:55:46.010 --> 00:55:50.340
But the problem is that terminals aren't two-dimensional arrays of characters.

00:55:50.980 --> 00:55:55.540
And it's for one reason is that some characters take up twice as much space as others.

00:55:56.060 --> 00:55:58.800
Chinese, Japanese, and Korean tags typically take up two characters

00:55:59.040 --> 00:56:01.280
because their characters are more complex.

00:56:01.620 --> 00:56:03.680
They deliver more information in a single character,

00:56:03.770 --> 00:56:04.960
so they have to be wider.

00:56:05.660 --> 00:56:10.400
There's also emoji, which many emojis can take up twice as much space.

00:56:11.300 --> 00:56:12.920
I'd have the snake emoji.

00:56:13.280 --> 00:56:13.540
Exactly.

00:56:14.380 --> 00:56:15.920
I think that might be two.

00:56:16.900 --> 00:56:17.840
I don't know how wide it is.

00:56:18.960 --> 00:56:21.520
Some emoji are one, like a smiley face or something,

00:56:21.760 --> 00:56:23.040
but some emoji are two.

00:56:24.040 --> 00:56:26.840
And if you were to treat it like a two-dimensional ray,

00:56:27.260 --> 00:56:28.960
it kind of falls apart at that point

00:56:29.220 --> 00:56:32.780
because if you subtract one from the Y coordinate,

00:56:32.920 --> 00:56:35.900
it's not directly above the original coordinate.

00:56:36.900 --> 00:56:38.320
So in situations like that,

00:56:38.490 --> 00:56:39.360
rather than trying to fudge

00:56:39.360 --> 00:56:40.580
things

00:56:40.580 --> 00:56:42.660
into the primitive

00:56:42.770 --> 00:56:43.780
that you first thought of,

00:56:44.340 --> 00:56:45.720
you can come up with a new primitive,

00:56:46.450 --> 00:56:50.600
a new way that represents the very lowest common denominator

00:56:50.780 --> 00:56:51.620
of thing you want to do.

00:56:52.580 --> 00:56:54.860
And for textual, that turned out to be segments.

00:56:55.590 --> 00:56:57.620
So rather than a character, it's like a pixel.

00:56:58.980 --> 00:56:59.700
We use a segment.

00:57:00.060 --> 00:57:04.040
A segment is a string, any number of characters, plus a style.

00:57:04.880 --> 00:57:09.620
And by assembling these segments, you can represent anything in the UI.

00:57:10.580 --> 00:57:14.920
And all the operations which are done are kind of built on segments.

00:57:15.620 --> 00:57:17.460
So I call this switching the primitive,

00:57:17.590 --> 00:57:20.040
because the original primitive was like a character's a pixel, right?

00:57:20.640 --> 00:57:21.420
Which didn't work.

00:57:21.620 --> 00:57:26.880
If you were to, you could use that with a bunch of fudges to build on top of it,

00:57:27.250 --> 00:57:28.460
but you might find that it falls apart.

00:57:28.880 --> 00:57:31.380
Things which should be straightforward suddenly become really complicated.

00:57:32.280 --> 00:57:36.400
And that's because as developers, we tend to layer primitives on top of other operations.

00:57:37.060 --> 00:57:42.120
And if the very foundational primitive doesn't represent your problem very well,

00:57:42.800 --> 00:57:43.660
then it can fall apart.

00:57:44.740 --> 00:57:48.200
So the switch from pixels to segments worked very well with Textual.

00:57:48.420 --> 00:57:51.500
and Textual is essentially a segment processing engine.

00:57:51.920 --> 00:57:54.840
Everything the compositor does takes in a bunch of segments,

00:57:55.480 --> 00:57:57.380
manipulates them, spits out new segments,

00:57:57.660 --> 00:58:00.120
and then those get turned into escape sequences.

00:58:00.960 --> 00:58:01.760
Yeah, very cool.

00:58:02.100 --> 00:58:04.060
I think this idea of switching the primitive,

00:58:04.860 --> 00:58:07.140
you know, people who are new to programming or new to Python,

00:58:07.820 --> 00:58:11.100
especially programming, I have a hard time.

00:58:11.420 --> 00:58:13.600
I see the code, I look at someone else's code,

00:58:13.700 --> 00:58:15.200
and I see the code, and it makes sense,

00:58:15.520 --> 00:58:17.760
but then when I sit down with a blank screen and try to solve a problem,

00:58:18.180 --> 00:58:19.560
I'm stuck. I don't know what to do.

00:58:20.200 --> 00:58:22.660
And this switching the primitive concept of like,

00:58:22.820 --> 00:58:26.340
we looked at it this way and it just seemed so complicated and intractable.

00:58:26.500 --> 00:58:29.620
And then I decided to rejigger maybe the data structures

00:58:29.810 --> 00:58:31.660
and how we organize stuff and how we combine them.

00:58:31.680 --> 00:58:34.140
And boom, it just unlocks simplicity, actually.

00:58:35.160 --> 00:58:37.240
Kind of like going back to our triangles and graphics.

00:58:37.730 --> 00:58:40.900
It's like, well, if you think in pixels, 3D game engines are impossible.

00:58:41.900 --> 00:58:43.360
With ray tracing and lighting and shadows,

00:58:43.770 --> 00:58:47.160
you think in triangles, all of a sudden it unlocks it, right?

00:58:47.320 --> 00:58:48.960
this sounds a little bit similar, and I think

00:58:49.420 --> 00:58:51.260
that's a pretty valuable lesson for people to take.

00:58:51.520 --> 00:58:52.960
That's exactly right. So if you had

00:58:53.580 --> 00:58:55.220
a game engine, and the only

00:58:55.360 --> 00:58:57.280
function it had was like put pixel,

00:58:58.040 --> 00:58:59.240
it would be a nightmare

00:58:59.340 --> 00:59:01.160
to build anything but the most trivial

00:59:01.440 --> 00:59:03.320
games, but the primitive of

00:59:03.320 --> 00:59:05.300
a triangle means you can build 3D

00:59:05.820 --> 00:59:07.180
anything. So that is the bare primitive.

00:59:07.400 --> 00:59:08.980
And they have angles, so they have reflection,

00:59:09.260 --> 00:59:10.840
and so they have all sorts of stuff, yeah.

00:59:11.280 --> 00:59:13.200
Yeah, something similar came up when

00:59:14.040 --> 00:59:15.340
Darren was building the text area.

00:59:16.220 --> 00:59:17.580
So the text area has lots of operations,

00:59:18.000 --> 00:59:21.240
like insert a new line, delete a character,

00:59:22.140 --> 00:59:25.960
delete a line, delete a paragraph, cut and paste, etc.

00:59:26.920 --> 00:59:30.680
And the primitive for that boiled down to a very, very simple primitive,

00:59:30.950 --> 00:59:33.600
and that was replace a range of text with new text.

00:59:34.320 --> 00:59:36.340
It's like anything you can do to a text area

00:59:36.560 --> 00:59:40.240
comes down to that primitive of a range plus new text.

00:59:40.640 --> 00:59:43.819
Like to delete something, you replace a range with an empty string

00:59:44.660 --> 00:59:46.000
to insert something.

00:59:46.490 --> 00:59:48.020
You replace a range with

00:59:48.690 --> 00:59:49.940
the insertion character,

00:59:50.060 --> 00:59:52.160
like a new line plus the previous

00:59:52.230 --> 00:59:53.960
string. So everything boils down to one

00:59:54.680 --> 00:59:55.460
very simple primitive.

00:59:56.400 --> 00:59:57.540
And once you've found the right primitive,

00:59:58.280 --> 01:00:00.120
bigger problems become much, much easier.

01:00:00.440 --> 01:00:01.540
Yeah, 100%.

01:00:02.120 --> 01:00:03.100
It's amazing the way it works.

01:00:03.600 --> 01:00:05.100
So we'll get short on time.

01:00:05.600 --> 01:00:07.760
We got, pick one more

01:00:08.060 --> 01:00:09.660
lesson from here that you want to

01:00:09.880 --> 01:00:11.980
talk about maybe. The spatial

01:00:12.160 --> 01:00:12.840
map was quite interesting.

01:00:13.460 --> 01:00:14.280
Yeah, I think they do.

01:00:14.550 --> 01:00:15.480
A bit further down, yeah.

01:00:16.250 --> 01:00:18.380
So one of the problems we had in textual,

01:00:18.940 --> 01:00:19.860
when interfaces get complex,

01:00:20.100 --> 01:00:21.760
we've got lots and lots of widgets.

01:00:22.660 --> 01:00:24.500
Some of them are visible and some of them are not.

01:00:24.640 --> 01:00:25.640
Some of them are scrolled off.

01:00:26.260 --> 01:00:27.140
They're still there in memory.

01:00:27.190 --> 01:00:28.400
We know exactly where they are.

01:00:30.000 --> 01:00:31.000
And when we come to render that,

01:00:31.130 --> 01:00:32.400
the most obvious way to do that

01:00:32.400 --> 01:00:33.880
is to step through them in a for loop

01:00:34.280 --> 01:00:35.720
or widgets in all widgets,

01:00:36.830 --> 01:00:37.580
do stuff to widget.

01:00:39.020 --> 01:00:41.380
But that means we're iterating over all the widgets

01:00:42.059 --> 01:00:42.960
every single time,

01:00:43.340 --> 01:00:44.760
even if they aren't visible.

01:00:46.300 --> 01:00:48.760
So the spatial map was an attempt to optimize that.

01:00:48.820 --> 01:00:50.800
Basically, it's a very quick way of deciding

01:00:51.240 --> 01:00:52.480
which the widgets are on screen

01:00:52.530 --> 01:00:54.680
and which the widgets are currently scrolled off.

01:00:55.310 --> 01:00:56.980
So we literally don't need to even loop through

01:00:57.420 --> 01:00:58.040
the scrolled off widgets.

01:00:59.120 --> 01:01:00.880
And the way we did that briefly

01:01:01.420 --> 01:01:04.620
is we kind of logically separated the terminal

01:01:04.830 --> 01:01:05.920
into a grid.

01:01:06.900 --> 01:01:08.540
There's a step where you go through

01:01:08.780 --> 01:01:11.480
and assign every widget to the grid squares

01:01:11.660 --> 01:01:13.180
that it might overlap with.

01:01:13.460 --> 01:01:19.480
small widgets might be right inside a grid square some may overlap one or two or more and then once

01:01:19.480 --> 01:01:25.480
we've got that information it's very easy to pick out which widgets are visible and exclude which

01:01:25.680 --> 01:01:30.480
widgets aren't because we can take the screen figure out which of the grid squares it covers

01:01:31.380 --> 01:01:35.660
and then we can go through those grid squares and there's probably just a handful of them and each

01:01:35.660 --> 01:01:38.740
of those grid squares is associated with a list of widgets which are under that

01:01:38.740 --> 01:01:39.780
you

01:01:39.780 --> 01:01:40.460
can combine that

01:01:40.480 --> 01:01:42.260
with a set and then very quickly

01:01:42.780 --> 01:01:44.060
you reduce that problem domain

01:01:44.380 --> 01:01:46.340
from being potentially unbounded very

01:01:46.500 --> 01:01:47.940
large to like very small

01:01:48.380 --> 01:01:50.200
some of the widgets might actually not be visible

01:01:50.270 --> 01:01:52.320
they might actually be in a grid square which

01:01:52.480 --> 01:01:53.560
is off the edge of the screen

01:01:54.700 --> 01:01:56.440
but we can just loop through those

01:01:56.520 --> 01:01:58.340
and discard those ones

01:01:58.410 --> 01:01:59.820
but that's a much smaller operation

01:01:59.820 --> 01:02:00.340
than

01:02:00.460 --> 01:02:01.760
looping through every widget

01:02:02.410 --> 01:02:04.180
in the location. Interesting. He talked about

01:02:04.500 --> 01:02:05.520
it's fast enough in Python

01:02:06.320 --> 01:02:08.200
and it's this kind of stuff that makes it fast enough

01:02:08.210 --> 01:02:10.440
in Python right? If you rewrote this in

01:02:10.780 --> 01:02:12.280
other native compiled language,

01:02:12.780 --> 01:02:13.020
it

01:02:13.020 --> 01:02:15.120
would be faster to go through every single one of them,

01:02:15.220 --> 01:02:17.380
but you're still potentially processing

01:02:17.510 --> 01:02:19.300
a tremendous number of things,

01:02:19.370 --> 01:02:20.580
and you get the compositor and overlap

01:02:20.790 --> 01:02:21.580
and all those kinds of things,

01:02:21.680 --> 01:02:22.780
and you're really worried about stuff

01:02:22.940 --> 01:02:23.720
that's way off the screen.

01:02:24.500 --> 01:02:25.960
Instead of going, we're going to rewrite it,

01:02:25.980 --> 01:02:27.560
you can just think, let me think about

01:02:27.770 --> 01:02:29.660
the right data structures and the right algorithms.

01:02:29.680 --> 01:02:29.840
Exactly.

01:02:30.420 --> 01:02:31.200
And so on, yeah.

01:02:31.460 --> 01:02:32.940
I mean, I would love it if Python

01:02:33.050 --> 01:02:34.260
just got so ridiculously fast.

01:02:34.680 --> 01:02:35.520
You don't have to worry about that,

01:02:35.520 --> 01:02:38.320
and I'll take any speed improvements again.

01:02:39.480 --> 01:02:41.320
But the optimizations you can produce yourself

01:02:41.600 --> 01:02:42.780
just by having the right algorithm,

01:02:43.440 --> 01:02:45.920
they tend to outweigh the benefits you could get

01:02:46.280 --> 01:02:48.000
from, say, running it in C.

01:02:48.280 --> 01:02:49.680
First, it would be implement that in C.

01:02:49.700 --> 01:02:51.040
It would obviously be faster,

01:02:51.500 --> 01:02:53.920
but it would still be much faster to have that algorithm.

01:02:54.780 --> 01:02:55.440
Yeah, exactly.

01:02:56.360 --> 01:02:58.800
I'll take my order of O squared

01:02:59.680 --> 01:03:03.260
versus your O factorial versus N squared.

01:03:03.680 --> 01:03:04.100
You know what I mean?

01:03:04.800 --> 01:03:05.180
Exactly.

01:03:05.820 --> 01:03:06.600
It's going to lose

01:03:06.600 --> 01:03:08.640
on N factorial no matter what you do, right?

01:03:08.960 --> 01:03:09.040
Yeah.

01:03:09.280 --> 01:03:11.240
I mean, Python wins because of the speed of development.

01:03:11.830 --> 01:03:13.040
We know it's not the runtime speed.

01:03:13.490 --> 01:03:13.840
Yeah, absolutely.

01:03:13.870 --> 01:03:15.560
The runtime speed is okay most of the time,

01:03:16.370 --> 01:03:17.340
but it's the speed of development.

01:03:17.620 --> 01:03:19.860
The fact that you have got more time to pick the right algorithm

01:03:20.660 --> 01:03:23.080
means it's not as slow as people might think.

01:03:23.340 --> 01:03:23.640
Yeah, absolutely.

01:03:24.350 --> 01:03:25.320
It doesn't get too complicated.

01:03:26.300 --> 01:03:27.080
Yeah, thinking about this,

01:03:28.020 --> 01:03:28.840
I think there's a lot of

01:03:28.840 --> 01:03:30.660
parallels

01:03:30.660 --> 01:03:31.660
back to game engines

01:03:31.730 --> 01:03:32.440
that I think about a lot.

01:03:32.620 --> 01:03:35.360
The game engines have this thing called oct trees,

01:03:35.520 --> 01:03:37.960
like basically break stuff into eight squares,

01:03:38.260 --> 01:03:40.860
and you say, well, which I'm looking for a thing

01:03:41.010 --> 01:03:43.280
if it's going to say intersect with this, right?

01:03:43.420 --> 01:03:44.680
Because it's like for hit detection and stuff.

01:03:44.770 --> 01:03:46.700
Like, well, is it in this half of this world

01:03:46.770 --> 01:03:47.260
or that half?

01:03:47.300 --> 01:03:47.840
Well, it's in this half.

01:03:47.870 --> 01:03:49.340
Okay, well, we're not even going to compare it

01:03:49.440 --> 01:03:50.840
against half of the things in the world

01:03:50.930 --> 01:03:51.420
that are in that half.

01:03:51.860 --> 01:03:53.100
Now, look at the hash, right?

01:03:53.240 --> 01:03:55.580
Like you can super quickly go,

01:03:55.660 --> 01:03:57.320
I have a million objects on screen,

01:03:57.860 --> 01:03:59.540
but I can determine if this thing hits it

01:03:59.840 --> 01:04:01.800
with five comparisons or something like that.

01:04:01.800 --> 01:04:02.120
You know what I mean?

01:04:02.180 --> 01:04:02.840
With just the right data.

01:04:02.880 --> 01:04:03.520
That's exactly it.

01:04:03.600 --> 01:04:04.460
It's super interesting.

01:04:04.700 --> 01:04:05.220
Yeah, yeah.

01:04:05.340 --> 01:04:09.240
It's probably no coincidence that I used to work in video games.

01:04:10.060 --> 01:04:10.980
Oh, did you? Okay, yeah.

01:04:11.120 --> 01:04:11.240
Yeah.

01:04:11.760 --> 01:04:13.100
So that was kind of my mindset.

01:04:13.280 --> 01:04:14.780
It's like reducing the problem.

01:04:15.599 --> 01:04:17.860
And Textual is quite a lot like a video game.

01:04:17.920 --> 01:04:20.700
If you imagine like a 2D video game that's got lots of sprites that are over here,

01:04:21.040 --> 01:04:22.000
we don't want to worry about those.

01:04:22.380 --> 01:04:22.460
Yeah.

01:04:22.700 --> 01:04:25.100
Replace sprites with widgets, and it's pretty much the same problem.

01:04:25.160 --> 01:04:25.560
Yeah, yeah, exactly.

01:04:25.560 --> 01:04:26.640
It's the same kind of mindset.

01:04:27.060 --> 01:04:27.780
It certainly is.

01:04:28.600 --> 01:04:29.880
All right, well, I think we're going to need to

01:04:29.880 --> 01:04:31.280
just kind of wrap it up here

01:04:31.400 --> 01:04:32.900
because I think we're getting short on time.

01:04:34.180 --> 01:04:37.320
Let's leave everyone with roadmap.

01:04:38.120 --> 01:04:40.660
Where, you know, you've hit this 1.0 milestone with Textual.

01:04:41.140 --> 01:04:41.640
Where are things going?

01:04:42.420 --> 01:04:44.860
So there's a whole bunch of features which I want to implement.

01:04:46.200 --> 01:04:49.780
I mean, Textual is usable as, you know, you can build fantastic apps,

01:04:49.940 --> 01:04:52.620
but there are a few things where we don't have parity with web apps.

01:04:53.400 --> 01:04:57.180
Something I've implemented on a feature branch is arbitrary text selection.

01:04:58.280 --> 01:05:02.540
So, you know, on a website, you can just draw your mouse over text you want to select.

01:05:03.880 --> 01:05:05.340
That didn't work well with TUI's.

01:05:06.360 --> 01:05:07.280
If the terminal did it,

01:05:07.550 --> 01:05:11.000
if the terminal doesn't understand the logical separation of widgets,

01:05:11.640 --> 01:05:14.480
it would just copy all the text on that line,

01:05:15.200 --> 01:05:17.280
which might get parts of one widget and parts of another.

01:05:18.500 --> 01:05:20.360
So I've implemented Arbitrary Text Selection,

01:05:20.450 --> 01:05:21.900
which seems to work quite well.

01:05:22.130 --> 01:05:23.780
And it's such a fundamental feature, I think.

01:05:23.940 --> 01:05:24.140
Wow.

01:05:24.660 --> 01:05:26.120
It'll make Textual more useful.

01:05:26.560 --> 01:05:27.300
Yeah, I guess if you've got

01:05:27.300 --> 01:05:28.880
a UI in Textual,

01:05:29.100 --> 01:05:30.320
and you're like, I need

01:05:30.320 --> 01:05:32.540
to get that and paste it into another document

01:05:32.540 --> 01:05:34.860
or search it, you know, highlight the map,

01:05:35.210 --> 01:05:36.960
the address to put in a map or something, right?

01:05:37.280 --> 01:05:39.000
Yeah, and things like, you know,

01:05:39.000 --> 01:05:41.060
if you're using Textual to talk to an LLM,

01:05:41.360 --> 01:05:43.140
an LLM writes some code,

01:05:43.400 --> 01:05:45.200
you don't want to transcribe that code visually.

01:05:46.280 --> 01:05:48.200
Yeah, and so now we can be able to like,

01:05:48.230 --> 01:05:49.420
we can select the entire code.

01:05:49.800 --> 01:05:50.500
You could add a button,

01:05:50.780 --> 01:05:52.460
but it's very convenient to drag.

01:05:53.380 --> 01:05:55.220
So that's something that's coming very soon.

01:05:56.140 --> 01:05:58.080
And yeah, there's a whole bunch of features I've got,

01:05:58.320 --> 01:05:59.660
which I'll be working on.

01:06:00.000 --> 01:06:00.760
Yeah, watch this space.

01:06:01.540 --> 01:06:01.820
Excellent.

01:06:02.400 --> 01:06:04.860
And PRs accepted, contributions accepted?

01:06:05.260 --> 01:06:06.620
Very much so, yep.

01:06:07.340 --> 01:06:08.300
There's a big pile of them there,

01:06:08.460 --> 01:06:10.860
but I tend to work on a big feature

01:06:11.300 --> 01:06:13.140
and then spend a few days going to the PRs.

01:06:13.620 --> 01:06:14.920
And I love to have PRs.

01:06:14.920 --> 01:06:16.780
It means that people are very interested.

01:06:17.260 --> 01:06:18.340
And it saves me time, of course.

01:06:18.750 --> 01:06:21.260
If someone else is fixing bugs and writing code,

01:06:21.660 --> 01:06:22.620
then it's a great thing.

01:06:22.920 --> 01:06:23.020
Awesome.

01:06:23.740 --> 01:06:25.060
All right, well, thanks for coming on,

01:06:25.300 --> 01:06:26.580
giving us an update on Textual

01:06:26.760 --> 01:06:28.320
and all the stuff that you guys built.

01:06:28.540 --> 01:06:29.840
It's super valuable to people.

01:06:30.160 --> 01:06:30.600
Always a pleasure.

01:06:30.860 --> 01:06:31.260
Thank you very much.

01:06:31.330 --> 01:06:31.940
Yeah, you bet.

01:06:32.180 --> 01:06:32.460
See you later.

01:06:32.900 --> 01:06:33.020
Bye-bye.

01:06:33.960 --> 01:06:36.600
This has been another episode of Talk Python To Me.

01:06:37.440 --> 01:06:38.360
Thank you to our sponsors.

01:06:38.820 --> 01:06:40.060
Be sure to check out what they're offering.

01:06:40.160 --> 01:06:41.500
It really helps support the show.

01:06:41.900 --> 01:06:45.560
This episode is sponsored by Posit Connect from the makers of Shiny.

01:06:46.040 --> 01:06:49.940
Publish, share, and deploy all of your data projects that you're creating using Python.

01:06:50.560 --> 01:06:56.600
Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quarto, Reports, Dashboards, and APIs.

01:06:57.540 --> 01:06:59.160
Posit Connect supports all of them.

01:06:59.460 --> 01:07:04.760
Try Posit Connect for free by going to talkpython.fm/posit, P-O-S-I-T.

01:07:05.700 --> 01:07:06.500
Want to level up your Python?

01:07:06.970 --> 01:07:10.620
We have one of the largest catalogs of Python video courses over at Talk Python.

01:07:11.080 --> 01:07:15.760
Our content ranges from true beginners to deeply advanced topics like memory and async.

01:07:16.160 --> 01:07:18.300
And best of all, there's not a subscription in sight.

01:07:18.800 --> 01:07:21.320
Check it out for yourself at training.talkpython.fm.

01:07:21.980 --> 01:07:26.180
Be sure to subscribe to the show, open your favorite podcast app, and search for Python.

01:07:26.640 --> 01:07:27.520
We should be right at the top.

01:07:28.060 --> 01:07:32.700
You can also find the iTunes feed at /itunes, the Google Play feed at /play,

01:07:33.070 --> 01:07:36.880
and the direct RSS feed at /rss on talkpython.fm.

01:07:37.540 --> 01:07:39.780
We're live streaming most of our recordings these days.

01:07:40.150 --> 01:07:43.240
If you want to be part of the show and have your comments featured on the air,

01:07:43.660 --> 01:07:47.620
be sure to subscribe to our YouTube channel at talkpython.fm/youtube.

01:07:48.640 --> 01:07:49.760
This is your host, Michael Kennedy.

01:07:50.180 --> 01:07:51.020
Thanks so much for listening.

01:07:51.190 --> 01:07:52.180
I really appreciate it.

01:07:52.480 --> 01:07:54.120
Now get out there and write some Python code.