I make tools to help people create wonderful things.

Journal

Vi modes in MonoDevelop

I've recently added simple vi modes emulation to MonoDevelop. It's been a relatively quick and easy hack, though I'm pretty sure I'm now running a deficit of free time. I'm not actually a vi user, but I've been hearing from several of our users that they miss vi navigation and commands. While most editors (for example emacs) can be simulated to some extend through a keybinding theme, it's impossible to replicate even the simplest behaviours of vi this way.

After seeing ViEmu, a successful vi emulation addin for Visual Studio, I realised that a vi mode in MonoDevelop would probably see a lot of use, and, as a challenge, decided to bootstrap it. I'm hoping that real vi/vim users will contribute tweaks and patches to bring it closer to a faithful vi experience.

Some of you might be wondering why I started from scratch, since over a year ago, Ankit embedded vim in MonoDevelop. There are several reasons why I don't think this is the best approach. Embedding vim means you have perfect vim support, but you have to manually integrate all of the MonoDevelop features one by one. Integrating code completion is only the first step. Consider integrating language item tooltips, refactoring/navigation commands, error underlining, code folding, language item combos, semantic highlighting, text templates draggable from the toolbox, debugger breakpoint and stepping markers, debugger value inspection tooltips. Even when you finish this, you have to deal with potential future features like per-project editor settings, contexual multi-field templates, and who knows what else. People using vim integration would always be second-class MonoDevelop users.

I don't want to bring MonoDevelop features to vim, I want to bring vi/vim features to MonoDevelop.

Spelunking deep into Mono.TextEditor code, I implemented vi modes and commands at the very core of the text editor. The action-based architecture made this pretty easy to do at the core, though I'm running into a few problems at the higher levels of MonoDevelop, particularly the C# smart indenter, which relies on hooking <Enter> keystrokes. Fortunately it's still very usable.

The code is in MD SVN, and can be enabled through a checkbox in the Preferences -> Text Editor -> Behaviour panel. Features implemented so far are:

Motions
h j k l w b % 0 ^ _ $ G { }
Delete commands
d d{motion} dd D x X
Change commands
c c{motion} cc C r R
Insert commands
a A i I o O
Ex commands
 :q :w :qw :q! :{linenumber}

In addition, keyboard directional keys act where appropriate, normal MonoDevelop keyboard shortcuts remain functional, and visual mode is implemented but so far can only be used with normal MonoDevelop keyboard shortcuts.

I have a pretty good idea of what I'd like to see and how I'd like to see them implemented, in particular with regard to refactoring so that macros and repeat commands can be implemented. This will not be easy, but there are many other low-hanging fruit: B W e E ( ) word and sentence navigation, simple search/replace, repeated motions (e.g. d10w), cut/copy/paste. I'd also like to add some ex commands for IDE features, e.g. build project, jump to definition, rename variable, go to base class, implement interface. These are pretty easy too, though naming the commands will take some thought. It might be worth borrowing some ideas from jVi/NetBeans.

Unfortunately I'm not likely to have any time to spend on vi modes in the near future, but I welcome contributions, and will be glad to provide guidance to anyone who'd like to contribute.

Hack Week: OGRE.NET Packaging

Last week was my second Hack Week at Novell. Massi and I had been intending to hack on a demo for embedding Mono in games, but realised that the overhead of bootstrapping a stable working environment would most likely frustrate our efforts to get something within the week.

Instead, I decided to package some game libraries for Mono on the openSUSE Build Service. I planned to package Axiom, OpenTK and OGRE.NET, and write some MonoDevelop templates for them, but got rather tied up in the details of packaging OGRE.NET and its unmanaged dependencies (I now know far more about packaging SONAMEd libraries than I wanted to!). As a result, I only completed the packaging for OGRE.NET, though I will get around to packaging the others sometime.

You can now install my OGRE.NET and OGRE packages for OpenSUSE 11, reference OgreDotNet and Math3D from MonoDevelop, and start writing code without having to worry about unmanaged libraries, etc.:

Screenshot of a MonoDevelop running an OGRE.NET demo.

Massi did an alternate Mono game embedding demo, and investigated how we could optimise SWIG (or some other binding generator such as DoxyBind) to generate better Mono bindings for C++ code.

Web Application Projects in MD and VWD

I'm very pleased that Visual Web Developer Express 2008 has now gained Web Application project support in Service Pack 1. This means that MonoDevelop users will be able to share ASP.NET projects with VWD developers.

