msgbartop
A site for my programming pet projects
msgbarbottom

12 Nov 09 ZenCoding Visual Studio AddIn

4 Feb 2010: I’m no longer working on this addin and cannot provide support for failed installations. I gave some information about possible causes for failed installations in this comment, you can see if that helps, or discuss with other users in the comments. There are unlikely to ever be new versions of this addin published by me, but Boris Sevo has forked the project and has a version with a newer zencoding library at http://zencoding.codeplex.com/. So go there for updates :)

The original blog post about the architecture of the addin is now completely out of date as 90% of the addin is now written in IronPython with just a tiny shim layer of C# to instantiate the IronPython classes. I’ll probably write a blog post about that architecture seperately (or generally about how to write addins for VS in IronPython). Those interested in the architecture can download the source and look at it.

A nice tutorial with screenshots on how to setup the keyboard mappings and use the addin has just been posted at http://www.netsi.dk/wordpress/index.php/2009/12/02/zen-coding-a-very-fast-way-of-generating-html-elements-in-your-editor/ so go there for your setup instructions. And there is now a dedicated rss feed for updates at http://tech.einaregilsson.com/zcupdates.aspx so subscribe to that to be notified of new versions. Eventually I’ll put an update check in the addin itself.

ZenCoding.VisualStudio v1.1.0.333

DOWNLOAD ADD-IN || DOWNLOAD SOURCE

RELEASE NOTES:

Version 1.1.0.333, 02.12.2009:

This release adds the following features

  • Uses latest version of zencoding python library
  • Wrap with abbreviation command
  • Use, create, edit, delete custom snippets (Tools->Options->ZenCoding)
  • Icons for commands
  • Some bug fixes

Also a total rewrite with everything now written in IronPython

Version 1.0, 12.11.2009:

Initial release, features:

  • Expand abbreviation

Original blog post follows:

Earlier this week, while reading Leon Bambrick’s blog I learned about a set of plugins, named “zen-coding”, which expand snippets of css-selector like code into full blown html and/or css elements. Leon’s article explains it better and there is also some documentation on the official zen-coding page. Anyway, this plugin is available for a number of text editors and IDE’s but not for Visual Studio. I use Visual Studio a lot and wanted zen-coding in there, so I decided to try and whip up a small add-in for it.

The original library is available both as JavaScript and Python. I really didn’t want to port or alter anything in the original code, since for future versions I want to be able to just drop in a couple of files from the original library and rebuild the add-in. The obvious choice then was to see if the library would work with IronPython. Fortunately the zen-coding library is just basic string manipulation and worked perfectly with IronPython right out of the box.

The next challenge was figuring out how to call into that from the add-in, which I wanted to write in C#. The library contained two functions I needed to be able to call. That turned out to be surprisingly easy. I made a wrapper class, ZenCodingEngine, which has two delegates with the correct method signatures, and then in its constructor I ran some custom python import code, and got references to the functions I needed and assigned them to my delegates. I changed that approach in the latest version and moved almost all of the logic into Python instead. Now the C# AddIn is very thin, it basically just receives events from VS and invokes a single exec_command() method that is defined in a python script. The interesting parts of that code are below:

private void ReloadPython()
{
  ScriptEngine engine = Python.CreateEngine();
  ScriptScope scope = engine.CreateScope();
  string folder = Path.GetDirectoryName(new
    Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
  List searchPaths = new List<string>(engine.GetSearchPaths());
  searchPaths.Add(folder);
  engine.SetSearchPaths(searchPaths);
  scope = engine.ExecuteFile(Path.Combine(folder, "vs_zen_coding.py"));
  engine.SetVariable(scope, "App", _applicationObject);
  execCommand = engine.GetVariable<Func<bool>>(scope, "exec_command");
}

public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
  handled = false;
  if (!CanExecuteCommand(commandName, executeOption))
  {
    return;
  }

  try
  {
    #if RELOAD_EVERY_TIME
    ReloadPython();
    #else
    if (execCommand == null)
    {
      //Load first time, to avoid making the VS startup slower
      ReloadPython();
    }
    #endif

    execCommand();
  }
  catch (Exception ex)
  {
    DisplayError(ex);
  }
  handled = true;
}

