Till Schneidereit

Partly, yes

Editing Git and Mercurial Commit Messages With Sublime Text 2

| Comments

Not only is Sublime Text 2 a fabulous code editor - it also works very well as an editor for shell commands.

At least for me, a major use-case for invoking an editor from the shell is editing commit messages in Git and Mercurial. Now simply setting sub, the shell command for invoking Sublime Text 2, as Git’s or Mercurial’s editor won’t work for that: sub returns immediately instead of waiting for the commit message to be written and saved.

Enter sub --wait. With the --wait (or -w) argument, sub doesn’t return until the file has been closed. The beauty of it is that it’s not necessary to close the entire application: as soon as the sub-opened file is closed, sub returns and the terminal window is focused again!

Wow, cool! But how?

While I don’t know a thing about how sub does this, I do know how to set things to use it.

For Git, run the following command:

1
git config --global core.editor "sub --wait"

For Mercurial, edit the file ~/.hgrc and add the following line under [ui]:

1
editor = sub --wait

Setting Up Eclipse CDT To Work On SpiderMonkey

| Comments

Note: This text has since been added to MDN, so that version is very likely to be more up-to-date than this one, depending on when you’re reading this.

The version of Eclipse’s CDT that’s will be released with the next major release of Eclipse, codenamed “Juno”, has some pretty decent features that make it an attractive environment to work in.

Over at the Mozilla Developer Network, there’s a guide for setting up CDT to work with the Mozilla codebase. As that guide is a bit outdated and doesn’t cover setting things up for just SpiderMonkey instead of the whole Mozilla codebase, here’s a short-ish guide for doing just that:

Step 1 - Preparing a SpiderMonkey build

For CDT to index all code, SpiderMonkey has to be built with debug information. The full process of and requisites for doing so are described on MDN. Please follow those instructions up until the point of invoking configure.

I prefer building with clang, so my modified build commands look like this:

1
2
3
mkdir _DBG.OBJ
cd _DBG.OBJ
CC='clang -Qunused-arguments -fcolor-diagnostics' CXX='clang++ -Qunused-arguments -fcolor-diagnostics' ../configure --enable-debug --disable-optimize --enable-debug-symbols

Note: due to a bug in CDT, it’s currently not possible (or at least not straight-forward) to build with ccache. See Step 4 below for a workaround.

Step 2 - Installing Eclipse and Setting Up the Project

The following run-down is a condensed and updated version of what’s explained in much more detail on MDN for the entire Mozilla codebase. Luckily, improvements in CDT have reduced the basic process to a manageable 10 steps:

  1. Download and extract “Eclipse IDE for C/C++ Developers” from the Eclipse Developer builds
  2. Download the latest snapshot of the CDT from Eclipse’s CI server without extracting the contents
  3. Start Eclipse and create a workspace somewhere
  4. Select “Install New Software…” from the “Help” menu
  5. Click the “Add…” button in the upper right to add a repository, then click on “Archive…” and select the CDT snapshot (use “sd90-snapshot” or something similar as the name)
  6. Select “C/C++ Development Tools” from “CDT Main Features” and whatever you want from “CDT Optional Features” and click “Next” and agree to licenses and installing unsigned packages and all that jazz until you’re prompted to restart
  7. Restart Eclipse
  8. Back in Eclipse, select “New > Makefile Project with Existing Code” from the “File” menu
  9. Give the project a name you like (“SpiderMonkey” has a nice ring to it) and use the “Browser…” button to select your checkout’s js/src folder for the “Existing Code Location”
  10. Choose the correct toolchain for your platform (i.e. MacOSX GCC on Mac) and click “Finish”

At this point, the indexer starts running and already produces a pretty decent index of much of SpiderMonkey. Still, there are a quite a few things that CDT doesn’t pick up yet: For everything to be indexed, CDT has to be aware of the project’s build details.

Step 3 - Index All the Code

