Wednesday, June 9, 2010

My .vimrc

This is another post for my future self: At the time of writing, my .vimrc looks like this:

" --------------------------------------------------------------------------------
" call system vimrc
" --------------------------------------------------------------------------------
source $VIM/_vimrc

" --------------------------------------------------------------------------------
" startup
" --------------------------------------------------------------------------------
autocmd GUIEnter * simalt ~X    " maximize window

" --------------------------------------------------------------------------------
" opening files
" --------------------------------------------------------------------------------

" change working directory to path of file
autocmd BufEnter * lcd %:p:h    

" reformat xml files (pretty print)
autocmd FileType xml exe ":silent 1,$!xmllint --format --encode UTF-8 --recover - 2>/dev/null"

" --------------------------------------------------------------------------------
" saving files
" --------------------------------------------------------------------------------
set backupdir=./_Backup,$TEMP,.

" --------------------------------------------------------------------------------
" searching
" --------------------------------------------------------------------------------
set hlsearch        " highlight matches to search pattern
set incsearch        " incremental search
set smartcase       " case sensitive if search string contains uppercase letters
set ignorecase        " case insensitive searching

" --------------------------------------------------------------------------------
" configure editor with tabs and nice stuff...
" --------------------------------------------------------------------------------
set expandtab           " enter spaces when tab is pressed
set textwidth=0         " do not break lines when line length increases
set tabstop=4            " use 4 spaces to represent tab
set softtabstop=4
set shiftwidth=4        " number of spaces to use for auto indent
set autoindent          " copy indent from current line when starting a new line

" make backspaces more powerfull
set backspace=indent,eol,start 

set ruler               " show line and column number


" --------------------------------------------------------------------------------
" encoding
" --------------------------------------------------------------------------------
set encoding=utf-8
"set printencoding=utf-8

" --------------------------------------------------------------------------------
" keyboard mappings
" --------------------------------------------------------------------------------
set langmap=¨]


Future Daren, you can find the location of the .vimrc by editing the file $MYVIMRC in vim itself! Unless it hasn't been created yet ($MYVIMRC will then point to the system-wide version). In Windows, just plop a _vimrc file in your %userprofile%.

Wednesday, May 12, 2010

Google Charts: AnnotatedTimeline

Note to future self: The Google Charts visualization "AnnotatedTimeline" displays inside a div element. As per documentation, you need to provide height and width of the div element. If you don't (or specify a size too small), the script goes into an infinite loop - I guess it is trying to scale to fit inside the div, but I didn't feel like debugging squashed code...

Wednesday, April 28, 2010

CakePHP and Umlauts (utf-8)

I spent the last couple of weeks writing PHP. Not my favorite language, but it does get the job done. I won't bitch about PHP here, since that would be snobbery.

What eases the pain a lot is the CakePHP framework. Except, I couldn't get Umlauts to work. Umlauts are special characters, like a, o and u, but with two dots on them: ä, ö, ü.

I found the solution on this page: http://www.missingfeatures.com/2008/10/23/using-utf8-in-your-cakephp-app/

Not only must you tell your browser that you are using UTF-8, but you must also tell the database connection to use utf-8. Check the database.php file in your app/config directory and add 'encoding' => 'utf8' to the end of the database configuration.

Wednesday, April 14, 2010

Wiki syntax for UML diagrams

Yay! I have just implemented my very first Trac Hack: YumlPreprocessorMacro for integrating yuml.me diagrams into the trac wiki.

I have come to depend on using Trac as a bug tracking and documentation tool. I really like using wikis for documentation. I like being able to create links quickly. I like being able to search the documentation in a webby way. I absolutely hate using MS Word for technical documentation.

Often, you want to add little UML sketches to your docs. The workflow normally goes like this:

  1. Open your UML editor of choice
  2. Create UML diagram
  3. Export as image
  4. Include in documentation
Notice how that can be a little disruptive for just a sketch? Most UML tools want you to go BDUF. They want you to create a whole model of everything, when all you really want to do is a little use case. I like the Violet UML Editor precisely because it lets me sketch. But yuml.me really changes the whole game!

Tuesday, March 23, 2010

Adding canned scripts to the Revit RibbonPanel

I feal really smug about myself today! I finally figured out how to add
shortcuts to the canned python scripts defined in RevitPythonShell.xml to the
Revit RibbonPanel. I'd like to share some of the fancy magic that went into r65.

