Introducing Line Surfer – A new way to visualize a cursor
A while ago I had an idea for an extension to Visual Studio Code. The goal was to provide a way to visually see the current line your cursor was on and the context of the surrounding lines above and below. I wanted the current line to pop. I thought it would be cool if the current lines font size was able to be set to a specific font size and the surrounding lines would interpolate down to the editors default font size based on the size of the context. As an example, let’s say that the current line was set to 24pt and the default size of the editor was set to 12pt. If you set the context, or height to be 4 lines above and below, you would get the interpolation from 24 to 12 stepping down on each line until it hit 12. I called this the “Wave”.
Having never explored the vscode extension api. I started to figure out how I could do such a thing. Turns out that vscode only allows this sort of manipulation in a custom editor, not the default packaged one. I knew I wanted to stay away from that complexity so I scrapped the idea and moved on. But the idea continued to stick in the back of my mind. As I continued to use vscode every day, I envisioned how cool it would be to see it working and how it could help visualize not only your cursors current line, but also the surrounding lines, drawing your eyes to the line you are working on.
About a week ago, I decided to give it another try. I headed over to the Extension API Docs to see what was possible and how I might be able to realize the idea. As I started building a simple Hello World Extension, I noticed that although I didn’t have control over the individual lines font size, I did have control over its other styles through Decorations. The background color style jumped out as the solution. Instead of font size, what if I used the background color to emphasize the current line and the surrounding lines? With that aha moment, “The Wave” was born.
As any good developer should, I sat down and laid out the pieces of the extension. I like naming things and relating them to real world objects since that helps guide me in understanding the aspects of what I’m wanting to make. I thought about the parts of the extension. First there was the current line and its background color. Next there were the lines above and below the current line and the color they would be set to. I also needed to consider how many lines above and below the current line to extend to. To me, this sounded like a wave. I googled the components of a wave and instantly had the names for the various parts of my extension. The current line became the Crest, the edges became the Troughs, and the height became the Amplitude. The areas between the Crest and the Trough were the sides. The crest would have a color and the troughs would have a color. The sides would interpolate to create a gradient. Finally, I had the definition of The Wave.
Next came interaction. How does the wave move? How can it be configured? What happens when you change an configuration, shouldn’t the wave reflect it? Enter event listeners. Vscode really has a rich API for interacting with the editors. On selection change, the current wave would rebuild based on configurable settings. When the configuration changed, the wave would be rebuilt. It really came together pretty quickly and more importantly, it worked!
There were a few bumps after release that rendered the system useless though. I didn’t think about selection. My wave was taking over the background color used to signify selected text. For this, I found a way to determine if there was a selection and in that case, I turned off the wave. Once the selection was back to an individual cursor, the wave returned. I also got some help setting the font-weight of the current line which I expanded to also interpolate out like the wave. The current line was the max configured boldness (900), and it would interpolate down to 0 at the troughs. I think it came out pretty cool looking.
I posted the extension on Reddit to see if anyone thought it would be useful. As expected, it was considered fun, but not really useful. I can understand that. But there was a comment that sparked something that I am currently working on. The idea, which I’m calling Sticky Waves is to pin the troughs to your current scope and let the crest move between those, changing the amplitude as you enter new scopes (or brackets). There is an extension that I use daily called Bracket Pair Colorizer. This extension draws a line from one opening bracket to the next and it works on any language. Here is what it looks like:
This is exactly what I needed to make my extension actually useful. If I could figure out how that extension finds its scoped brackets, I could get the start and end lines and use those as my trough pins. I started to dig into the code and found that under the covers it uses the same engine that vscode uses for its grammers and tokenization. The first is vscode-textmate and that uses a regex library called vscode-oniguruma. Currently, I’m working on adapting the code from Bracket Pair Colorizer into my extension in hopes of providing this functionality. So far, it has been an uphill battle, but once I get to the top, I might have made something cool. Oh, and of course I gotta write some unit tests…..haha.
Some might ask why? My answer to them is: Why not? Why wouldn’t you want to explore what you can do and challenge yourself. In this exercise, I’ve learned a lot about how vscode works and how it interacts with extensions. I’ve learned how to publish extensions and how to support an opensource project. And above all, it’s fun. What is life without a little bit of fun? So I challenge you to find something new, explore it and see what you can build. You might learn something cool.
Happy coding!