 And we already know how to do that pretty much. We're going to type, say, print, and we'll see the thing on the next line. Here's something interesting. I just did get status, and we saw some stuff in color. Here's something else interesting. I just used LS. And I should mention, for this presentation, if you've got a computer with you and you can get to a Unix-style terminal, there's some stuff you can try interactively. And one of the things you should try is LS here. Because you'll see that as you change the size of your terminal emulator window, the output of LS changes. It dynamically decides how many columns of output to use based on the size of your terminal. So there's another kind of mystery that we'd like to solve today. How to do color, how to do LS. So that's doing different things differently. Also, LS gives you different output if you're piping it versus if you're looking at it interactively. So those are some of the things that we'd like to learn how to do. Here's some other ways that we use our terminals. You've got top here, which is filling up the whole screen. And maybe we can know how to do that by printing a bunch of text really quickly and then waiting and then printing it again. But that's not what's happening. Because as we see when we quit, it all goes away. So there's something else going on here. There's a third or fourth mystery, if you're keeping count. So many. Another thing is once we know how to, say, build up an interface like this, we're going to be able to do stuff like I just went too quickly. We're going to be able to do things like build a fully windowed system. We can build basically graphical user interface applications. We're going to call them text user interfaces. This is PUDB. It's the debugger that I like to use. It's kind of a nice interface over PDB. And you can imagine. You have a lot of opportunities open to you. As soon as you want to use your interface, you don't have to jump to QT. You don't have to go to the web. You could use something like this. And even if you take nothing else from this talk, this is a great debugger. You should use it. All right. What are terminals? What I mean by this is when I say the word terminal, I'm talking about this thing. You can see I've even got the little Mac thing there. That's important because this is only going to be relevant to UNIX terminals. Portions of this are relevant to Windows things, but I don't know how much. I'm not going to go into how much. I mean a terminal emulator. And we say emulator because the thing that we're emulating is these things, video terminals. But a video terminal was already emulating something else. And that was originally a teletype machine, maybe an electronic typewriter that sends signals. These have been around for about 100 years. We've had these for a long time. We had a typewriter, and you could change it such that it sent signals. I'm going to read a little bit of text from an ad from 1957. This was the 50th anniversary year of a teletype corporation. A teletype printer is a communications device with a keyboard similar to a typewriter that enables you to send and receive printed messages. So this is a copy for maybe a business person in the 50s to figure out that they wanted one of these things. With it, you can send, written word can be sent instantaneously by wire within the office or plant or clear across the country to a single destination or many at a time. So we're starting with this model of a terminal as basically a typewriter where it's not connected to anything. Your finger hits a key that causes the arm actuator thing to hit to put ink on paper. That's our beginner. But then we add the teletype part where we're sending a signal over a metal wire or a telegraph application. Maybe that's a telegraph operator somewhere else in another part of the country. Maybe that's a computer program. And then maybe we send signals back somehow. I don't know. There's maybe some metal wire involved, signal processing or something. Let's look at a modernized version. We're going to say we have these system calls like f-read to return bytes. We have f-write, which is going to print things. And now we're using a terminal emulator. There's some gooey stuff that happens to get the stuff to the screen and still keep presses. Go to the terminal. Because this is the Python talk, we're going to talk about print and input instead. This is a Python 3 talk. So input means raw input and Python 2. The first thing we should look at is what bytes we can write to a terminal and what happens when we write them. So I have kind of grayed out if you can tell some of the reading portions there. Well, what bytes can we send? First off, we can send ASCII bytes. This is kind of boring for most part. In Python 3 here, you can say sys.standardout.buffer.write and then send some bytes. Those will end up at your terminal. You can try this now if you want. And then we also have control characters that we can send. These are really small ASCII bytes. All right, let's give this a shot here. Say that I was going to try this here, import... import sys and we're going to do sys.standout.buffer.write and we can write some byte string here. But this is going to be a little confusing to look at because we've got a return value down here. So I'm going to do something a little bit different and you can do this too if you've got a computer there. I'm going to run a server over here that's just listening for bytes. So we're not going to see the input and output interleaved and then over here we're going to do import socket sys.socket s.connect to this thing and let's send some bytes. Great. So now we can tell that when we send ASCII bytes we get simple things like this. We're just sending them over. Here's our ASCII table. We're looking right now at the ones on the right. Kind of boring, but there's all this other stuff and remember this all makes sense in the context of a typewriter. ASCII things are, this is typewriter times. So what do these do? Let's try a few of them now. One we could try that you'll probably know what's going to happen here is satsend what happens when we write a new line? Guesses as to what's going to happen there. This is one you should be able to predict because we write new lines all the time. The cursor went down to the next line. You can sort of imagine that's what would have happened. Let's try something else here. We're going to write now a backslash ideas of what's going to happen here. Anyone want to use this one? You look, the cursor is moving backwards. So this is the thing that sort of makes sense on a typewriter. You could move it back and forth and now we could do something like overwrite that with a space. So you could see how we can implement maybe a backspace thing. Maybe we could also do a carriage return which means move the carriage of the typewriter back to where it started. And that moves the cursor over here. So we've just unlocked the power, the ability to rewrite a line and what that lets us do is progress bars. So here's a program that has a progress bar. We can now do this just with this knowledge of being able to write a carriage return to rewrite the current line. How would we go about doing that? In Python, we might do something like this. Just the general shape of the code. The important parts here are, let's see, that we're flushing. We'll do that a little bit later, but it may be important to flush if you're not writing a new line. We're writing a standard error. Also, we're not writing byte strings anymore. This is still Python 3, but now we're writing... I hope this is Python 3, but now we're writing unicode strings and we'll get in a little bit to how that works. But this code would work perfectly well for progress bars. So now you can add progress bars to your interactive tools. Who writes command line tools all the time, it can be fun to add some of these features to them. Let's look at what else we've got. So we can do terminal encoding. Terminals generally have an encoding. In fact, they had it the whole time, but the ASCII stuff overlaps because it was UTF-8. If you try this, I won't try it now, but this gives us an NEA. And then we can just say sys.standardout.write if we're using unicode strings because Python will take care of the encoding for us. We don't make sense on typewriters. These only really make sense on these video terminals. These are ANSI escape sequences. Before we look at them, let's try one here. I'm going to write slash x1b. If you're not familiar with this syntax, this is a way of specifying a byte that doesn't have a nice printable representation. Open 33m... Oh, it doesn't look like anything happened. All right. So the lesson here, the lesson we're about to learn is that terminals have state. So when I sent those bytes, it said, oh, I'm going to start writing in yellow now. And then when I sent more bytes, we're still stuck in this yellow mode. So this is the kind of thing that... You know, it's good to know that the way you signal this to the terminal is you send it some special bytes, and some of the bytes don't mean put characters on the screen. They mean change your state for future invocations. Let's look at some of the other kinds of things that we can do. The word ANSI implies there's some standardization that happened here. We can move the cursor around the screen. We can clear the entire screen. We can hide the cursor so that you could print things without seeing where the cursor is writing right now. Start writing in bold, start writing in red. So there's a lot of this, and you can just start playing with this now. A great Wikipedia page is the one on ANSI Escape Sequences which describes, hey, here's how to write in red. Here's how to write in blue. So now, look at a little parable. Say it's 19... How do we restart this? So the year is 1984. You can do this live. I think he has it up right now. And you log into some kind of BBS system, or you tell that somewhere, and it starts sending you sequences, and it's really cool. Maybe you're 12, and you think it's really cool, or maybe you're 40, and you think it's really cool. But unfortunately, on your friends' terminal, these show up correctly, and on yours they don't quite show up right. So this is the first iteration of... Who uses JavaScript? Sometimes a little bit. Who uses jQuery? So there's this thing called jQuery in JavaScript that became popular in this abridged history that I'm telling two main reasons. One, it papered over differences in browsers, and this was huge. There were browser incompatibilities, so we have that same problem with terminals. Different terminals behaved differently. We still have this to some extent, but it's less necessary now because things are more standardized. People are more likely to be using the same kinds of terminals. The other reason I think jQuery became popular is it's a nice interface, and we're going to look at some libraries in Python that similarly give you a better interface than the native one. So we have compatibility concerns. I was talking about the first things we did that would come up with databases of different terminals, how you do these different capabilities in different terminals. TermCap and then TermInfo did this. They wrote a library for applications to use called curses that accesses these databases and lets you say, oh, I want to draw a square, and it will figure out how to do that, and some lower level things too. On your machine, you can probably say man tput, or try tput space, and you have to know some magic sequences, and that will look up in that database how to make things red, how to move the cursor up. And then another thing you can look at is Info, CMP was going to dump information about these mappings with your particular terminal setup. Here is an example. So something you can do if you don't want to learn the Python ways to do this, you can shell out and say, hey, I want to clear the screen, and that's maybe easier to learn, but we don't want to do that. You can do these kinds of things probably in bash, probably system commands you have, but instead we want to use blessings. Blessings is a wrapper over curses, which is the normal interface that we use for accessing these databases to do a different thing in a different terminal, but it's much nicer. Here we're doing print this and thing in bold. Now the important thing to know about blessings is that mostly it just gives you strings. So t.bold of high there is going to be a string, and it's still your job to print that string, but it's going to be built for you, so you don't have to type in those escape sequences. Right, so let's solve the full screen mystery with blessings. So we saw before that using top, the entire screen was taken up, we could write things, and then it all went away. One more of these. Let's try from blessings, import terminal. We build one of these things, which looks at our settings. Whoops. This looks at our settings and figures out, oh, you have this kind of terminal, looking at the environmental variable term, and then we can say something like, what we're going to send here is t. let's do enter. Enter full screen, and then we're going to encode that for our terminal, and now we're back in the full screen thing. You can see it kept the current line, and there's some differences in how different terminals do this, but now we can write stuff, and then we could send our exit, and we're back into our original one. All right, so these are some of the kinds of things we can do by writing bytes to the terminal. So this is just knowing the language to speak. It's kind of in-band signaling, where we send bytes, some of the bytes don't result on things being on the screen. A high-cursor alternate screen, you can read them for yourself, and you can read man pages that will tell you more about how these different ones work. All right, next let's talk about what happens when the user types at the keyboard. You probably are familiar with it. You can say raw input or input in Python, and it's going to wait until the user types a whole line of text and then hits enter. So how does that kind of work? First off, there's this thing called the line discipline, which describes when you hit what keys, what it's going to do, when these bytes become available to the application from a read call. You can kind of play with, see, how this is implemented in the kernel, and you can see how they're implemented by playing with, if you type cat, then type some stuff. You'll see that you don't have control A, you don't have control E, as your kind of Emacs-style read line shortcuts. All that you have is kind of reprint, I guess we listed them here, backspace, delete word, reprint, delete line, and the application can't get the contents of that buffer until you hit enter. And then there are a lot of other terminal settings. This is the one that we're going to use as an example is echoing. So normally, right, when we go back to our typewriter analogy, if you have a typewriter, your finger hits the key, right now, and then a signal is sent, and then maybe on this copper line, it comes back and the typewriter can do something else, but it's always going to hit there. Hitting the key, the active hitting the key causes inks to go to paper. So it doesn't make sense. That's where this echoing thing comes from, but we're not stuck with that anymore with our video terminals. And the way we're going to do this is with this other interface, this out-of-band signaling, we're going to go out the terminal and say, you know what, I don't actually want you to, every time you hit a key, show that. So let's look at those here. Again, the relevant man pages are probably the best place to read exactly about how to do this, but we're just going to skip that and talk in detail about echoing. S-T-T-Y minus echo turns off echo. So this is a command line program you probably have, and then you can write echoes turned off. We can try this real quick. But you can't see it. Uh-oh. And then we can S-T-T-Y echo. And we're back. When your terminal is in a weird state, you probably want to type reset, like this, if it doesn't help. So who's cat at a binary file, or somehow your terminal gets into a pretty weird state, or a weird font, maybe, it gets messed up, and you're like, shoot, what am I going to do? Okay, so you want to type reset, and then when that doesn't work, you're already in the buffer that made it, so what you actually typed was blah, blah, blah, reset. So that's the other big hint from this. Type reset twice. I feel like that saves me a lot. So we can turn back on echo here. Let's do it in Python, though. We want to be using Python. There is GetPass in the standard library, which uses this, so let's look at the source for GetPass and see how that works. I'd mostly... So this is real code from the Python standard library. I would worry about just the shape of this generally. Term iOS, TC, GetAdder is the thing that we're saying. Like, hey, show me the status of all those knobs, and then you do some bit mask stuff, and you say, set the knobs in these ways. I'm calling them knobs, because imagine we have our video terminal right here. Maybe there's a knob on it, and it comes through and says, hey, please set your terminal in this mode. You say, oh, okay, I'll do that. That's kind of what we're doing here. And then really important, we have the try finally. So the terminal is a resource external to your program. So if you don't want to mess it up in that way that happens to us all the time, then you should be careful about... You wouldn't want to have an error without... and then not clean up after yourself, and then not restore the terminal to that echo state, and that's when you have to type reset. So we want to do this, but it's Python, so this would be a good fit for a context manager. In fact, we'll look at some libraries that do provide these kinds of context managers, but the sort of thing we want to do is say, oh, I want to modify standard in, I want to change it in these ways, and then I want to undo those changes. Here it's using that context manager. All right, so here are the kinds of things that we can do by setting these knobs. I'm not going to go into exactly what they are because we're going to use libraries that paper over them, but if you know that these things are possible, you can look up how to do them. Turn off echo, send keys, and merely I'm just reading again. OS.isaddy, oh, this is great. This is, does it look like a TTY? It is the thing that you're wired up to terminal, an interactive one, and that's how LS is saying, oh, should I display things in columns based on the width of the screen, or should I be just putting them out because you're piping this to grep, and you want each thing on a different line? And it's your responsibility if you start doing these fancy terminal things to make sure that your program still works well with piping if it's supposed to, and probably should. If it doesn't, then you get in the situation where you have a program that only works interactively, and now someone else has to try to use it in a script, and there are ways to do that. We'll look at it a sec, but it'd be nice if you can just work, check to see if you should be doing fancy formatting or not, where this is a TTY call. What else do we have? So echoing characters, okay, mapping bytes to keys. So again, you can do this with cat. If you type cat, enter, and then use your arrow keys, you'll see that, first of all, your arrow keys don't work, but secondly, that several bytes are being written there. So there's this mapping of bytes. If you hit A, yeah, it's going to be A, but if you hit F11, you get something funny. If you do shift tab, you have something. So if you're writing a program that's supposed to interpret these, it's your job to figure out how to deal with this. And again, there are libraries you should probably use, but it can be helpful to see that this is what's happening. What changed there? Nothing. Bites sent without being typed. This is a, well, we'll look at this quickly. This is a fun exercise where do you really understand how your terminal's kind of working. We're going to write some bytes to our, you can try this now. These bytes to our terminal. And what the terminal's going to do in response to this is write some bytes on standard in that we're supposed to read, figure out they didn't come from the user. They're a response to our query and interpret. And this doesn't really make sense if you're in that buffer and you only make the data available to the application when they hit enter mode. You should be in C break or when these other modes we'll talk about in a sec. But if you try this now, you'll probably get something like this and that prompts there on purpose. On the prompt, there will be characters because they've been written on standard in. And it's just funny to think about that a program could write to standard in or that you could end up with characters there that appear in your buffer like this. And what I was really trying to say is like, this is a cursor query. It's saying, where is the cursor on the screen? And you don't need this for much, but occasionally you do when you're doing interesting resizing things. Briefly signals. This is just another thing that we can get and set. Like hey, you know what, when you do control C, I don't want that to cause a signal that will cause a signal handler to run and I have to set that up. I would rather have this other thing happen. I just want the control C. Let me figure it out. Some of the signals we can get. SIG int for control C. TSDP is the suspend thing. Winch is for there's a window change. And the things to know about this are these three different modes. Cooked, raw and C break. These are groups of different settings that you might want to use if you're writing an interactive program. Raw is this mode where all signal handlers are turned off. I think all. And hitting keys just passes those keys immediately directly to your program. So you could say read and you would get them immediately. And then C break is a hybrid where you still have the signal handling. This is probably what you want to use because you still want the user to be able to break out of the program with control C. Now I'm going to run these right away. Alright, so now we're going to go through some of these... Alright, so we'll do questions later, but these are what I found useful. Some tools that are useful for this. How we should actually be doing this. Because I think it's fun to experiment with the actual codes, but then once you know that you should be using some library on top of it instead. The first off is blessings that Eric Rose wrote. We looked at it earlier. You want to be using... This is basically the library to use. that lets you say things like, as we see here, write this in bold, move the cursor over here, write this text. But there's some cooler stuff that's in blessed, which is a fork of blessings by Jeff Quast, and it's almost merged, but it's been almost merged for about a year. So if you wanted to go play with this right now, I would use blessed, and then hopefully in the next month or something, all the features will be merged back in. There's a branch on the GitHub for blessings that has all these features. They've been refactored a little bit, or not refactored, they've been changed a little bit. This lets you do cool stuff like the t.cbreak. So that puts us in cbreak modes, or keys available to us immediately. t.nkey translates the bytes in the buffer into a key press with a pretty name, and we can say, ah, that was spacebar, ah, that was shift, control, t, or something. And also some interesting formatting things. Anyway, Jeff did a great job, there's some really cool stuff in this, and if you just want to play with this now, I would start with blessed, and then hopefully it'll be merged soon with blessings. Erwid, that's how we were doing PUDB. This is a, shoot, this is Ian, I forgot his last name now, that wrote this, and it's a widget library. It's like, if you want to be using your terminal for some kind of full screen application, this is probably what you want. It works like a GUI library, if you're familiar with QT or something, it's gonna be kind of like that, or WX Python or something. Here, again, let's remind you that PUDB is cool. Well, it's gonna take too long. PUDB, the debugger we saw, is pretty cool. Some other tools that use this, forgetting now, but there's some other ones that use it that are similar, pretty neat, right? You want to write things like this, this is pretty cool. Clint and Klick are two command line utility libraries, so if you're still writing this call and response style application, but you want to progress more, but you want to print something that is wide as the terminal. You want to have something in red, you want to wait for a key. These are maybe the libraries you want to use. I've not used these much, so I can't talk about them much, but I've heard buzz about both of them, that they were good. Readline, if you want fancy editing on the command line, this is probably what you want. You don't want to re-implement this from scratch. This gives you control A, control E. I think in Python three, four now, this is kind of enabled by default, it's with the tab completion and things, but if you want your own tab completion, you can use this. And a lot of the times, when people I think want to do fancy terminal stuff, they're thinking of the things they get for free with Readline. So Readline is a way to put in user space what usually happens in kernel space. Normally the kernel is in charge of buffering up these characters, letting you do a few things, like deleting a word or deleting the line, but Readline says, all right, I'm gonna C routine, I'm going to put us in C break mode, so we get those signals immediately, and then, so I get a key, and then it can say, oh, you did control A, I know that that means move the cursor back to the beginning of the line. Oh, you did control E, I'll modify it in this way. So you're in user space while you're doing that stuff, and you can modify Readline, and I've done a little bit of this kind of forking Readline to do interesting things with it, and it's kind of fun because lots of programs use it. Next up, okay, this is a program that I wrote, which I shouldn't spend too much time on, but we wrote it for B Python, which is the thing I had in the left tab before. This is an older version where we're having a little demo of what keys you're pressing, but similarly to Erwid, the idea is what if you had the whole terminal as a canvas and you just paint over it, except it's more of a hybrid where you still have a column response kind of thing, but you get to pop up windows over it, or but you get to, we're gonna do it in sec, you can rewind back, so we're gonna do control R in sec, here it comes, I guess we're getting lots of text first, but you can do things, there we go, so we rewound back up, so these are things that don't make sense, if you're doing this kind of thing, you can't be using Readline anymore, you can't be using the normal, you need full control of the terminal, and I shouldn't spend too much time on this because Python Prompt Toolkit by Jonathan, someone or other, is much better, it's just better code, it's better than the library that I wrote, I don't think we're gonna migrate to B Python anytime soon, but this is great, and if you wanna do, there's some great interactive MySQL and Postgres interface library, or interface tools that have been written with this, this is great for, I want a command line tool, but I want the pop-up auto completion, but I want an editor in my command line, and here's a, we'll briefly a demo of this, the cool thing that they're doing there is this full editing anywhere kind of IPython style, I'm not sure how to describe it, I'll just wait for it to pop up here, so it pops up at what looks like an editor, but you're still in your terminal, there's a OCaml REPL called UTOP that does some of this, the Julia REPL has some of these things, but it's just nicer, this is a syntax error and it popped me back up to where the syntax error was, this is pretty cool, but I don't know a bunch about it. Okay, a concept we should be familiar with is a PTY, this is a pseudo-terminal, this is what you use when you wanna run another program in such a way that it looks like it's using a terminal. Probably you should be using a library over it, okay so a PTY lets you do kind of meet things like take the output of a program and re-render it, what we're doing here, this looks kind of like Python, it's a working Python interpreter, except that there's a case transformation thing going on every five seconds or something, it flips the case, so it's just kind of funny, but you could imagine kind of transforming the output of some program, so this is a pseudo-terminal, this is also how terminal emulators are written, and where I first saw this was people writing tools for assisted net hack play, so they're playing a game and they're not gonna change the code for net hack at all, this is one of the rogue-like overhead things, but they want to modify the input and the output, so this can sit between you and some other program. You probably want to look at PXPECT, which is a Python version of the XPECT program, this is for interacting with command line tools that want to be interactive, they want to have a user at the helm, but you want to script them, of course. Okay, a cool tool here, if you've got a computer open, I try right now typing telnet space termcast IO, Jesse didn't write the original termcast, but he wrote the Python versions and the Python conference, so here you should check these out, he's written, this is the idea that because terminal sessions are just a series of bytes, you could beam those bytes to everybody, you could say, hey, check out these bytes, I guess we should try this now. All right, I think I'm not online, it's probably a problem, right? All right, so let's not, oh, thank you, RG, right? Termcast.org, all right, we'll skip this for now, but the gist is you can see, if someone else has a session and they're sending, oh, I sent this byte, I sent the byte that makes it red, I sent the byte that moves the cursor over here, you could just get those bytes and then replay them in your own terminal, and you have very high fidelity, kind of low bandwidth screen casting, basically, of just your terminal. So check this out, also you can, it's easy to broadcast your own terminal session if you mostly work in a terminal, or you could broadcast a TMux session, something like that. And the more web-friendly version, kind of user-friendly version of this is, I gotta remember how to pronounce it, anybody? Askinima, there's a nice way to pronounce it that has the word cinema and aski in it and doesn't have ass and other words in it. But this is a cool tool for recording a terminal session and then making it playable in a browser. And finally, I'm gonna talk about a few ways that I've used interesting terminal things. Here's one where I'm using, I think this is maybe a common possible use for interesting escape sequences and formatting things, which is formatting test failures. This is one where we're doing it in B Python, which is like, hey, there's something funny, instead of any, it says Armadillo and we kind of highlight those. And if you do it in your own terminal, it also blinks, which is kind of fun. And then I have another program where I needed to test that the window resizing was working correctly. So there's a program called TMux P, which lets you script TMux in Python. And I have some tests that open a TMux session and then try resizing the window and see if we're treating that correctly. I just found that with the easiest terminal emulator that was scriptable. So you see it's running these tests now, not yet. It's gonna run the tests in a second. And we'll see a resizing TMux window to test to see if we're kind of correctly treating these things. And that's about it. I have some kind of further reading things. This is not posted anywhere yet, but I will let you know on Twitter when I finally have a blog post up that lists all these resources or at least a version of the slides that's successful. Thanks, that's it. I think we have a few minutes for questions. Maybe not a good question, but how does the syntax for the special characters work? Like the slash x1, the bracket? Sure, yeah, yeah. So the gist there is that when you have Python string representations, you can do stuff like, whoops, you can, there are multiple representations for a string. Where I guess we're gonna, are we in Python three? So I guess these are gonna be like unicode strings here. But if you say slash x61, and then you say a, these are identical. Slash x61. So slash x61 is a way of describing, in fact, maybe it's clear if we try ord, oops, ord of a. Yeah, but this is, you know, this is hex, right? Right, exactly. Yeah, this is hex. But in those special characters, you had like other letters like one n, and n is not a hex, this is all digits, so what is it? Right, right, so just when Python renders strings, some of them end up, so if I say slash x61 slash x02, some, oops, not ord, sometimes it renders them, sometimes some letters have pretty renderings, like 61, some don't, or hex 61, and some don't like 02. So isn't the Python wrapper code where it says, ah, this one isn't? If we try printing it, then it's gonna just not print, oh, sorry, it's doing well, right, we just don't see it, because it's not like a printable thing. When you send that to a terminal, it doesn't do anything. So it's just a different way, is it just like you can put single quotes or double quotes around a string? It's a different way of describing the same literal, and then in the print method it says, ah, does this one have a pretty representation or not? Is that? Not exactly, I get that, but you had those special terminal characters, like slash x1b, bracket, one and something, and I don't know if that's hex or what is it, like how do you read it? Because I had problems with it because I have a setup, I have a Windows machine talking to a remote Linux through Tmux and through Midnight Commander, and I basically have problems with character encoding all the time. Sure, so these kinds of things here? Yeah, what is that? So that is, I mean, the first one is an escape byte, so it's that random byte. The next one is a real open square bracket, then it's a real three, a real one, and then an M. So they really are those characters here. The difficult one to deal with, I think is the first one, the escape character, which, and I have similarly similar setups where it's like, okay, I've got this thing, then I've got Tmux, and then I'm SSH'd in somewhere, so you have to trace it through each level and hope it kind of passes it through. So what we're looking at really is, so the start writing in red is one, two, three, four, five bytes because the first one is the escape byte, and then it's a real open square bracket. And if you read the Wikipedia article on the ANSI escape sequences, it please hand waves about it a little bit. It says, all right, when we have a sequence, it's gonna be more than two bytes. We use this longer escape thing instead of just an escape character. We use the open square bracket as well. So yeah, the pass through is difficult. Yeah, I agree. I've had trouble with that as well because you have to trace it at each level. Are you really getting those bytes? And they're not visible bytes, so you have to do it like to a file and then use something that can read those bytes. Okay, thanks. When talking about the read line library, you mentioned several key bindings like control A and control E. What would be the authoritative source for all of those key bindings? Because like you've probably seen that there's support for that in macOS, but it's sort of, sometimes it works, sometimes some of them don't. Where would be the authoritative source? When I've looked for that, I've Googled for read line. I don't remember what site I was at. I've just Googled for read line shortcuts. And I found one that looked kind of authoritative. And so we had to do this for B Python. We re-implemented all of read line, basically. And so I learned a lot of read line shortcuts. I didn't know about whatever it is, meta close bracket, is it? Or something, maybe it's meta slash, that runs, copies down the previous word or something. There's a lot of these. I only, right, sure, yeah, yeah. So it's using real read line, I think it should. And it's looking at your dot input RC and things like that. So I don't know, but I would blame whoever wrote that program, either they're not using read line correctly or they re-implemented it and only re-implemented some of the shortcuts. You still have time for one short question, if someone has? Hello? What was the name of that called interactive Python? Oh, that's exactly the question I was hoping to get. Yeah, this is called B Python. Okay, that is B Python then. It's great. You should all check it out. Really good. Look at this. Is that available online or? Look at that. And then capitalize. How does that work? Oh, those are the docs. Isn't that great? Check this out. I can undo. Now A is not defined anymore. Wow, yeah. You should all check this out. This is great. I'll be sprinting on this because I've just ignored some issues and pull requests that have come up. So at least on Saturday I'll be looking at this a bit. And I think we have bite-sized bugs if anyone wants to kind of help contribute with this. All right, thank you. Great, thanks. Thank you.