Jake Ginnivan’s blog

Improving the Carnac Codebase and Rx Usage (Part 3)

Parts one and two have covered the InterceptKeys class which exposes a feed of raw keyboard events and the MessageProvider which turns key presses into messages to display on the screen. There is a class between those two, the KeyProvider which I am not going to actually blog about as it doesn’t introduce any new concepts which I have not covered in parts 1 and 2 of this blog series.

Part 1 - Refactoring the InterceptKeys class
Part 2 - Refactoring the MessageProvider class
Part 3 - Introducing the MessageController class
Part 4 - Removing state mutation from the stream

Instead we will dive into the MessageController class which brings the streams from the KeyProvider and MessageProvider together then maintains the list of Messages displayed on the screen. The requirements are:

  • Add any new messages into the messages collection
  • After 5 seconds set a flag on the message which triggers an animation
  • 1 second after that the message is removed from the messages collection
  • If a message is updated the 5 second countdown should start again.

Old implementation

The previous implementation was quite simple but it was hard to test. Also Rx can solve this problem very nicely, so why not.

  • New messages were added to the messages list
  • A timer fired once a second, the callback did:
    • A foreach loop over every item which had a LastUpdated property more than 5 seconds go, then set the IsDeleting flag to true
    • A foreach loop over every item which had a LastUpdated property more than 6 seconds go, then removed it from the list

Lets rewrite this into Rx

Improving the Carnac Codebase and Rx Usage (Part 2)

This post is the second part in a series covering a series of improvements in the carnac codebase, specifically to improve the usage of Rx. The next class I will be rewriting is the MessageProvider.

Part 1 - Refactoring the InterceptKeys class
Part 2 - Refactoring the MessageProvider class
Part 3 - Introducing the MessageController class
Part 4 - Removing state mutation from the stream

As a bit of background, in carnac a KeyPress is not directional and it also contains information about if modifiers were pressed at the same time. For Instance ctrl + r would be a KeyPress. A Message is what is shown on the screen.

The message provider as it is does the following:

  • Is IObserver<KeyPress>
  • It aggregates multiple KeyPresses into logical messages with the following rules:
    • Shortcuts are always shown in their own message
    • If there has been more than a second between the last keypress a new message is created
    • If the key presses were entered into different applications a new messsage is created
  • Apply ‘Only show shortcuts’ filter

Here is what the code looked like before the refactor.

Improving the Carnac Codebase and Rx Usage (Part 1)

Carnac is an open source project created as part of Code52. It is a simple utility which overlays key presses on your screen as you type which is pretty handy for presentations. Carnac also ships with some keymaps for different applications so it understands when you are pressing shortcuts.

Recently Scott Hanselman blogged about a Quake Mode console and mentioned carnac, this triggered Brendan Forster and myself to think about carnac again. When we started writing carnac there was not any Rx experience amongst the team and we did a pretty bad job. I think carnac is a great Rx problem and the code can be improved to take advantage of Rx and be a really good non-trivial Rx sample. This blog series is all about the things we did wrong and the process I went through to refactor carnac into a much simpler code base and really leverage the power of Rx.

Part 1 - Refactoring the InterceptKeys class
Part 2 - Refactoring the MessageProvider class
Part 3 - Introducing the MessageController class
Part 4 - Removing state mutation from the stream

My Typical TeamCity Build Setup

I posted Simple Versioning and Release Notes a few weeks ago talking about how to simplify release notes and versioning. This post is a bit of a cheat sheet for how I set up my builds.

Structure

I normally have two but sometimes three builds for each project. The structure is something like this:

  • TeamCity Project
    1. CI
    2. Acceptance/UI Tests (optional)
    3. Release

1. CI builds the solution with correctly versioned assemblies (update assembly info files with version before build), runs all unit tests then creates any packages which are required. This includes NuGet packages, Chocolatey packages, zipped binaries, clickonce installers etc. This build monitors pull requests and is triggered automatically when there are new commits/branches.

