Vim — :TOhtml & Customization

When I first started this blog, I was surprised (and disappointed) that Google’s Blogger platform didn’t have some nice built-in feature for code formatting and syntax highlighting. I experimented with a number of third-party solutions, but didn’t find anything that I particularly liked, so my posts have had some ugly-looking code in them. Until now.

…Well, until my previous post, anyway.

A then-coworker told me a while back about vim’s :TOhtml feature, but it wasn’t until last night that I actually checked it out. As it turns out, it was just what I was looking for. Out of the box, it’s a little cumbersome for my purposes, but a little vim scripting helped a lot.

Default Behavior

To start, I set a few options in my .vimrc:

let html_use_css = 1 ” Use stylesheet instead of inline style
let html_number_lines = 0 ” don’t show line numbers
let html_no_pre = 1 ” don’t wrap lines in


I also choose a vim color scheme I like (wombat). You can look through examples of tons of schemes here. (I spent a while trying to figure out why I couldn’t set the color scheme (after I downloaded it to .vim/colors/), and the answer I found was that color schemes only work in gVim.)

So, having set some options in my .vimrc, and chosen a colorscheme in gVim, calling :TOhtml on

class Person
  attr_accessor :age

  def speak
    "Hi!"
  end

  def say_age
    "I am this many: #{| * @age}"
  end
end

gives:

http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>~/demo.rb.htmltitle>
    <meta name="Generator" content="Vim/7.2">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <style type="text/css">
      
    style>
  head>
  <body>
    <span class="PreProc">classspan> <span class="Type">Personspan><br>
      <span class="Statement">attr_accessorspan> <span class="Constant">:agespan><br>
    <br>
      <span class="PreProc">defspan> <span class="Function">speakspan><br>
        <span class="Special">"span><span class="String">Hi!span><span class="Special">"span><br>
      <span class="PreProc">endspan><br>
    <br>
      <span class="PreProc">defspan> <span class="Function">say_agespan><br>
        <span class="Special">"span><span class="String">I am this many: span><span class="Special">#{span><span class="Special">span><span class="String">|span><span class="Special">span> * <span class="Identifier">@agespan><span class="Special">}span><span class="Special">"span><br>
      <span class="PreProc">endspan><br>
    <span class="PreProc">endspan><br>
  body>
html>


That’s pretty good. If your goal was a stand-alone HTML file you’d be done, but for paste-ready output we need a little vim scripting help.

Altered Behavior

Instead of wrapping the output in a full html page, I really just want it wrapped in a div. I also want to strip out some “extra” (according to Blogger’s HTML interpreter) line breaks, and pull out the CSS definitions (for later). To accomplish this, I’ve put together a simple vim script, which defines a new method :DivHtml

function! DivHtml(line1, line2)
  exec a:line1.‘,’.a:line2.‘TOhtml’
  %g/<style/normal $dgg
  %s/

nn//
  %s/.vim_block {/.vim_block {/
  %s/(.*)>n/

1>/
  %s/n/</div>
  %s/
//g

  set nonu
endfunction
command range=% DivHtml :call DivHtml(<line1>,<line2>)

Now, calling :DivHtml on the ruby code above gives code I can just cut & paste into the ‘Edit Html’ Blogger window:


.Identifier { color: #cae682; }
.Type { color: #cae682; }
.Statement { color: #8ac6f2; }
.Constant { color: #e5786d; }
.Function { color: #cae682; }
.Special { color: #e7f6da; }
.String { color: #95e454; font-style: italic; }
.vim_block { color: #f6f3e8; background-color: #242424; font-family: monospace; }
.PreProc { color: #e5786d; }
>
<div class="vim_block"><span class="PreProc">classspan> <span class="Type">Personspan>
    <span class="Statement">attr_accessorspan> <span class="Constant">:agespan>

    <span class="PreProc">defspan> <span class="Function">speakspan>
      <span class="Special">"span><span class="String">Hi!span><span class="Special">"span>
    <span class="PreProc">endspan>

    <span class="PreProc">defspan> <span class="Function">say_agespan>
      <span class="Special">"span><span class="String">I am this many: span><span class="Special">#{span><span class="Special">span><span class="String">|span><span class="Special">span> * <span class="Identifier">@agespan><span class="Special">}span><span class="Special">"span>
    <span class="PreProc">endspan>
  <span class="PreProc">endspan>
div>

(which renders as the ruby snippet I pasted above)

The only part of the process that is still kinda annoying is that you have to copy/paste the CSS into your header or external CSS file. Both :TOhtml and :DivHtml only output the CSS definitions for styles actually used in a snippet, so it’s up to the user to check if all the definitions in a new snippet are already in your layout, or if you need to add them. The alternative would be to use inline CSS (:help :TOhtml), but that’s ugly.

To finish things off, I gave the wrapping div the vim_block class, and gave that a background-color and border in my header, to make it look a little nicer. I also got rid of the “font-family: monospace” bit, because I thought it made the code hard to read.

Other than manually checking the CSS, it’s a very painless process to put code snippets on the blog, and I’m happy with the look and feel of them.

Published by

Patrick Schless

I'm a (mostly) ruby/rails developer, living in Chicago. I work at Braintree, and I have lots of side-projects.

9 thoughts on “Vim — :TOhtml & Customization”

  1. Very nice. One (minor) downside of using CSS vs. inline styles is that the coloration doesn't make it through to feed readers. But I'm used to viewing the original when code is present, so that isn't such a big deal.

  2. nevans — Thanks for the heads up about the indentation. I had written this post as I developed my vimrc, and the snippet in question actually had been generated with html_no_pre unset. For some reason, not setting that option means you won't get nbsp's for spaces (and the css doesn't manage indentation, either). I regenerated that snippet with the version of my vimrc represented in the post, and now it looks better 🙂

    As for the the lack of CSS in readers, I hear ya. I'm ok with it, though. I'm like you — if a post in Google Reader looks funky, I just click on the link.

  3. nevans — Oh, after regenerating the snippets, RSS readers now correctly show the indentation (because I'm now using nbsp's). It doesn't have colors, but I think it's much more readable now (with indentation) that it was before.

  4. I see a lot of interesting articles on your blog.
    You have to spend a lot of time writing, i know
    how to save you a lot of work, there is a tool that creates readable, google friendly articles in couple of minutes, just search in google – k2 unlimited content

  5. I read a lot of interesting content here. Probably you spend a lot of time
    writing, i know how to save you a lot of work, there is an online tool that creates
    high quality, google friendly articles in seconds, just search in google
    – laranitas free content source

Leave a Reply

Your email address will not be published. Required fields are marked *