To let CDT know about the build, it has to invoke make itself (or, as is done in the guide for the whole Mozilla codebase on MDN, read a log of the build). This can be setup in another set of decently simple steps:

  1. Open the project’s properties by selecting its root and clicking “Properties” in the “File” menu and select “C/C++ Build”
  2. Under “Builder Settings”, deactivate “Use default build command”
  3. Instead, change “Build command” to read make -w (this is required because CDT needs detailed information about which directories make operates on, which using -w causes make to provide)
  4. Change the “Build location” to the build directory configured in step 1. For me, that means changing “Build directory” to read ${workspace_loc:/SpiderMonkey/_DBG.OBJ}
  5. Under “Behavior”, make sure that “Enable parallel build” is deactivated, as CDT’s indexer will freak out otherwise
  6. Remove “all” from “Build (Incremental build)”
  7. Deactivate “Clean” so that your builds don’t take ages
  8. If you’re using clang, a bug in CDT requires changing one more setting: in the project’s “C/C++ General -> Preprocessor Include Paths, Macros etc.” settings panel, select the “Providers” tab, then select “CDT GCC Build Output Parser” and change the content of the “Compiler command pattern” input field to read (gcc)|([gc]\+\+)|(clang)
  9. Start the build by selecting “Build All” from the “Project” menu
  10. Start the indexer by selecting “Index > Rebuild” from the project’s context menu

And that’s pretty much it: Large parts of SpiderMonkey should now be indexed. Unfortunately, there are also large parts that aren’t properly indexed, leading to errors and warnings being shown for perfectly valid code, but I find that the parts that do work do so nicely enough to make it totally worth it.

That leaves us with only one thing to do:

Step 4 - Speeding It Up

As mentioned above, CDT doesn’t like ccache for some reason. Until that bug is fixed, a somewhat simple workaround is to hide the usage of ccache by wrapping it with shell scripts for gcc/g++ and clang/clang++, respectively. I use clang, so I put two scripts into /usr/local/bin/:

cclang:

1
2
#!/bin/bash
/usr/local/bin/ccache /usr/local/bin/clang $@

cclang++:

1
2
#!/bin/bash
/usr/local/bin/ccache /usr/local/bin/clang++ $@

After a quick chmod u+x /usr/local/bin/cclang*, use the following configure command to start working with ccache after all:

1
CC='cclang -Qunused-arguments -fcolor-diagnostics' CXX='cclang++ -Qunused-arguments -fcolor-diagnostics' ../configure --enable-debug --disable-optimize --enable-debug-symbols

On Beginnings

| Comments

On December 31, 1995, Calvin and Hobbes boarded their sled and took off into the blank canvas that to them was the stark white, freshly snow-covered scenery.

That’s not what this post is about. At least in part, it is, however, about endings. Just as that last comic strip Bill Watterson ever published.

In the fall of 1999, I discovered this fantastic little tool called Macromedia Flash 4. To cut a long and boring story short, the result was that instead of going to university, I immediately kicked off my career as a professional web developer in the advertising industry. While in hindsight, that claim of professionalism was bordering on the ridiculous in its utter optimism and naïveté, the good news is: it somehow worked and while I did start university a year later, it had to take a back seat to my main occupation.

Now, twelve years on, it seems like not that much has changed. Granted: I spent the last five years not only developing but also managing teams and doing conceptual work. Still, at the core of things, I am what I was all those years ago - a web developer.

As you might have guessed, though, the real changes are a bit more subtle. As time went on, I became more and more aware of two important facts: first, neither my talents nor my interests really lie in the frontend; second, twelve years of doing advertising is enough for a lifetime.

Don’t get me wrong: I don’t have any deeply-rooted problem with advertising in and of itself. I do, however, think that there’s a fundamental problem with projects in the advertising industry: they lack real stakeholders. Now I might be completely off the mark here, but that was my overarching impression in almost all the projects I was ever involved in and it makes a lot of sense to me, too: the companies you work for in advertising have their stakes in their products, not really in marketing them.

Whether I’m right about this doesn’t really matter, though: real or imagined, this gap I experience is enough of a problem for me that I want to change what I’m working on.

The other part of the equation is that I enjoy building systems, applications and frameworks, not microsites. The projects I enjoy the most are along the lines of Robotlegs, Swiftsuspenders and Reprise - an MVC framework, an IoC container and a CSS-based layout and components framework. Building a CMS abstraction layer to be used by the hundreds of agencies building modules and microsites for the NIVEA website was pretty neat, too.

For these reasons, I have decided to close my current business as the tech lead of a small team of sub-contractors to advertising agencies at year’s end.

