<![CDATA[Left of Null]]>http://leftofnull.com/Ghost 0.5Sun, 04 Jan 2015 23:40:46 GMT60<![CDATA[Enhancing Sublime Text Context Menus on Windows]]>Sublime Text

It's a great code editor. It can be an IDE if you want it to be, but at it's heart it's a highly extensible text editor. I love it! You can even get intellisense for C# now if you visit OmniSharp.net and follow the steps to install. I'll do some more blogs on how I have my Sublime Text set up and one to set up OmniSharp. This is really just some quick enhancements to make a great product a little better. By the way, Sublime Text is free with some nag-ware. I highly reccomend you pay for it and support the team, I did and it was well worth it.

Enhancing the Context Menu

Sublime Text, by default, will give you the option to add Open with Sublime Text to the context menu when right-clicking any file. This is great and I use it a lot, make sure you've selected it during the install before starting this.

One thing that I have trouble with is that I do have other context menu enhancements and the Open with Sublime Text doesn't always jump out at me. So one thing we're going to do is add the Sublime Text icon to the existing context menu option. The other thing we're going to do is add an Open Directory with Sublime Text action to the context menu when we right-click on a directory. All it takes is creating a .reg file to update your registry.

1. Create a file on your desktop

  1. Right-click on the desktop
  2. Click New > Text Document
  3. Name it "SublimeContext.reg" make sure to drop the .txt extension

2. Open in Notepad (or Sublime Text)

  1. Make note of your installation directory of Sublime Text. I'm running Windows 8.1 with Sublime Text 3 in the default location. so for me, it is C:\Program Files\Sublime Text 3\sublime_text.exe
  2. If your's is the same, no need to do anything, otherwise you'll have to edit the block below with your default installation.
  3. Copy and paste the following block into your file.

    Windows Registry Editor Version 5.00
    [HKEY_CLASSES_ROOT\*\shell\Open with Sublime Text]
    "Icon"="C:\\Program Files\\Sublime Text 3\\sublime_text.exe"
    [HKEY_CLASSES_ROOT\*\shell\Open with Sublime Text\command]
    @="C:\\Program Files\\Sublime Text 3\\sublime_text.exe \"%1\""
    [HKEY_CLASSES_ROOT\Directory\Background\shell\Sublime Text]
    @="Open Directory with Sublime Text"
    "Icon"="C:\\Program Files\\Sublime Text 3\\sublime_text.exe"
    [HKEY_CLASSES_ROOT\Directory\Background\shell\Sublime Text\command]
    @="C:\\Program Files\\Sublime Text 3\\sublime_text.exe \"%V\""
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\Sublime Text]
    @="Open Directory with Sublime Text"
    "Icon"="C:\\Program Files\\Sublime Text 3\\sublime_text.exe"
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\Sublime Text\command]
    @="C:\\Program Files\\Sublime Text 3\\sublime_text.exe \"%V\""
  4. Save and close your file.
  5. Double-click on it and say yes, you want to add it to the registry.

What's it doing?

I know I'm suspicious of modifying the registry, so let's walk through each line.

[HKEY_CLASSES_ROOT\*\shell\Open with Sublime Text]
"Icon"="C:\\Program Files\\Sublime Text 3\\sublime_text.exe"
[HKEY_CLASSES_ROOT\*\shell\Open with Sublime Text\command]
@="C:\\Program Files\\Sublime Text 3\\sublime_text.exe \"%1\""

These two are merely updating an existing key. The first HKEY is ensuring that you have the Open with Sublime Text context menu. The Icon String Value is a new one we're adding. It's simply adding the Sublime Text icon to the context menu. The second HKEY was an existing key that executes the command of opening the file you right-click in Sublime Text.

[HKEY_CLASSES_ROOT\Directory\Background\shell\Sublime Text]
@="Open Directory with Sublime Text"
"Icon"="C:\\Program Files\\Sublime Text 3\\sublime_text.exe"
[HKEY_CLASSES_ROOT\Directory\Background\shell\Sublime Text\command]
@="C:\\Program Files\\Sublime Text 3\\sublime_text.exe \"%V\""

These two add the new Open Directory with Sublime Text to the background context menu, we'll cover each line specifically below which adds to the right-click context menu in the same way.

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\Sublime Text]
@="Open Directory with Sublime Text"
"Icon"="C:\\Program Files\\Sublime Text 3\\sublime_text.exe"
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\Sublime Text\command]
@="C:\\Program Files\\Sublime Text 3\\sublime_text.exe \"%V\""

These two are completely new. This is what adds Open Directory with Sublime Text to the right-click context menu. The first HKEY adds the text to the context menu and the Icon. The second HKEY adds the command of opening the directory you right-clicked in Sublime Text.

It's not much, but it adds a nice little touch to an amazing product. Have fun with it!

