Wednesday, August 26, 2009

CodeRush … Take some Time to Tune.


So you’ve just been handed a copy of CodeRush and told that it’s the future.. Whomever told you this, is very insightful and deserves much of your respect :D

After installing, the first thing you should do, is to give CodeRush an idea of how you like things done. I have decided to compile this little list of the options that I change and why, in the hopes that this will help ease you into working with your new best friend.

So options… where are they then?

Access to the options screen is granted via the options entry on the DevExpress menu.

If you see no DevExpress menu, then you either don’t have CodeRush installed, or you are running the Xpress version (I think MS asked that it not have the DevExpress menu)

If this is the case, you have 2 options…

  • Suck it up and hit Ctrl+Shift+Alt+O and your options should appear.
  • Bust out RegEdit and go to town on your registry. (Note that the latest version is 9.2 not 9.1)

Ok so now you’re into the options screen. Each page (on the left in the tree) is created and dynamically added to this tree by the plugin that it represents. This means that as a plugin developer I can seamlessly add pages to this tree for my own plugin.

Additionally some of the options pages are considered Advanced or Expert rather than the default of New User. see the little Level dropdown in the bottom left of this screen to alter your current setting. Further, some pages are language specific, so you’ll need to set the Language dropdown (a little to the right of the level dropdown) to the language you’re looking to configure.

So what settings do I alter?

Code Style (Editing\Code Style\Identifiers)

There are a few pages under Editing\Code Style which you should definitely browse through. I generally find the default to be more than satisfactory. However my own personal preferences differ slightly on the Identifiers page. I prefer Pascal Case for everything, but will prefix fields with an ‘m’ (for module level). This is purely a readability issue.

Organization(Editor\Organization\Member Mover)

This relates to the “Move to Region” function under the little icon to the left of each of your method signatures. If clicked, it presents you with a list of regions into which you might wish to move the method in question.

This list contains regions that already exist with the current code file. The options page allows you to preconfigure an additional list of regions which will appear in this menu, regardless of whether or not they already exist in the code file.

I tend to configure the following regions (each on a separate line)

Fields

Simple Properties
Constructors
UI Events

Extraction and Generation

There are several places in the options where CodeRush gives you the option to specify the location where generated code will appear, relative to your current position. I don’t like having to tell CodeRush where to place generated items each and every time. I’d far rather set up a default.

Therefore:
Create Method Stub (Editing\Refactorings\Create Method Stub)
Insert Method: After source method property.

Extract Method (Editing\Refactorings\Extract Method)
Insert new methods: Below the source method or property.

Extract Property(Editing\Refactorings\Extract Method)
Insert new properties: Below the source method or property.

Property To Method (Editing\Refactorings\Property To Method)
Insert method(s): After the source property.

Decompose Initializer (Editing\Refactorings\Decompose Initializer)
I don’t like an automatic “With block” so I turn this off (VB.Net Only)

Early Experience(Editing\Refactorings\Early Experience)

Hell Yeah :D
– The bleeding edge is where it’s at :) but perhaps this does not suit everyone.

Encapsulate Field(Editing\Refactorings\Encapsulate Field)
Insert New Property: Below the field. (Similar logic to other extractions)
When references to the field exist : Do not Replace anything.

I use properties for external access to a field. If I’m accessing the property from inside the class it’s a special case rather than the rule.

Templates (Editor\Templates)
I have always maintained my own little set of templates which I store in a Custom root folder. These need to be imported if I am starting from scratch. I suggest that you place any new Templates you create in a similar “Custom” root folder. This makes the export and import of these templates, all the easier.

Shortcuts (IDE\Shortcuts)
I like to place new shortcuts in a Custom folder. you’ll see a pattern in several of my choices for common keys. This is because I am already so well trained in the art of Alt+Tab