For those of you who haven't heard the story behind this, Web Application projects are support for developing your ASP.NET site as a project. Although VS.NET and VS.NET 2003 did this, it was removed in VS 2005 in favour of "Web Sites", which consider a web site to be a directory. As I'm sure you can guess, the latter system is convenient for editing websites in-place — and they even had FTP support for this purpose — but in my opinion it's a poor system for well-structured development. Clearly other people thought so, because Web Applications were added back to Visual Studio 2005 as an optional addon, and included in VS 2008. Finally in VS2008 SP1, it's reached the free version. The reason for this is quite simple; it's a necessity for proper ASP.NET MVC development.

At the moment, MD trunk does a passable job of opening projects from VWD 2008 SP1, but building and deployment isn't so great, because when I originally implemented these, I had to work around some of the limitations in MD's build and deployment system. These workarounds aren't quite compatible with the MSBuild projects from VS. I'm currently trying to make this seamless by tweaking our MSBuild loader to more closely match the MSBuild build targets and file copy semantics, making the MD deployment system slightly more generic, and implementing the build and deployment targets "correctly" for ASP.NET projects.

Support for importing Web Sites may come later, but for now, it's good to see that we can now interoperate with Microsoft's free ASP.NET development tool.

Demoing Mono in Games

I'm trying to plan some examples of using Mono in game development, so that we have time to get together some solid demos and samples for next year's GDC.

I'm primarily interested in showing how Mono fits into the existing games development ecosystem; we don't really have an XNA-like story for developing fully managed games in Mono at this point. The focus of the demos will therefore be:

  • How easy it is to embed Mono into a game and use it for scripting and gameplay programming.
  • How the Mono and .NET development tools make development faster, easier and more robust.
  • How Mono's performance compares to popular scripting engines such as Lua and Python.
  • (Possibly) using Moonlight as a Mono-scriptable, artist-friendly UI engine.

