Posted on by & filed under Content - Highlights and Reviews, Programming & Development.

A guest post by Ingo Richter, a Computer Scientist/Web P&A with Adobe Systems who is currently working on Brackets and you can find him @ingorichter.

In the first part of this series of blog posts, I gave you an overview of Brackets and what technologies and components we used to build this code editor. I’ve mentioned that Brackets is built with the languages and tools of the modern web: JavaScript, HTML5 and CSS. In this post I will show you how to leverage your knowledge in these technologies to extend Brackets and add “the missing feature,” that you want your code editor of choice to have. Remember: Brackets was built from the beginning with extensibility in mind.

Have a look at the Brackets Extension Registry before you start churning out the next great Extension. Somebody might have already solved the problem that you want to solve.

Where Extensions can contribute

An Extension can contribute to basically every area of Brackets, allowing you to add:

    • A menu item
    • A context menu item
    • A menu divider
    • A keyboard shortcut
    • New UI elements (it’s all HTML & CSS)

If your Extension is about to contribute to Brackets’ core features, it’s recommended to use the well defined interfaces if possible. This list contains the core feature and the API that is intended to make contributions:

      • Quick Edit – EditorManager.registerInlineEditProvider()
      • Quick Docs – EditorManager.registerInlineDocsProvider()
      • Quick Find Definition – QuickOpen.addQuickOpenPlugin()
      • Quick Open – QuickOpen.addQuickOpenPlugin()
      • Code Hints – CodeHintManager.registerHintProvider()
      • Syntax Coloring – LanguageManager.defineLanguage()
      • Code Linting/Inspection – CodeInspection.register()

You can find more information about these features on the Brackets Wiki or by searching for the functions in the Brackets source code.

Let’s write some code

If you’ve installed Brackets on your machine, then you are ready to develop your first Extension. I recommend using the latest version from the Brackets Website. I’m going to create an Extension, that provides a transpose command to swap two words. This is some functionality that I liked in Emacs, and I don’t want to miss it in Brackets anymore.

Structure of a Brackets Extension

A minimal Brackets Extension consists of one file named main.js. You can pack all of your Extensions’ functionality into this one file. Packaging and releasing your Extension to the Brackets Registry requires a package.json file with some metadata about your extension (author, keywords, dependencies). A handful of example Extensions come installed alongside Brackets. You can find them inside the src/extensions/samples directory of your Brackets installation.

Now, launch Brackets and select Help->Show Extensions Folder from the menu bar. This is the location where user installed Extensions are stored and loaded from.

Open the user directory and create a new directory BracketsTranspose here. This directory will contain all of the files required for your Extension. Drag the BracketsTranspose directory onto the Brackets application icon. This will open the newly created directory and treat it as a project. Now right click in the area underneath the project name and select New from the context menu. Save this new file as main.js. This is the main entry point for your Extension.

Put the this code snippet into main.js, save it and select Debug->Reload Brackets. This will reload Brackets and all Extensions:

Now you should see something like this:

BracketsHelloWorld

Well done! What happened here? First of all, we defined a module for our Extension. Since Brackets uses require.js to load extensions, the extension entry point has to comply with the module definition:

We load a module from the Brackets context. AppInit provides a function that will notify us, once Brackets is fully loaded and running:

The simple function that we will call once loading Brackets is done.

The appReady function takes a callback function that will be called when Brackets is fully loaded. If you see the dialog box, then everything works as expected.

Adding a Menu Item

To add a Menu Item, we have to add two getModule statements to get a handle to the Brackets Menubar and the Command infrastructure. Why do we have to use getModule and not require? Brackets uses require.js to load dependent files. Calling getModule will load a file from a different context, namely Brackets and not from the Extension context.

Add these lines after the first getModule call in main.js:

Then add these lines above the AppInit.appReady(...) function:

Remove the call to helloWorld in the appReady callback function, since we don’t want to have this function called anymore when Brackets starts.

After reloading Brackets with Cmd/Ctrl+R, you would see a new Menu Item at the bottom of the Edit menu. If you select this Menu Item, you should see the same Hello World dialog coming up. Now we need to implement the transpose functionality that swaps the position of two words.

