Jekyll2021-03-19T16:37:23+00:00https://mhut.ch/feed.xmlmhut.chMikayla Hutchinson's home on the webMikayla HutchinsonReflections After Surgery2018-09-15T00:00:00+00:002018-09-15T00:00:00+00:00https://mhut.ch/journal/2018/09/15/reflections-after-surgery<p>The past couple months I’ve been recovering from bottom surgery (gender
reassignment surgery). It’s been a strange liminal period of relief and
reorientation.<!--break--></p>
<p>I don’t doubt at all that this is a huge and positive milestone in my
life. I’ve despised a part of my body as long as I can remember, doing
my best to hide it and write it out of my consciousness to cope with my
dysphoria. It was evidence of my bodily masculinity, dredging up horrible
feelings in an instant if I ever let my guard down.</p>
<p>Now it’s gone, and I have something new and unfamiliar. Do I like it?
I don’t know, it just <em>is</em>. I suspect that’s how many people feel about
their bodies. It’s still changing as it heals, still a source of discomfort
and awkwardness, so I reserve full judgment, but I do know that I’m a
lot happier.</p>
<p>It’s hard to describe gender dysphoria to someone who hasn’t experienced
it. You are yourself, but your body is wrong, people don’t treat you
right, and you can’t express yourself without risking ruinous ostracization.
You overcompensate to fit in and make yourself miserable, and no-one ever
sees your real self because you do your best to hide it away. Every day
you see other people living aspects of the life you wish you had,
blissfully unaware of their fortune because they never imagined anything
different.</p>
<p>The worst part is how it’s all tangled up. We’re socialized to rigidly
associate body shapes with gender, and gender with behaviors. There’s
no objective way to define what makes a man or woman, it’s emergent
from a whole array of factors. All the aspects of dysphoria feed into
your sense of identity. Your body, how people treat you, and how you are
able to express yourself all feed into your sense of self identity, which
in turn affects how you feel about those things.</p>
<p>I’ve overcome a lot of inhibitions, and in many ways I don’t care what
people think about me. But when I look into a mirror, and part of my
body looks male, I don’t feel real. When someone calls me “sir”, I
don’t feel real. I feel like an impostor. I feel like I’m pretending
to be someone I’m not, that “reasonable” people would consider me
delusional. When people treat me well, I suspect it’s simply because I’m
somehow fooling them, and if they had the full picture, of course they’d
think I wasn’t real. Or they’re just humoring me to be nice.</p>
<p>The biggest contributor to those feelings for me is gone, and it’s a huge
relief. It would be pretty damn hard for anyone now to claim to
objectively call me a man. Of course, that means I’m now worrying about
other things. Should I get top surgery (breast augmentation) or FFS
(facial feminisation surgery)? They’d lessen my remaining dysphoria,
but I don’t know how much. Can I justify the expense, pain and time?
Is it a moral failing to conform to male gaze centric beauty standards
instead of helping to redefine what it means to be a woman?</p>
<p>After obtaining hormones and making a social transition, bottom surgery
for me was a given. I hated that part of myself more than anything else,
so fixing it was a priority. That took time and work: multiple
psychological evaluations, repeated laser hair removal in delicate
areas, time gates, waiting lists, insurance criteria. Part of me still
feels like I showed up fifteen years late, but once I started I made
it over the finish line with a respectable time.</p>
<p>And now I’m done, and I’ve completed all my major goals: social
transition, hormones, bottom surgery. I’m at a loss for what to focus
on next. I’m much happier, but I’m not entirely comfortable in myself.
Hair removal and voice therapy are ongoing, and I’m working on my
empathy, my self confidence, my social anxiety, but none of these
have discrete resolutions. It’s awfully tempting to consider other
surgeries, but I want to do them for the right reasons.</p>
<p>I still look in the mirror, or hear my voice, and although I’m well
into diminishing returns I’m not entirely happy. I’m lucky that many
people think I look and sound cis (not trans), as we’re all socially
conditioned to value normalization. But I‘ve trained myself to spot
differences, and I have a lot of internalized transphobia. I’m my
own worst critic and I can’t escape myself.</p>Mikayla HutchinsonThe past couple months I’ve been recovering from bottom surgery (gender reassignment surgery). It’s been a strange liminal period of relief and reorientation.Migration to Jekyll2018-09-02T00:00:00+00:002018-09-02T00:00:00+00:00https://mhut.ch/journal/2018/09/02/migration-to-jekyll<p>I just finished migrating this site to <a href="https://jekyllrb.com/">Jekyll</a>.</p>
<p>I’m a little sad. I ran Drupal for <a href="/2005/01/30/and-so-it-begins">over 16 years</a>, and there are few things in my life that have
been constant that long. But all things come to an end, and it served its
purpose well.<!--break--></p>
<p>It’s interesting to come back round to static pages. Before I settled on Drupal,
I briefly wrote my own static site generator, but comments, analytics and online
editing proved too tempting. Now I have them via mechanisms that simply didn’t
exist in 2005.</p>
<p>I’d been kicking my Drupal instance and Debian Linode VPS down the road for
years without any issue, but a few months ago a Bitcoin mining worm settled in
my machine, carried in by <a href="https://www.drupal.org/sa-core-2018-002">Drupalgeddon
2</a>. I fixed the vulnerability and did
my best to clear out the infestation, but I didn’t trust the machine any more.</p>
<p>Faced with rebuilding a full LAMP installation, I decided instead to smuggle out
my data and set up again elsewhere. I chose Jekyll because I’d used it a few
times, and it’s popular and relatively well supported. As it ran on <a href="https://pages.github.com/">GitHub
Pages</a>, I could stop administering my own Linux
server.</p>
<p>Migrating the content with the <a href="https://import.jekyllrb.com/docs/drupal7">Jekyll Drupal
importer</a> was pretty straightforward,
though I ended up having to do a lot of manual fixup to preserve permalinks and
redirects. I manually migrated years of content from a mismash of HTML and
custom Drupal filters to Markdown and Jekyll Liquid tags, and got a <em>lot</em> more
familiar with <a href="https://code.visualstudio.com/">VS Code</a>.</p>
<p>Wading through decades old posts was weird. My writing style, my <em>self</em> and the
social environment have all changed. Blogs are still around, but many of the
ways they were used have been replaced by Twitter, Reddit, Tumblr and Facebook.
I almost decided not to allow comments, but during the migration I found some
good discussions in my archives, and so enabled <a href="https://disqus.com/">Disqus</a>.</p>
<p>For theming I started with <a href="https://fongandrew.github.io/hydeout">Hydeout</a>, and
made a lot of minor tweaks. Eventually I want a unique design, and although
that’s probably a way off, I’m confident I have a good foundation.</p>
<p>There were a few more unanticipated complications. Recreating my archives and
tags wasn’t possible with the sandboxed Jekyll environment supported by GitHub,
so I <a href="http://joshfrankel.me/blog/deploying-a-jekyll-blog-to-github-pages-with-custom-plugins-and-travisci">set
up</a>
a <a href="https://travis-ci.org/mhutch/mhutch.github.io">Travis CI job</a> to build and
deploy the site. I also set up Cloudflare as it was the easiest way to port
pattern-based URL redirects from my old domain. Maybe it’ll come in handy
someday if I attract the wrong attention.</p>
<p>Now I just need to make time to write more. I’ve missed it 😊</p>Mikayla HutchinsonI just finished migrating this site to Jekyll. I’m a little sad. I ran Drupal for over 16 years, and there are few things in my life that have been constant that long. But all things come to an end, and it served its purpose well.Easy pull requests from master with git-offload2016-08-03T00:00:00+00:002016-08-03T00:00:00+00:00https://mhut.ch/journal/2016/08/03/easy-pull-requests-from-master-with-git-offload<p>When using git, I often find myself committing some work to master locally, and
having to move it all to a branch from which I can make a pull request. Then I
have to clean up afterwards. I do this often, yet it’s tedious and I still
sometimes have to look up the exact format of the git commands. So, I wrote a
script to automate it, <code class="language-plaintext highlighter-rouge">git-offload</code>.<!--break--></p>
<p>Simply pass in the new branch name and the remote to you want to push the new
branch, and git-offload automatically does the following things:</p>
<ul>
<li>Creates a new branch from your current commit</li>
<li>Pushes that branch to an upstream of your choice</li>
<li>Goes back to the original branch</li>
<li>Resets the original branch to its upstream state</li>
</ul>
<p>You can <a href="https://gist.github.com/mhutch/722fff2315597fc7db28e660423efb5c">download git-offload from
Gist</a>.</p>
<noscript><pre>400: Invalid request</pre></noscript>
<script src="https://gist.github.com/722fff2315597fc7db28e660423efb5c.js"> </script>Mikayla HutchinsonWhen using git, I often find myself committing some work to master locally, and having to move it all to a branch from which I can make a pull request. Then I have to clean up afterwards. I do this often, yet it’s tedious and I still sometimes have to look up the exact format of the git commands. So, I wrote a script to automate it, git-offload.MSBuild Code Generation in VS20152016-04-19T00:00:00+00:002016-04-19T00:00:00+00:00https://mhut.ch/journal/2016/04/19/msbuild-code-generation-in-vs2015<p>A couple of weeks ago I was helping <a href="http://xfcomplete.net">Jason Smith</a> debug
an issue with the build-time code generation in Xamarin.Forms. The build targets
were based on my <a href="/journal/2015/06/30/build_time_code_generation_msbuild">Build Time Code Generation in
MSBuild</a> post, but in
recent Visual Studio 2015 versions the generated classes would occasionally
disappear from IntelliSense.<!--break--></p>
<p>Eventually we figured out that this happened after a very specific sequence of
circumstances: when the project was cleaned, then closed and reopened.</p>
<p>I verified that the <code class="language-plaintext highlighter-rouge">CoreCompile</code> target is still run on each project when first
opening a solution in Visual Studio. However, it wasn’t getting run when the
solution was closed and reopened unless the project file had changed, or the SUO
files were deleted. All of this pointed to Visual Studio caching the <code class="language-plaintext highlighter-rouge">Csc</code>
inputs in the solution options in order to improve solution load performance by
eliminating the need to run <code class="language-plaintext highlighter-rouge">CoreCompile</code>.</p>
<p>This is a fine optimization, except for one minor detail. The cache was not
getting flushed when the project was cleaned. This is a HUGE problem when the
<code class="language-plaintext highlighter-rouge">CoreCompile</code> target creates input files for <code class="language-plaintext highlighter-rouge">Csc</code>, and the <code class="language-plaintext highlighter-rouge">Clean</code> targets
correctly cleans them up. If the solution is closed and reopened after a clean,
and no build has taken place since the clean, the input files will be missing!</p>
<p>For now, a reasonable workaround is simply not to incrementally clean generated
files, and I’ve updated my original post with this. As long as you regenerate
and collect the generated files correctly, skipping cleaning them shouldn’t
cause any problems except wasting a tiny bit of disk space.</p>Mikayla HutchinsonA couple of weeks ago I was helping Jason Smith debug an issue with the build-time code generation in Xamarin.Forms. The build targets were based on my Build Time Code Generation in MSBuild post, but in recent Visual Studio 2015 versions the generated classes would occasionally disappear from IntelliSense.Some Changes Around Here2016-03-08T00:00:00+00:002016-03-08T00:00:00+00:00https://mhut.ch/journal/2016/03/08/some-changes-around-here<p>I’d like to make a brief announcement. I’m coming out as transgender - I
identify as a woman, I am changing my name to Mikayla, and I am switching to
she/her/hers pronouns.<!--break--> Going forwards, I would like to ask people to
use my new name and female pronouns, and avoid using my old name and male
pronouns unless unavoidable.</p>
<p>I realize this may see like an abrupt change, but I’m still the same person, and
it shouldn’t really matter to other people. For those of you who want to know
more, I’ve posted <a href="/coming-out" rel="nofollow">a list of questions and answers</a>.</p>Mikayla HutchinsonI’d like to make a brief announcement. I’m coming out as transgender - I identify as a woman, I am changing my name to Mikayla, and I am switching to she/her/hers pronouns.Build Time Code Generation in MSBuild2015-06-30T00:00:00+00:002015-06-30T00:00:00+00:00https://mhut.ch/journal/2015/06/30/build-time-code-generation-in-msbuild<p>Build-time code generation is a really powerful way to automate repetitive parts
of your code. It can save time, reduce frustration, and eliminate a source of
copy/paste bugs.</p>
<p>This is something I’m familiar with due to my past work on MonoDevelop’s tooling
for ASP.NET, T4 and Moonlight, and designing and/or implementing similar systems
for Xamarin.iOS and Xamarin.Android. However, I haven’t seen any good
documentation on it, so I decided to write an article to outline the
basics.<!--break--></p>
<p>This isn’t just something for custom project types, it’s also something that you
can include in NuGets, since they can include MSBuild logic.</p>
<h2 id="background">Background</h2>
<p>The basic idea is to generate C# code from other files in the project, and
include it in the build. This can be to generate helpers, for example CodeBehind
for views (ASPX, XAML), or to process simple DSLs (T4), or any other purpose you
can imagine.</p>
<p>MSBuild makes this pretty easy. You can simply hook a custom target before the
<code class="language-plaintext highlighter-rouge">Compile</code> target, and have it emit a <code class="language-plaintext highlighter-rouge">Compile</code> item based on whatever input
items you want. For the purposes of this guide I’m going to assume you’re
comfortable with enough MSBuild to understand that - if you’re not, the <a href="https://msdn.microsoft.com/en-us/library/dd637714.aspx">MSDN
docs</a> are pretty good
for the basics.</p>
<p>The challenge is to include the generated C# in code completion, and update it
automatically.</p>
<p>An IDE plugin can do this fairly easily - see for example the <em>Generator</em>
mechanism used by T4, and the <code class="language-plaintext highlighter-rouge">*.designer.cs</code> file generated by the old Windows
Forms and ASP.NET designers. However, doing it this way has several downsides,
for example you have to check their output into source control, and they won’t
update if you edit files outside the IDE. Build-time generation, as used for
XAML, is a better option in most cases.</p>
<p>This article describes how to implement the same model used by
WPF/Silverlight/Xamarin.Forms XAML.</p>
<h2 id="generating-the-code">Generating the Code</h2>
<p>First, you need a build target that updates the generated files, emits them into
the intermediate output directory, and injects them to the <code class="language-plaintext highlighter-rouge">Compile</code>
<code class="language-plaintext highlighter-rouge">ItemGroup</code>. For the purposes of this article I’ll call it
<code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> and assume that it’s processing <code class="language-plaintext highlighter-rouge">ResourceFile</code> items and
emitting a file called <code class="language-plaintext highlighter-rouge">GeneratedCode.g.cs</code>. In a real implementation, you
should use unique names won’t conflict with other targets, items and files.</p>
<p>For example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Target</span> <span class="na">Name=</span><span class="s">"UpdateGeneratedFiles"</span>
<span class="na">DependsOnTargets=</span><span class="s">"_UpdateGeneratedFiles"</span>
<span class="na">Condition=</span><span class="s">="'@(ResourceFile)'</span> <span class="err">!=</span> <span class="err">''"</span>
<span class="nt">></span>
<span class="nt"><ItemGroup></span>
<span class="nt"><Compile</span> <span class="na">Include=</span><span class="s">"$(IntermediateOutputPath)GeneratedFile.g.cs"</span> <span class="nt">/></span>
<span class="c"><!-- see https://mhut.ch/journal/2016/04/19/msbuild_code_generation_vs2015
<FileWrites Include="$(IntermediateOutputPath)GeneratedFile.g.cs" />
--></span>
<span class="nt"></ItemGroup></span>
<span class="nt"></Target></span>
<span class="nt"><Target</span> <span class="na">Name=</span><span class="s">"_UpdateGeneratedFiles"</span>
<span class="na">Inputs=</span><span class="s">"$(MSBuildProjectFile);@(ResourceFile)"</span>
<span class="na">Outputs=</span><span class="s">"$(IntermediateOutputPath)GeneratedFile.g.cs"</span>
<span class="nt">></span>
<span class="nt"><FileGenerationTask</span>
<span class="na">Inputs=</span><span class="s">"@(ResourceFile)"</span>
<span class="na">Output=</span><span class="s">"$(IntermediateOutputPath)GeneratedFile.g.cs"</span>
<span class="nt">></span>
<span class="nt"></Target></span>
</code></pre></div></div>
<p>A quick breakdown:</p>
<p>The <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> target runs if you have any <code class="language-plaintext highlighter-rouge">ResourceFile</code> items. It
injects the generated file into the build as a <code class="language-plaintext highlighter-rouge">Compile</code> item, and also injects
a <code class="language-plaintext highlighter-rouge">FileWrites</code> item so the file is recorded for incremental clean. It depends on
the ‘real’ generation target, <code class="language-plaintext highlighter-rouge">_UpdateGeneratedFiles</code>, so that the file is
generated before the <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> target runs.</p>
<p>The <code class="language-plaintext highlighter-rouge">_UpdateGeneratedFiles</code> target has <code class="language-plaintext highlighter-rouge">Inputs</code> and <code class="language-plaintext highlighter-rouge">Outputs</code> set, so that it is
incremental. The target will be skipped if the output file exists is newer than
all of the input files - the project file and the resource files.</p>
<p>The project file is included in the inputs list because its write time will
change if the list of resource files changes.</p>
<p>The <code class="language-plaintext highlighter-rouge">_UpdateGeneratedFiles</code> target simply runs a tasks that generates the output
file from the input files.</p>
<p>Note that the generated file has the suffix <code class="language-plaintext highlighter-rouge">.g.cs</code>. This is the convention for
built-time generated files. The <code class="language-plaintext highlighter-rouge">.designer.cs</code> suffix is used for user-visible
files generated at design-time by the designer.</p>
<h2 id="hooking-into-the-build">Hooking into the Build</h2>
<p>The <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> target is added to the dependencies of the <code class="language-plaintext highlighter-rouge">CoreCompile</code> target by prepending it to the <code class="language-plaintext highlighter-rouge">CoreCompileDependsOn</code> property.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><PropertyGroup></span>
<span class="nt"><CoreCompileDependsOn></span>UpdateGeneratedFiles;$(CoreCompileDependsOn)<span class="nt"></CoreCompileDependsOn></span>
<span class="nt"></PropertyGroup></span>
</code></pre></div></div>
<p>This means that whenever the the project is compiled, the generated file is
generated or updated if necessary, and the injected <code class="language-plaintext highlighter-rouge">Compile</code> item is injected
before the compiler is called, so is passed to the compiler - though it never
exists in the project file itself.</p>
<h2 id="live-update-on-project-change">Live Update on Project Change</h2>
<p>So how do the types from the generated file show up in code completion before
the project has been compiled? This takes advantage of the way that Visual
Studio initializes its in-process compiler that’s used for code completion.</p>
<p>When the project is loaded in Visual Studio, or when the project file is
changed, Visual Studio runs the <code class="language-plaintext highlighter-rouge">CoreCompile</code> target. It intercepts the call to
the compiler via a host hook in the the MSBuild <code class="language-plaintext highlighter-rouge">Csc</code> task and uses the file
list and arguments to initialize the in-process compiler.</p>
<p>Because <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> is a dependency of <code class="language-plaintext highlighter-rouge">CoreCompile</code>, this means that
the generated file is updated before the code completion system is initialized,
and the injected file is passed to the code completion system.</p>
<p>Note that the <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> target has to be fast, or it will add
latency to code completion availability when first loading the project or after
cleaning it.</p>
<h2 id="live-update-on-file-change">Live Update on File Change</h2>
<p>So, the generated code is updated whenever the project changes. But what happens when the contents of the <code class="language-plaintext highlighter-rouge">ResourceFile</code> files that it depends on change?</p>
<p>This is handled via Generator metadata on each of the <code class="language-plaintext highlighter-rouge">ResourceFile</code> files:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><ItemGroup></span>
<span class="nt"><ResourceFile</span> <span class="na">Include=</span><span class="s">"Foo.png"</span><span class="nt">></span>
<span class="nt"><Generator></span>MSBuild:UpdateGeneratedFiles<span class="nt"></Generator></span>
<span class="nt"></ResourceFile></span>
<span class="nt"></ItemGroup></span>
</code></pre></div></div>
<p>This takes advantage of another Visual Studio feature. Whenever the file is
saved, VS runs the <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> target. The code completion system
detects the change to the generated file and reparses it.</p>
<p>This metadata has to be applied to the items by the IDE (or the user). It may be
possible for the build targets to apply it automatically using an
<code class="language-plaintext highlighter-rouge">ItemDefinitionGroup</code> but I haven’t tested whether VS respects this for
<code class="language-plaintext highlighter-rouge">Generator</code> metadata.</p>
<h2 id="xamarin-studiomonodevelop">Xamarin Studio/MonoDevelop</h2>
<p>But we have another problem. What about Xamarin Studio/MonoDevelop?</p>
<p>Although Xamarin Studio respects <code class="language-plaintext highlighter-rouge">Generator</code> metadata, it doesn’t have an
in-process compiler. It doesn’t run <code class="language-plaintext highlighter-rouge">CoreCompile</code>, nor does it intercept the
<code class="language-plaintext highlighter-rouge">Csc</code> file list, so its code completion system won’t see the generated file at
all.</p>
<p>The solution - for now - is to add explicit support in a <a href="/addinmaker">Xamarin Studio
addin</a> to run the <code class="language-plaintext highlighter-rouge">UpdateGeneratedFiles</code> target on
project load and when the resource files change, parse the generated file and
inject it into the type system directly.</p>
<h2 id="migration">Migration</h2>
<p>Migrating automatically from a designer-generation system to a build-generation
system has a few implications.</p>
<p>You either have to force migration of the project to the new system via an IDE,
or handle the old system and make the migration optional - e.g. toggled by the
presence of the old files. You have to update the project templates and samples,
and you have to build a migration system that removes the designer files from
the project and adds Generator metadata to existing files.</p>Mikayla HutchinsonBuild-time code generation is a really powerful way to automate repetitive parts of your code. It can save time, reduce frustration, and eliminate a source of copy/paste bugs. This is something I’m familiar with due to my past work on MonoDevelop’s tooling for ASP.NET, T4 and Moonlight, and designing and/or implementing similar systems for Xamarin.iOS and Xamarin.Android. However, I haven’t seen any good documentation on it, so I decided to write an article to outline the basics.MonoDevelop.AddinMaker 1.22015-03-12T00:00:00+00:002015-03-12T00:00:00+00:00https://mhut.ch/journal/2015/03/12/monodevelop-addinmaker-1-2<p>I’ve finally released <a href="/addinmaker/1.2">MonoDevelop.AddinMaker</a>,
making it easier than ever before to customize and add features to Xamarin
Studio and MonoDevelop. This release has been stalled for a while due to factors
beyond my control, and I’m very happy to be able to make it available at
last.<!--break--> Thanks to <a href="https://twitter.com/slluis">Lluis</a> for getting rid
of the roadblocks!</p>
<p>This release improves the basic user experience by introducing the concept of
“Addin References”. Instead of referencing an addin’s assemblies and explicitly
adding a dependency on that addin, you can add an addin reference, which will
automatically take care of both of these things for you.</p>
<p>However, the most important changes are below the surface. Switching to the
MSBuild engine allows you to use custom MSBuild syntax to customize your build
process, and enables command-line builds via MSBuild/xbuild. More importantly,
it provides a solid foundation on which to build future improvements.</p>
<p>Happy extending!</p>Mikayla HutchinsonI’ve finally released MonoDevelop.AddinMaker, making it easier than ever before to customize and add features to Xamarin Studio and MonoDevelop. This release has been stalled for a while due to factors beyond my control, and I’m very happy to be able to make it available at last.Razor Preprocessed Templates2012-12-08T00:00:00+00:002012-12-08T00:00:00+00:00https://mhut.ch/journal/2012/12/08/razor-preprocessed-templates<p>When <a href="https://twitter.com/migueldeicaza">Miguel</a> asked me to investigate making
MonoDevelop support using
<a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx">Razor</a>
templates in <a href="http://xamarin.com/monotouch">MonoTouch</a> and <a href="http://xamarin.com/monoforandroid">Mono for
Android</a> apps, I realized that it could be
done simply and with very few dependencies by taking the same approach as <a href="http://msdn.microsoft.com/en-us/library/ee844259.aspx">T4
preprocessed templates</a>,
which I implemented for MonoDevelop a couple of years ago.<!--break-->
Fortunately, this time the hard part was already done: I could use <a href="http://aspnetwebstack.codeplex.com">Microsoft’s
open-source Razor parser</a> instead of writing
my own parser. I also found a Visual Studio extension called <a href="http://razorgenerator.codeplex.com">Razor
Generator</a> that was very close in
functionality to what I wanted, and was able to use this as a basis for my work.
I was able to hook it it into the fantastic Razor editing and code completion
support written by <a href="http://pdowgiallo.pl/gsoc/">Piotr Dowgiallo</a> in the Google
Summer of Code this year.</p>
<p>After a few days work implementing, tweaking and tuning (and bouncing ideas off
<a href="https://twitter.com/bojanrajkovic">Bojan Rajković</a>), I present Razor
Preprocessed Templates in MonoDevelop.</p>
<p>As a basis for this demo, I created new a MonoTouch iPhone Single View
application, added a UIWebView to the View’s xib, and connected it to an outlet
on the controller called <code class="language-plaintext highlighter-rouge">csharpwebview</code>. However, you can use these templates
in any project type.</p>
<p>Just add a new <em>Text Templating -> Preprocessed Razor Template</em> file to the project:</p>
<p><img src="/files/images/MonoScreenshots/PreprocessedRazor-1-NewFile.png" alt="Adding a new Preprocessed Razor Template" /></p>
<p>You will see that this adds a cshtml Razor C# file to the project, grouped with
a C# file that contains the generated code. Like T4 files, this uses the “custom
tool” extensibility mechanism. By setting the custom tool property on the
<code class="language-plaintext highlighter-rouge">cshtml</code> file set to “RazorTemplatePreprocessor”, it causes MonoDevelop to use
this new custom tool to regenerate the <code class="language-plaintext highlighter-rouge">cs</code> file whenever the <code class="language-plaintext highlighter-rouge">cshtml</code> file is
saved.</p>
<p><img src="/files/images/MonoScreenshots/PreprocessedRazor-2-AddedFile.png" alt="The files added by the Preprocessed Razor Template" /></p>
<p>I wrote a simple Razor page to demonstrate the power of Razor. It uses a simple
Razor helper to demonstrate that Razor helpers work correctly. The page also
demonstrates using the <code class="language-plaintext highlighter-rouge">@model</code> directive to specify the type for a Model
property, which easily allows us to pass data into the template before running
it. Since this demo is very simple, I just used an <code class="language-plaintext highlighter-rouge">int</code> as the model instead of
defining a proper model class.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">@model</span> <span class="kt">int</span>
<span class="n">@helper</span> <span class="nf">boldtd</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="p"><</span><span class="n">td</span><span class="p">><</span><span class="n">b</span><span class="p">></span><span class="n">@i</span><span class="p"></</span><span class="n">b</span><span class="p">></</span><span class="n">td</span><span class="p">></span>
<span class="p">}</span>
<span class="p"><</span><span class="n">html</span><span class="p">></span>
<span class="p"><</span><span class="n">head</span><span class="p">></span>
<span class="p"><</span><span class="n">title</span><span class="p">></span><span class="n">Multiplication</span> <span class="n">Table</span><span class="p"></</span><span class="n">title</span><span class="p">></span>
<span class="p"></</span><span class="n">head</span><span class="p">></span>
<span class="p"><</span><span class="n">body</span><span class="p">></span>
<span class="p"><</span><span class="n">h1</span><span class="p">></span><span class="n">Multiplication</span> <span class="n">Table</span><span class="p"></</span><span class="n">h1</span><span class="p">></span>
<span class="p"><</span><span class="n">table</span><span class="p">></span>
<span class="err">@</span><span class="p">*</span> <span class="n">Header</span> <span class="n">row</span> <span class="p">*</span><span class="err">@</span>
<span class="p"><</span><span class="n">tr</span><span class="p">></span>
<span class="p"><</span><span class="n">td</span><span class="p">/></span>
<span class="nf">@for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span> <span class="p"><=</span> <span class="n">Model</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span> <span class="p">{</span>
<span class="nf">@boldtd</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="p">}</span>
<span class="p"></</span><span class="n">tr</span><span class="p">></span>
<span class="err">@</span><span class="p">*</span> <span class="n">Main</span> <span class="n">table</span> <span class="p">*</span><span class="err">@</span>
<span class="nf">@for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span> <span class="p"><=</span> <span class="n">Model</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span> <span class="p">{</span>
<span class="p"><</span><span class="n">tr</span><span class="p">></span>
<span class="nf">@boldtd</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="nf">@for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span> <span class="n">j</span> <span class="p"><=</span> <span class="n">Model</span><span class="p">;</span> <span class="n">j</span><span class="p">++)</span> <span class="p">{</span>
<span class="p"><</span><span class="n">td</span><span class="p">></span><span class="err">@</span><span class="p">(</span><span class="n">j</span> <span class="p">*</span> <span class="n">i</span><span class="p">)</</span><span class="n">td</span><span class="p">></span>
<span class="p">}</span>
<span class="p"></</span><span class="n">tr</span><span class="p">></span>
<span class="p">}</span>
<span class="p"></</span><span class="n">table</span><span class="p">></span>
<span class="p"></</span><span class="n">body</span><span class="p">></span>
<span class="p"></</span><span class="n">html</span><span class="p">></span>
</code></pre></div></div>
<p>When writing this, the Razor code completion was very helpful. It has full C#
completion, including locals, helpers and members from the generated class and
base class, including the generated <code class="language-plaintext highlighter-rouge">Model</code> property:</p>
<p><img src="/files/images/MonoScreenshots/PreprocessedRazor-3-CSharpBaseCompletion.png" alt="Code completion for C# in Razor Templates" /></p>
<p>There’s also HTML completion and on-the-fly underlining of HTML and Razor errors:</p>
<p><img src="/files/images/MonoScreenshots/PreprocessedRazor-4-HtmlCompletion.png" alt="Code completion and error underlining for HTML in Razor Templates" /></p>
<p>After saving the <code class="language-plaintext highlighter-rouge">cshtml</code> file, you can look at the generated <code class="language-plaintext highlighter-rouge">cs</code> file. It’s
pretty messy, so I won’t show it here, but note that it includes a
well-commented generated base class. If you want, you can specify a base class
using the <code class="language-plaintext highlighter-rouge">@inherits</code> directive, so you can pull that generated base class out
and share it between multiple templates, or customize it. The template’s only
dependency is <code class="language-plaintext highlighter-rouge">Action<System.IO.TextWriter></code>, and the default base class’s
dependencies are only <code class="language-plaintext highlighter-rouge">System.Web.HttpUtility.HtmlEncode(string)</code> and
<code class="language-plaintext highlighter-rouge">System.IO.StringWriter</code>, so it can easily be made to run anywhere. If your
target framework lacks the one potentially awkward dependency,
<code class="language-plaintext highlighter-rouge">HttpUtility.HtmlEncode(string)</code>, you can provide an alternative implementation
via a custom base class.</p>
<p>More documentation on the generated class and the available directives can be
found <a href="http://monodevelop.com/Documentation/Preprocessed_Razor_Templates">on the MonoDevelop
website</a>.</p>
<p>To use the template, I simply added two lines to my <code class="language-plaintext highlighter-rouge">ViewDidLoad</code> method to
instantiate the template, generate a string using the <code class="language-plaintext highlighter-rouge">Generate()</code> method, and
load it into the <code class="language-plaintext highlighter-rouge">UIWebView</code>:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">ViewDidLoad</span> <span class="p">()</span>
<span class="p">{</span>
<span class="k">base</span><span class="p">.</span><span class="nf">ViewDidLoad</span> <span class="p">();</span>
<span class="kt">var</span> <span class="n">template</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MultiplicationTable</span> <span class="p">()</span> <span class="p">{</span> <span class="n">Model</span> <span class="p">=</span> <span class="m">12</span> <span class="p">};</span>
<span class="n">webview</span><span class="p">.</span><span class="nf">LoadHtmlString</span> <span class="p">(</span><span class="n">template</span><span class="p">.</span><span class="nf">GenerateString</span> <span class="p">(),</span> <span class="k">null</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Then run the app, and you can see it in action:</p>
<p><img src="/files/images/MonoScreenshots/PreprocessedRazor-5-RunningOnPhone.png" alt="Razor Template running on iPhone" /></p>
<p>This is a fantastic way to generate HTML pages without pulling in the whole
System.Web stack, and I hope you’re as excited about it as I am. It isn’t
available today, unless you build MonoDevelop from source, however the code is
committed to <a href="http://github.com/monodevelop">MonoDevelop master</a> and should make
it into the next 3.x release.</p>Mikayla HutchinsonWhen Miguel asked me to investigate making MonoDevelop support using Razor templates in MonoTouch and Mono for Android apps, I realized that it could be done simply and with very few dependencies by taking the same approach as T4 preprocessed templates, which I implemented for MonoDevelop a couple of years ago.The State of MSBuild Support in MonoDevelop2012-08-19T00:00:00+00:002012-08-19T00:00:00+00:00https://mhut.ch/journal/2012/08/19/the-state-of-msbuild-support-in-monodevelop<p>I occasionally get questions about support for advanced MSBuild features, and my
answers are usually fairly short. This post aims to be a more comprehensive
description of the current state state of MSBuild support in MonoDevelop, so I
can refer people to it. If you’ve never hand-edited custom targets for an
MSBuild file, this doesn’t affect you at all, but feel free to read it if you’re
curious.<!--break--></p>
<p><a href="http://msdn.microsoft.com/en-us/library/dd393574"">MSBuild</a> is the
Microsoft build engine that was introduced with .NET 2.0 and Visual Studio 2005.
It’s the format for the project files of Visual Studio 2005 and later, and has
been MonoDevelop’s default/native file format since MonoDevelop 2.0. It’s
XML-based, so it can be handled easily and reliably by tools such as IDEs. It’s
essentially intended to be consumed primarily by IDEs — but it also has
the power of an advanced, extensible build system that lets you do pretty much
anything if you’re willing to get your hands dirty. Calling it “Makefiles in
XML” wouldn’t be too far off the mark.</p>
<p>The MSBuild engine and hosting API are part of the .NET framework. Mono has its
own implementation called xbuild, which runs on Mac, Linux and Windows. The core
features of xbuild are solid, but it’s missing some of the advanced features
added to MSBuild in .NET 3.5 and 4.0, and some of the common targets such as the
ASP.NET web project targets.</p>
<p>MSBuild is extremely complex and exposing all its features in the MonoDevelop
GUI would be practically impossible. However, the projects created by the IDE by
default use the “common targets” to build the project, which understand a
certain number of properties (e.g. “OutputPath”) and item types (e.g. “Compile”,
“EmbeddedResource”), and implement certain targets (e.g. “Build”, “Clean”) that
operate on these items and are controlled by these properties. They also make
very limited use of conditions, by conventionally having several groups of
properties conditional upon the value of the “Configuration” and “Platform”
variables. To edit projects that haven’t been hand-modified, the IDE only really
has to understand the item types, properties, and targets used by the common
targets.</p>
<p>MonoDevelop has an internal project model that represents the projects and their
properties and items. When loading the project, MD deserializes the MSBuild file
into its internal model, and ignores the items, properties and imports it does
not understand. When saving MSBuild projects, MD serializes its internal model
into the MSBuild format and substitutes them for the parts of the MSBuild file
it understood, thereby preserving the parts of the file that it did not
understand: custom items, properties, targets, conditions, and imports.</p>
<p>There are a couple of things the serialization doesn’t handle — when
hand-edited projects use properties or items as <em>values</em> of any of the standard
properties or items. MonoDevelop does not evaluate these — doing so would
require a full MSBuild engine — and even if it did, it would not easily be
able to present them cleanly in the UI and serialize back any changes to the
values. It might be possible to special-case some things, but it’s not something
that can be fully solved in a generic way. Probably the best we could get would
be to have MonoDevelop detect property/item values it cannot handle, evaluate
them via the MSBuild engine when loading, make them non-editable with a warning
flag in the Project Options GUI, and skip them when serializing.</p>
<p>Wildcards in items paths are a similar problem. For example, evaluating a
wildcard in an item when deserializng would result in adding several items to
MD’s internal model. And in simple cases, we could match all those items back to
the wildcard MSBuild item when serializing. So far so good. But what happens if
a new file is added on disk outside of MD while the project is open? What
happens if the user manually removed a single item in the solution tree? What
happens if the user changes the metadata of a single item? In all of these
cases, the items can no longer be mapped back to the single wildcard MSBuild
item. It would probably be possible to remove the wildcard item and serialize
all the items to MSBuild individually — but that might not be what the
user expected. This is just one example of how supporting a simple MSBuild
feature in the IDE might not be as simple as it looks.</p>
<p>For building the projects, MonoDevelop’s story is much better, because it has
the ability to build the projects using the actual MSBuild/xbuild engine,
thereby supporting all features that MSBuild/xbuild does. There are currently
two build codepaths in MonoDevelop: the old internal build engine, and the
MSBuild engine. The internal build engine is very old, and predates the
existence of MSBuild. It operates directly on MonoDevelop’s internal project
model, and is extensible via the addin system. The MSBuild engine loads the
actual project files into a builder process and builds them using the MSBuild
hosting API.</p>
<p>By default MonoDevelop uses the old engine, but the addins for individual
project types can opt into using the MSBuild engine for just those projects
— Mono for Android does this. Enabling the experimental option “Compile
projects using MSBuild/XBuild” in MonoDevelop’s preferences (and restarting
MonoDevelop) causes the MSBuild engine to be used for all projects. This is
marked experimental because it does not work for all project types — for
example, there are no MSBuild targets for MonoTouch, MonoMac or ASP.NET projects
yet. User projects that depend on MonoDevelop’s old custom build command system
will not build correctly with the MSBuild engine. And some of the old
MonoDevelop custom project types such as translation projects and C/C++ projects
would need to be migrated to a new file format before they could even have
MSBuild targets.</p>
<p>In general, expansion of the MSBuild support in MonoDevelop is not a high
priority for the MonoDevelop team, since these advanced build features are of
interest to a very small subset of users, and there are other things that could
be done to improve the IDE experience for a much greater number of users.
However, it’s an area of ongoing improvement and will likely become more
important in the future.</p>Mikayla HutchinsonI occasionally get questions about support for advanced MSBuild features, and my answers are usually fairly short. This post aims to be a more comprehensive description of the current state state of MSBuild support in MonoDevelop, so I can refer people to it. If you’ve never hand-edited custom targets for an MSBuild file, this doesn’t affect you at all, but feel free to read it if you’re curious.MonoMac video from NDC 20112011-06-26T00:00:00+00:002011-06-26T00:00:00+00:00https://mhut.ch/journal/2011/06/26/monomac-video-from-ndc-2011<p>The videos from NDC 2011 are <a href="http://www.ndc2011.no/agenda.aspx?cat=1071&id=-1&day=3728">now
online</a>, including my
talk <em>Developing .NET Applications for the Mac App Store</em> (<a href="http://ndc2011.macsimum.no/SAL4/Fredag/Live%20stream%20archive%2010.06.2011%2014.58.wmv">direct
link</a>).<!--break-->
You can also download a printable version of <a href="/files/talks/MonoMac-NDC11.pdf">my
presentation</a>. Hopefully there will be an
official torrent of the videos soon, because there were plenty of other sessions
that are worth seeing. Thanks to everyone who helped make it such a great
conference!</p>
<p><em>Correction: In the presentation I said that native objects don’t retain
references to managed objects, which is incorrect. The problem I intended to
refer to is a common coding error where views are retained but their controllers
are not, e.g. <code class="language-plaintext highlighter-rouge">mainView.AddSubview(new ChildController().View)</code>.</em></p>Mikayla HutchinsonThe videos from NDC 2011 are now online, including my talk Developing .NET Applications for the Mac App Store (direct link).