http://leftofnull.com/2015/01/04/enhancing-sublime-text-context-menus-on-windows/b9fb88a0-d0fe-4615-a240-71eabb2f2d1cSun, 04 Jan 2015 23:38:22 GMT
<![CDATA[Setting up the package.json for node.js. The short, short version]]>Package.json

Most tutorials start with the package.json. This is a very important step. Here's an example of a live package.json, this is Ghost v0.5's package.json:

  "name"        : "ghost",
  "version"     : "0.5.0",
  "description" : "Just a blogging platform.",
  "author"      : "Ghost Foundation",
  "homepage"    : "http://ghost.org",
  "keywords"    : [
  "repository"  : {
      "type": "git",
      "url": "git://github.com/TryGhost/Ghost.git"
  "bugs"        : "https://github.com/TryGhost/Ghost/issues",
  "contributors": "https://github.com/TryGhost/Ghost/graphs/contributors",
  "licenses"    : [
          "type": "MIT",
          "url": "https://raw.github.com/TryGhost/Ghost/master/LICENSE"
  "main": "./core/index",
  "scripts": {
      "start": "node index",
      "test": "./node_modules/.bin/grunt validate --verbose"
  "engines": {
      "node": "~0.10.0"
  "engineStrict": true,
  "dependencies": {
      "bcryptjs": "0.7.10",
      "body-parser": "1.6.3",
      "bookshelf": "0.7.6",
      "busboy": "0.2.3",
      "colors": "0.6.2",
      "compression": "^1.0.2",
      "connect": "3.0.0-rc.1",
      "connect-slashes": "1.2.0",
      "cookie-parser": "1.0.1",
      "downsize": "0.0.5",
      "express": "4.8.3",
      "express-hbs": "0.7.10",
      "express-session": "1.0.4",
      "fs-extra": "0.8.1",
      "html-to-text": "^0.1.0",
      "knex": "0.6.21",
      "lodash": "2.4.1",
      "moment": "2.4.0",
      "morgan": "1.0.0",
      "node-polyglot": "0.3.0",
      "node-uuid": "1.4.1",
      "nodemailer": "0.5.13",
      "oauth2orize": "1.0.1",
      "passport": "0.2.0",
      "passport-http-bearer": "1.0.1",
      "passport-oauth2-client-password": "0.1.1",
      "rss": "0.2.1",
      "semver": "2.2.1",
      "showdown": "https://github.com/ErisDS/showdown/archive/v0.3.2-ghost.tar.gz",
      "sqlite3": "2.2.3",
      "static-favicon": "1.0.2",
      "unidecode": "0.1.3",
      "validator": "3.4.0",
      "when": "3.2.3",
      "xml": "0.0.12"
  "optionalDependencies": {
      "mysql": "2.1.1"
  "devDependencies": {
      "blanket": "~1.1.5",
      "bower": "~1.3.5",
      "grunt": "~0.4.1",
      "grunt-cli": "~0.1.13",
      "grunt-concat-sourcemap": "~0.4.3",
      "grunt-contrib-clean": "~0.5.0",
      "grunt-contrib-compress": "~0.5.2",
      "grunt-contrib-concat": "~0.4.0",
      "grunt-contrib-copy": "~0.4.1",
      "grunt-contrib-jshint": "~0.8.0",
      "grunt-contrib-uglify": "~0.5.0",
      "grunt-contrib-watch": "~0.5.3",
      "grunt-docker": "~0.0.8",
      "grunt-ember-templates": "~0.4.18",
      "grunt-es6-module-transpiler": "~0.6.0",
      "grunt-express-server": "~0.4.11",
      "grunt-mocha-cli": "~1.4.0",
      "grunt-shell": "~0.7.0",
      "grunt-update-submodules": "~0.4.0",
      "matchdep": "~0.3.0",
      "mocha": "~1.15.1",
      "nock": "0.27.2",
      "rewire": "~2.0.0",
      "request": "~2.29.0",
      "require-dir": "~0.1.0",
      "should": "~2.1.1",
      "sinon": "~1.7.3",
      "supertest": "~0.8.2"

Notice the dependencies, optionalDependencies, and devDependencies sections. These list the referenced packages that are required for the system to work. When you clone Ghost you can run ~/ghost $ npm install from inside the Ghost directory and all the dependent packages will be retrived. If you're a .NET developer, you can think of these as References, or better yet, NuGet packages with the "auto-download missing packages" feature enabled.

The scripts section allow you to run the application by aliasing ~/ghost $ node index for ~/ghost $ npm start. Additionally you can run the test suite by using ~/ghost $ npm test. npm "understands" these as default scripts. So what makes this the short, short version?

Rapid setup

Don't bother with trying to create the package.json yourself. You can tweak it by hand for sure, but there are much simpler ways to create it. Ways like this:

~ $ mkdir myProj
~ $ cd myProj
~/myProj $ npm init

npm init is a tool that will walk you through creating a package.json via a cli wizard. Just answer the questions it asks you like this:

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See 'npm help json' for definitive documentation on these fields
and exactly what they do.

Use 'npm install <pkg> --save' afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (myProj) MyProj
version: (1.0.0) 0.0.1
description: Sample npm init
entry point: (index.js) app.js
test command:
git repository: <git repo url (if applicable)>
keywords: npm, node, tutorial, package.json
author: Alexander Kahoun
license: (ISC) MIT
  "name": "MyProj",
  "version": "0.0.1",
  "description": "Sample npm init",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "repository": {
    "type": "git",
    "url": "<git repo url (if applicable)>"
  "keywords": [
  "author": "Alexander Kahoun",
  "license": "MIT"

Is this ok? (yes) yes

Now you have a package.json all ready to go. Another cool tip, you can auto-save dependencies to your package.json as you go. All you need to do is add a flag to your npm install <packageName> command. For instance:
~/myProj $ npm install mongoose --save will both install mongoose into your myProj directory and it will add the following to your package.json:

"dependencies": {
    "mongoose": "^3.8.18"

Alternatively npm install mongoose --save-dev or npm install mongoose --save-optional will install the packages just the same, but put them into your package.json in the devDependencies section or optionalDependencies sections respectively.


Too long; didn't read

Make sure you use npm init and npm install <package> --save for quick setup of a project:

~ $ mkdir myProj
~ $ cd myProj
~/myProj $ npm init

Answer the questions it asks you, don't be afraid to leave them blank if you don't know.

~/myProj $ npm install <package> --save

Repeat as necessary.


You may want to be careful with some of the packages. Some packages like express.js are great for rapid setup, but when you run the express command to set up your project, it will overwrite any existing package.json. So if you have a package that sets up your package.json for you, make sure to install your dependencies after you run the command.

Happy coding!

http://leftofnull.com/2014/10/28/setting-up-the-package-json-for-node-js-the-short-short-version/c7bae75e-1189-4ddf-ba2d-07e6b9adb754Wed, 29 Oct 2014 02:31:38 GMT
<![CDATA[Virtual Desktops for Windows]]>There's been some speculation of Windows finally getting virtual desktops as a feature in Windows 9. To be honest, this is a very welcome change. After all, Linux has had it for almost 20 years now.

If you'd like to get it now and you're running XP, Vista, 7, 8, or 8.1 (meaning you're not from the past), you can get the functionality right now with Dexpot!

Dexpot is free for private use and only costs $32 for a single user license. Free is great, but it's always nice to support your friendly devs, especially when they provide such an incredible tool.

You can configure your Windows system to function with Virtual Desktops suprisingly similar to Mac OS X desktops. I personally have it set up with 4 virtual desktops with a filmstrip animation. You can configure all your hot keys to scroll between them, jump to a specific one, navigate with the mouse or double click on the icon to view all desktops (as seen above).

Out of the box you'll be able to double click and select a desktop, no cofiguration necessary. Here is a list of default actions and what they do for you:

  • Ctrl + Shift + Mouse Wheel: Scroll through virtual desktops.
  • Alt + 1: Go to desktop 1, change the 1 to any number and jump to that desktop.
  • Win + F2: Display all active programs on the current desktop expose-style.
  • Win + F3: Show all desktops, same as double-clicking the icon

This is just a small sample of what you can do with Dexpot, it's a really great tool.

Setting up Filmstrip animation

Open the Dexpot settings by right-clicking the icon in the notification area and selecting Settings.

Go to the last option of Plugins and Extras. Make sure you have Dexcube enabled. Select it and click the configure button.

I personally like the filmstrip option becuase it's most like my Mac, but there are a bunch of options. Choose the one you like most. You can also adjust the animation speeds on the right. You'll notice that I've sped up my transition from the default.

That's it! Have fun with multiple desktops in Windows right now!

Memory concerns

I have none personally. Dexpot is really good on memory. As you can see from the task manager screen shot below, Dexpot and all it's plugins take up a total of 11.7MB. If that's a concern for you, you may want to consider upgrading your system or time-travelling here from 1996 (since you're living in the past, you may not have a compatible OS either).


http://leftofnull.com/2014/08/24/virtual-desktops-for-windows/fb0a789d-37b4-42d7-b57b-7f46eae023fcSun, 24 Aug 2014 22:23:11 GMT
<![CDATA[The Importance of the Ubiquitous Language]]>Ubiquitous: /yoo-bikwitəss/
  • existing everywhere: present everywhere at once, or seeming to be

Language: /láng-gwij/

  • communication with words: the human use of spoken or written words as a communication system
  • speech of group: the speech of a country, region, or group of people, including its vocabulary, syntax, and grammar
  • system of communication: a system of communication with its own set of conventions or special words

Ubiquitous Language:

  • system of communication: a system of communication with its own set of conventions or special words that exists everywhere within a given business domain

Eric Evans first coined the term in his book on Domain Driven Design, which is available in kindle-edition now by the way. If you haven't read it, I recommend adding it to you reasing list. I'll hone in on the same excerpt that Martin Fowler did in his post on the topic.

By using the model-based language pervasively and not being satisfied until it flows, we approach a model that is complete and comprehensible, made up of simple elements that combine to express complex ideas.

Domain experts should object to terms or structures that are awkward or inadequate to convey domain understanding; developers should watch for ambiguity or inconsistency that will trip up design.

-- Eric Evans

When I start a new project, no matter how big or small, I like to take the time to fully understand what the users do as a workflow. I think all of us do to some extent. UX experts create Journey Maps to illustrate what they've learned from such sessions. I like to put together a Ubiquitous Language Dictionary. It's more of a wiki though, to be honest.

I'm sure you're familiar with the adage, "Measure twice, cut once." This is part of the measuring process. You are measuring your, and potentially the team's, understanding of the domain you are working in. In some cases you will be testing the users' knowledge as well. People are creatures of habit and we tend to do things without asking why, because it simply works. Your job is to ask why and to keep asking it until you've reached the bottom. Case in point, why is Wednesday spelled as it is?

When I set out to start my dictionary for a project, I aim to gather two things right away; Nouns and Verbs. Nouns are, well, nouns. They are things like Product, Order, Employee, Manager, User, etc. Verbs are what you do with the nouns, Place an Order, Hire an Employee, Sell a Product, etc. In terms of self-documenting code, you can take the Nouns and make them your Domain classes or abstractions; Verbs become your methods either on the Domain classes or in an Application Service layer, if you've chosen that path. That's really another discussion though. This allows me to have a solid foundation to start with before the complexities come into play.

The complexities are that you almost always are going to have different user types or personas that use the system in different ways. A Product to a Customer means something different than a Product means to a Seller. They may have many similar properties, but the verbs around them to each persona could vary greatly. A Seller Sells a Product, a Customer Buys a Product. It's these nuances that you have to identify and figure out. This is where it gets complex in that you need to make sure you identify the global domain definition of a Product and its Verbs and what the Product means to all the different personas. It's okay to have a Noun and/or Verb listed multiple times in different, or similar, ways for each persona involved. So expect to have global Nouns and Verbs along with persona specific Nouns and Verbs. The separation is what Evans refers to as Contexts. In a given context Product means [insert definition here].

So why is this any more important than any other requirements gathering? Well this is where it all starts and ends, communication. If you're taking the time to speak and write code in the language of the customer, you reduce miscommunication and increase supportability of your software. It's been said that homicidal maniacs read code too, make it easy on them so that when a user says, "Hey, I can't place an order," the next developer supporting the software can easily find the PlaceOrder method and start there. Your code now mimics the language of the user(s).

At the end of the day, if you're able to articulate to users the issues you're having or ask them about processes in their own language you will get a much more valuable response if you're all using the same vernacular. One thing that should set off red flags for you is when someone says you can use multiple terms for the same thing. Why? Are they truly the same? Are they the same thing, but at different phases in its life-cycle? Who uses which term when? These are the questions you need to ask when you encounter this. Keep in mind that language is a complex medium. It won't always be easy, but you can do it.

Conway's Law

organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations

-- Melvin Conway

Another way of putting it is, why not try to change the communication structure of a team to match a system design that you want to build.

Happy Coding!

http://leftofnull.com/2014/06/29/the-importance-of-the-ubiquitous-language-2/937222bf-f5d8-4446-9912-447db5905fe6Mon, 30 Jun 2014 04:02:38 GMT
<![CDATA[Why are you using source control?]]>Top Reasons

1. Save code other than on a local drive

2. Share code among teams

3. Version Control

Everyone that uses source control will list these reasons. I list all these reasons. They're all perfectly accurate too, butare you really using it for all three reasons?

Save code other than on a local drive

Of course you do this, if you're using any kind of source control server you can't get away from it. This is, after all, one of the prime selling points to business if they don't understand why you need it. All you have to do is explain that if you don't do this all of the code could be lost in the blink of an eye. You're laptop or computer could get stolen, you're hard drive could fail, you could get hit by a bus... The list goes on, but I'm sure you're well familiar with it.

Share code among teams

Again, if you're on a team you most likely are already doing this. Unless you're emailing eachother the zipped up source code or all working on a network share. ::shudder::

Version Control


Here's where it gets interesting. Are you really taking advantage of the version control capabilities of your source control provider? Every change you commit is stored in the history. To truly realize this functionality you should be committing as often as possible. Depending on your version control system, this doesn't always mean pushing it to the source control server, but creating a bookmark for yourself. More of a personal stash that's stored locally or on a server.

Far too often I encounter a file/module/component with the suffix V2 with no good reason. There are always exceptions to this, so if you encounter a V2 or Vn don't fly off the handle until you're sure previous versions truly aren't needed... then fly off the handle. ;)

See if you are concerned about rolling back or commenting out old code, please don't. This is exactly one of the reasons that version control exists in the first place.

http://leftofnull.com/2014/04/04/why-are-you-using-source-control/9d145aae-adf1-4183-9b40-e3646b8ab71dSat, 05 Apr 2014 03:38:31 GMT
<![CDATA[Constant Vigilance: Classes or Structs in C#]]>I'm going to have a recurring theme on the blog from time to time. I'll probably have several, but this is the first. The theme here is constant vigilance. The same advice that Mad-Eye Moody gives to Harry Potter in the books. The constant vigilance theme will address poor coding habits that are encouraged by the tools we use. Don't get defensive just yet, and read on. If you disagree, I welcome your comments and will do my best to keep up.

Constant Vigilance

Classes or Structs in C#

Many of the tools we use, such as ORMs, require us to map to POCOs (Plain Old CLR Objects). WCF encourages POCOs for DataContracts for DTOs and SOAP Objects. This is all fine as they suit the needs of their intended purposes. There's absolutely nothing wrong with it at all. The problem is us. The more these tools are used the more the format becomes old hat. We get used to doing things this way and never question mimicking it in our own systems, even when it's not needed. Let's look at the basic differences between the two.


Classes are generally stored on the heap and are cleaned up when the garbage collector no longer detects any references and deems it safe to destroy. Classes are also generally passed by reference. In terms of C++, you're dealing with pointers. Albeit pointers that are managed and cleaned up for you. Keep in mind this is an overly simplistic view of classes and the same over simplicity holds true for the Structs section below. For a very in-depth analysis of stack vs heap, read this article by Eric Lippert.

Classes excel at a few things. They are good at/for:

  • Encapsulating Data
  • Hiding Data
  • Inheritance
  • Polymorphism
  • Composition
  • Abstraction

Keep that in mind when we look at the next section.


Structs are generally stored on the stack. This alone gives them an advantage over Classes. The stack is accessed quicker than the heap. Mind you, this is a micro-optimization and you're at the mercy of the JITer you're using. This also means that they are generally disposed of upon loss of scope, meaning you don't have to wait for garbage collection to run.

Structs are also good at a number of things, like:

  • Data Encapsulation
  • Polymorphism

So which should you use?

The answer, as always, is that it depends. Take a look at the lists above. Are you trying to hide implementation details? Use a Class. Are you taking advantage of abstraction, composition, or inheritance? Use a Class. Otherwise, you could use a Struct. I would even argue when you're using abstraction, if you're not inverting control, do you really need the abstract? True, you should strive to eliminate duplicate code, but sometimes it's worth a little exploration to see if one performs better than the other. Remember, it's a fine balancing act between a writing clean code and writing software that users want to use. If you're going to go against the grain though, make sure you comment as to why you are doing so.


Let's say that you need to handle some events that look like this.

public class MyClassCreatedEvent
    public int Id { get; set; }
    public DateTime Stamp { get; set; }

    public MyClassCreatedEvent(int id, DateTime stamp)
        Id = id;
        Stamp = stamp;

There's nothing wrong with this, but couldn't it be as simple as:

public struct MyClassCreatedEvent
    public int Id;
    public DateTime Stamp;

    public MyClassCreatedEvent(int id, DateTime stamp)
        Id = id;
        Stamp = stamp;

There really isn't much difference between the two, but there's no reason at this point to make it a Class. I say 'at this point' because you may need to change it down the road. That's okay. Software changes, it's inevitable. This is where YAGNI comes into play. If you don't need it right now, then don't waste effort on building it right now. This again is a balancing act, but the point is to not do more than you need to, because what you think you need may change tomorrow.

http://leftofnull.com/2014/03/19/constant-vigilance-classes-or-structs-in-c/25b83864-0ce7-4b37-bd09-f83f62e59ed1Thu, 20 Mar 2014 02:52:46 GMT
<![CDATA[Using GitHub Pages with Ghost and Buster on Windows (part 2)]]>Hacking Buster and Deploying

Part 1: Taking Inventory and Setting Up
Part 2: Hacking Buster and Deploying


In the first part of the series we talked about setting up your Windows machine with Node.js, Python, MinGW, Git Bash, and Pip. If you haven't done so already, please use the link to part one above.

Getting Ghost

Let's get start on getting you set up with the Ghost blogging engine. You should start by heading over to the Ghost GitHub Repository. The README has a lot of great info in it and goes over various ways to install. We'll cover cloning the repo so you can run it locally. Let's start by firing up your Git Bash and entering the following:

$ cd ~

This assumes that you want to run everything in your users directory, if not change to a path where you want to install ghost. Now we'll clone ghost.

$ git clone https://github.com/TryGhost/Ghost.git
$ cd ghost
$ npm install --production
$ npm start

You should have Ghost running on the default url . You can start to create an admin profile and access the admin settings any time at /ghost. Now if you want to set a specific URL for your GitHub Page let's set that repo up on GitHub first. Go ahead and hit Ctrl+C in your Git Bash.

Setting up your GitHub repo for GitHub pages

The best info, as always, can be found from GitHub themselves at GitHub Pages. As a quick abbreviated version, we'll set up a new repo for this exercise. Go to your GitHub account and create a new repo.

Name the new repo whatever makes sense to you. Make sure to select Initialize with README. It's not necessary but it makes the next step that much quicker. Now in your new repo, create a new branch called gh-pages. It's very important that it be exact, this is what GitHub Pages works on.

When you're finished it should look like this:

Setting up your new site in git locally

Now that you have the repo set up, let's pull it down. There should be a link in the bottom right of your repo page on GitHub that looks like this:

Click the "copy to clipboard button to grab the clone url"
Fire up your Git Bash again and use the following commands:

$ cd ~
$ git clone https://github.com/leftofnull/mywebsite.git <this will be the url you copied, not this exact one>
$ git checkout -b gh-pages

You should now have your repo set up!

Modifying the default URL in Ghost

Make sure Ghost is not running. Navigate in the file explorer to where you cloned Ghost and look for config.js. Open it any any text editor and find the url: property and change it to http://username.github.io/repository.

Hacking Buster

Unfortunately for Windows users Buster was not designed with Windows in mind. So we'll have to do a little hacking. I have a forked version of the Buster repo that can be cloned here:

$ cd ~
$ git clone https://github.com/leftofnull/buster.git
$ cd buster

The original repo can be found at https://github.com/axitkhurana/buster. The main differences are in the buster/buster.py file.

Starting at line 39, original:

if arguments['generate']:
    command = ("wget \\"
               "--recursive \\"
               "--convert-links \\"
               "--page-requisites \\"
               "--no-parent \\"
               "--directory-prefix {1} \\"
               "--no-host-directories \\"
               "{0}").format(arguments['--domain'], static_path)

And the modified version:

if arguments['generate']:
    command = ("wget "
               "--recursive "
               "--convert-links "
               "--page-requisites "
               "--no-parent "
               "--directory-prefix {1} "
               "--no-host-directories "
               "--restrict-file-names=unix "
               "{0}").format(arguments['--domain'], static_path)

We've removed the \\ characters as they cause Windows to escape the string, in *nix based systems it allows you to use a carriage return and keep typing the same command. We've also added the --restrict-file-names=unix flag which will prevent some of the default escaping in html files that Windows performs with wget. This also negates the --convert-links flag unfortunately, we'll fix that in a minute.

Next on line 50, original:

file_regex = re.compile(r'.*?(\?.*)')

We'll need to modify and add another regex:

file_regex = re.compile(r".*?(@.*)")
html_regex = re.compile(r".*?(\.html)")

We have to modify the file_regex for Windows and we're going to create another to identify html files.

At line 52 in the original:

for filename in filenames:
    if file_regex.match(filename):
        newname = re.sub(r'\?.*', '', filename)
        print "Rename", filename, "=>", newname
        os.rename(os.path.join(root, filename), os.path.join(root, newname))

We'll tweak to:

for filename in filenames:
    if html_regex.match(filename):
        path = ("{0}").format(os.path.join(root, filename).replace("\\", "/"))
        with open(path, "r+") as f:
            file_contents = f.read()
            file_contents = file_contents.replace(arguments['--domain'], "")
            file_contents = file_contents.replace("%hurl", arguments['--domain'])
    if file_regex.match(filename):
        newname = re.sub(r'@.*', '', filename)
        print "Rename", filename, "=>", newname
        os.rename(os.path.join(root, filename), os.path.join(root, newname))

Here's our big cheat. We're going through all html files and swapping out any instances of the root url, in this case or where ever you're running it locally and replacing it with a relative url path. Hacking Complete! As you can imagine, this has some built in performance degradation, but it works!

Installing your modified Buster

Open your Git Bash, if you haven't already, and use the following commands:

$ cd ~
$ cd buster
$ python setup.py install
$ buster --version

That's it!

Setting up Buster

Run the setup and when it asks for your GitHub url, use the one you will be using for your gh-pages that you set up earlier. If you need to, grab the clone url again before you start.

$ buster setup

And follow the prompts.

Now you'll need to open another instance of Git Bash and run:

$ cd ~
$ cd ghost
$ npm start

If you didn't finish setting up the admin stuff before, you'll need to set it up now. You should have the welcome post by default, we'll leave that for now so we can test it out. Once that's finished, leave Ghost running and switch back to the Git Bash where you ran the setup for Buster from.

$ buster generate --domain= --dir=/c/users/username/mywebsite
$ buster deploy --dir=/c/users/username/mywebsite

This will generate the static content and deploy your site to the gh-pages branch in GitHub. You can try navigating there by putting the http://username.github.io/repository in the location bar of any browser window.

That's it! You now have a blog on GitHub Pages with Ghost and Buster. Any time you want to add new blogs or modify it, just run ghost locally, make the changes, and run the buster generate and deploy commands. Let me know in the comments if you run into any issues. Happy Coding!

http://leftofnull.com/2014/02/24/using-github-pages-with-ghost-and-buster-on-windows-part-2/e9921512-c54e-4bc6-9752-90addf06fdefTue, 25 Feb 2014 04:57:14 GMT
<![CDATA[Using GitHub Pages with Ghost and Buster on Windows (part 1)]]>Taking Inventory and Setting Up

First and foremost, if you are using Linux or OSX, follow this guide here and save yourself a lot of time.

Part 1: Taking Inventory and Setting Up
Part 2: Hacking Buster and Deploying

List of software

I'm assuming you have a GitHub account already, if not go create one now. I'll wait.

Installing node.js

node.js download

Installing node.js on Windows is really straight forward and very easy thanks to Joyent's installer. It truly is just a next, next, finish install. The one thing to watch out for is to make sure that you can access node and npm after the install. You may have to reboot for it to take full effect.

Let's make sure node is installed properly. Open a console and type in:

node --version

If it's installed properly, you should get a response like this:
v0.10.25 keep in mind your version may be different from when this article was written.

Now let's make sure NPM is installed correctly:

npm --version

Expect similar output as the first statement, but the versions won't match and they aren't meant to either. If you're having any trouble, try rebooting and repeating these steps first.

Installing Git Bash

Git Bash download

The installation of the Git Bash in Windows is done equally as well. It's another next, next, finish. There are some extra options that display during the install, but as long as you stick with all the defaults, i.e. don't change anything, you'll be fine.

Installing MinGW

MinGW download

Here's where we start to get a little more difficult. Follow the prompts and leave the default settings. Feel free to change the install directory, in fact it's very important that you keep track of it. For this reason, I installed it to C:\dev\MinGW. This will come into play as we install Python and when we modify our PATH. Once you have it installed, you'll want to set up the packages that we'll be using. Let's launch the MinGW Installation Manager.

Select the Basic Setup from the menu on the left. We just need to make sure we have two packages here, mingw32-base and msys-base. It should look like this.

Now let's get one other package we'll need. Click on the All Packages and scroll down to find msys-wget and set that package to install. Lastly click the Installation menu at the top and then Apply Changes. When you're done it should look like this.

As a final touch we're going to have to modify our PATH environment variable.

Modifying your PATH

Use the [Windows Key] + [Pause/Break Key] to launch your System Properties dialog. From here you'll want to click on the Advanced System settings. As soon as that dialog launches, click on the Environment Variables... button at the bottom.

Select the PATH variable and click Edit. All the values are semi-colon delimited. We'll need to add two new ones. Move to the end of the line of values and now make sure you add to following so the end looks like this:


This will add all the msys tools and the mingw tools to your path so you can access them from any command prompt in Windows.

Installing Python

Python 2.7 download

Make sure you grab the 2.7.6 version or earlier. 3.0 or higher will not work right now. The author of buster is using the print statement throughout the package and in version 3 they changed it to a method call print().

Here I changed the installation directory to C:\dev\Python27 to keep all the libraries in the same root folder.

Once complete we'll need to modify the PATH again. Make sure you add the following to the end of the PATH values:


This will add Python and any scripts you install to the PATH so they can be called from any command prompt in Windows.

Let's test it!

Launch your Git Bash, or preferred command prompt. Type in the following command and if you get a version number back, you're good!

python --version

Installing PIP

PIP download

Don't get scared when you click on that link, it's supposed to look like that. Just right click anywhere on that page and select Save As.... Make sure to name the file get-pip.py. I would suggest saving it to the C:\dev folder to make it easy.

Once that's done, let's launch Git Bash and type in the following commands:

$ cd /c/dev
$ python get-pip.py

You'll see it install PIP. Now to test it out. If you get a version number, you're good!

pip --version

Setup Complete!

You're now ready to move on to the next part which will be getting Ghost and buster running.

http://leftofnull.com/2014/02/07/using-github-pages-with-ghost-and-buster-on-windows-part-1/5298623a-7437-45a0-891e-6d252ab23bf0Sat, 08 Feb 2014 04:21:43 GMT
<![CDATA[Choose Your Tools Wisely]]>

Let's face it programming a computer is a little more involved than programming a VCR (if you're old enough to remember those, Wikipedia for those that don't). Those of us that have been doing it for a while can make it look easy but part of that starts with our tools. Let's look at the developers second most critical tool. An IDE.

This topic came up where I currently work, Neudesic, with some other developers. They were soliciting advice on what IDEs we preferred for what languages. Understandably there was a lot of feedback and a lot of discussion on what was best. I'm only going to cover some for .NET and JavaScript because this post would never end if I didn't cut it off somewhere.

What is an IDE

IDE stands for integrated development environment. It's a software tool that helps you write code. Some key features in this regard are intelligent code completion, build engines, source control integration, debuggers, and project file management. Some IDEs have all of these features, while others have a mixture of them. Like I said , they are tools that help you write code. If your IDE isn't helping you write code, you've chosen the wrong one.

One IDE to rule them all

What's the best IDE? There isn't one.

You may have to switch IDEs based on what language you are currently writing in. You may find that you don't have to but you may want to due to languages. Some IDEs are better or have more features for certain languages. Take, for instance, Visual Studio. There are extensions galore for web development that really make JavaScript a first-class citizen, yet when I developed in CoffeeScript I preferred Sublime Text. One thing to keep in mind when reading on is that I will focus more on the ones I've used most. Another thing to keep in mind is that an IDE is a matter of preference.

The key here is that you want to choose the IDE that suits you. Your collegues may have different preferences and may espout their chosen IDEs features, but if it doesn't work for you then you may as well get a pipe and smack you keyboard and call it coding.


Visual Studio

How can we not start here. It's the main-stay of .NET IDEs and it's what I use on a daily basis. Visual Studio comes in a variety of flavors, Express (free), Professional, Premium, and Ultimate.

The main drawback of Express is that there isn't just one version. There are several that all depend on what you want to do. There's one specifically for web, one for desktop, one for RT (interface formerly known as metro), one for Phone, etc. They all have MSTest built in too so you can create unit tests. To be honest, for open source projects or single dev shops, you don't really need much more. One major drawback is that you can't install extensions like you can for the Pro and higher versions, which means no ReSharper.

Professional is identical to the Express editions with the addition of extensions (yay ReSharper support), and it's one version. Over the years the Professional version has become really watered down and, in my opinion, doesn't cut the mustard for large projects anymore.

Which brings us to Premium. All of the versions are buy-ups so to speak, so you get all the goodies of the lower-priced versions but with added features. The biggest thing that Premium gets you is the Team tools. From here you can solicit code reviews, view your tasks for the project/sprint, perform code reviews for others, etc. When I say solicit code reviews, I don't just mean create a task, I mean full-featured reviews. You can create a task for someone and they can open that task and see all of the files you changed and do a side-by-side comparison of the changes. You even get to highlight and comment the changed code and send those comments back. When you get the comments you can click on them and it will jump you right to the line under discussion. Really cool feature and essential for larger teams.

Last is Ultimate. Which has all of the features. The two big draws here are the Architecture tools and the Load and Performance test tools. In earlier versions of VS you could perform Load and Performance tests at the Premium SKU, but as of 2012 that has changed. If you're on a larger team/project, I recommend that at least one person have one of these licenses.

Alternative .NET IDEs

Alternatives are SharpDevelop, which I haven't used but I hear is a very nice alternative to VS. Another one is MonoDevelop, which if you're doing development in Mono instead of C#, you have a choice of VS or MD, but MD is really nice at it. If JetBrains were to create an IDE for .NET and package ReSharper into it, I have a feeling that would become dominant (hint hint JetBrains :-)).

JavaScript IDEs


This is a really nice free offering from Microsoft. If you're a .NET developer making a transition to Node.js or just don't want to load Visual Studio, this is a really great stepping stone. It has default templates for .NET Web Projects and Node.js projects among many others. It will also automatically configure your IISExpress to run Node.js websites. You can even install a NPM extension that lets you grab packages right from the IDE.


This one is by JetBrains and is a world class web IDE. It's biggest draws are going to be the intellisense (code completion) and refactoring tools. It's a really nice IDE and feels very comfortable to work in. You can try before you buy and can pick up a personal license for $49 (USD).

Sublime Text

This one is my personal favorite. It's comparable to TextMate if you're familiar with it. It can even use TextMate packages. It has word completion instead of code completion out of the box so you'll have to be aware of that going in. You can enable VIM-mode out of the box too (this may not be for everyone, but my beard demands it). The thing that really sells Sublime Text for me is the packages and a package called Package Control. It makes installing packages a few keystrokes away. There is a rich community developing packages for Sublime Text and you could even create your own. Want JavaScript Snippets? It's there. What Express.js Snippets? They're there too. How about jsLint or jsHint? Yup. You can make it be as robust as all the other IDEs or as simple as notepad. It's completely up to you. After using it for CoffeeScript, JavaScript, and as my primary Node.js IDE it makes Visual Studio feel like an 80-tool swiss army knife (nice, but unweildy). You can try before you buy and can pick up a personal license for $70 (USD).

No matter what IDE you choose, make sure you learn the ins and outs of it. There are things that an IDE can do to make your life so much easier when coding. Don't ignore those things and make sure you fully explore. Happy Coding!

http://leftofnull.com/2014/02/04/choose-your-tools-wisely/abff37fd-9c63-4510-9a4c-5b3771fe3bc0Wed, 05 Feb 2014 04:09:05 GMT