2. Acceptance/UI Tests is an extra I use when I have long running or UI tests, for example TestStack.White on TeamCity (sign in as guest) has this build setup and it runs Whites UI tests. The reason I separate it is for speed reasons, I want my CI build to fail fast and only if it is successful do I run this slow build. This build triggers whenever 1. CI succeeds

3. Release (or 2. Release if there is no acceptance/ui test build) is run manually and it releases the artifacts build by 1. CI, if that is a NuGet package it is pushed to NuGet.org, chocolatey packages get pushed to chocolatey.org, zip files get pushed as a GitHub release etc. Once this build succeeds it should tag the VCS root and push that tag.

Updating Chocolateys Release Notes With GitReleaseNotes

Today I saw a tweet from Rob Reynolds today that Chocolatey 0.9.8.24 RC1 was released so I clicked the link which was straight to the closed issues list on GitHub.

I also noticed that many of the RCs and betas were not tagged in Git so you can’t see what was fixed each beta.

I have been working on a little utility to solve exactly this problem called GitReleaseNotes, the idea is that you install it via Chocolatey, then run GitReleaseNotes /outputFile ReleaseNotes.md /allTags and it will connect to your issue tracker (if the issue tracker is a REMOTE in your Git repository) fetch all the closed issues since it was last run and append them into your release notes. For public GitHub repos using GitHub issues these are the same so it just works, for Jira and YouTrack you will need to specify additional command line parameters

You then can manually edit, group and do whatever you want. All your modifications will not be changed when you run GitReleaseNotes again.

Using Approval Text in Tests

Using Approval Text in tests

I am currently using TestStack.BDDfy as my BDD testing framework. v4 has some great changes which make BDDfy really really awesome.

One of the things I am testing is generated confirmation text based on a number of selected form inputs. I want the approved generated text to be put into the BDDfy output. First steps are to read the approved file, here is a quick snipped which does this:

protected string GetApproved()
{
    var namer = new UnitTestFrameworkNamer();
    var basename = string.Format("{0}\\{1}", namer.SourcePath, namer.Name);
    var approvalFilename = new ApprovalTextWriter(string.Empty).GetApprovalFilename(basename);
    var approved = !File.Exists(approvalFilename) ? string.Empty : File.ReadAllText(approvalFilename);
    return approved;
}

Then I can just add my step in BDDfy .Then(_ => ApprovedGeneratedConfirmationShouldMatch(sut.DealSummary.ToString()), string.Format("Approved generated confirmation should be:\r\n{0}", GetApproved()))

Low Friction Octopress/GitHub Pages Setup

My blog uses Octopress which is basically Jekyll plus a whole bunch of plug-ins preconfigured and it is hosted on GitHub Pages. But sometimes I really miss being able to simply create or edit posts online. I started looking around and found Prose.io.

Prose is an awesome open source online Jekyll site editor for GitHub. Then if we setup TeamCity to automatically regenerate and deploy our blog when we make any commits we have a really simple way of making quick blog posts online.

Cannot Type Capital v on Sculpt Keyboard

At the MVP summit last year I picked up a Sculpt Ergonomic Desktop pack, mainly because I cannot stand the UK keyboard layout and wanted to stay on the US layout while working in London.

I just had a very strange issue, I could not type a capital V, lowercase worked fine. Plugging into another machine showed the same issue.

One of the problems with the Sculpt is that the function keys get stuck. Apparently if the F5 key gets stuck, then you can no longer type a capital V. If the F2 key is stuck then you won’t be able to type a capital C.

If you hit this random issue, hopefully you will read this post before returning your keyboard.

Disable thumbs.db

Thumbs.db is created by windows whenever a folder has images in it as a cache for the thumbnails for the images. But it gets locked and stops me switching branches in git and I have to restart my PC sometimes.

Save this as KillThumbsDb.reg and run it as administrator:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer]
"DisableThumbsDBOnNetworkFolders"=dword:00000001

I have no idea why thumbs.db is being created in local folders, but this fixes it for me.