I’ve updated the Random Lipsums group in the TextExpander Tools. Again. I removed some services that weren’t working any more, and expanded some of the other tools. The biggest new addition is a Random Markdown generator, complete with tables, definition lists, footnotes and more. It’s perfect for testing stylesheets and, if you happen to develop a Markdown preview app, it’s also perfect for testing various processors. There are also versions included in the snippet group that include Maruku for going straight to HTML.

The two versions of the snippets are based on Alice in Wonderland and 1984 (quite hilarious when mixed together1), using the raingrams Ruby gem to slice and dice local text files. You can grab a copy of the source files I use, or find your own substitutes at Project Gutenberg. The two text files need to be located in a “words” directory off of your home folder (~/words/inputtext.txt and ~/words/alice.txt).

To install raingrams and maruku, type this in Terminal:

sudo gem install raingrams maruku

It should install for you without issue. Once that successfully completes and you have the text files in place, the Snippets will generate random and often hilarious text for you.

Here’s the script (Mavericks-compatible), which can also be used as a standalone for creating text with a Service or from the command line. It’s a little brute force in some areas, but it’s dependable.

randommarkdown.rbraw
#!/usr/bin/ruby
# Generates a bunch of random Markdown text (with footnotes/tables)
# REQUIREMENTS:
# raingrams gem ([sudo] gem install raingrams)
# a text file at ~/words/alice.txt containing lots of words
# I recommend using mine from http://ckyp.us/kZWQ

require 'rubygems'
require 'raingrams'

include Raingrams

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

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

@model.refresh

# generates a paragraph with random sentences
# min = minimum sentences
# max = maximum sentences
def graf(min,max,footnote=false)
  # 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)"
  if footnote
    return para.join(' ') + "[^#{footnote}]\n\n[^#{footnote}]: " + sentence(10,20) + "\n\n"
  else
    return para.join(' ') + "\n\n"
  end
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"
end

def block(type,min,max)
    block = ''
    prefix = type == "quote" ? "> " : "     "
    (rand(max-min) + min).times do
        block += prefix + sentence(10,15) + "\n"
    end
    block + "\n\n"
end

def deflist(min, max)
  list = ""
  (rand(max-min) + min).times do
    list += sentence(3,6) + "\n"
    list += ": " + sentence(10,20) + "\n\n"
  end
  list
end

def table(width,rows)
  table = "|"
  headers = sentence(width -1 ,width -1).split(" ")
  counter = 0
  while counter < width do
    if headers
      table += "#{headers.pop}|"
    else
      table += "|"
    end
    counter += 1
  end
  table += "\n|"
  width.times do
    table += ":-----:|"
  end
  table += "\n"
  rows.times do
    cells = sentence(width,width).split(/\s/)
    width.times do
      if cells.length > 0
        table += cells.pop + "|"
      else
        table += "|"
      end
    end
    table += "\n"
  end
  table + "\n\n"
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)
end
# Level 2 headline
o += "## " + sentence(4,7) + "\n\n"
# 1 short paragraph with footnote
o += graf(2,4,"fn1")
# an unordered list
o += list('ul',5,8)
# 1 more long paragraph
o += graf(6,8)
# image
o += "![dummy][img1]\n\n[img1]: http://placekitten.com/400/300\n\n"
# Level 3 header
o += "### " + sentence(5,9) + "\n\n"
# table
o += table(rand(5) + 3,rand(10) + 5)
# medium paragraph
o += graf(4,6)
# blockquote
o += block('quote', 2, 3)
# ordered list
o += list('ol',5,8)
# another graf with footnote
o += graf(3,5,"fn2")
# hr
o += "\n---\n\n"
# code block
o += block('code', 5, 7)
# sentence
o += sentence(10,15)
# definition list
o += deflist(3,7)

print o

Pick up the TextExpander version on the TE-Snippets page and see what else is available on the TextExpander Tools project page.

  1. Filthy greenish water like this other people round abruptly. Actually he remember and hatching his nose and Big Brother the door closed down in time of solid-looking men with horror. Momentarily he KNEW. Down down down both sat down important as look like being upset and sneezing all moved off Beau ootiful Soo oop of bread-and butter But they COULD NOT SWIM you please. Stuff and once without considering how old fellow.