The ReloadPython() method is not called on startup, instead it is called the first time the command is called. IronPython performs well, but there is still some startup cost and I don’t want to add that to the startup time of Visual Studio. Instead you pay the price the first time you actually need it. Then we have the Exec method which is from a VS interface and is called when the command is invoked. There I use a compilation constant, RELOAD_EVERY_TIME, to check if I should reload my python script every time I invoke the command. This has proved to be INCREDIBLY useful, instead of constantly starting VS up again and again I just edit my python script, save it and the next time I execute the command the new code is used. And of course I turn this constant off for release builds.

Another nice trick to play around with the VS API, start up an IronPython shell and type:

>>> from System.Runtime.InteropServices import Marshal
>>> app = Marshal.GetActiveObject(”VisualStudio.DTE.9.0″)
>>> app.ActiveDocument.Name
‘ZenCodingAddIn.cs’

This gets you a reference to the running instance of VS2009 which you can then experiment with.

You can download an installer for the add-in or get the source. The add-in is licensed under the GPL v3, the same license the zen-coding library uses. The add-in works for Visual Studio 2005, 2008 and 2010 beta 2.

Now, once you’ve installed the add-in, nothing happens. Well, actually what happens is there’s a new command available in Visual Studio, named ZenCoding.Expand, or ZenCoding.VisualStudio.ZenCodingAddIn.Expand, depending on where you are looking for it. (The keyboard mapping uses the full command id, but when adding it to a toolbar you get a shorter friendly name for it). By default it is not mapped to any keyboard combination. This is because it’s late and I can’t be bothered to figure it out I strongly believe that add-ins should not force a keyboard shortcut on you, possibly overriding something you have set yourself. So, map the command to your preferred keyboard shortcut (mine is Ctrl+E,Ctrl+K). Or you can drag the command onto a toolbar, which is fairly useless, but possible.

Enjoy!

UPDATE 13.11.2009: The main zen-coding developer also told me that I’m using an older version, the latest version has a lot more features, including user defined snippets. I’ll start looking at that when I have time, which won’t be just yet.