Does anyone know of any complete games or cool demos for which source or C/C++ SDKs are available, so that Mono could be embedded as a scripting engine? (I'm already considering Source Engine and Quake 3).

Nice ideas for demos would be useful too, though obviously developing a serious game from scratch is out of the question...

Building an IDE Navigation History

MonoDevelop has a code navigation history. When you switch views, or jump around between definitions, it logs the history, and you can browse back and forth like a web browser. However, it has some major issues -- the history it generates is unintuitive and erratic. It seems like it should be a really useful feature, but in practice is frustrating to use, so I recently decided to give it an overhaul.

Unfortunately, navigation isn't an easy thing to get right in an IDE. It's easy to log too many points. For example, if navigation points are logged every time the user switches between all their open document tabs looking for something, it gets very cluttered.

The most important thing is how it fits into the users' code navigation, so I decided to blog in order to get some feedback on my current thoughts.

In my opinion the following actions should not trigger logging of navigation points:

  • Switching through files by control-tabbing or clicking on the tabs.
  • Jumping using the search pad or the error pad
  • Navigation between items using the document outline or the class browser
  • Moving the cursor around with the keys and/or mouse (but this should alter/update the existing nav point)

Whereas the following points should be logged:

  • The destination of a "Go to definition" command
  • The point that's left behind when executing a "Go to definition" command, if it's not too close to the current point
  • A jump to an event handler from a designer
  • Locations in which text is edited, though these points should be carefully pruned so that there are no more than one or two per file

In summary, only direct interaction with the document -- and in particular, large jumps -- should be logged.

How will this fit into your coding flow?

Colour Completion

When I initially wrote the ASP.NET code completion, I added support for completing attribute values for enums and bools. More generalised completion using TypeConverter.GetStandardValues isn't so easy, since I don't want to load arbitrary types into the MD process, so I skipped this for now. However, I did special-case System.Drawing.Color, since it's used a lot.

This morning, on a suggestion from Aaron, I tweaked it to generate custom icons for each colour:

Screenshot of a code completion window showing appropriately coloured icons for each named colour.

In other news, I landed the new ASP.NET completion parser, which is much more robust, and is also able to generate a tree, so it will soon replace the DOM parser too. The new design also means I'll be able to unify it with the XML and Moonlight (XAML) addins.

I recently returned from a family holiday in Maine, and will post photos when I got them sorted out and uploaded to Flickr.

Whales, Beavers and Snakes (Oh My!)

My family is visiting me here in Boston, and over the Independence Day weekend we toured Western Massachusetts for a few days. I captured some interesting photos. Having finally convinced myself to purchase some nice lenses for my SLR, I am particularly pleased with this haul.

Humpback Whale

Boston Harbour

July 4th Procession

Beavers

Garter Snake

Progress on ASP.NET Source Editing

I have been making good progress on ASP.NET source editing, as evidenced by the following screenshot:

Screenshot of an ASP.NET file in MonoDevelop with error underlining, code folding and a path bar.

Yes, that is code folding, error underlining, and a path bar. However, the document outline pad isn't hooked up yet for ASP.NET[Update 2008/5/2: outlining implemented].

I've been getting a lot of practical experience with handwritten parsers recently. The ASP.NET addin has two parsers; the first builds a full DOM, and the second provides document path information very efficiently.

The path parser is designed to accept individual characters as the user types them, instantly providing information about the current context. This is very useful for code completion and smart indentation, and is obviously near-ideal for the path bar too. It's about as robust as I can make it, recovering effectively from most errors. However, I wrote a state-based XML parser where each state was a path object, which has proved rather unwieldy to extend cleanly for ASP.NET, so this may well get replaced soon.

The DOM parser was originally written for the CodeBehind field generation. It's based on Mono's ASP.NET tokeniser, which makes it rather fragile; when it encounters a syntax error, it dies. For its original use, this is sensible behaviour, but for a text editor it needs to be much more robust, so I intend to modify the path parser to build this DOM instead.

I plan to roll a lot of this back into the XML addin, which will provide a solid base for XAML completion for Moonlight apps.

Shiny Feature of the Day

Today I implemented an oft-requested feature for MonoDevelop: making the code completion and info tooltips transparent when the Control key is held down. This enables you to take a look at the code that the window's obscuring, without dismissing the popup:

Screenshot of a semi-transparent code completion window.

This feature's in MonoDevelop trunk, and can be tried out right away. You'll need GTK+ 2.12 or above (GTK# only needs to be 2.8 or above) and Compiz or any other compositing window manager. It's also available in my MonoDevelop trunk builds on the openSUSE build service.

This behaviour is encapsulated in a class that can be attached to any Gtk.Window, and handles a couple of nasty hacks and workarounds.

Miscellanea

Here's a quick summary of interesting things from the past few months that I haven't blogged. Unfortunately I can't give each topic the time it deserves, but I think that's better than not mentioning them at all.

GHOP Results

The Google Highly Open Participation contest finished, and was a great success, with 40 completed tasks, a great improvement over my earlier post. Of particular note was the huge number of rules implemented for Gendarme. I'd like to thank all of our successful students and their mentors, and congratulations to Dan Abramov, our Grand Prize winner. I'd also like to single out Andreas Noever, another absolutely stellar student who very narrowly missed out on the top spot.

Novell Hack Week

During Novell Hack Week I worked on an automatic error reporting system that I intend to use in MonoDevelop at some point. I got rather hung up on collecting as much system and process information as I could, so it unfortunately wasn't completed.

However, I did have fun "architecting" a client/server/webserver data channel, which I planned to re-use for several other purposes: reporting problems' solutions back to the user, and collecting application usage data. Now that I've seen how useful such data can be, in Jensen Harris's awesome presentation on how the Microsoft Office ribbon was developed, I'm particularly interested in having something similar in MonoDevelop.

Game Developer's Conference

Towards the end of February some of us on the Mono team went to the Game Developers Conference in San Francisco to promote Mono as a game scripting engine, and find out what games developers need to make this work for them. All in all it was great fun, and very successful. Miguel has a longer writeup.

I would be interested to find out what we could do to make Mono more attractive for gaming, both for embedding as a scripting engine, and as a portable runtime, and how this could be supported by MonoDevelop. One of the real strengths of Mono is the development tools, and I would like MonoDevelop to become part of the gaming development ecosystem. One suggestion would be an "Axiom Studio" addin for MonoDevelop as an alternative to XNA.

MonoDevelop 1.0 Release

After years of development, we released MonoDevelop 1.0 alongside Mono 1.9, and work is already well underway on the next release. I'm already working on ASP.NET code completion, which is coming along quite nicely. I've also updated and integrated Matt Ward's XML Editor into MonoDevelop trunk.

Google Summer of Code

MonoDevelop is once again taking part in the Google Summer of Code under Mono's umbrella. I really enjoyed mentoring Marcos last year, and I'm looking forward to doing some mentoring this year.

Visit to the UK

These past couple of weeks I was in the UK visiting family and friends. it was nice to see people again after 5 months in another continent!

Pages

Subscribe to Journal