Neovim Builtin LSP Tutorial: Customizing Renames w/ Nick Nisi

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
uh i'm just really impressed with how approachable all of this really is because it's that was not my expectation going into this and bisco says hi youtube yes indeed hello there hello chat say hi to say hi to nick um i don't know if you want to follow along with twitch tattoo you can open up you can just open up the stream and then [Music] you'll be able to see them they may ask they may ask some questions as well as we're going and we'll just see we'll just see what's going on so uh if oh i should add uh bang guest so if you're looking for this you can do exclamation guess for some info about who nick is so nick's uh developer at c2fo emcee of typescript conf us a panel's on js party and apparently uh his words not mine one hit wonder youtuber i always think one hit wonder sounds a little bit you know too it's not as cool as it is like you made a lot of people really happy that seems like uh that seems like a good thing you know that seems like a good thing there's nothing to be ashamed about for having a big hit you know but but anyways so anyways that's what's going on nick and i were on uh the change log we recorded what like last week or two weeks ago i have literally no concept of time anymore um it was bad enough before uh covet and everything but even even worse now that i i'm just bad at calendars uh and so we were chatting we're chatting on change log about new oven built in lsp i was telling them about something i was doing with go and he was like oh that's really cool um maybe we should do some i was like we should just uh experiment with doing something similar uh together i think actually i might need to put you more like let's see if i can put i just might make both of us a little smaller with two people here there we go we'll be we'll be like a little bit smaller we're we're going to be a little close on screen but i think that that probably is a little bit better just make nick the background oh true we could filter out the background color of this and just kind of have nick be sort of like this in the background judging as we're as we're going i i don't know i don't know the technical uh details of setting it up but i do have a green screen behind me that i could say oh no it's it's good it's good it's no it's no big deal we're we're we're sitting next to each other right now on the stream uh i don't know if you probably oh right because i'm just sharing you my actual uh editor window but anyways so we're just like hey cool that's fun we should uh we should just maybe hang out and see if we can make something so nick suggested a cool idea of doing something along the lines of hey when you do a rename it would be cool to be able to see all the places that you did the rename which i i responded with yes that seems pretty cool we should just explore doing that so we're kind of gonna work through that uh nick stop me ask questions you know give comments all that kind of stuff and i'm gonna maybe do um we'll go through things you know in more of a way how i would explore if i didn't already know some of the answers i already know some of the answers to what i want to do right but we'll we'll maybe pretend like oh i don't know what this you know what this thing looks like so we're going to need to explore that or something you know something along those lines so absolutely cool so that's so that's the general plan um and i'll just uh do this kind of like inside of here and then maybe we'll do i'm trying to think what's the easy one that i that i'm con well we could do this inside of the luaus b2 because it'll it'll rename stuff and it'll easily extend to other things so so the first thing that we should start with is uh whenever i'm thinking about doing anything inside of vim or neovim where where should we start nick what what would be your guess of my suggestion of where we should start if i'm saying when we're in here start as in the help menu sending the plugin or sending the yeah probably for me that would be my doc files yeah right so we can we go in our dot files we can see what else we're working on and then if we're looking to extend lsp i'm starting to think first place i want to check is i'm just going to be like inside of help for lsp so that's just a general note right chat knows that i love i love these docs i may have written a lot of these docs here so i may be partially biased of course but um this is really good info generally about how does the like built-in lsp work how is it designed why did it make certain decisions et cetera et cetera and there's a lot of good sort of generic information here but the part that we're going to be focusing on today while we're making sort of this extension is uh we are going to be making a new handler so handlers are a special word that we use i don't know if you're familiar with the term yet because it's somewhat neo-them specific i don't know if anyone else is using the exact word but when when we talk about an lsp handler it's a very specific sort of like function signature and it means something special we just tried to pick some words that generally represent sort of like you know that that would be unique enough that we could always reference this idea but still like somewhat makes sense because it's real all it's really going to do is handle a request nothing crazy you know nothing crazy but they effectively always have this format so when you send a request to the lsp um using something like helpvim.lsp.buff.uh assume that we want to do buff request this sends a request to the lsps from this buff of a certain method with these parameters and then you can pass a handler right so handler is going to be basically the callback that gets called on the successful response from the servers right so this is sort of the general idea what we're doing oh and i should just mention as well these words like method and params are exactly the words that you would find if you go look up like microsoft lsp specification and you go and you click to go here and you look at this these words are as close as possible as we could do for um for that so that you know when you're looking at these docs and you're wondering you know how does how does this work what what is this request any of these kind of things that's all happening as close as we possibly can to this spec so that you don't have to learn two separate things versus one that's that's awesome yeah i was actually just looking at this last night for the first time oh yeah i'm a long-time lsp user from the client perspective right digging into the actual inner workings of it is is relatively new to me yeah but it seemed like these docs were very approachable and seemed really straightforward so that's exciting that uh neovim also is kind of trying to follow that pattern so that it translates over to that really well yeah so that that's our that's our major goal so what we're going to do today is we're going to be playing with rename right so we can pretty much just go like find the rename request which should probably be in here somewhere yep rename so we can just go here and this will tell you exactly number one what you send to the server right so that's going to be the neovim side what we're going to send and then it tells you also what uh in general you don't have to worry too much about these capabilities this is just saying whether the server actually is able to do it or not and then the client says whether it can handle it or not we're just going to assume that that part is mostly working right now like uh because we're assuming that the rename works inside of the server that you're using because otherwise you have to take a few steps back before you try and do this extension right like it's not going to do that so you'll notice here method is text document rename right and then we have some params here which are just like text document position params basically and a new name so new names could just the name that you're going to choose and we actually have some quite nice um like helper functions for a bunch of these things to do so i'll just give uh we'll just make some scratch file here uh lsp rename extension something like this so let's say we've got local x is five print x right if we're hovering on top of this x here we can do something like vim.lsp.util.make position params and that actually just generates the text document position params for the current spot that you are in right is that just built in yes that's just built in so so this is sort of like you know you can read there's a quite a few things in health then.lsp.util um there's like we just have a bunch of different little utility functions some some of these may change over time or whatever util is a little bit we're a little bit less um 1 000 committed to every single one of these going forward forever because they're utility functions right but like a bunch of them will probably not really change like make position params which tells you hey this creates a text document precision params object for the current buffer and cursor position oh okay cool well i'm looking at this and it's like params is text document position prams cool okay well now we have this part right now all we need to do is basically generate that like new name thing right so that would be um we'll just make some global function here global funk so that i can just uh and we'll just do so i can just source this uh file while we're doing this just to show us some examples local i don't know f is a function and inside of here we've got this going on right so inside of here we could do something like local uh position params vim.lsp.util.make position params right so that's going to be the current position then we can do local new name and then we can basically ask them to say hey new name for nick's thing and then like this right and then it'll ask that and so we could just do something like position params.new name equals new name right so that's basically like we're going to oh sorry i forgot that i have to do this uh the i excuse my luaness you know i'm not i'm not a type type script native i forget that i gotta change how i do my casing my apologies uh but then we could do something like print vim dot inspect uh position params right so we could do this and then i could do um lua global function next thing so we could say blah and then voila right we've got this new table that has the new name this matches the request that we're trying to make for text document slash rename following so far yeah cool cool cool cool so that's like so that's the first part right so that sends the request and then what we get will be a response and responses are whoops i didn't mean to click wherever i just clicked um sometimes this just sends you to random places that's one of the things i don't like about this okay this sends you a bunch of workspace a workspace edit okay so okay we're like i don't know what a workspace editor is me neither we can go look at this and so we can read a bunch of this but the main the main gist of this is that you're going to get some changes which i maybe we should read this i i actually don't remember offhand which one this is going to send whether it's going to do like changes or document changes or why would send one over the other but but we could you know we can explore that but the the part one way that i usually do as i'm here is like i want to know sort of what the shape of that request is so i would actually maybe do something or the response i might actually do something like this instead so we can buff request and if we're looking at the the help for that right buff number so we can send zero for the current one then we need to say text document slash rename because that's what we're the request method that we're doing and then the params are these position params and now we have a function um that should have this signature basically this is we're saying hey give us a function that has this signature and then we'll be able to uh that's going to get called with the result so we can just do this method results client id buff number config something like this we actually don't need config right now and we may leave a few of those other ones in a bit let's just do something like this um print air we'll just print all of them air method result fine id buff number so we probably also don't need buff number in lua if you don't pass a param it just gets discarded or you don't have a prim in there just gets discarded it's very friendly about passing arguments more or less so there's no problem with sort of dropping these guys here we also don't really need yeah go ahead because you're you're calling that text document rename event on your own and passing in this custom handler it's not going to do the like the default handling exactly right exactly right yes so um there's actually some info in this document just down here about how does uh built-in lsp determine what like handle handler will be called by default if nothing gets passed here and there's basically like okay well if you pass one here it's gonna call this if you passed one specifically to this server so that was how like um on changelog i was talking about in golang i have a special like go to implementation handler and for your thing that you want to do especially for typescript you could also like pass that in the server config um and then it will sort of like override the response for this and then last off is oh do we just have some the globally defined vim.lsp.handlers which if you look at something like dot table keys m.lsp.handlers you see we've got like all of these are just the different requests those are sort of like your globally default backup ones you know so for stuff like text document slash definition sure in in general you're always just going to go to the definition nothing special you could override that either per server or per request as sort of like defined in this dock but it's basically just like if you pass one that's gonna do it if your server's got one it's gonna do that next or it's gonna use the global one but through that object like in our case if you just wanted to have this print and then make it do the normal thing you could just access like pass in the the methods to or the the parameters to that exactly right so we could literally just do vm.osp.handlers text document slash rename and then pass in air method result and we'll just pass in the rest of the things here so that they all get passed um so then we could say something like print calling rename print done with rename so this is really cool too because this sort of lets you you could sort of like preempt this you could modify the result right you could like remove some entries that's effectively what i do for the one where i want to not go to like mocked implementations right yeah right like i can just say like oh i don't actually care how this is implemented for like go to definition or whatever it is right i just don't want my mocked ones to show up because i literally never want to jump there um or if i do i will just open the mock file and then like search for it right like 99 out of 100 i never want to do that so this is sort of like um the built-in lsp's design is like primarily like you pass around lua functions and they will keep on doing whatever you want and if you want to do more with them you just make a higher order function that does that or if you know so like it's the design is supposed to be like you're in control of how each of the requests happen but we're trying to make like same defaults that would work well for you like the first time that you spin it up and you asked to go to definition it's like sorry you haven't turned on go to definition no no we said go to definition of course we want to go to definition so um so yeah so that's what's going on here so for right now i won't do the rename yet we'll turn that on in a second if i sort if i run this file again we should be able to do something like this um lua global function it's going to ask for a name so i'll say hello or something like this and then we should see in our messages we have we just have some table here basically right so i didn't inspect the table so that's why it's just printing out a table but you'll see we got a response and it called our function we actually didn't do the rename obviously if we instead turn this back on and i just have a shortcut to literally do lua file this file so that just executes the file again so that updates this global function that i can keep on calling to sort of iterate on on what's going on um and i'm actually just going to change this instead of asking me what the new name is i'm just gonna put that this is new name just you know nothing it's just gonna make it into a new name so that it doesn't prompt me every time because that's uh not helpful for anyone to see so notice now a change from x to new name right and it says hey we called this we did the name boom boom boom boom right very very easy to do so now it's like okay interesting interesting now pitch me basically your idea of why you want why you were thinking like we want to do something with this result and then let's see if we can iterate towards uh doing what you were thinking okay so yeah the the thing is i love using that rename capability it's really nice but it um you know it just goes and does that and then there's a bunch of unsaved buffers that i have to go and find and of course i can just go to like the you know the most recently used list and see all of those and or hit save all and do it that way yeah but i i thought it might be cool to have like a list of all of the files that are specifically changed here in case i have like other unsaved edits or something that i want to also have but then i could maybe i don't i don't know when it would be useful but maybe being able to do something on top of something after you do a rename yeah i think like like you're saying too what popped into my head was even just like where did i rename you know like i don't even know what i just did maybe i actually don't want to do this and i'm gonna you know like go through these buffers and undo or something like that right like maybe i just don't want to actually do that so so you know i thought that's a really cool and like thinking of putting it in the quick fix list that's one of the things i like about this as well is like yeah let's just let's just reuse sort of the primitives we already understand and already have mapped and already have working out and like let's just put it inside a quick fix list and then if you're done with it you're it's okay it's all done doesn't matter yeah and full disclosure i i've been using vim for like 10 years yeah the whole time but i really only started looking into the quick picks list i think after a primogen video on it oh nice there you go prime very recently prime will be happy to hear that we'll tell him later maybe he'll stop by today we'll see um okay cool so so now we're here right and we've got um we're we're just going to print what the what this result looks like in a little bit more detail vim.inspect is a sort of like must-have thing doing doing stuff right where it's like this actually prints instead of just getting table you get what the table looks like um without that before you were just getting like the memory right yeah so we could do like print x equals true and it's just gonna be like that's a table and you're like sure but i was kind of wondering like what does that table maybe look like yeah so object object in javascript yeah you're right exactly you're just playing object object on the screen you're like no nobody wanted this actually nobody wanted this ever um so vim.inspect will let you do something like you know x equals true here and then it will print hey this is what this is what that looks like x equals true right um i actually have um a in my in my mind an indispensable function that i use all the time which is just p capital p it's a global that i can use anywhere and this just prints this and returns it so i could even do something like local x equals p requests or something like this and i just literally like will get it back if i need to but usually i just do like just print this thing so that's super nice because that i don't write i don't like writing print binbot and spec over and over and over um but i will write it out today so that it's obvious what we're doing for future viewers of the of the video right so if we're um if we're here now and we call our global thing and we look at our messages we'll see that we actually got um two we got changes right so this is if we look back at the spec it says hey you might have changes here okay well that's cool what what are inside changes and it just says hey you're going to have a uri and then a bunch of text edits so for us the main thing would be um i can make this a little bit taller so we can read this we see that we've got a file here which this is good i can get the file name from this and i can add that to quick fix list right and then i've got sort of uh the range so we've got a start and an end which if we're looking at something like help set qf list it says that you can have a list of actions and what do you want to put in there um so we'll get into exactly the format that we need to do for some of these but basically there's like you just make some dictionaries drop them in and then you're able to get them directly into the quick fix list nothing too nothing too crazy there but they're we're gonna need like the range right so that when you are inside of the quick fix list you can actually jump to the spot that it's renaming um and we'll see that we just we just literally have two we have a list of two edits which makes sense for this one because they're both just these two things nothing you know nothing crazy about that um so really all we need to do is we just want to transform these entries into a list that we can put inside quick fix list so that makes sense so far not nothing too i'm too mind-boggling there i don't think right yeah so it's the quick fix list just wants like pretty much a file name and line numbers is that yeah we can do um pretty like so basically um each dictionary item so these are the items that we would pass in list should just basically have this like format so we can ask um we can just use some of the built-in functions here to transform them to this and then do vim.fn.set qflist right and then it'll just do this so there's like line number and call so we happen to have line and character and i think those will uh i think they're off by one or uh i don't remember which way it is i always get it wrong the first time because they're the one no one can agree on whether text editors should be zero or one indexed and then no one can agree whether lines should be zero and one indexed or column should be zero or one index and then we have different languages with different semantics about what all of those things mean so it usually takes me two tries or sometimes three uh or i or ten when you realize you did something wrong the first time um yeah so basically we're just going to look to make something like this we're going to make a list of entries and then uh we should check if um so something like if result.changes right so this is sort of if we've got this uh thing as part of result this change is here right uh then we're gonna do something inside here we'll leave ourselves a to-do handle the i don't even remember what that other thing was document changes i don't know why you would have handled document changes i don't know what this is but we'll leave that as an exercise to the reader that may not be that may not be necessary but in this case we don't get document changes from the server so it doesn't matter for our for our example here there's nothing you know no worries so now we've got this changes and this is a map right of uh of a uri to a list of text edits so we can just do something like for um uri edits in pairs uh result dot changes uh okay so just as a note for people here or if you're not super familiar with nick nick do you know the difference between pairs and eye pairs by any chance i do not cool so uh in lua tables are like there's only one kind of table right and it's it's it's both a list and uh a map right so they just have this one sort of table structure so there's two different ways that you can built in that you can iterate over tables i pairs just looks for like literally numerical indexes and is faster and guarantees order for things that are actually lists right but it will never find something like this file here because that's not a number so it will not it will not do that right so when you're looping over like a dictionary you have to use pairs if you're looping over a list then you can do i pairs no warfare not a number that's that's javascript talk you know yep would uh would pairs work with a numerical index it does it does return the numerical indexes the only problem is it doesn't i i don't know if i've ever actually seen it not do it but it doesn't guarantee numerical order um so like i don't know exactly how pairs is working under the hood i imagine there's probably some platforms where maybe like pairs no longer returns it due to how it calculates what's next to check i think in general i've seen it return an order but i just always use eye pairs because i don't need that in my life um yeah uh velmat asks does it work with numbers stored as string yes uh like in lua you can put literally anything as a key to a table so i could do something like this example and i can do example function print hello world and equals true and this is valid this will work there's nothing there's nothing crazy like i mean it's a little bit crazy that it works but you can just store these as keys there's no problems there um so i pairs would not find this function but pairs would find this function so that's just something something to to note uh about lua in general but that's yeah it actually is like it comes in really handy and fun because you can do all sorts of you know you can just store data in like whichever way you feel like makes sense and you're not surprised later when it's like what do you mean i can't use like this as a key no like everything works as a key can you use the table itself as a key into the table oh interesting um i've never tried to do that it's super interesting so let's see i will just do like this example the example example is true example yes so it's totally fine with doing that lua doesn't care yes you can use a function as a key that's i was just showing that uh just just a second ago so it's it's totally fine with doing that it doesn't care it just would be weird that you would want to do it i guess but but anyway so that's just a little bit just a little quick side tangent about tables while we're here um and explaining why we're using pairs here instead of i pairs um so now basically we've got this uri and we've got a list of edits right so we're still going to have to iterate over the audits but let's first just try and get the associated buff number so you might be thinking how do i get a uri from buff number help vim.uri from buff number or two buff number hey oh that's cool it's like we thought about this and thought you might need to do this when we built the built-in lsp so we could just do something like local buff number is uh vim.uri to buff number uri and let's just for right now just print this out print uh all right buff number and we'll just print the buff number okay so if we try doing this again and we call our global function we got buff number is one and hopefully that's correct yes we're in buffer number one cool so that'll transform this uri into the buff number and we needed that right so that when we're doing set qf list we can set the buffer number does that make sense yeah cool uh so then the next bit is really just for um edit in eye pairs edit so this is a list so we can do i pairs and i don't need the index i don't care about it because i see that a lot in lewis i'm new to lua too yeah yeah okay um yeah so that's so in general um like you could do anything you wanted and say like anything you want here but it's sort of like uh it's not in like golang underscore is like literally special it's not considered like a new variable um in lua you could still do like lua equals one and lua print underscore and it will it will work but don't use underscore as things you'll be sad um a little bit of a tangent but yeah quick question when you're defining edit like that is that considered uh locally scoped to just that for loop um yes yes it'll be only available for here i think it's only in this scope okay cool it does not uh leak till later i'm pretty sure although i guess i haven't checked that in a long time i usually don't do that uh i think yeah it's fine i think that would tell me if it's not in scope so okay cool so now we're gonna loop over each of these edits and we've got basically a range of stuff here right so we can just do something like um table dot insert so this is how you just drop a new thing into a list entries and we need to make a new table we're going to say buff number is buff number uh we don't need to say you say file name because we already passed buff number i don't know even when you would ever pass module i don't think i've ever used that we need l num so we can do elnum is and we can just maybe pick the start i guess that's probably the best one to use right so we could say like edit dot range right so we're gonna do edit now we've got range and then we're gonna do dot start dot line and i think it's minus one or maybe it's plus one let's look at it it says line is one but really it's on two so i'm pretty sure it's a plus one and call is edit dot range dot start dot character plus one now this might not actually handle like multi byte things and stuff like that i don't i don't know you know you may have leave it as an exercise to the reader for now and we do have some stuff that's helpful um for that we even have in the lsp.util dot um i know we do this already for set qf list with some locations but i don't that's they're they're not the same type but i could check sure let's just so one thing this is a good tip in general when you're doing this as well is just literally look at the neovim source code for the built-in lsp because it's all just lua so if you're wondering like how does this do set qf list and it has items or whatever um or i think it's like locations to items there we go so this takes uh returns the items with the pie position calculated correctly and in sorted order for display in quick fist and location list so that's nice these are locations not text edits right so it's not the right format but we can actually just like check some of these and we could probably copy and paste whatever we actually needed to like do for these right if that makes sense so like this has the start ranges so like okay cool i see that they're doing ranges here oh cool well we have a range that's kind of nice like they sort the in order of those okay vim uri to afname uh we think that those are already open buffers so i think it's fine time does start table insert get lines ah interesting so this is how they actually grab the lines uh i don't i don't even remember that row column row plus one complex one texas line okay cool so that's um i think we're on the right track actually so that's good so we could we could check that and then now we could just do something like um them.fn.set qf list um and trees and i don't remember what the other arguments are action uh action will be i think we gotta do like r so items appended no we want to replace so we can do r like this and then i don't remember what the last thing is in here what i don't think what matters either i think it's okay so we can do something like this well we'll just see what happens um so if we call our lua function again so we've got two column nine three so we're there the only thing we haven't done is actually get the text of those yet um which if we wanted to do that then we'd probably just do it's like okay cool we've got a buff number and we've got a line start and end basically right well we do we do have ways to grab text from buff numbers right so i would do something like help enven buff get lines um and so we could do something like this which will allow us to get the lines here so we can do um we need to calculate the text for this yeah so local line is uh get lines uh buff number so we're just going to reuse the buff number that we've got we've got a start line which we've already calculated here so let's just say start i should call that start line really and i can't spell uh start line start line plus one false so this just gets us this just gets us this line and we can get the very first uh first one which is not zero it's one in lieu i've been writing too much go lang almost made a classic mistake and chat would laugh at me big time they love laughing at we me when i mess up one index and then lua painful painful painful and let's just say text is line here uh this isn't this probably isn't exactly right but we'll see what this does um did i just oh i can do uh c open oh right i switched that there you go so print x and end oh oh right of course of course i'm i'm so silly here this is actually zero indexed because it's a reasonable interface so we actually want to do this embarrassingly to get the right line uh tell us that you get it wrong the first time yep there we go sweet so done now you've got the places where you've actually done that lsp rename so so first try first try obviously yeah um yeah so i'm interested you know what are what are your thoughts what are some questions you have about the process we can chat a little bit about it and maybe where you'd think of like stuff that's interesting to go next or something yeah so my immediate reaction to this is that this is really simpler than i thought it was going to be there's a lot of built-in vim or neo-vim goodness that is just really nice to be able to tie into like being able to you know get the um the the buff number and the get the lines and right all of that i thought that we were gonna have to do a lot more of like traversing an ast to figure a lot of this stuff out yeah and not having to do that really is a lot nicer yeah in general i would say um lsp actually makes it impossible to think about an ast like it's designed in such a way that you only get like text editor things back and you can only ask for text editor things and the language servers are the only ones allowed to do that principally because as soon as you give programmers the tool to like play oh just just play like a little bit with the ast over lsp you're like okay it's game over like it's just game over after that right like you're not you're not getting anything uh anything that's edited or agnostic anymore it's always going to be like well the this sent me the definition so uh vs code implemented 10 000 lines of typescript to handle this and do the corresponding thing for typescript you're like the heck no that's not what it's supposed to be about so i do get that people think of that a lot at the beginning um but then after you do it a few times you realize oh right it's literally just going to send me this he's just literally going to send me the spec yeah that that's what it was like it wasn't really sending you anything about right on asd it's just those those locations and then i thought that that would be a little daunting but with all of those built-in helpers like it was really way simpler to go find all of that stuff which is really nice the other thing that i'm really thinking about is like as the gears are turning on this like there's a lot of events that the lsp works with uh by default like rename and all of those yeah and i'm trying to think of ways that i could manipulate one or multiple of those events to do other things that are more customized i don't have any ideas of that yeah but trying to think of that i think like the way that i've approached it for a lot of things is like oh so like we talked about the golang example and that one's just easy because it's really easy to understand the thing that i like a lot about the way lsp is implemented for neovim is it's like it puts me in the driver's seat of how i want to handle a lot of the like responses and like for 99 of the time or whatever or 90 or 75 whatever it does exactly what i want already which is awesome but then if there's something that's happening like over and over and you're like i know programmatically i can solve this question especially if it's like does the file name have the word mock in it i'm like well i can figure out yes whether the file name has mock in it or not and no longer jump to that if there are other options in fact um i think i i don't remember if i've got it inside of here yeah so um i have like this is my thing for implementation that i that i wrote which is just simply like if i check like is this file type go lang right then i'm just literally going to filter the results to not show things that have the word mock underscore in the name like it's not even 1 000 guaranteed but no one uses the word mock underscore in a file name if it's not a mock file and go like or like we will tell them stop doing that in our projects right so it's like this is so this is all i did and i removed this big annoyance that i had for jumping to mocked implementations of an interface which are like all over the place in in golem um so i think it's like you know you practice maybe a few a few of these things um sort of like okay cool and i figured out now that i can put this into the quick fix list now next time you encounter some lsp problem right um then you could just try and fix that particular one small problem just the way you like it that's like my recommendation for people to do which is which is pretty fun uh someone's asking about how does how does this how does that actually work new result is just a new table um and i basically just check so when i filter the things that they shouldn't have mock in their name but if i don't have anything that's not in a mock file like maybe we only implement a mock in our code then i'm not going to replace the result and this result just gets literally passed down to the normal handler for text document implementation so that's like so it's sort of that next it so if neovim improves the built-in text document implementation i will just get that for free i don't i don't you know i don't have to update my code i don't have to update my config i don't have to like tweak some new setting or do anything like that no no i'm just literally calling the same thing that i had before and now i'm all done um which is which is pretty cool yeah that's great yeah so so that's that's my thing so like you know you were talking about for typescript uh what was what was the situation you were mentioning for typescript yeah another idea that i was thinking of and i this is completely half-baked but i was thinking like a lot of times you know if i want to go to a reference or go to an implementation but i don't actually have the implementation because maybe it's just like a a uh ambient type file like yep um maybe it doesn't make a ton of sense to jump into that file and do something else like maybe i just wanted to open in a pop-up or something yeah like a simple idea yeah we won't actually write the code for that today but you could totally imagine um let me hop back to where i was here doing something like function example ts here doing something like uh okay so you're gonna make an lsp buff request again and it's basically gonna look exactly like uh this rename that we have right except it's gonna say definition i think or implement i don't know what it would be for typescript we'll just say definition for now i don't know which one it would be i think this actually also takes position params um so we don't even need anything there it'll just look exactly the same but then what you could do is you could do almost exactly the same idea that i had uh with my handlers which we'll just run back into here again and check this um golang one which is you can just do something like this where you're checking the results but yours would be like dot d dot ts or something like this um and this should probably say something this just means match it literally from the first character i think if i have the arguments right i always forget um so if you if you did this right then what you could do is you could say uh and you would actually only want to look for things that actually do or no it would be something like this you'd probably do like okay if um the length of new result is one right so it's like our result sorry then uh oh we'll do i guess and uh result one dot uri uh this now we could do like string.find this dot dot ts1 true then do something here and return right otherwise you're just going to do something like uh vim.lsp dot handlers text document slash definition like this right and you can just pass error method result dot dot like this so this would be like open nice little floaty window act cursor with that file in it or something like that right which would be crazy hard in fact um i believe and then open win has a cursor option on here for like the config here so you could do something like relative equals cursor and you could just pick the size you know 20 by 20 30 but whatever you want to do etc right so now you've done this you can just basically um read the file or if it's already open that dot dot ts file you could just like set this windows buffer to be the corresponding buffer for that dot d dot ts file right because you like buffers can be displayed in multiple windows buffers are just view ports into or buffers are like the memory windows are just viewports into that buffer right um so it's like uh yeah so you could you could potentially do something like that where you'd just be like bim dot api dot nvim open win um you know you could find the appropriate buff number buff number here which could be you know whatever um local buff number is open or get buff number or something like this right whatever you needed to do to get that open the window pop it up at your cursor boom and then the last bit would you probably want to do something like and you see this quite a bit in uh lsp util for neovim is we do some oh actually we already have some utils for like making little floating pop-ups so you should probably just use something from vim.lsp.util uh to do a very similar thing to like what we're what we're doing or you can use you know whatever your favorite there's like a bunch of plugins too that are like wrappers around pop-ups or whatever so if there's like a a plug-in api that you like better or that works really nicely it's your config you'll have it installed just depend on that plug-in and have it work that way so that's sort of like i think that's the really fun part for me for doing this right is like oh i don't actually ever want to open a dot d dot t s file you know like that's just no just no actually you know but some people might want to do that right some people want to jump in and look around or do whatever and then cool that's fine we're not going to make it impossible uh but you could just write your own little thing here just see if all it matches is a d.t.s file and do your own special stuff i mean you could even make it so that it just like pops up the little preview window down here or like literally just prints the line at the bottom you know you don't even have to have it be a floating window if it's just like a function definition or something in a dot d dot ts file you could just print it out as your first approximation to see if that's good um yeah and you could keep on doing even more you know more i was just thinking like a cool thing would be a local last requested position could be like nil so you could do something like you get the position that you called this function in if you call it from the same position twice you skip this section so like you could even do it so that it's like oh you know if i call it twice i actually do want to jump to the dot dot yes like the one in a hundred years when i do that like okay sure i'm gonna do it that way um but yeah i think this is why like the interface of just being like hey you know what the spec is because you can just click here and go to spec right and you're a programmer most likely or you have some affinity to liking programming related things because you're using neovim like let's make that really easy for you to do what you want with it and like lsp becomes its own in my mind like cool interface uh that interfaces with neovim like generally not just for the lsb client right which i think is is cool because it's like a standard way of thinking about editors which is quite fun yeah yeah cool any other any other thoughts um that those were kind of the two that i thought of and i thought that they they'd be pretty cool um to play around with and thank you for for showing me that uh i'm just really impressed with how approachable all of this really is because it's that was not my expectation going into this so awesome great maybe what we should do is if you get around to implementing this dot d dot ts thing you should come on again on some other friday and we'll just uh chat about what you did and we can uh do a little code review sesh or something and we can we can sort of make a part two because i'll upload this to youtube as its own little as its own little thing so maybe we should do that again you know sometime in the future maybe maybe around when we release uh the changelog episode we're both on yeah that'd be great cool and bisco says hi youtube yes indeed right uh well with that i think i got to work on some telescope stuff today so i gotta run and uh and start working on telescope otherwise the people will be angry um everyone say bye to nick uh nick do you want to plug anything um yeah i'm i'm on twitter at nicknessie and um go listen to the jsparty podcast if you're a javascript developer it's a lot of fun and uh don't miss out on the changelog podcast with tj and i uh talking about neobin yeah great cool awesome well thanks nick i really appreciate it and i think we'll be uh we'll be talking soon again yeah sounds good thanks cj see ya
Info
Channel: TJ DeVries
Views: 5,939
Rating: 5 out of 5
Keywords:
Id: tAVxxdFFYMU
Channel Id: undefined
Length: 52min 44sec (3164 seconds)
Published: Sat Aug 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.