Reader's Comments

  1. |

    That’s brilliant Einar!
    Works a treat.

    At this minute I’m using vs2008 on a locked down windows XP machine, which is a particularly hostile environment for add-ins. Yours installs just fine, and performs nicely.

    Love it.

    (hey, the generic types in your code snippet above were eaten by wordpress’s failure to turn < into <)

  2. |

    Thanks for this!! Works really well. Is there any way to select some existing text or markup and wrap it with more html?

  3. |

    Hi Jake. There isn’t right now. But Sergey, the developer of the zen coding library has a new version that has some new features, I just haven’t packaged it yet. The features I know about in the new version are:

    * Custom snippets, you can create your own.
    * Output profiles that have options for things like whether to insert newline, whether to use single or double quotes for attributes and more.
    * Some feature that selects surronding tags I think. I think it’s about having <tag> text|</tag> (where | is the cursor pos) and being able to select from <tag> to </tag> with a single command.

    But if there are features you want to get into zencoding you should contact the zencoding devs through http://code.google.com/p/zen-coding/ , I just handle the Visual Studio plugin itself. If they add new features I’ll try to get them into the plugin.

  4. |

    Hi, Thanks for the work. Can you tell us when you are going to update this.

    Thanks

  5. |

    I guess I’ll have a new version ready sometime in the next 7-10 days, depending on how busy I am. It will be updated in this blog post, and I’ll add a comment to the feed, so subscribe to this pages rss feed if you want to get notified that way.

  6. |

    Thank you so much, Einar! This is brilliant! :)

  7. |

    It doesn’t work with visual studio 2005 (installer)
    After installing and binding to Ctrl+E,Ctrl+K I see error –> ZenCoding Error …. library is not registered ….

    what am I doing wrong?

  8. |

    Hi Sergey

    Ok, it looks like some COM library is not registered. I would think that it would be some COM library specific to VS2008 that I’m using and I don’t see the error because I have it installed. In my project I had a reference to EnvDTE9.0 (which is VS2008) but wasn’t using it anywhere so that shouldn’t be a problem. Can you do one thing for me? Can you open VS2005, create a new project and then do Add Reference. There in the .NET tab can you see which of these components are available to you:

    EnvDTE
    EnvDTE80
    EnvDTE90
    Extensibility
    Microsoft.VisualStudio.CommandBars
    stdole

    Also, which version of VS2005 do you have? Is it by any chance an Express version?

  9. |

    Hi einar,

    Here are 2 screen shots

    http://dl.dropbox.com/u/1631205/1.JPG
    http://dl.dropbox.com/u/1631205/2.JPG

    first one with .net references
    the second one with vs2005 version

  10. |

    @Sergey: Ok, this is mysterious. Can you try one other thing? Download the file at http://tech.einaregilsson.com/downloads/ZenCoding.VisualStudio.dll and put it in your ZenCoding installation folder (typically C:\program files\ZenCoding.VisualStudio). Then start VS2005 again, now you should get some message boxes giving you different errors. Let me know what they are, then maybe I can figure this out.

    I’ve taken out the EnvDTE9.0 reference but I wasn’t using it anyway. I don’t know if the Python code that accesses Visual Studio tries to use some VS2008 interfaces, but I’m 99% sure it doesn’t.

  11. |

    Hi einar,

    I’ve replaced my dll with your and seen messages like python module loaded without any problems, got reference … without any problems and then oops…. magic !

    my shortcuts start working :)

    So it looks like after replacing original dll with yours it’s working fine.

    Here is the link to original dll (that doesn’t work)

    http://dl.dropbox.com/u/1631205/ZenCoding.VisualStudio.dll

  12. |

    Looks like I’ve figured out.

    Zen coding somehow conflicts with vs.php plugin
    After installing vs.php I’ve got the same bunch of errors.

    Please take a look at me screen shots

    http://dl.dropbox.com/u/1631205/1.JPG
    http://dl.dropbox.com/u/1631205/2.JPG
    http://dl.dropbox.com/u/1631205/3.JPG

  13. |

    Ok, it might be that that plugin also uses IronPython but a different version, or that it messes with VS in some way. Sorry but I cannot figure that out, I’m trying to get a better version of ZenCoding out asap and don’t have time to investigate more conflicts right now. I’ve put the same dll as I gave you last time but without the message boxes up at http://tech.einaregilsson.com/downloads /ZenCoding.VisualStudio.dll , if that gives you problems as well then I’m afraid I don’t know what to do. We’ll see in the next version, maybe this will disappear then :)

  14. |

    Hi einar,

    I’ve tried you dll and still experiencing the same troubles.

    So waiting for new version of zen codding adding

  15. |

    So. Einar. When’s the next version coming out, mate? :)

  16. |

    Hi Einar,

    I’m relatively new to VS, but I’m encountering a problem when I try to install your plugin.
    I’ve installed the ZenCoding.VisualStudio to the ‘plugins’ directory inside the main installation directory of Visual Studio (C:\Program Files\Microsoft Visual Studio 9.0\plugins\ZenCoding.VisualStuidio) However, when I open my IDE, and try to install the addin via Tools->Add-in Manager, I get the following error message:

    The Add-in ‘ZenCoding’ failed to load or caused an exception. Would you like to remove this Add-in?
    If you choose yes, the file it was loaded from, ‘C:\ProgramData\Application Data\Microsoft\MSEnvShared\Addins\ZenCoding.VisualStudio.AddIn’, will be renamed.
    Error Message : The system cannot find the file specified.
    Error number: 80070002

    I also cannot find the file it mentions in the directory generated by your installer.
    Have I done something wrong?

    Thanks in advance,
    Jason

  17. |

    I seem to have gotten it working.
    The installer you provided doesn’t seem to have all the files necessary to add the plugin, so I grabbed the files you provide in the source, placed them in my plugins directory, then installed using the installer to the same directory. Using Tools->Add-in Manager then worked without a problem.
    Now, however, I’m not sure how to register the commands.

    Again, any help is appreciated.

    Jason

  18. |

    @Jason: I don’t know what the problem might have been. I tried installing into the same folder as you and it worked on my machine. Is it possible that you don’t have write access to your Program Files folder? You might want to try installing the latest version that I have just released. If that doesn’t work then it’s either a rights issue on your machine or the installer fails for some reason.

    For registering the commands, if you go into the Tools->Customize menu, then press the Keyboard… button and then enter “ZenCoding” into the textbox named “Show commands containing” then you should see one or two commands (depending on your plugin version). If you don’t see them then something failed completely during initialization.

    Try the new version and let me know how it works out. Also try installing into My documents or somewhere other than program files.

  19. |

    @Thomas: You’re in luck, the new version has just been uploaded :) . See release notes at the top of the page.

  20. |

    NEW RELEASE: VERSION 1.1.0.333

    This release adds the following features

    * Uses latest version of zencoding python library
    * Wrap with abbreviation command
    * Use, create, edit, delete custom snippets (Tools->Options->ZenCoding)
    * Icons for commands
    * Some bug fixes

    Also a total rewrite with everything now written in IronPython

  21. |

    Hi Einar,

    Thanks for getting back to me.
    I eventually figured out how to register the command, but for some reason, it would not let me register CTRL+E. It seemed to accept the assignment, but when I tried to actually use it, nothing would happen, except a message at the bottom of the IDE saying something like ‘waiting for the rest of the chord’. So, I changed to command to CTRL+E, CTRL+E, and it works.

    I’m going to try upgrading to the new version later today.

    Thanks for your hard work putting this addin together.

  22. |

    @Jason: The chord thing is because you have some other keyboard shortcut that is Ctrl+E,Ctrl+SomethingElse. That means that when VS sees a Ctrl+E it cannot be sure if you want a shortcut that starts with Ctrl+E or one that is just Ctrl+E. As far as I know it’s this way because there are a lot of commands in VS and so only allowing single shortcuts would drastically reduce the possibilities.

    AddIns like ReSharper can also mess with this. I tried to map over a keyboard combination that ReSharper had assigned to something else, but even when VS said it was mapped to my command ReSharper seemed to intercept it so it didn’t work.

    Let me know if the new version causes you problems.

  23. |

    Look like a cool plugin, but won’t show up anywhere in VS2010 beta 2 :(

    ..but i’ll be checking back :)

    Merry X-Mas!

  24. |

    Hi Robert

    It has been tested in VS2010 Beta 2 and worked there. Can you tell me where you installed the plugin (which folder) and what operating system you’re running? It might be some problem with the addin registration.

  25. |

    Hi n tnx for the reply.

    I’m running windows 7 x64 retail. It does seem like a registration problem as it seems to install fine, just doesn’t show up anywhere in VS2010.

    It installs to:
    C:\Program Files (x86)\ZenCoding.VisualStudio

    Not sure if this has anything to do with it.
    With reflector i see that ZenCoding.VisualStudio.dll has references to:
    C:\Windows\assembly\GAC\
    EnvDTE
    EnvDTE80

    however in the gac i also see:
    EnvDTE90
    EnvDTE90a
    EnvDTE100

    and if i look at the properties of each dll i see:
    EnvDTE80 : VS2005
    EnvDTE90 : VS2008
    EnvDTE100: VS2010

    ..just wild guesswork, don’t know anything about making plugins, just websites :)

    Thanks for your time!
    Robert

  26. |

    The problem must be with the addin registration. I tried to put it in a place where it should work everywhere, but according to http://msmvps.com/blogs/carlosq/archive/2009/01/16/the-strange-case-of-quot-allusersprofile-datos-de-programa-microsoft-msenvshared-addins-quot-add-in-file-path.aspx that might be a problem, especially if you run a localized version of windows.

    So, what you can do is check the folder

    C:\Users\All Users\Application Data\microsoft\MSEnvShared\Addins

    and see if you have a ZenCoding.VisualStudio.AddIn file there. Try moving it to [my documents]\Visual Studio 2010\AddIns instead and see if it gets picked up there. If you don’t have the file on your system you can download it at http://tech.einaregilsson.com/download/ZenCoding.VisualStudio.AddIn . Check the file to see that all paths in it point to the correct place where you installed the addin. Then restart VS.

    If this still doesn’t work then try going into VS and open Tools->Options>Environment>AddIn/Macros Security. There is a list of the locations that VS searches for addin files. Put the .AddIn file in one of those places.

  27. |

    Nice!

    Effectively, i have a localized version of windows.

    Got it working by copying to the mydocuments path as you said.

    Copied from:
    C:\ProgramData\Microsoft\MSEnvShared\Addins

    To:
    C:\Users\[UserName]\Documents\Visual Studio 2010\Addins

    Thank you very much for your time with this!

    Robert

  28. |

    [...] @ Google Code Zen-Coding @ Smashing Magazine Plugin para Visual Studio [...]

  29. |

    Great plugin, very useful.

    Just one quick question. When I type li it generates:

    and ul+ (as an example) generates:

    This seems to be the general pattern. Is there any way to tweak the code so that li generates:

    and ul+ (as an example) generates:

    If not, don’t worry, it would just make the outputted code a bit more manageable.

    Ta

  30. |

    *** Try again ***

    When I type li it generates:

    li
    lorem….
    /li

    and ul+ (as an example) generates:

    ul
    li
    lorem…
    /li
    /ul

    This seems to be the general pattern for how the expanded code is formatted. Is there any way to tweak the plugin code so that li generates:

    li lorem…. /li

    and ul+ (as an example) generates:

    ul
    li lorem…. /li
    /ul

    If not, don’t worry, it would just make the outputted code a bit more manageable.

    Sorry if the code above looks weird but the first time I tried with the angle brackets in it removed them and their content.

    Ta

  31. |

    Hi.

    In the zencoding library itself there are some options for how the output is formatted, it’s just not available in the VS plugin. What you want to look at is two lines in addin.py in your installation folder that look like this:

    zen_core.expand_abbreviation(abbr, self.doc_type(), ‘xml’)

    the final parameter, ‘xml’, is the name of the output profile used. Try changing it to one of

    plain
    html
    xml
    xhtml

    (Watch out that you do it for every call to expand_abbreviation)

    That changes some of the output options. If you want to get deeper into this you can look at the zencoding library itself (zen_core.py) and look at what the output profiles can do.

  32. |

    Can zen coding will work on Visual Web Developer 2010 Express Edition too?

  33. |

    It seems doesn’t work with mine .
    I install Zen Coding for my VS 2008 but there’s no zen coding part in options :|

  34. |

    [...] Studio — external download, [...]

  35. |

    Great tool!

    Is there any way to share custom snippets created in VS? Not sure where those custom snippets are stored, but it would be great to be able to share a common set of snippets amongst team members…

    Thanks for all the great work, einar!

  36. |

    @Pete: The snippets are stored in a my_zen_settings.py file that are stored in your application data folder. In my case (Windows 7) it is C:\users\myusername\AppData\Local\my_zen_settings.py

    You can send the whole file to your team members but there is not any kind of export/import feature.

    And, I’m sorry to say, I don’t think there ever will be one, at least not made by me. I’ve kind of lost interest in this project, I got it to the state I needed for myself and that’s about as far as I’m gonna take it. But of course anyone is free to take the source and run with it, it’s all available for download and not really that complicated.

  37. |

    Becuase Einar doesn’t have plans to improve its work I merged its code with the current version of the ZenCoding plugin (http://code.google.com/p/zen-coding/) and created a new project on CodePlex. Source code can be found here: http://zencoding.codeplex.com/

    Einar, if you have any complaints about the new project or the modified source code please let me know.

  38. |

    @Boris: Excellent, I’m just happy someone wants to take this over. Only thing I’d recommend is that when you make changes to any code you add some information about it in the header, as I don’t want code that has been modified from what I did to only have my name on it.

    I’ve put a link to your project on the top of the page so people know where to go, not everyone reads every last comment :)

  39. |

    Ok, I will modify headers where original code is changed.
    Thank you for the link.

  40. |

    [...] Studio — external download, [...]

Leave a Comment