Linking things together

In order to bring a little more “hyperness” to the project, I drank an excessive amount of coffee to keep me awake after all of the late nights, then sat down and worked on some code changes to allow actually following links. With this in place the system is already a fairly useful help system, assuming that you only want your help to be a single page.

Like yesterday, lets start off with an animated GIF showing link navigation in progress (click to view). For the next few days, work will be done on the core back end code, so this is probably the last day for the immediate future that there will be something excitingly visual to look at.

Sample Link Navigation

Sample Link Navigation

Pressing enter while the cursor is currently on top of a link in a help document will trigger the new code, which collects the text of the link and then tries to find an anchor in the current document that matches it. If one is found, that location is jumped to in the same manner as just navigating between anchors, focusing the view on the appropriate area.

For a little extra interactivity, this is also triggered by double clicking on a link. In order to pull this off the code takes advantage of knowing that the drag_select command is invoked when you double click, with an argument that tells it that it should select by words. We listen for when that command is about to execute to know that someone is double clicking somewhere.

From here we can convert the location of the double click to a position in the view and check to see if the underlying text is a link inside of a help document or not. If it’s not, we do nothing further and the selection continues as per normal. If it turns out that the text is actually a link, we manually invoke the command that will follow the link and then block the execution of the selection command.

In both cases the search for an anchor that matches the link that was activated is done in a case (and language) insensitive manner. I can’t think of any compelling reason to have multiple anchors whose only difference is the case of text. Having this search be case insensitive allows you to make a section header appropriately capitalized and link to it with a normal case link.

Once that change was done I worked a little bit on some more useful help that better describes how everything currently works, so that as things proceed everything is more or less self documenting. Along the way I ended up making some changes to how the syntax of the help markdown works in order to make things more visually pleasing.

First off it’s important to note that Sublime syntax highlighting works based on the text that is physically in the buffer at any given point. That makes trying to come up with a syntax for help that allows for some interactivity, color highlighting and useful scopes to delineate the structure of the help document a bit tricky. 

A good example of this is hidden anchors and how they’re currently supported. In order to detect where a hidden anchor is, it needs to be wrapped in a specific set of characters so that it can uniquely be identified. However once those characters are not there, the text loses its special status. That’s why in order to handle hidden anchors we need to first find them by their syntax defined scope, then remember where they were before we remove the characters.

One thing that has been bugging me for a while is that it was not possible to have space characters inside of key bindings, links or anchors. The reason for that is that there is no way to prevent the syntax match from possibly detecting use of those special characters as something else. For example, you might have the text “this * that * the_other == madness”. If spaces are allowed in anchors, suddenly there is an anchor in a location where you didn’t mean for there to be.

As a programmer your first thought would be to quote the asterisk so that it’s known that it’s not supposed to be interpreted as anything other than a literal asterisk. However now you have the problem that the help text has quoted asterisks in it, and you can’t remove the quote characters because that brings back the ambiguity.

In the case of wanting to have spaces inside of special constructs, there is actually a way around this and I’m sort of kicking myself that I didn’t think of it earlier. While writing the help I added a couple of paragraphs regarding using a consistent style in help documents so that everything seems cohesive to the user.

This sparked the notion that you should probably not use tab characters in your help since you have no way of knowing what tab size other people might be using, assuming they use tabs at all. As such a good way to enforce that rule and also solve the problem of spaces in places where they might be ambiguous is to enforce a setting in the buffer that tabs are a single character wide and never translated into spaces.

With that simple change in place it becomes trivial to have what appear to be spaces inside of various constructs because a tab one character wide is  visually indistinguishable from a space. Once this change was in place I went back through the help in order to make things a little nicer in places.

In addition to this, the syntax has also been extended to support separator lines, which are defined as a sequence of four or more “-“ or “=” characters in a row. An example of these in use is the section headers in the help. Currently they’re both scoped the same way to make them visually distinct from the surrounding text. A future update may scope each one separately to allow more variation.

The next few steps will be to  incorporate the idea of having more than one help file available in a single package as well as having multiple packages that have help as well. In order to do that an overall help index system needs to be defined. That will be the task of the next few days, which will lay some important ground work for things to come.