RevitPythonShell lets you define a list of named scripts in the
RevitPythonShell.xml file. An exerpt from my personal file looks like this:

  <Commands>
    <!-- a list of preconfigured commands -->
    <Command name="dumpdpvfolder" src="C:\RevitPythonShell\Commands\dpvdumpfolder.py"/>
    <Command name="read model" src="C:\RevitPythonShell\Commands\readmodel.py"/>
    <Command name="Report" src="C:\RevitPythonShell\Commands\report.py"/>
    <Command name="View Model" src="C:\RevitPythonShell\Commands\viewmodel.py"/>
  </Commands>

These are commands I use all the time during development of the
DesignPerformanceViewer (DPV). I use these commands to test parts of the DPV, run
automated tests on lots of input projects etc.

So far, these commands where only displayed in a toolbar above the interactive
shell. On the RibbonPanel provided by Autodesk Revit Architecture 2010 only a
single button was displayed: Open Python Shell. The main reason being: To add
an item to the RibbonPanel, you have to provide a path to an assembly and the
name of a type inside that assembly implementing IExternalCommand.

In the case of RevitPythonShell, we can't specify such an assembly. There is none.
And we can't use a generic type as the IExternalCommand and load the python script
in the Execute() method either, since the arguments to Execute don't contain any hints as
to which button was clicked!

This is where dynamic assemblies and Reflecion.Emit enters the stage: When RevitPythonShell
starts up (IExternalCommand.OnStartup), the list of canned commands is read and a dynamic assembly
is created to hold a dynamically created class for each canned command defined in RevitPythonShell.xml.

This is done with Reflection.Emit in the method RevitPythonShellApplication.CreateCommandLoaderAssembly():

        /// <summary>
        /// Creates a dynamic assembly that contains types for starting the canned commands.
        /// </summary>
        private static void CreateCommandLoaderAssembly()
        {
            var assemblyName = new AssemblyName {Name = "CommandLoaderAssembly", Version = new Version(1, 0, 0, 0)};
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            var moduleBuilder = assemblyBuilder.DefineDynamicModule("CommandLoaderModule", "CommandLoaderAssembly.dll");

            foreach (var command in GetCommands())
            {
                var typebuilder = moduleBuilder.DefineType("Command" + command.Index,
                                                        TypeAttributes.Class | TypeAttributes.Public,
                                                        typeof(CommandLoaderBase));

                var ci = typeof(CommandLoaderBase).GetConstructor(new[] { typeof(string) });

                var constructorBuilder = typebuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
                var gen = constructorBuilder.GetILGenerator();
                gen.Emit(OpCodes.Ldarg_0);                // Load "this" onto eval stack
                gen.Emit(OpCodes.Ldstr, command.Source);  // Load the path to the command as a string onto stack
                gen.Emit(OpCodes.Call, ci);               // call base constructor (consumes "this" and the string)
                gen.Emit(OpCodes.Nop);                    // Fill some space - this is how it is generated for equivalent C# code
                gen.Emit(OpCodes.Nop);
                gen.Emit(OpCodes.Nop);
                gen.Emit(OpCodes.Ret);                    // return from constructor
                typebuilder.CreateType();
            }
            assemblyBuilder.Save("CommandLoaderAssembly.dll");            
        }

Now, this is the first time I have ever emitted IL in my life. Naturally, I wanted to get as much done in C# as possible, so the types
generated all inherit CommandLoaderBase:

    /// <summary>
    /// Starts up a ScriptOutput window for a given canned command.
    /// 
    /// It is expected that this will be inherited by dynamic types that have the field
    /// _scriptSource set to point to a python file that will be executed in the constructor.
    /// </summary>
    public abstract class CommandLoaderBase: IExternalCommand
    {
        protected string _scriptSource = "";

        public CommandLoaderBase(string scriptSource)
        {
            _scriptSource = scriptSource;
        }

        public IExternalCommand.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            var executor = new ScriptExecutor(commandData, message, elements);

            string source;
            using (var reader = File.OpenText(_scriptSource))
            {
                source = reader.ReadToEnd();
            }

            var result = executor.ExecuteScript(source);
            message = executor.Message;
            switch (result)
            {
                case (int)IExternalCommand.Result.Succeeded:
                    return IExternalCommand.Result.Succeeded;
                case (int)IExternalCommand.Result.Cancelled:
                    return IExternalCommand.Result.Cancelled;
                case (int)IExternalCommand.Result.Failed:
                    return IExternalCommand.Result.Failed;
                default:
                    return IExternalCommand.Result.Succeeded;
            }
        }
    }

