I know, I said I was done with the Lorem Ipsum generators. Then Dr. Drang responded with a brilliant solution which doesn’t require Internet access to generate some beautiful dummy text. I set it up and ran it myself, and loved the results. Then I found myself wanting to expand it to do more, such as multiple paragraphs, list items and other things I use regularly when making dummy layouts. The problem is that I’m only good for one-liners in Perl, and didn’t want to take take the time to learn what I needed to in order to make the modifications. So I redid it in Ruby.1

I used a Gem called Raingrams, along with Maruku for processing Markdown to HTML. See, if I had it output Markdown to begin with, I had the flexibility to do both easily. I’m posting the main script, which you can modify to output various elements and amounts of text. Even if you don’t know ruby, you can probably find your way around with a little guessing. In the section after the function definitions you can take any of the lines and output what you want by mixing or removing those elements.

This script requires Rubygems, and the Raingrams and Maruku gems. If you have Rubygems installed, you can just type sudo gem install raingrams and sudo gem install maruku at the command line to quickly get both on your system. If you don’t have Rubygems, you might want to skip this one, as you’re in for more trouble than this will pay off…

You’ll also need a text file to pull from. I’m using a chopped up version of 1984, with just enough paragraphs to get some good randomness. You can find it here, if you want it. Otherwise, choose your favorite text file and make it long enough to be random and short enough to be fast. That might take some experimentation. Put the text in a file called inputtext.txt in a directory called words in the root of your home folder. The final path should look like /Users/[YOUR USER NAME]/words/inputtext.txt.

The big script

The script should have enough comments to make it relatively easy to dissect and rebuild as a TextExpander snippet for any individual part of it.

#!/usr/bin/env ruby -rjcode -Ku

require 'rubygems'
require 'raingrams'
require 'maruku'

include Raingrams

# All (min,max) pairs need max > min

@model = BigramModel.build do |model|
  model.train_with_text File.new(File.expand_path('~/words/inputtext.txt'),'r').read
end

@model.refresh

# generates a paragraph with random sentences
# min = minimum sentences
# max = maximum sentences
def graf(min,max) 
  # grab the paragraph and split it into words
  para = @model.random_paragraph({:min_sentences => min,:max_sentences => max }).split(' ')
  # add a random italics element
  em = (rand(para.count - 10) + 10)
  para[em] = "*#{para[em]}*"
  # add a random bold element
  strong = (rand(para.count - 10) + 10)
  # make sure they don't overlap
  strong = strong - 2 if strong == em
  para[strong] = "**#{para[strong]}**"
  # add a multi-word link
  link = (rand(para.count - 10) + 10)
  linkend = link + (rand(6) + 2)
  para[link] = "[#{para[link]}"
  para[linkend] = "#{para[linkend]}](http://dummy.com)"
  return para.join(' ')
end

# returns a random sentence, used in headlines
# min = minumum words, max = max words
def sentence(min,max) 
  return @model.random_sentence.split(' ')[0..(rand(max - min)+min)].join(' ')
end

# returns a random list
# type = ul or ol
# min = minimum number of list items
# max = maximum number of list items
def list(type,min,max)
  list = '';
  prefix = type == "ol" ? " 1. " : " * "
  (rand(max - min) + min).times do
    list += prefix + @model.random_gram.to_s + "\n"
  end
  list += "\n\n"
  return list
end

# Sequentially builds an output variable (o)
# Chop this apart to make snippets as needed

# Level 1 headline
o = "# " + sentence(2,5) + "\n\n"
# 2 medium paragraphs
2.times do
  o += "#{graf(4,6)}\n\n"
end
# Level 2 headline
o += "## " + sentence(4,7) + "\n\n"
# 1 short paragraph
o += graf(2,4) + "\n\n"
# an unordered list
o += list('ul',5,8) + "\n\n"
# 1 more long paragraph
o += graf(6,8) + "\n\n"
# Level 3 header
o += "### " + sentence(5,9) + "\n\n"
# medium paragraph
o += graf(4,6) + "\n\n"
# ordered list
o += list('ol',5,8) + "\n\n"

# Process Markdown to HTML

# if you want just the Markdown
# delete the two lines below
# and replace with 'puts o'
doc = Maruku.new(o)
puts doc.to_html.gsub(/\/li>\n/,'/li>').gsub(/\/li><\/([uo])l/,"/li>\n</\\1l")
# the gsub is just to clean up maruku's double-spaced list output

Here’s some sample output, generated in nvALT, using TextExpander with this script as a shell Snippet, and posted to Peggd. As you can see, it needs some fine tuning. The list items, strong and em could be multi-word, the links could check to see if there was a period-space-capital and prevent overlapping sentences, etc. It’s enough for my purposes, though, and between the script and this post, I’ve lost over an hour of what was supposed to be a productive weekend. I’m out!

  1. This isn’t a one-up on Dr. Drang; it’s a rough script, and I’m just posting what I wasted half an hour on last night.