Month: January 2018

Home / Month: January 2018

An OSD700 Contribution Update

Interesting concept, it’s a very surreal experience to explore and work on a project while using said project as the tool for development and exploration.

For a good part of the weekend, I’ve put aside time to look into how Visual Studio Code handles and manages the Command Panel, a tool / extension which I use daily for accessing various extension actions, configurations, and accessing files. The reason for trying to undercover the goldmine which is le Command Panel can be found in my attempt to add a color picker toggle to the list, a work in progress pull request can be found here.

Fully Customized VSCode, Command Panel Displayed

Attempt #1

My first attempt towards adding a command to the command panel was based off of how the comment extension accessed the panel. Later I would be pointed to a better example which I address in Attempt #2. In this attempt, I tried to create a wrapper which would expose the ColorPickerWidget class to the command panel, similar to how it is done here.

The idea at first made sense, till I realized that the implementation of CommentLineAction was directed to manipulation of the code close to the cursor. Furthermore, I didn’t need the kbOptions related scope in this case, since the original intent is simply to toggle a Color Picker through the command panel. I should have kept the code as an example here of what Attempt #1 looked like, but I had reverted back to the branch’s version prior to writing this post.

Attempt #2

After much research and discussion over the VSCode Slack Channel, I came to the conclusion that the first attempt should be redone using a better reference: hover.ts, which compared to comment.ts, provided a much better context. Thanks to Eric Amodio (Creator GitLens) for the tip there!

Attempt 2 for Color Picker

Through this process of trial and error, I learned the basics of how the command panel worked: How commands and context are loaded into its elasticsearch-esque data-store, how said commands call different scoped functions and contexts, and how to add my own command into the mix!

Putting EditorActions (Commands) into the Command Panel

A command you see in the panel is really an extension of the abstract class EditorAction, which extends EditorCommand. This extension allows for one to program the context of how the implemented run command, contexts, editor-permissions, and keychords while providing a type inferred structure which is compatible with the original EditorCommand interface.

You can see in the snippet of code linking to my second attempt, the super call in the constructor handles creating a IActionOptions object, which is an extension of the abstract class ICommandOptions. It is this portion of the object which is placed in the Command Panel to provide context, labels, translation and scope. The Comment extension ~/src/vs/editor/contrib/comment.ts shows the alternative way of handling the IActionOptions, which you can see below. I prefer this method due to a much cleaner and easier to read since the scope does not include the functionality, but the command alone.

The final part is to call registerEditorAction which is imported from ~/src/vs/editor/browser/editorExtensions as you may have guessed. The total amount of imports from that file derives directly with the context and actions that your command will need or perform, below I’ve listed the common ones which I encountered when looking through the comment, and hover extensions.

EditorCommand

Location: Github Link
The function which extends Command, and provides the inner-architecture required to bind and remove actions to the command panel. It’s public functions are:

Command

Location: Github Link
Command is the base class which appears to be replacing (based on the commit history favoring it over ICommandOptions for updates / improvements), and is extended by EditorCommand.

ICommandKeybindingsOptions

Location: Github Link
ICommandKeybindingsOptions appears to act as another context-aware object, this one containing an optional weight (of importance / override?) variable which makes me believe that this is used for keyboard chords (ala Emacs) and priority only-after the precondition in Command has been met.

IKeybindings

Location: Github Link
This class is extended by ICommandKeyboardOptions, which provides the correct keyboard-codes for Emac style keychords.

ICommandHandlerDescription

Location: Github Link
As the name suggests, this object handles description of the Command Object, not to sure to be honest what the purpose of this object since all labels are handled at the root of the object which would be displayed.

ContextKeyExpr

Location: Github Link
The ContextKeyExpr is an abstract class which contains the following public functions for working with the cursor:

IEditorCommandMenuOptions

Location: Github Link
This class appears to dictate the context of when an action is available in the command panel, checking against the ContextKeyExpr object it appears.

Making Your Command Execute Specific Scope & Functions

In the class which extends EditorAction, you have to implement the function titled run. This function is crucial, for it is exactly as you’d guess, the code which is hit upon calling your command from the panel. Since my own isn’t 100% complete at the time of writing this blog post, I’ll reference comment.ts again for how a proper run implementation works.

It is still unclear to me why editor.pushUndoStop() is executed twice, perhaps to correct duplicates? Perhaps I still have more to research and understand regarding the command panels data store, for the only hint I found being the code comment itself, Push an “undo stop” in the undo-redo stackfound here

ICodeEditor