This base class has a constructor that accepts the path to a python script and
creates a ScriptExecutor (check RevitPythonShell source code) to execute that script in its implementation of
IExternalCommand.Execute().

And now the Reflection/IL stuff starts to make sense: Create a type inheriting from CommandLoaderBase, adding a parameterless constructor (called by
Revit) which in turn calls the base constructor with the path to the script. The resulting IL looks something like this:

    .class public auto ansi Command0
        extends [RevitPythonShell]RevitPythonShell.CommandLoaderBase
    {
        .method public specialname rtspecialname instance void .ctor() cil managed
        {
            .maxstack 2
            L_0000: ldarg.0 
            L_0001: ldstr "C:\\RevitPythonShell\\Commands\\dpvdumpfolder.py"
            L_0006: call instance void [RevitPythonShell]RevitPythonShell.CommandLoaderBase::.ctor(string)
            L_000b: nop 
            L_000c: nop 
            L_000d: nop 
            L_000e: ret 
        }

    }

With "Command0" being the name of the type to instantiate for the first canned script in RevitPythonShell.xml. The C# equivalent looks like this:

    public class Command0 : CommandLoaderBase
    {
        // Methods
        public Command0() : base(@"C:\RevitPythonShell\Commands\dpvdumpfolder.py")
        {
        }
    }

I used Red Gate's .NET Reflector to disassemble the resulting assembly and also as a hint on how to write the Reflection.Emit stuff (created a dummy subclass of CommandLoaderBase with the desired constructor, compiled and then disassembled in Reflector).

Now I need to add a nice interface to manage the canned commands - any ideas?

Wednesday, March 10, 2010

Using RevitPythonShell to dynamically load plugins for debugging

Ever since I read Jeremy Tammiks blog post Reload an Add-In to Debug, where he
describes about John Morse's technique for dynamically loading plugins without
having to restart Revit, I have been itching to get this working in
RevitPythonShell!

Finally, with revision 55 and the loadplugin script, I can rapidly iterate
working on my C# projects - no more waiting for Autodesk Revit to restart after
fixing a small mistake!

Here is a little sampe session from the project page:

>>>import loadplugin
>>># use actual path here... (if you don't already have RvtMgdDbg.dll installed, you probably want to go and do so 
>>># right now - check ADN!)
>>>assembly = loadplugin.loadAssembly(r'C:\...\Visual Studio 2008\Projects\RvtMgdDbg\bin\RvtMgdDbg.dll')
>>># result is an assembly object
>>>assembly

<Assembly RvtMgdDbg, Version=1.0.3671.26458, Culture=neutral, PublicKeyToken=null>

>>># pretty cool: IronPython lets you use the assembly like a namespace
>>># also note the use of the special predefined variables for executing plugins!
>>>assembly.RvtMgdDbg.CmdSnoopDb().Execute(__commandData__, __message__, __elements__)

(<Autodesk.Revit.IExternalCommand+Result object at 0x000000000000002D [Succeeded]>, '')
>>>


So how dows it work? Basically, you load an assembly as a byte array and then
use Assembly.Load to load the assembly from the byte array. Dynamically loading
assemblies this way does not lock them on the hard disk, allowing Visual Studio
to overwrite the DLLs at build time.

I suggest you write a test script for your plugin, that you can then save as a
canned command in RevitPythonShell, that loads it via loadplugin.loadAssembly and
does some exercising: Instantiate some types, execute IExternalCommand instances etc.

To make interaction with plugins easier, RevitPythonShell now supports some predefined variables, that give you more access to the context in which the plugin itself was loaded.
This lets you simulate the user clicking on PushButtons in the Ribbon.

Also, I have included a fork of the IronPythonTextBox control, to make plain interactive
use of RevitPythonShell smoother.

Please let me know, if this is of any use to you. Also, I would really appreciate some help, especially in getting the system more user friendly (e.g. script repository etc.).

Thursday, February 25, 2010

Extracting music from Mac formatted iPod in Windows XP

I used these tools to extract the music from my iPod (Mac formatted) under windows:

HFSExplorer lets you extract data from an HFS file system hooked up to your PC. In this case my iPod. After loading the filesystem from a device (see file menue), navigate to the folder /iPod_Control/Music and extract it to your PCs filesystem, e.g. your Desktop.

The music shows up as a lot of funny folders and files (F00, F01, ...). This is where Mp3tag comes in: One of the functions of this tool is to read the meta information from your music files and create a directory structure from them, with proper file names, folder names for the albums etc. Sweet!