As of January 2012, I will do some exploring of a blank canvas of my own and be available for bookings as a freelancing developer specialized in building systems, renderers and complex applications. I’m perfectly capable of doing and will do the occasional frontend programming if an otherwise perfect job requires it, but as said above, I strongly believe that my real talents lie a bit deeper down the stack. If that sounds like something your company could use and you’re either located in Germany or could include me working remotely then please do get in touch!

Flash >= CS5 and version control: Of binary data and wasted bandwidth

| Comments

With the advent of Flash CS5, Adobe switched the format of .fla files from the quirky binary format it was in previous editions to what every self-respecting developer of document-creation tools uses nowadays: A compressed archive consisting of an XML file (the actual document) and lots of additional files.

This in itself would be pretty nice, what with enabling third-party tooling and all. What I want to get at, though, is that they were nice enough to also enable working with those same documents saved as an uncompressed folder: Choosing Flash CS5 Uncompressed Document (*.XFL) as the file format when saving a project causes a folder with the project’s name to be created. Inside this folder is everything that would normally be contained in the .fla:

  • The file DOMDocument.xml, which is the equivalent of the .fla file without any embedded assets or settings
  • The file PublishSettings.xml, which contains exactly what you think it does
  • The file MobileSettings.xml, which also contains exactly what you think it does
  • The file META-INF/metadata.xml, containing the documents’s creation and change history
  • The folder LIBRARY, which contains the documents library, neatly structured in the same way as your library itself, but with additional folders for binary assets, such as BMPs
  • The folder bin, which contains cached versions of the binary assets, pre-converted to their output representations as compiled into the published SWF

The beauty of this setup is that you can work with all these different files just as you would with any other text or binary files: You can edit the XML files in your editor of choice, replace images with newer versions you get from your designer or use your diff and merge tools on them.

This last part is the most important to me: By replacing your .fla files with XFL folders, you allow them to be version controlled in a sane way. Instead of forcing your VCS to deal with incomprehensible blobs of binary data, hoping that it will make the best of it, you allow it to live up to all the hype about its efficiency and speed that caused you to use it in the first place.

One last tip on that: Use whatever means your VCS provides to exclude the *.dat files in the bin folder from versioning. They’re really simple caches that get re-created if missing.

Mario Mushroom: Now with 80% less awesome

| Comments

tl;dr: Don’t use the Mario Mushroom Operator if you don’t want your setter to be invoked more than once.

Update: I totally forgot to mention that I found out about this problem with @darscan while working on Swiftsuspenders and Robotlegs code.

The Details I think it was @robpenner who coined the term “Mario Mushroom Operator”.

In case you’re wondering, the Mario Mushroom Operator is this: ||=.

A good translation for how the MMO™ works seems to be this:

1
if (!field) { field = value; }

In case you’re still wondering, here’s how you’d use it:

1
2
function useRuntimeDefault(input:Object):void { input
||= getDefaultValue(); }

I.e., the most important use-case for the MMO™ is to apply runtime-determined default values for method arguments.

Now, that’s really useful and you might be wondering what could possibly go wrong with that.

Consider this snipped of code:

1
2
3
4
5
6
private var _setOnce : Boolean; private var _value :
Object;

public function set value(value : Object) : void { if (_setOnce) { throw new
Error('Value can only be set once'); } _setOnce = true; _value = value; }
public function get value() : Object { return _value; }

Used in a class, this code encapsulates a value that can be set exactly once, after which it can only be read.

With me still? Splendid.

In fact, you’re probably already guessing what comes now: Using the MMO™ to assign this once-settable value iff it hasn’t already been set:

1
value ||= {};

And here, finally, things go awry. As it turns out, the MMO™’s translation given earlier isn’t quite correct. Instead, the compiler (or the VM, I haven’t checked the bytecode) seems to translate our usage of the MMO™ to something along the following lines:

1
field = field ? field : {};

In summary, instead of guarding the assignment to a field as an if statement would do, the MMO™ only chooses between two values to use in the assignment like the ternary operator does.

In case you’re now thinking that that doesn’t affect you because you, just as every sane person you know, don’t ever have use-cases for one-time assignable fields, ask yourself whether you can be certain that all your setters are side-effect free if you re-assign the same value and that you never, ever, care about the overhead associated with double-setting values needlessly. “Yes” and “yes”? Cool. “Mmh” and “not sure”: Weep with me.