Location: Github Link
An interface of the editor itself. Listening for events and acting as the glue between the user’s keypresses and the rest of the system. This is fed into the run command to provide access to context, events and user input. If that doesn’t provide enough weight towards just how powerful this interface is, the current structure spans 409 lines (which does include 5 lines roughly of TSDoc providing documentation to an estimated 81 (409 / 5) functions!

Comment Command Action

Conclusion to this Experience

I can admit there will probably be quite a few mistakes, missed scopes or crucial details that a weekend of research and speculation cannot provide, but in that time I’ve tried to acquire as much as possible, in the process learning a great deal of how Code’s command panel operates, the overall architecture relating to the editor and it’s extensions, and how CMD+T (or CTRL + T on Windows and Linux) brings up a contextually aware panel full of options and usability. I cannot understate just how vital it is to seek guidance from other developers, developers who have already contributed and work to the project and thus, can help guide you through the never-end maze of classes, interfaces, services, observables and architectures which make up such a huge project.

On an architectural footnote, VSCode (and perhaps in response, React) follows a very different order of components, services, and delegation of tasks compared to Angular does. The difference is quite colorful at first, some being obvious compliments such as Observable / RXJS patterns, others being grotesque and difficult to understand. I was looking forward to both ends of the spectrum jumping in, for it allows me to compare and perhaps even evaluate the different development decisions made between my own projects, work projects, Code, and tutorials. I hope that through this, future projects are inherently improved upon in design and implementation from said experiences. Interestingly enough, I’m reading The Art of Unix Programming by Eric S. Raymond, which provides different insight still relevant even this day to the idea of software development and architecture. The parallels between Code and Unix’s philosophy appear more and more the deeper I look, and I’m hoping to gather enough on the topic to write a blog post later in the year explaining such.

.

Building Visual Studio Code

January 25, 2018 | Open Source, Web Development | No Comments

On MacOS High Sierra

Building Visual Studio Code is quite the interesting process, mostly because the dependencies differ in obtainability between operating systems. For this article, I’m going through the process on MacOS High Sierra since it will be primary development machine for upcoming bug fixes, code improvements and contributions to Microsoft’s Visual Studio Code.

Set Up

Visual Studio Code requires the following prerequisites, Git, NodeJS, Python, GCC, Make, and Yarn. Of all the dependencies for this project, Yarn required me to use homebrew for installation, which is supposed to be as simple as brew install yarn if you have it configured correctly. I didn’t, so following the excellent single step found here https://brew.sh helped set up and configure Homebrew on MacOS. Finally, running through the CLI yarn will install all other dependencies over the course of an hour depending on your internet connection.

Building & Launching A Development Instance of Code

After installing all dependencies, the setup guide simply says to run yarn run watch which will compile and build Code. From there, if you see no errors or warnings you’re good to proceed!


Launching via ./scripts/code.sh for Linux or MacOS, or ./scripts/code.bat results in the final compiled application executing!

Going Forward

Right now, I’m looking into bugs relating to Visual Studio Code’s Color Picker, which is a front-end developers best friend when it comes to writing CSS Framework overrides and theme templates. Currently, I’m exploring the following potential bugs:

One pattern that I’m starting to discover among many of the bugs reported, is a lack of administration among the various domains. Bugs have been fixed, merged, etc, the tickets themselves remain open and untouched. More research is being conducted to discover bugs which line up with my interests and end goals, worst case being moving to a different domain of the project, or trying to find a different open source project to contribute to such as Angular Material https://material.angular.io.

City Bokeh by Gabriele Santiago

I’ve been a major fan of Bulma ever since discovering it through the weekend project of developer Hassan Djirdeh (@djirdehh), https://www.cryptovue.com. On top of introducing me to the Bulma CSS framework which I instantly fell in love with, it also introduced me to VueJS, a JavaScript framework which, like Bulma, is capturing the attention of developers quicker and quicker each day. It’s been at least five months since I had first discovered Bulma, and in that time it’s already become my favorite CSS Framework and goto tool for Front-end Web Development. It’s replaced Bootstrap, Foundation, and Semantic UI within the span of months; a task which I wouldn’t consider easy by any means.

Bulma is written entirely using CSS alone, meaning that the developers are reliant on their own code alone if they want to introduce functionality such as a hamburger menu toggle it’s CSS class; an opinion that I highly am a fan of, since it reduces the bloat that I was often uncomfortable with when it came to Bootstrap or Foundation. On Top of that, Bulma is written using flexbox instead of traditional CSS grid mechanics, making it much more accessible and extendable where needed. If you hadn’t heard of the framework or played with it, I highly recommend seeing the documentation and comparing it to your favorite framework: bulma.io.

I often browse the issues and pull requests of projects which interest me for that time, and when an issue caught my attention as a topic which I highly needed, or wished for as well, I’d jump in offering to help in anyway possible. This behavior resulted in a week long discussion with Jim Blue, a contributor who had raised the the bug which caught my attention; the result being the solution which would follow the bulma culture best. is-small, and is-large css classes were created for the hamburger button, allowing for the developer to intentionally double or halve the hamburger button while styling the navigation bar to their requirements.

This small contribution perhaps means little to most developers, but I found the fix to be quite useful since in my own projects, I’ve had two instances (so far) where I had to override the defaults of the hamburger button to follow a new desired width / height, this in consequence requiring the spans having to be adjusted to accommodate the ratio as well. The addition of these classes make it much more accessible, and provide non-intrusive options for when the defaults don’t fit your criteria.

During this process, I learned over the week-long discussions and idea-throwing just how easily it is to misinterpret user experience expectations, even when written in the simplest of terms. The concepts from either side being misunderstood resulted in three seperate ideas and implementations, all for a simple CSS bug. That’s amazing! It’s amazing when I reflect on this, thinking of how much bigger projects with developers all over the globe get only conventions, concepts and rich-text to convey such delicate ideas effectively. The world of Open Source is amazing like this, where barriers which separate communities are simply ideas conveyed through language and language alone.