Accessing the Editor Contents

Next, we need to access the content of the current editor and the underlying document. Brackets provides a thin layer on top of the underlying CodeMirror component to ease the access to the editor and the document.

Note: To save some space, all of the comments have been removed from the source code in this post. You can find the complete project with comments on github.

We need to add these two lines to the existing getModule lines at the top of main.js:

The function to handle the transpose command uses the EditorManager to get access to the current editor. Once we have a valid editor, we can continue to access the text in the editor, extract the line of text where the cursor is currently placed, and start the transpose operation. After the text has been altered and the words have been transposed, the cursor will be placed after the second word, just as in Emacs and bash.

Add the following piece of code above the line where we defined MY_COMMAND_ID:

Putting it all together

Add this function above handleTranspose, since it’s needed by _getWordPositions:

_getWordPositions provides the core of the transpose functionality. The function takes a string and an index position inside the string as arguments. Beginning at the index position, the function will figure out the word at this position. The previous word (if any) returns an object containing the information about both words, their start- and end- index. This function doesn’t have any dependency to Brackets, since we only operate on a string that could have any origin.

We need to add this code snippet after the isWordChar function:

transposeWords handles the transpose operation, based upon the information that was returned by _getWordPositions. A new string is created and returned as the result:

Now we have everything in place for a fully functional Extension.

Let’s see it in Action

Reload Brackets one more time to load the Extension with all of the changes that we made to it. Create a new document (Ctrl/Cmd+N) and paste The quick brown fox jumps over the lazy dog into the new document.

Place the cursor on the word fox and transpose the words brown and fox by either selecting the menu item or by pressing Alt+T. Do it again and see the words switch places to their previous locations.

Conclusion

In this post I gave you an overview of how easily you can extend Brackets and add new functionality to them. I’ve added a Menu item, a keyboard shortcut, and modified the contents of a document. But I’ve only scratched the surface of what an Extension can do. There are some many areas (localizing, testing, debugging) that I haven’t touched yet.

Additional information can be found in the Brackets Wiki about how to create your own Extension. Another great resource is the Brackets Extension Registry, where you can find numerous Extensions and their source code location for you to study.

If you have any question regarding the Extension or general Brackets question you can contact me via @ingorichter or ask your question in the Brackets Google Group.

Be sure to visit the Brackets Transpose Extension on github and the Brackets Extension Registry.

If you want to know more about Brackets, I recommend starting with the GitHub Project page, and look below for some great JavaScript resources from Safari Books Online.

Not a subscriber? Sign up for a free trial.

Safari Books Online has the content you need

Learning JavaScript Programming Video teaches you the basics of programming with JavaScript, the worlds most used programming language. The tutorial is designed for the absolute beginner – no prior JavaScript programming experience is required in order to get the most out of this video training. You will start with learning what programming is, and specifically, what JavaScript is, how it it used, and its limitations. You will discover variables and data types, and how to take input and create output. Craig covers conditions, loops, arrays, sorting, functions, paramaters and debugging. You will even learn advanced concepts such as OOP, string manipulations, regular expressions and other programming patterns.
Eloquent JavaScript is a guide to JavaScript that focuses on good programming techniques rather than offering a mish-mash of cut-and-paste effects. The author teaches you how to leverage JavaScript’s grace and precision to write real browser-based applications. The book begins with the fundamentals of programming—variables, control structures, functions, and data structures—then moves on to more complex topics, like object-oriented programming, regular expressions, and browser events. With clear examples and a focus on elegance, Eloquent JavaScript will have you fluent in the language of the web in no time.

About the author

IngoPortrait-1 Ingo Richter is a Computer Scientist/Web P&A with Adobe Systems, and is currently working on Brackets. He has successfully worked through five release cycles of the Adobe Creative Suite and is experienced in creating products from start to finish. He moved from Hamburg, Germany to the Bay Area to explore the Wild West. You can find him on Twitter @ingorichter.

Tags: Brackets, Brackets Extension, CSS, Github, html, Javascript,

Comments are closed.