I assign Alt+` to CodeRushTrainingWindowToggle which allows me easy reach of said window, whenever I Forget something.

I assign Alt+1 to Refactor.

I assign Alt+2 to Navigate. I don’t use this as much as I’d like, but I’m learning (We never really stop learning eh?) Not got used to it yet, but I figure it’s the best place for it, given it’s proximity to Alt+1

I assign F2 to Refactor with a parameter of Rename. Ironically this is so that I don’t have to learn another shortcut. It is already deeply ingrained within me that I can rename a folder/file in windows explorer with F2, so it seemed like a good fit. this particular shortcut is already in CodeRush but is disabled. You can find it in the IDE\Shortcuts options page. In the 'Refactor!\Alternate Bindings' folder.



I guess that’s it for now. I’ll try to keep this post up to date with various changes I make to these settings. I assume there’s someone out there who’ll benefit :)


Tuesday, August 25, 2009

Why do I find CodeRush so indispensable?

 

I recently said “CodeRush has become an integral part of my workflow.”
and was asked by Braden Powers … “Do you have a blog post or something that explains why??”

I realized that I didn’t, and so here it is…

It comes down to the fact that I use certain facilities provided by CodeRush so often and without even thinking, that without CodeRush present, I end up spending several seconds staring at the screen wondering why some series of keystrokes isn’t doing what I think it should be.

Why should I ever be in such a situation. Well there are a couple of reasons.

  • Some of my colleagues have PCs that frankly cannot cope with Studio, so their chances of being able to cope with *any* addin are nil :( Using such a PC is sometimes unavoidable.
  • Sometimes I get caught on the hop. Between versions as it were. I have received a link to a beta or daily build of CodeRush and have been caught having already uninstalled my previous version and not yet having installed the new version. At this point it’s amazing how the universe almost always arranges a phone call to distract me… after which I forget that studio doesn’t currently have CodeRush.

So which facilities do I find to be most useful? Which ones to I use so often that I honestly forget that they are not a part of studio?

The answer is hard to define explicitly without currently being in one of the above scenarios but I will try.

Essentially the most used functions for me are those that are accessible from the CodeRush SmartTag menu. The Refactorings and the Code Providers.

Now between these 2 categories there are 225 separate functions. Obviously I don’t use all of these on a daily basis. If I were to be presented with the entire list every time I invoked the SmartTag, then I would go absolutely insane and dropkick CodeRush in a heartbeat.

CodeRush manages to provide a wonderfully intuitive interface here. Each Refactoring and Code Provider is intelligent enough to know if it is suited to your current context.

  • The Rename refactoring simply isn’t available if your caret is on a language keyword.
  • The Declare Class Code Provider isn’t available, unless the element under the caret is not currently declared and could potentially be a class.

This means that my one keystroke (I’ve rebound the CodeRush/Refactor key to ALT+1), I’m never presented with more than 5-8 options to pick from.

Next add to that, the fact that CodeRush moves the available items up and down on the menu based on your usage of those items. Constantly re-evaluating how far each should sit from the top of the menu.

Additionally, If CodeRush feels that there’s only 1 function which makes sense given the current context, then you can elect to have CodeRush not even show you the menu, but to move straight on to performing said function. So there’s even less for you to have to do.

ok Enough fluff… Which items do I use so often as to make Studio unusable without them

Note this is just my personal list.. CodeRush has much much more and these simply represent those facilities, whose absence actively slows me down.

First there are the Refactorings:

    • Rename
    • Extract Local
    • Extract Method
    • Extract Property
    • Inline Temp

I cannot stress enough how useful the above 5 Refactorings are in writing any code.

The ability to properly shape a solution as you go is phenomenal. I mean seriously… When you have to nail 2 bits of wood together … Do you use a rock or a proper tool like a hammer?

…Then there are the Code Providers

    • Declare Local
    • Declare Method
      • With parameters all in place based on your usage.
    • Declare Property
    • Declare Field With Initializer
      • Create a suitably named field of the correct type and assign the parameter to the field.
    • …and many more

…all available with a single keystroke (Alt+1 in my case)

Prototyping code has never been this easy

After this we are on to navigation:

  • Navigation
    • TabToNextReference
      • Place your caret on a variable and hit tab. CodeRush immediately underlines all references to this variable on the page and jumps to the next reference in the sequence. It should be noted that the “sequence” covers all references in your entire solution
    • References Tool Window(Shift F12)
      • The References tool window collates all references to any variable of your choice in a single location allowing you to seamlessly skip from one to another.

I feel I should also add add a quick section on the templating system here. I don’t use these nearly as much as I use the SmartTag facilities but it would be hard to since I’m sometimes hitting the CodeRush/Refactor key what seems like every 30 seconds or so.

So some of the template I use more than any others are:

  • Templates
    • Property declaration (pi, ps, pd8 etc)
      • Create properties of various types, with or without backing store, in only  couple of keystrokes.
    • ReadOnly Property declaration (ri, rs, rd8 etc)
      • As above but without the setters
    • Method Declaration (mi, ms, md8)
      • Same again but with methods.
    • Create Constructor (cc)
      • Generates a Constructor which takes various parameters based on your selection of any of the fields supported by the class.

Now It should be pointed out that prototyping any class is now insanely easy

c<space> – Class is created
vs<space>FirstName
vs<space>LastName
vi<space>Age

vi<space>GolfPar
4 Fields are now Created
cc<space><Enter> Constructor created
The constructor takes 4 parameters which are used to populate the fields.
Oh yeah and Readonly properties have been created to expose your fields. All of this is Totally configurable.

The final reason I can’t code without CodeRush is it’s extensibility. When I need something that CodeRush doesn’t have, I use it to create what I need using the DXCore plugin platform.

Checkout what others in the community have done with this amazing platform: Seriously check these out.


Friday, August 07, 2009

What’s your Windows 7 “Virtual Machine” Strategy?

I ask because it’s something I almost overlooked completely.

There are many Virtual PC style options on the market but up until now I have been using VPC 2007 SP1 because Its’ a Microsoft product and it’s free. Perhaps not the best strategy, but it worked … And I assumed that it was going to continue to work.

I was wrong.

I run several VMs under VPC at work and I need them to all continue to work.

But when I tried to run VPC2007 SP1 under Windows 7 (admittedly the RC) I was greeted with a dialog which suggested that VPC was not compatible with Win7.

“Ok” I thought, so where’s the version that is compatible. 

I found this … http://www.microsoft.com/windows/virtual-pc/download.aspx which is the Windows Virtual PC RC install. ( also the XP Mode RC install)

On the surface it looks good, but Microsoft seem to have player the same confusing trick they did with Messenger back in the day.

This is “Windows Virtual PC” (Win 7 Version) which is not the same as “Microsoft Virtual PC” (VPC 2007 SP1).

This *requires* AMD or Intel Chip level support (called VT Support on the Intel side) this is non- negotiable.

So it’s worth checking your chip to see if it provides VT support. The Intel side can use this utility.

However my work machine does not support this.

I am apparently stuck between the MVPC which runs on Vista and WVPC which runs on Windows 7 but only if you have VT support. At first looks this seems to mean No VM Support on Windows 7. This is not workable.

It seems that, at least for the moment, if you have an older (in some cases not that old) machine, and you require the ability to use a VM, that you’re up a certain creek without a paddle.

In my particular case I was lucky enough to have been introduced to VirtualBox (Yes I know you could use VMware, but AFAIK that’s not free and VirtualBox is just as free as Virtual PC. As indicated in the comments, VMWare Server is apparently Free.)

This is a wonderful app produced by Sun which seems to have little to no issues running VHDs created for use with VPC.

The one issue I encountered, was that I had to change the default network adapter from "PCnet-Fast III" to "PCnet-PCI II" before my guest OS would recognise the External network and the internet beyond.

That done though, everything seems fine, and the last of my Win7 worries have evaporated.

I will be installing Win7 RTM on both my home and work machines over the weekend :)


Thursday, August 06, 2009

New CodeRush Plugin: CR_MethodPreview

The other night I saw a tweet by Neal Culiner (@NCSoftware) regarding a plugin he’d like to see developed. 

Shortly there was a response was a tweet by Matthew MacSuga (@csharpbydesign). He mentioned that he’s asked for something like this a while back.

What they’re after, is a way to preview the code of a method, without having to visit that method.

I feel a little guilty because I remember Matthew mentioning this a while back. I think I started a debate at the time on "what should trigger the functionality” and we (well probably I) got bogged down in the details. Sorry Matthew :(

This time I just thought .. “Sod This” - (Wasting time that is, not talking to Matthew and Neal) - “Let’s just get something out there, and we’ll see where it leads afterward”.

So after a quick vote on the name of said plugin (Where Neal suggested the name and we all agreed :D) I was off to build a new plugin.

Where to start?

So I created a basic plugin and dropped an action in place. (For details please see a previous post)

From here I needed 2 things:

  • A function to determine which method to preview.
  • A function to actually do the preview.

There are some complexities in the original brief that I didn’t feel comfortable with initially.

  • “Select method based on method call under cursor”.
    • I have elected to use caret position in this first version.
  • “Hold a key down to see Preview”
    • I have elected to use a toggleable action in this first version.

Which Method?

So the first thing to do is to work out which method to display a preview for.

Some Terminology:
Given the sample…

    Public Sub Method1() 
Call Method2()
End Sub


  • “Method2” is known as the MethodReferenceExpression


  • “Call Method2()” is the MethodCall.



I would like this plugin to function from either of these 2 locations, so I need to return the declaration of the method to which either refers.



-------------------------------------------------------------

    Private Function GetMethod(ByVal Element As LanguageElement) As Method


        Dim Method As Method = Nothing


        Select Case Element.ElementType


            Case LanguageElementType.MethodCall


                Method = TryCast(Element, MethodCall).GetDeclaration


            Case LanguageElementType.MethodReferenceExpression


                Method = TryCast(Element, MethodReferenceExpression).GetDeclaration


        End Select


        Return Method


    End Function


-------------------------------------------------------------



To this method, I can pass CodeRush.Source.GetNodeAt(CodeRush.Caret.SourcePoint)



Later I can replace this with something which passes the element under the cursor, and I won’t have to change much at all.



Next we need to determine the code behind the Method in question.

-------------------------------------------------------------


Dim TheCode as String = CodeRush.CodeMod.GenerateCode(Method)


-------------------------------------------------------------


And now we have the code we’d like to render in our preview window. So lets crack on and create the preview itself.




The Preview Window



Building a preview window is easy… (Isn’t everything with the DXCore? :P)



The following function accepts the code and a location for the preview and builds the preview accordingly. It also places the preview on screen.



(The code to hide the preview has been omitted here but is even simpler.)



-------------------------------------------------------------

Private mPreviewWindow As CodePreviewWindow





Private Sub ShowCodePreview(ByVal Code As String, ByVal insertionPoint As SourcePoint)


    mPreviewWindow = New CodePreviewWindow(CodeRush.Documents.ActiveTextView, insertionPoint)


    mPreviewWindow.AddCode(Code)


    mPreviewWindow.ShowPreview()


End Sub


-------------------------------------------------------------





And so things come together in the main ToggleMethodPreview_Execute() as…





-------------------------------------------------------------


Private mShowingPreview As Boolean = False





Private Sub ToggleMethodPreview_Execute(ByVal ea As DevExpress.CodeRush.Core.ExecuteEventArgs) Handles ToggleMethodPreview.Execute


    If mShowingPreview Then


        Call HideCodePreview()


    Else


        Dim Method As Method = GetMethod(CodeRush.Source.GetNodeAt(CodeRush.Caret.SourcePoint))


        If Not Method Is Nothing Then


            Call ShowMethodPreview(Method, CodeRush.Caret.SourcePoint)


            mShowingPreview = True


        End If


    End If


End Sub


-------------------------------------------------------------



Summary



That’s pretty much all there is to it.



To use this plugin, simply bind a key to the “ToggleMethodPreview” action and activate it when your caret is in a suitable location.



For this plugin I wrote all of 42 lines of code including signatures.



Proof once again, as if you needed it, that the DXCore makes plugin writing ridiculously easy.



So now we have a first draft of “CR_MethodPreview”… go play… see what you think… And we’ll see where it goes from there.



-------------------------------------------------------------

For more DevExpress news, check out their Facebook page


-------------------------------------------------------------


How to: Bind a key in CodeRush.

If you would like to use CodeRush to bind a key, you're going to need to access the Options dialog.

This is available from the DevExpress Menu if you have the full version of CodeRush.
Alternatively, if you have CodeRush Xpress, you can press CTRL+Alt+Shift+O.

The left hand side of the options screen should look like this:

This screenshot was taken from the full version of CodeRush. Your version may be missing some items.

This might be because:

  • The 'user level' setting in the lower left of the options screen may be set to something other than expert.
  • You may be running CodeRush Xpress which has less features than the full version of CodeRush.

Select the 'IDE\Shortcuts' node as indicated in the screenshot.

The list of CodeRush bindings will appear:

As you can see, I typically create my shortcuts beneath a 'Custom' folder. this helps when it comes time to backup my customizations.

A new folder or shortcut can be created either from the Toolbar at the top of the shortcuts tree, or from a context menu triggered by right-clicking within the tree itself.

When you create a key binding, the right hand side of the screen will light up thus:

This section allows you to enter:

  • A keystroke which triggers your shortcut.
  • A command to execute once triggered.
  • Any params you wish to pass the command. (Optional)
  • A Context to limit your Shortcut’s use. (Optional)

Once you’ve filled out these elements, you are free to either create more bindings or save via the Ok or Apply button and start making use of your new binding.

----------------------------------------------------------------------------------------
Just a thought: Why not swing by the DevExpress Facebook page. You know you want to :)
----------------------------------------------------------------------------------------


Tuesday, August 04, 2009

CodeRush Templates – What makes them different?

The full version of CodeRush ships with several features not found in the Xpress version.

Simultaneously the most well known and least known about of these features is the CodeRush Template Engine.

So what can a Template do?

Well at it’s core, a template is nothing more than a bunch of text omitted on command.

Yup that’s it. :)

Type some characters hit <space> (the default template expansion key) and a whole slew of text is thrown into your editor as if you typed it yourself.

I know what you’re thinking….

You’re thinking … “but my clipboard can do that. What’s so special?”

Well you’re right… your clipboard can do that, but it has some comparative limitations.

For example:

  • Your standard windows clipboard can carry, at most, 1 set of text for pasting.
  • Visual studio has an enhanced clipboard which can carry about 20, but it does this in a way which forces you to have to cycle (Using that most painful of keycombos CTRL+Shift+V) through this ‘ring’ of clipped items until you’re, frankly, lucky enough to stumble upon the one you were looking for.  Your <deity of choice> help you if you happen to hit this key combo 1 time too many. (Round the cycle you go again)

So what does the template system do which makes it anything other than a glorified clipboard?

Well the Template system quite a few advantages.

  • Context Sensitivity:
    • You can learn a single template and use it in differing circumstances to produce subtly different effects.
    • Templates expand differently or not at all based on the context at the time of expansion.
  • Mnemonics Naming:
    • The template names are designed to be easy to remember and/or calculate.
  • Some Templates are Generic/Dynamic:
    • Dynamic Templates are those whose trigger is not defined entirely by their name, but have some external component.
  • The system of mnemonic naming, reduces the amount of learning to a bare minimum.
  • Language Agnostic
    • The vast majority of VB.Net and C# templates have counterparts in the opposing language which generates the equivalent code in that language. So once you are used to using CodeRush, switching languages is even less of an issue.
  • The CodeRush Template library is vast:
    • VB.Net has more than 920.
    • C#has more than 940.
    • Another 150+ dedicated to xaml, xml and html.
    • These figures don’t take into account the multiplier effect caused by some of those being Dynamic/Generic. for example, each template referencing the ?Type? dynamic list, is some 70 times more useful, than if it did not.
  • Templates have Links, Fields, Markers, Targets, Selection definitions and many other Text Commands and String Providers with which to augment the template they are embedded.
  • The template system is extensible.
    • You can create as many new templates as you like.
    • You can customize your templates with Text Commands and String Providers.
    • You can write your own custom Text Commands and String Providers in and .Net language.

Ok… So that’s something of a bulleted list… Let’s dig a little deeper…

Digging Deeper

Mnemonic Naming

A mnemonic is an aid to memory. Each character in the name (aka the trigger) of a CodeRush Template, represents a part of what it is going to generate. It represents what will happen when the template expands.

Lets take a simple example… ‘Variables’:

If you want to declare a variable of type ‘string’, you type vs<space>
If you want to declare a variable or type ‘double’, you type vd<space>
If you want to declare a variable of type ‘date’, you type vd8<space>

See the pattern? A similar logic works for properties:

If you want to declare a property of type ‘string’ you type ps<space>
If you want to declare a property of type ‘double’ you type pd<space>
If you want to declare a property of type ‘date’ you type pd8<space>

For readonly Properties…

If you want to declare a readonly property of type ‘string’ you type rs<space>
If you want to declare a readonly property of type ‘double’ you type rd<space>
If you want to declare a readonly property of type ‘date’ you type rd8<space>

A property of type string is ps<space>
A readonly property of type string is rs<space>
A method returning a string is ms<space>

Other mnemonic devices are at play all over the CodeRush Template library.

Context Sensitivity

As previously discussed, vs<space> expands to form a declaration of a variable of type ‘string’.

What hasn’t been show so far, is that, dependant on where this expansion occurs, several different expansions might occur.

  • If the caret (flashy vertical bar indicating where text is inserted) is positioned inside a class or structure, the expansion should declare a private field of type string.
  • If the caret is instead within a method, the declaration will be a local (changing structure and keywords, where appropriate in the case of say… VB.Net).
  • If the caret is within the brackets representing the signature of a method, then the expansion is appropriate to declare a parameter.

Similarly r<space> will create a readonly property with backing store of type Object, if expanded within a class.
However, if expanded within a method, it will yield the return keyword.

There are roughly 190 contexts shipping with CodeRush which can potentially be true or false. This allows it to have a pretty good idea of whether or not a given template is appropriate for your current situation.

CodeRush uses this information to streamline it’s operation, eliminating vast swaths of templates from consideration when they are simply not appropriate. Because of this, we *could* arrange to use a valid keyword, such as ‘switch’ or ‘select’, outside of it’s normal context allowing it to trigger a template expansion whilst leaving it inert, in it’s natural context so as not to disturb the natural flow of the developer.

Text Commands and String Providers

As you will no doubt have realised whilst expanding some of those previous examples, templates are not just static text.

Text Commands and String Providers are another example of how CodeRush Templates are a step above the available alternatives.

String Providers are akin to functions which return strings, in that they generate string values based upon some logic, which are then injected into the templates at the point from which they are called.

You can have a template which inserts the current date, time or username into a header string. They can also be used to inject the name of the current method, class, project etc.

One interesting use of a String Provider is to inject a value previously saved to a location in memory by another String Provider or Text Command. This has the effect of allowing 1 template to pass parameters to another. Also it means that a useful part of 1 template can be extracted and made available to be called by several other templates. This makes the library as a whole more efficient.

Text Commands are subtly different, they are closer to void procs (or Subs for those who use VB.Net like myself). They emit no text into the template they are placed within, but they can perform other tasks. Text Commands are used to Add References to your project, position the caret, indicate a selection, turn text into a field or link and many more things besides.

Links, Fields, Markers, Targets, BlockAnchors and Caret

These are some of the more common Text Commands you might find in CodeRush Templates.

  • Fields are used to wrap discrete sections of the output for further customization after expansion.
  • Links and TypeLinks are used to link sections of output together so that post-expansion customizations affect each linked area in the same way.
  • Markers (both hard and soft) can be added to the code to allow you to revisit a section of output and at a later time.
  • A caret (with an optional BlockAnchor) can be used to set the initial position (and selection) post-expansion.
  • …and a target can be used to set the final destination of the caret once all fields are filled.
Generic/Dynamic Templates

Some templates are defined a little differently to others. Dynamic (Sometimes called Generic) templates are defined such that their name (or trigger) is not hard coded as a single sequence. In fact it may surprise you to know that the templates we have been using up until now are just such templates.

The template vs<space> is not actually named vs. Instead it is named v?Type?. This is an indication to the template system, that it may use any mnemonic from a Dynamic List called Type (stored else where in the CodeRush settings) in place of the ?Type?. This particular list is provided by CodeRush and happens to contain approximately 70 different .Net types.

What this effectively means is that any template that happens to allow the use of the ?Type? list, can have it’s effective usages multiplied by 70. That’s quite the effect for a couple of lines of template.

Some Templates use dynamic lists more than once in their name, which causes their potential combination of uses to skyrocket. you may never use many of these, but it’s good to know the flexibility is there if you need it.

Extensibility

All templates that come with CodeRush are editable. You can customize them to your liking, or you can create entirely new templates using the same techniques as those who created this extensive library.

Further you can create entirely new Text Commands and String Providers for use in your templates as well as other features. Each is simply a component dropped on the design surface of a plugin and given appropriate code in it’s Execute or GetString methods. additionally you can create your own Dynamic Lists to hook your own templates up to.

What next…?

In a future post I will give some examples of Templates to be found in this vast library and show you how to use them to good effect. Additionally I’ll show you how to use some of the techniques described here to formulate your own templates.

----------------------------------------------------------------------------------------
Blatant Advert: Why not swing by the DevExpress Facebook page. You know you want to :)
----------------------------------------------------------------------------------------