Vimlike Editor in Rust #09 - Gutter and Keymappings

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right hello hello everybody Welcome Back to another stream or another video working on my rust editor Vim like editor and first I wanted to go through the things that we accomplished uh since the last stream but before that uh let me tell you if you want to hang out and talk a little bit about the development not only of the editor but future projects or if you want to talk about rust in general or even programming in general I just created a Discord server and uh invite is going to be in the description of this video make sure you join and uh and come chat with us there all right all right so let's start talking about progress um so in our last video um we were s able to successfully parse uh the themes from vs code and we had an issue that we were uh being hang hang uh we were having problems mapping the vs code Scopes to the ones that that we uh get from treer right and so if I open the code here we were and I go to the vs code theme parer basically what I did since the last the last video was I went through all the Scopes that we get uh from U treer and I mapped them to the ones we get from a vs code uh theme I think it's still not perfect and you'll see that we have a few um things that don't quite match 100% but we get on vs code but I'm definitely calling it good enough for us to not worry about theming anymore at least for a while okay so let me show you uh what that looks like let me make this a little smaller and here we go so if we look at the themes uh folder here we have a couple right and let me see the one that I have here the last one that I tried was Dracula let me open the page for Dracula uh let me get vs code here vs code that's not how it works okay Ides you know what Dracula vs code here so this is what it should look like in vs code right so if we run it here now um this is what it looks like in our editor as I said not 100% the same but I think it's pretty darn close especially if you look at it here and here you see that it's close enough that I'm calling it good but not only for this theme right let me open another one I have here Nord oh nard has a comment let me open no and I'm not yeah let me put that as a to-do vs code themes allow comments and leading dangling Comas so we can address that later let me just fix that real quick like this one here let's see if we have more I don't think so all right let's oh this one like that let's try it again so we have one in 319 no we don't so what is this about 319 interesting okay well I guess n's not going to work let's try night Fox there's night Fox and I think it works pretty well as well as we move through so yes I'm calling this good enough for now and then we're going to take take it from here all right so and then what's the plan what's the game plan for today so today I want to start working with the gutter which basically is this uh part of the editor where the lines are shown uh then apply some Styles if if it's available from vs code themes and if we get to do that which I don't see why we wouldn't be able to uh I'm going to go to stretch goes and start working on some editor configuration and then the the other thing that I wanted to do is to get enough movements working in a way that I can start building the editor with my editor if that makes sense or at least trying to right to see the gaps that we have all right let's uh let's then start working with the gutter and let me just say here that we're starting this at 00 08 55 so I can do the proper chapters on the VOD all right so let's keep night Fox here and I think uh if we go back to the editor what we should do is go to the draw method and I'm going to add a method here that before drawing The View part we're going to do oops self. draw gutter like this and let's implement this new function so it's going to be oops Pub don't need to be public function draw gutter take some mutable self and it can fail okay all right so what we need to do let me turn off co-pilot like that uh we need to for all the lines that are visible in our viewport we basically need to go to the position of that line and render the line number right I think that's easy enough so for um line for n in zero to self. V height um of course so uh standard self standard out uh um Q style print uh let's do a space and then the line number um with spaces after it and let's do uh n where and format where n is going to be n + one like that okay then okay and then here I think we need to do n and here it's going to be something like let me remember how to do that uh format rust uh padding yeah so let's do that um with the width and for now let's instead of doing like this let's just do uh five I don't know so cursor move to zero n like that and of course the viewport is uh going to be rendered on top top of it so let's disable temporarily the draw of the view part let's see what we get so seems reasonable seems like we have the lines the way I expected uh the only thing is that I think we should what happens if we go one page down so it's always showing yeah of course this is not respecting the initial uh line of the buffer let's adjust for that and I know we have that somewhere cursor X cursor y is that the vtop no I think that's let me check I think it's vtop let's see so for n in self. vtop no not here so n is going to be+ one plus self. vop yeah yeah yeah cannot add your size 36 oh this is e I6 U6 actually let's see so if I go one page down seems to be working so if I go back to the top and then I manually go yep seems to be perfect so let's just do the following let's see what is the maximum number so we can only use the number of spaces we really need for the gter uh here how does this work do we increase if we get those line like thousand that's a good question but I think we can do the way I'm proposing so let's see draw gutter so we're going to do let max line is going to be self. V height plus uh self. vtop b top is your size like that and then let's L is going to be Max format Max line. Len like that and then we can do instead of five here let's do wiith and then wiith is going to be uh Len and it really should be Max Len yeah let me remember how to do that um so what if I want to do this from a variable the optional few characters provider with the width okay format variable weight length sorry with oh my god um format view variable with this oh the dollar sign is after so like that okay yeah so we always display the gutter with the amount of spaces that we need that's good for now um I think maybe we should do this for the whole line yeah do we know how many lines our buffer have I'm sure we do Len so yeah let's uh go back and let's make this MAX Line instead of this let's do self. buffer. Len like that this way if the file has a thousand we always optimize for that and you can see that now as long as we are on the same file the lines are not going to take more space good I like that better okay now we need to restart drawing the viewport but we need to to start drawing The View part at the proper place because if we just uh oops we just restore it's probably going to override when we did before so let's take a look at draw view Port um okay we need to have the viewport X where the viewport should start so let's take care of that so that's going to be a u16 as well and then VX is going to be zero do we have the buffer we do so I think we should do VX is going to be okay let's go to that MAX Line let's make this a calculation so let's create a function called max line or gutter with and this will return a u16 okay and then we want a space before it and Max L yeah then we don't need to do this I'm thinking hold on what's the best way to do this cuz the width is going to be okay thinking yeah can do Max Lin minus one yeah I think that's fine so width is going to be self. gutter width minus one from my next line self. buffer n we can do actually I think self self. buffer. len. pars string do L maybe let's see this is going to return a u size um U size to string rust two string okay two string L and then let's make this use size self. gutter WID and then we can do minus one here like that that should be doing the same thing even though yeah we don't have let me just uh disable the The View part again just to see if our little refactoring here worked and it looks like it did but it's no longer aligning correctly I think let's see oh what just happened I just went back to the beginning ah it's not using the same width every time let's see what I'm doing wrong here so let Len equals to this log Len Len equals Len like that and then let's return Len run L equals three oh it's plus one it's not so let me think the L is not oh it is yeah let's break it this down so what's the maximum line and then let Len equals to Len so the last line is 693 which has indeed three numbers so the width has to be the gutter with minus one which is oh it's notus one this is not gutter width this is if it's gutter width we need to do L plus one and then we can safely do this here right let's see yeah it feels like it's right now so if we go here and we go back to the beginning yep fixed all right so now we can restore what this was before like this and just return it like that should continue to work which it seems like it does oh no we're doing gutter with three now here we have to do plus one and now it's working perfect all right so now that we have the gutter we need to re we need to move the viewport a little bit to the right so let's tle that so X is always zero so we're going to start with self. VX let's see what happens if we do that nothing changes why if we are uh so let's see x x equals z so every time x equals zero we need to do self. VX like this try it again still nothing Prett print charm uh is VX being set no it is not so let's go back to New so when we instantiate the editor this is being set to zero but instead we need to set it to self dogter with we don't have that here of course we don't but we do have the buffer right so cutter with so I'm just going to yink it for now like this not self but just buffer borrowed yep because I'm passing it here let VX equals to this paste it here good yep that's a lot better uh let's just do plus three and it's taking shape look at that the cursor is wrong and all of that but I think it's starting to take shape so for now let's make sure that we draw the the gutter with the same color that we have for the default color for the editor so if we go to draw gutter instead of just print we're going to do print styled content and then where do we mhm we pass a style so we can pass the theme Style stle let's see what is this style used for is this used oh it is so when you do two content style it it has a fallback style which is the default I'm a little bit confused but I think we can leverage this guy draw gter so instead of print styled content oh no we can't use this what we're going to do instead is we're going to instantiate uh so let thinking thinking thinking what's the best way to go about this because our default um style can have like a foreground but not a background so let's do what happens if we do this format here and then we do with self. theme do style. foreground yeah let me see what's the issue consider using uh expect right let's do that like that for now on self. theme. style. bg. exect BG is defined for theme like that and with that I think we're going to be rendering correctly and no it doesn't look like it oh it does it's the separation that is wrong here because we are not clearing after so here we need to do like one two for now and now we have this correctly good okay and here we only have one space let's do the same so where we are VX equals let's do plus two and then if we go to render gter or Draw gter where we do three spaces here let's just do two yeah I think that's looking good now let me open a vs code theme uh let me get the one that I'm using there which is Dracula base and C bride so here we have terminal background foreground do we have something for lines let's see editor line number foreground I think that's what we need so and that's coming from colors okay let's go back to to our theme um and let's add uh where's theme here let's do Pub line or gutter style is a style right um and then let's go to vs code so here we are missing the feud gter Style and so let's get that so let gutter style is going to be vs code theme dot before we do that let me go back to the other file what's the name of the Dracula it's colors so let's start parsing colors for the theme where is the here oh you're already doing that okay but is that line number editor line number we are already using the we already have the colors being pared so which is great so this way we can just go ahead and add that uh here so let's do the following La gutter style equals to uh style and then foreground it's going to be uh vs code theme. colors. eater. find color where sorry it's going to be color and value where color is editor dot uh line editor line foreground or editor color editor line number foreground like that dot unwrap or no this is an optional so we can do it like that and then background is going to be same thing so maybe we can do no we have to run it again V to the end of the line yank p paste replace this word to background there we go okay what is the issue can compare string with an Str strr okay two string maybe oh this is a double we need to do that expected types option color oh of course we need to parse RGB here do map we have the hex uh parse RGB hex like that what's the issue now yeah so MH found reference value why is that this is returning string this returns an option of the key and the value that's exactly what I wanted so what is vs code theme let's take a look colors is string and value that's the problem so the value yeah we need to yeah that makes sense value has to be a string so s sr. expect colors need colors are a an XX string mhm expected option color found that option result yes because this can fail um unwrap for now there we go like that and then we need to just do this to dot to string then we need to do reference C twice missing Fields B and let's the B false italic false or rather can we do default here we can okay so now we have the gutter style Let's uh just add that that gutter style perfect uh we're not using V here and we're not using C here same here and same here okay and I think we have our gutter being parsed let's go back to our editor and where where we doing that cell theme gutter Style gter style yeah and in this case we can do this so hold on so let's do let FG is going to be self. theme. Style no not style do gutter style. FG unwrap or self. theme. yeah we can copy what we have there here and then paste like this and then the foreground is going to be the same but with BG so let's just do this oops equal self then this so let's just uh replace FG with b g like this and then here with BG and this is BG actually and this is FG so now we should be using the gutter style and if we don't have the gutter style we're falling back to the theme default very nice let's see now what we get and looks like this is correct I think it's using a different color altogether for the line and attempt to subtract with overflow at line 248 so self. withth minus X yeah and this can be let's do uh dot uh saturating sub X and we don't need this anymore I think that's fine with is a U6 right it is let's see now what happens if we go to the end of the file and we try to move further that's fine perfect yeah we need to stop printing this let's take care of that um draw gter selfie height um let last line is going to be self. V height or whichever is is less right or what we can do actually is if let line number equals to this and we can do line number here cannot mutate to mut yeah that makes sense and then if line number more than self buffer. Len continue let's see now if we go to the last page you ran this correctly no more artifacts when we oh interesting so yeah this line we need to handle line wrap let me add that but for now what I'll do is I'm going to truncate the line so if we go to the last line yeah this line here is definitely wrapping so let's see if we are trimming the line and if we are probably we are not accounting for the gutter um size so let's see draw viewport here um PR chart I think we just uh keep doing it while let some is e. next yes so if x is less than self. viewport wi we print this I don't think this is going to do anything but we can try seems like it worked good all right I'm happy with that okay so next we need to fix the cursor position because we need now to account for the for the gutter so let's see where we are drawing the cursor um status line viewport set cursor style Q show let's see where we're doing the move to here so it's going to be self. cursor X now I think cursor X needs to start self. CX if self C XIs zero and this is the I think it makes sense to move it because we're resetting it to zero so if you go to the draw um let's see what happens if we do here self. viewport X Plus self cursor X okay seems to work nice um and I'm thinking here the gutter can be drawn after we do this right before we flush I think maybe not that's uh yeah I was trying to optimize because it's feeling really slow like the cursor is blinking badly when you move things around but I'm not going to try to optimize it just now let's worry about optimization after okay now let's see insertion does insertion works it does look at that undo works let me delete a line undo continue to work nice I'm impressed this is working better than I expected okay so I think let's see what we achieved oh I forgot to put the time for this guy but both of this things are done so let's go to our stretch goals uh do we want to do editor configuration or do we want to improve movements thinking thinking thinking thinking actually let's do the following let's commit more example themes uh so let's go and here's the view part yes yes yes gutter style yes yes and yes um edit gutter so gutter with line number Lumber okay good so let's start thinking a little bit about editor configuration I did some work um so let's try the other theme here which is Frapp the one that I'm using on my vim and let's compare I think it's pretty oh we need to add mouse support as well like that let's go to the beginning here yeah I mean the one designed for new Vim has a few things that I like better better like it's highlighting better but I mean it's good enough right all right so now let's go to that config branch that I created uh let me talk a little bit about what I was thinking for the configuration okay so uh I was thinking about um how ZJ does configuration because the main thing that I wanted to do is to start allowing uh the user to remap keys and I think I like the way that zel J uh tackles that and it's also a project that I really like and they use this configuration language called KDL and basically if we go to my configs and we open zel um we open zel J and config KDL this is how they do the key binding right you have the modes you have normal locked resize and whatnot and then they do bind then the key that you want to do and then a sequence of things you want to accomplish when you do when you press the key right so it supports a lot of different things which I find is very interesting uh so for instance you can do like switch to normal and then you can provide the mode you want to switch to there is this very complex example here where you launch a plugin pass in some uh attributes to your plugin and do then do another action that you can like do actions in sequence as well which I think is pretty interesting right so and I played with this idea let me see here uh um red we are on the branch let me see so what did I do let me see here config so I created this structure the only thing that I found a little bad with KDL is parsing is not as straightforward as you would think for instance here I think I created a test here I created a test where we have key bindings then pretty much emulating what we had on ZJ and let me show you how nasty it is to parse this so basically you have to parse it into a KDL document and KDL document you can get like pieces of the document so in case I get the key bindings and I think it's beneficial for us if I open another uh the config file here so you can know what we're talking about actually let me go to configure s because we're talking about this structure here actually so then you get key bindings you see key bindings is like a top level node you get its children and then you do let me see key bindings is the structure that I'm I created that I want to parse is this here so we have normal and insert and then basically you need to get the children of the bindings node and iterate through them and then you do uh you get the name of this node here and then you see is this node normal or insert if not we say invalid keepy mining setting uh then you do get all the nodes of the children sorry we we get all the children of the the node so the normal node let's say and you iterate through them uh and then here you have to map entries it's no longer nodes it's entries and then the entries let me see what I I'm doing here I'm converting them to string and then collect collecting as a vector of strings then I get the children off this node and then let me see um try trying to remember this this a long time ago because what I ultimately wanted to do is to get this action descriptor let me let's take a look at that so action descriptor oh wait what did V just quit on me what that was interesting action descriptor come on there we go so I wanted to have like a the name of the action let's see normal so the name of the action and a vector of things that we want to perform right so I think the name of the action would be like J and then a vector of things we can do which be this case would be only move down that's I think was the ultimate goal here and then you either add the this action description which I I'm calling actions here so you would have a vector of them so with all all of this and we would then add it to either the normal or the insert key binding so that's what I did and then if we look at the test that I did here is basically I think that where you would do disy binding and then I get the J ke key binding and then I make sure that it created uh I have an inem here that it's either a binding soe an action or bindings let's see keep bind oh yeah yeah yeah um so bindings take up bindings no no no bindings is a key map which is which is a hash map of a string and an action descriptor I'm a little bit lost to be honest let's see but let's see the test that may should make it clear so down here yeah I'm making sure that this that J maps to an action oh but the letter D oh yeah yeah now I remember like the letter D here is not only D is DD when you delete the line so the the child of this command is by itself an action descriptor you can think that you could have multiple commands that do that right and now I remember where I stopped and I was having second thoughts about this is that like for instance if I do if I am at a line here and I do let me open key Caster let me see if this is working a yeah let me put it here so if I press delete two and then colum it's going to delete to there right so the idea here is how do I configure uh those bindings to accept like a a wild card key right because I can do delete two and then anything right uh and how would I pass this thing up to delete to next car so let's say that I in this case I I did DT and this right and then I would need to call this with the column as my attribute and that's where I was strugging struggling a little bit to think what would be a good representation for this third parameter right and I was thinking maybe it's zero here which is like a the zeroth or the first parameter or something like that but then I need to reflected here so that was a little Annoying and I didn't know what to do and the main reason for that that you could say like uh okay so why not do anything that is more than one character but I can't because like Escape is valid here we could have something that is hardcoded like I don't um like this Char right but then what do I write here do I do Char and then I need to start worrying about like the the this uh when anything starts with a column then it's a special parameter H didn't sound right to me I don't know so that's where I started to struggle um so I think um if you're watching this video right now and you have a good idea on how we could do this uh please leave a comment down below otherwise um I mean it's a solved problem right I'm sure a lot of editors do this how do how do Helix do keybind these now I'm I'm um curious let's see maybe we can find some ideas here no maybe I have a I probably have a a configuration for Helix um Helix config TMO so they use Tomo which I much prefer oh so they do it like this Keys insert key I think we're doing this okay I love this so much simpler and then the actions are things that are oh no this is a because it's a command okay that makes sense and then yeah the actions are actually those items okay H I think we have a winner here I'm just curious to how do they do with commands that take uh extra parameter so I'm thinking about it so maybe if go to start line go to line start is an inum and that inum takes a value and that value is not passed that's maybe how you figure that out let's see um so just to remember how does Helix do delete two I don't know delete three lines multiple lines 5xt so you do the yeah you precede that with five but what delete until character Helix delete everything until a character it's End of Line yes this one here until there's a builtin support go to last modification so maybe they do not support that delete to End of Line uh the red is a character in Helix but on him so T rat D okay okay yeah so I think we should do Tomo that uh for me is now that I saw this I don't think we should go any other way so we're definitely using tumml so let me abandon this idea of using um KDL let's go back to master um let's rename this Branch here config let's do get check out Branch config KDL let's go back to master which branch delete config good all right let's start a new branch and then let's create Source config let's cargo add TL then let's take a look at the TL crate and then let's create a config TL and let's see key bindings uh config Helix config tunnel okay keys I like Keys let's do that so in our example let's see that I wanted to remap uh let's see what I remaping one example of things that I remap on them uh so here key map so yeah control a um let's see one here that we already can use yeah there there's a lot of vi v spits and things like that okay let's uh create something here so uh let's do that um let's map undo to P we're not using p right now so edit uh config helix config so here we would do like P equals 2 and then let's open Editor to see um move to okay let's say that P is going to be move up right like this then we could do multiple things right let's see p is going to be move up and then move right like this so we would trigger two actions um tunnel array tunnel array yep even better so P would be move up and move right like this right and I think we should start by parsing this and then remapping the key maps Oh but before we do that I think what we actually should do let me do this let's open the editor here let's go to the actions uh because now we're doing keymaps um hardcoded so let's create a config that actually has all our mappings here they are so actually let's keep this one as a funny example uh but on the normal mode what we need is O it's going to be insert line below cursor and I wonder if I can do just this here yoink p word delete same thing here delete delete delete delete insert this like that then we can do perfect oh and we actually don't want this okay then set waiting command takes an attribute how do we pass that in uh set waiting command in this case here no it's going to be can we have a key on Tomo that is an array I don't think so but I think what we can do is the following um let's see data types inline table let's see Tomos spec so in case I want to have multiple commands under G think I might need to do something like this here so G is going to be oh and actually I don't even need those do I let me see let's keep them ah and they do have the same deal where if you have multiple okay so yeah p is going to be not P but d g so G I have the handle handle waiting command and then for the command G we have GG that goes to top okay so then we do G again yes and that's going to be moved to top love it um then we have Z but hold on let me go back to our normal so we did up to here let's do those let's copy everything why not yank paste whole thing delete like that good so good all right and then when we have some action like this we want to do like this then we can do this and oops same here okay and then here we can do this home move to line start or beginning start same thing here move to line end then end is also going to be this then this is going to be also moved to line then let's uh do replace this by this here same thing like that and then d d is going to be if we do do is delete line what else do we have on DD I think that's the only one we handle so far um handle waiting command DD handle waiting command and then if yeah D is the only one and the only one for Z is z and if it's Z what we do is move move Line to vport Center like this okay we have b b is so actually it's control B this ways greier um page up and then control f is page down okay so I think we mapped everything on the normal mode that we have here uh except those look here yank paste let's see if I can record a macro here recording Q go to the end no q q let's go all the way to here let's do V end of the line move left twice yank create a new line paste oops create a new line ask paste go to the beginning insert a comma stop go to the end add add a comma stop go up [Music] go two words right then do V end of the line yank down add equals Escape paste and then Q again how do I redo the macro is that like this Vim replay macro recording your macro q q yeah I pressed I think I pressed s Escape so I ruined everything so but I'm going to do it again okay so let's start recording a macro let's go to here then we're going to do V end of the line move left twice yank create a new line Escape paste go to the beginning of the line insert this go to the end of the line add this equals then go up uh visual mode to the end copy down down add actually go to the end of the line paste uh go down delete line and I think that's it let's see now how do we replay it so like this almost that didn't work too well oh bummer let's see if we can do that again so here recording Q let's go here visual end of the line to yank open a line above it Escape paste let's stop here what happens if I repeat this at the beginning of this line here oh I didn't yeah so let's see Q There we go there we go yeah I think I was close but you know what I'm going to try it again so here we are here uh let's start our macro let's go here move for do uh visual at the end of the line to here yank create a new line Escape paste escape and then I go to the beginning of the line and two down to here let's see now we got it perfect very nice slowly but surely okay we move down here and then control+ V Let's insert V oops insert that okay ready for another micro let's go so we're here um copy from here to the end of the line yank um go to the end of the line paste insert equals Escape move right insert move Escape go down delete the line go to the beginning of the line and that's it let's see check this out not too shabby right yeah it's very fun to learn them hopefully with time I'll get more acquainted to it that's partially the the reason why I wanted to do this exercise actually all right so we have our file with our key findings for everything so let's see if we can um adapt this to using that all right so let's go to our config do we have anything no Let's do let's create um Source config RS and let's create a function Pub let's see before that let's create our config so like this and then we're going to have um key keys which going to be um for each mode let me see here um Pub struct keys and then we're going to have normal key then this is going to be a hashmap of a string to a vector of actions maybe yeah I have to think about it let's see okay and then I think not only actions because we can have like in this case here enter mode mode insert I think like this most likely it's going to be enter mode and then mode takes a mode right enter mode action enter mode enter mode yeah so we'll have to see about that um Vector of action actions so each action can be either yeah let's let's leave it at that for now and then we have normal and we have insert and then the config is going to have keys and then let's also do the theme which can be a string pointing to the file I think that's fine so let me see here yep pretty much what we have let's do theme equals themes slash um nx. Json now why is not is mine not being oh it is it's just that if you use quotes here yeah yeah yeah nice all right um so we have a combination of keys and then theme pretty much that okay so let's start writing some tests co-pilot off um mod test use super asterisk and then Pub um co-pilot disable function test load config then we're going to do actually let's do the following test persist config then let's do let's config config equals to config then keys are going to be Keys normal it's going to be hashmap um I think it's from let's see here um rust hashmap from yeah I think this it's this guy yeah then you have a topple off let's do this uh then you're going to have this is a string so let's do o to string and then the key is a vector of actions let's do it like this and then action uh insert line below cursor like this now let's go here to Main let's do mod config this let's save this let's go here to the next one let's make sure we import hashmap Next One Import action um let me see if faction is actually it's not public as in um s uh Pub we're going to have other structures okay I thought mode is mode public already I think we're going to have to make it public so I'm going to go ahead and do that Pub okay perfect so config missing few theme yes theme is going to be theme nighto fox. Json okay and then let's do tumml let's see how we do serialization in the tumml crate we do pars from s strr then to serialize do you do two string okay let Tomo equals tho to string config do un rep PR L uh tunnel like this here we go to string missing Feud insert yeah yeah insert is going to be hash map new Keys has normal and inserts we're missing a qu comma here there we go so if we try to run this now it's probably going to give us an error that we do not Implement serial eyes but let's see yep derive serialize deserialize this this guys also need to be seriz is not satisfied oh because action is not serializable let's go ahead and do them yank and then we need to make mode as well serialize the seriz like this perfect now let's run our test so if I want to so we have the theme yeah I wanted to print this Tomo Tomo is going to be string already so we don't need this so let me take a look theme theme Keys normal o insert below cursor oh this is an array always uh we're going to have to make this a n because either it's going to be an array or just a single action so let's do that um Pub no it doesn't have to be Pub so enum it will enum um key action it's going it can have like a single which is a string not a string but an action so did it work for the action already that's awesome single action or multiple V of actions like this good we need this let's paste it here and I think this is has to be untagged so let's do Sur untagged and then here uh this and this ah this and this go to the end of the line move back change to uh key action like that what happens if we try to run this now oh key action single it's not a vector anymore this let's try this nice now it goes like this uh yeah I don't have a problem necessarily with it being like this without a quote I don't think there's a way to force it to be a quote but as long as we can like parse it I'm fine with that let's see test let test parse config you do the following copy config Tomo source. fixtures so let me see how to deserialize let config um which is config is Tomo from from from there's no from file let me see what we have here from SDR or to S strr okay okay so let toml equals FS read let's see uh so read oh there it is to string then it's going to be not themes but um fixtures config tommel co-pilot disable unwrap from SDR Tomo like this let and then here we're going to do another print line and this time around we're going to do config config and then this doesn't Implement debug we can surely fix that there we go [Music] okay mismatch types uh Tomo from this has to be a an Str strr this and then unwrap and let's try this again uh no such firor directory so is this like Source fixture let's see yes so we're further along what's the issue here um invalid array something theme yeah what I think is happening let's see here config Tomo let's see how far we can go so if we run it like this it works no it doesn't Oh missing Feud insert we have to do insert here it has to be Sur default I think same thing here Sur default let's see yep we got it the config is loaded let's do it like this perfect so we have have single quit insert yeah let's undo this oh but the action can also be a nested table of actions yes Soh then it can be nested and then if it's nested we're going to have a key action no what do we have is a hash map of string and key action yes it's going to be a hashmap of string and key action is another thing this can be so let's see I think he likes it maybe oh I didn't save it too bad okay invalid array so let's see if we can go as far as this I think we can let's see what it what did it do with the g yep perfect let's go to here I think we can go all the way to here to be honest let's redo this one failed it's really hard to understand what the error is move line to viewport so let's see still failed to make this easier on us let me like delete this this config RS let's try this again toal message valid array expected closing bracket is it here the problem of course we don't have a freaking quote here okay so now I think we can go to here let's see if I'm right on that assumption one failed uh duplicate key K ah nice yeah because I did this twice okay now it passes multiple keep move up and move right love it and now this is the tricky part maybe it will work maybe it won't we'll see failed um data did not match any variant tagged in Num action yeah I I agree with you on that uh so let's see what happens on the counterpart if we if we come down here and we create what we want for the I action let's try that so now we want to do letter I is going to be key action single action enter mode and then normal no not like that this will be mode normal like this yes um this is going to be here this why like this perfect just missing a two string here there we go all right what happens if we run this test sorry this test here how do you represent I oh really no I don't want that ah oh man normal do I really okay I think we'll have to do that so keys. normal. I enter mode no not like that equals normal okay what can you do let's move everything back to here like this like got Let's uh run the test again and now it passes oh no I ran i r the wrong test this one failed let's uh see why invalid string expected did I up again with the quotes where was this expected this or this you see here here jkl zero is that because of this let's see no let's comment those here it works so the problem is down here somewhere let's go to here doesn't work so let's come in this one run fails oh is it the contrl F no that's a string so that's fine uhuh see expected a quote and got single quote I don't know so now it passes yep I've just spotted it all right and now it still fails what is the issue now did not match uh key action do we have something here that is not an action Let's uh try again okay this works but if we uncomment this one still works is it delete line the problem let's see yes it is so it's not delete line let's see here editor delete line current line and yes now we're passing good all right um now what we need to do we need to start mapping the keys um so if we go back to our editor here for a second we are using keys yes so we're going to have to do some interpretation of the keys all right so before we do that let's go to Main and let's uh load the config file so let config equals 2 and then we need to repeat what we did on config here for now let's make sure let's uh just uh handle the config on the same folder we are later on we're going to put it that on the proper config folder but for now we're good so we're just going to load config TMO then import config import this guy like this oh boy oh crap all right now we have a config let's feed that to our team Parts vs C theme and then uh tommo dot sorry config do theme like this and then here uh actually we can feed the config inside we don't need to par the vs Cod theme here uh maybe we will so config theme and buffer config like this let's make sure that we have a config here and let's pass it here okay now handle normal event so then if we have key code yes so hold on thinking um yeah so we we have to check the modifiers to come up with the key for the the action that we want to do before I do that let me just uh fix my camera like this good okay so if it's a key event here's what we're going to do going to do um event no let me think um the event it's itself is a key event right key event and then I have code modifiers and the rest like this now let mutable key is going to be the but it can be yes if it's up left those things we need to H this is up here hold on let me readjust my zoom here there we go okay so now going back here this can be either a character or a known key okay so can we do code. to string no what happens if if we do it like this format code what do we get so let's um comment everything here okay compatible types what's going on oh because we are not returning anything yeah let's do none okay so let's ta just want to make this smaller okay that's too small so here we're going to do run and then let's tail here so what is the issue um config is private okay main we going to make this Pub and we also going to make this Pub all right can we run it nope what is the issue okay we don't have a config on which file editor so let's go to editor what's the issue let's import it good no more issues let's run uh invalid array expected okay we need basically to copy config Tomo to our config Tomo yank shift p then we don't need those okay let's try it again there we go so now if we press down oh there's a lot of other l let me find log those two have to go so we're going to do it like this and we don't need those V buffer anymore and we don't need this keyword anymore good let uh oh we can't quit anymore okay too bad run like this and then let's tail and now if I do press it down left right up see is Char s okay so this gives us a good idea of yes of what we need to expect while doing our actions handle handle normal so let mutable key doesn't have to mutable key is um match code uh key code Char C it's going to be uh format C otherwise it's going to be the code like this okay that's important key code oh man try ignoring modifiers not yet because we need to do that let's see now oh man not being able to quit these are really a problem isn't it where is the quit here key code code Q return some action quit Okay action quit there we go it's not code it's Char so let's uh fix that go run again no this uh this okay so now if I press J it's just J same with cops perfect let's quit we can quit okay so now we need to figure the modifiers um match modifiers what modifiers are key modifiers how are we handling that yes okay uh then if this is key modiers control we're going to do I'm going to return key here so let's do to let key equals and then if we don't have anything it's just going to be key uh if it's control we're going to do format control and then the key like this oops so now if I press contrl F there we go nice let me do um same thing here for control and out it's going to be out like that and then I think we can handle the key to do that what do we need to do we need to ask our config for our action let action equals self. config do uh normal no key keys let me dot normal dot get key so this has to be public and this as well considering borrowing here I sure can perfect and then I think we just return this so go to self like that and the problem is that this is what does this return again it's a hashmap of string key action and key action is not what we're returning so we need to handle multiple actions yes we do so for now I think we can pretty much delete all of this we're not going to need it anymore and yes this is trying to return a single action but if we go back to config this can be either a single action multiple action or it can be nested and we need to handle the nested right yes so let's go back okay the action is going to be this then we return sum of the action like this and then if let action key action U multiple [Music] um no not multiple nested that's correct um and then if it's nested what we're going to get is another yeah so I think yeah so let's see nested equals to action to do handle nested actions and then we're just going to log can't yet handle nested action then action sorry nested like this return none okay none okay and then this thing is either going to return a single action or a multiple action okay so this is going to be a key action what is action here yeah expected key action cargo check okay so here action oh that's right you know what we don't need to handle this here I don't think we need to handle this here yeah let's uh just add to our config Tomo our quit action oh we have it already good okay um those are the cases if it's not a character what has been pressed we're going to do something else good and then we're returning it's an option off option what is the type of this guy option option so we're not going to be handling waiting command yet so let's uh just comment this guy so what is the action here it's an option of option oh like that so what now key action we're going to clone it for now not sure if we need to expected key action okay so it's not here so where is the key action it's this guy right yes um clone cloned okay that's fine trade bound key action clone is not defined but we are defining it now config RS here clone clone is not action is not clonable go to definition it is now it's going to be now cloned log is not being used now what's the issue expected option action me see does this oh yeah yeah yeah this is now going to be a key action let's go to handle insert event now we need to map escape and enter on normal so let's do that config tunel let's do Keys insert so Escape is going to be we need to do that notation where keys do insert. Escape is going to be this yoink and paste so this is going to be inserts no normal this is going to be insert right and then Escape we don't have to handle anymore uh then enter it's going to be a new line like this good good so let's get handle insert event let's put it right right above handle normal event here so we can so we can copy stuff from it and here is where we are handling the event so I think we have to add another layer here we have handle event handle insert event let's add another function here um event to key action and this is going to take an event and it's going to return same thing just going to copy that soon and this guy has to be just self I think for now let's copy this to the end of the line yank uh here paste like that and then we're going to need this code here but how do we know if we're in normal mode or yeah this is the thing that we need to pass in so basically those are the mappings so this is going to be a hash map of something of string to key action key action and this can be a reference like this that's important hash map and then here here it's going to be mappings getet key. cloned and this doesn't have to be a result just an option like that there we go mhm let's go here perfect so this now returns an option key action okay yeah this I don't know if this needs a result we'll keep it just for a consistency but so event to action then this is going to be self. config do normal like that no uh self. config Dot keys. normal like this actually this doesn't have to be tied to self so let's put it here this just knows how to get an event and make it a key action let's get rid of this no no longer self they lead to this we copi this guy and we paste it here like so and then this is going to be insert mode so like that uhuh key action yes sir like this and then we have handle events execute action here is where we need to handle the different cases so if uh match action then if it's a key action single Easy Action we do what we were doing here so this now if it is key action multiple actions what we're going to do is um for Action in actions self. execute action like this and if it's key action nested actions uh good question what do we do if it's nested I don't think we handle it here uh why do you use iterm instead of aloc so the jvmx uh the main reason is because I don't use t-x never got used to using t-x so I use it for the panels I like it better uh for the panels but when I use yeah and when I'm in Linux I use West and not alloc that's the only reason and welcome to the stream by the way I thought nobody was here as usual so I was talking just to myself but yeah that's the reason and I I really like it term I have used it for a long time now if that makes sense okay so if we have Nest directions yeah we have to let's do a to-do here uh we need to be in our waiting for extra uh events and then handle them with the subset of actions we can handle here like that okay uh we don't have to do this anymore or do we I think we do um self. execute if it's quit we don't do anything yeah we're going to have to have a flag quit requested uh you know let's uh just let's make execute return a Boolean for now and then if we want to quit we just return false return true or false let that do true for now and then here at the end we return true return no no return just true true Perfect all right now we need to check for the return of our execution here let quit equals this if quit uh break okay so if not self. execute so if any of the actions request to quit we return true otherwise here we return false Okay match type expected enum yeah it's not return is it um quit equals false mute and then here quit becomes true and then here we just return quit or can we do break true I think we might be able to and then this becomes false uh use break on its own without a value inside this for Loop okay so you can't do that so this becomes quit to be a typol right and this is false let's prefix it with an underscore like this let's see what happens now if we go to our editor what happens if we press a key it quits immediately so let's do uh some logging soon let's press let's see uh so J equit um why self. execute action quit return through through and then L is much faster than I ter I compare it with mouse scrolling test 43 yeah but I don't know if I'm it's a hot take or not but when I'm doing coding um at least when I'm coding not when I'm following a log or things like that I don't think that difference makes any difference right um I don't think it you know having a super fast terminal unless I'm like doing a lot of scrolling I don't think that changes the experience at all don't get me wrong I probably have Al here no not on this computer but I I use Al a lot with ZJ and things like that but I never I never had like a a time where I say oh you know what I wish my terminal R faster does that make sense but I never ran into that situation okay why is this quitting we don't know we need to debug so let's see here if quit um log requested to quit just to make sure that it's this is the point that is uh giving us the Yeah so basically we requested to quit so let's log the action [Music] here action is going to be action and if we run it here single move down requested to quit so single move down I'm calling execute move down this guy here what am I returning true that's your problem okay now it's working what if I go right left left is not working I'm moving up when requesting so let's see maybe I did this wrong if I press K what do I have move up up J move down right left seems to be correct let's see the key that I pressed hold on so that's on event here um if it's a character it's uh this guy here uh log pressed key let's see J move down L move right uh oh no this is working I tested it wrong okay perfect then page down page up okay seems like our configuration reader is doing what it's supposed to do let's see if we can change a theme from nightfox let's go back to um what's a light theme here I think latte let's see yep so you can see that we now have a different theme here very nice um but let's undo that and let's see let's create a a a command here that does m multiple things let's create something like paste that we don't have yet this is going to do the following move down move down oh not not like this oh I have it already here move up move right and then yeah just like that let's test it so if I do if I'm here and I do P I expect the cursor to go up and right to the S and it's just quits okay glad I tested this um the action was correct it's a multiple move up right but I requested to quit because probably when I'm handling the multiple uh event I'm doing something wrong quit is false if uh the execution returns false then I said quit to hold on so if execute returns true I said quit to true that's the the mistake all right let's do it again so if I press P now I expect the cursor to go up but it can be considered from point of view Energy Efficiency it's much better better time that absolutely I totally agree regarding the CPU you're absolutely right right now I'm plugged in but that's something I'm going to consider because I do think you have a point in that regard especially if you're doing like if you're coding at a coffee shop and you have like a laptop that can be a huge difference like 43 versus 130 you're right so let's press P now and see there we go we moved up and right all right so I think we tested everything with the exception of nested commands and I'm good to do a commit so let's see uh we added the tumml crate there um then we have the new types of Action Now needs to be serialized and whatnot we created the config file we pass that to the editor we remove this debug this o debug yes we are now handling single actions and multiple actions but not uh nested actions uh yes we're now deferring handling keys to our new method that should appear here soon this one um this is config handling and config parsing and I think we're good so let's commit this um handle um theme and simple key mapping on config very very nice uh we need to do a force because we used to have a different config branch and oh I forgot to add those new files so let's add them get commit amend no edit like that now get push and we're good so let's remember what we did today I think we did awesome stuff like um we completely redid the oh let me go to this file here so let me add here we did actually do the editor configuration as well so we did we added the gutter um so if we go back to the editor here let me close this guy so I don't know if you guys saw the other uh videos but we didn't have a gutter uh this left hand side indication of the lines now we do so that's one thing we did uh apply style effects existing from theme uh not sure what this one is oh to the gutter yes so the second thing we did which I think is kind of nested here is the color that we render the line here the line numbers is coming from the vs code themes that we're parsing so that's very nice as well and finally we did all this editor configuration which was heavily inspired by by what what Helix does so if we take a look here at our config file uh this is what we get we get a theme um then then we have keys on insert mode and if we have keys uh actions that take parameters like enter mode needs a a mode to enter that's how we do we do Keys insert and then we press Escape it goes to the normal mode uh we ported almost not we ported all the keys that we already supported to here we created this um nested not nested but uh a key press that does multiple things it moves up and then moves right so we have a key combo here uh when you press or an action combo when you press p uh the last thing that we did was to have nested Keys like this when you press GG so the first G key press um waits for a second one we didn't handle this case yet I think this is going to be what we're going to do on the next video and yes um I think this is very good progress towards having a fully functional editor and I think after we finish handling the nested commands what I really wanted to do was to start this thing here to add enough movement support to our editor in a way that we can use the editor to continue developing the editor if that makes sense that would be very very cool right okay so I think I'm going to call it here this this has been the longest video that I did so far uh we've been going for two hours and a half wow that time flew today so if you made it this far and you like what I'm doing uh please check the links down the comments especially the new Discord server and consider joining our Discord server where we can hang out talk about rust other programming languages in general and more than that talk about future project ideas or even talk about the progress of this editor what we can do to this Editor to differentiate it from what's out there um and what would be fun things to try on an editor like this if you have any ideas or not if you just want to talk uh make sure that you join our Discord okay thank you so much for watching and I'll see you on the next stream thank you byebye
Info
Channel: CoderSauce
Views: 417
Rating: undefined out of 5
Keywords:
Id: oDhEr2OdRqo
Channel Id: undefined
Length: 115min 29sec (6929 seconds)
Published: Sun Feb 11 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.