Err the Blog Atom Feed Icon
Err the Blog
Rubyisms and Railities
  • “Cheat!”
    – Chris on September 01, 2006

    I’ve got this cheat sheet hanging on my wall. It’s for migrations. The Rails kind. It’s nice. I can never remember whether the method is add_column or create_column or what (it’s add_column btw). So, yeah. Todd’s got a bunch of TextMate ones hanging on his wall. Literally, like, four. And PJ? Don’t get me started.

    The thing is, I’m a command line junkie. I use vim and svn like many other Rubyists. I wish there was a way to pull up cheat sheets from my command line, but unfortunately most cheat sheets are distributed as images (or PDFs) and just so damn pretty.

    Until now.

    Imagine a world, if you will, of plain text cheat sheets accessible from any Ruby capable command line. That world is the Internet.

    sudo gem install cheat

    Try it out:

    $ cheat strftime

    wanstrathc@chrisw:~$ cheat strftime
    strftime:
        %a – The abbreviated weekday name (``Sun’‘)
        %A – The full weekday name (``Sunday’‘)
        %b – The abbreviated month name (``Jan’‘)
        %B – The full month name (``January’‘)
        %c – The preferred local date and time representation
        %d – Day of the month (01..31)
        %H – Hour of the day, 24-hour clock (00..23)
        %I – Hour of the day, 12-hour clock (01..12)
        %j – Day of the year (001..366)
        %m – Month of the year (01..12)
        %M – Minute of the hour (00..59)
        %p – Meridian indicator (``AM’’ or ``PM’‘)
        %S – Second of the minute (00..60)
        %U – Week number of the current year,
            starting with the first Sunday as the first
            day of the first week (00..53)
        %W – Week number of the current year,
            starting with the first Monday as the first
            day of the first week (00..53)
        %w – Day of the week (Sunday is 0, 0..6)
        %x – Preferred representation for the date alone, no time
        %X – Preferred representation for the time alone, no date
        %y – Year without a century (00..99)
        %Y – Year with century
        %Z – Time zone name
        % – Literal ``’’ character

    Oh man that feels good. TextMate, anyone?

    $ cheat strftime | mate

    See all the available cheat sheets:

    $ cheat sheets

    Hot damn. Where’s all this coming from, though? I’ll tell you.

    http://cheat.errtheblog.com

    I’ve setup a little Camping wiki with a YAML backend from which the cheat command line tool gets its power. It caches stuff locally, of course. If you update a cheat sheet on the wiki and you’re not seeing changes on the command line, pass cheat the --new option:

    $ cheat strftime --new

    Here’s a few of the first cheat sheets added:

    $ cheat assertions
    $ cheat bash
    $ cheat cheat
    $ cheat migrations
    $ cheat sprintf
    $ cheat strftime

    Please be kind to the wiki. And, uh, keep the cheat sheets Ruby-centric. Bash is okay but Python is banned.

    Thanks to Hank and Evan for help finding bugs and that kind of thing. Enjoy.

    Update:

    Or, you know, $ inflate cheat. It’s like a free trial version.

    The Windoze problems may or may not be fixed. Either way, there’s Cheat 1.0.1 on the gem server:

    $ sudo gem update cheat

    We’ve also got some new cheat sheets for you to consume:

    $ cheat iomodes
    $ cheat sti (single table inheritance)
    $ cheat validations

    Eric Anderson hacked a JEdit macro for Cheat. In Java, no less! Check it out in the comments. Where’s the TextMate Cheat macro, guys?

    And hey, Digg.

    Update 2: Ed Silva knocks it out of the park with his Cheat TextMate command.

    Steps:
    1. ctrl+alt+apple+b to open Bundle Editor
    2. Plus sign in the bottom left => New Command
    3. Name it Cheat.
    4. Put Ed’s code in the body
    5. Change the Output dropdown to Show as HTML
    6. Click on the Activation text field and hit ctrl+c (c for cheat!).

    That’s it. Highlight a word in TextMate and hit ctrl+c. Lovely.

    Evan Weaver, slayer of Indian Chiefs, wrote some smart plaintext wrapping now in use by Cheat. No more wrapping by hand!

    New gem with wrapping, 1.0.2:

    sudo gem update cheat

    Finally, new sheets are slowly popping up. Get ‘em before your teacher catches you:

    $ cheat deprecated (inspired by topfunky and Kevin Clark)
    $ cheat svn
    $ cheat wmii3 (you know about wmii3, surely)
    $ cheat environments (more lewt stolen from Kevin Clark)

    Oh yeah, we’ve got an RSS feed for recently updated cheat sheets making the rounds, too. That’ll help you figure out if you need --new.

  • evan, about 11 hours later:

    Don’t hate on Python. It will come silently in the night and indent you, and then you’ll be sorry.

  • Carl, about 11 hours later:

    This is SO COOL! Thank you tons!

  • Chris Carter, about 11 hours later:

    Hey, this is pretty cool! When can we expect the source code for the interface and for the backend?

  • Chris Carter, about 11 hours later:

    Oops, just found it. Nevermind that :)

  • yerejm, about 12 hours later:

    I had to change HOMEPATH in def sheets; end to HOME to make it work on win32. HOMEPATH doesn’t have the HOMEDRIVE which seems to make mkdir choke.

  • Chris Carter, about 12 hours later:

    Some line wrapping would be nice, dooing it by hand is ugly and hard.

  • Dr Nic, about 20 hours later:

    The ENV[‘HOMEPATH’] doesn’t seem to be the best ENV option (that is, it isn’t working :)

    HOMEPATH=\Documents and Settings\Nic Williams (note: no drive path)

    Alternatives: USERPROFILE=C:\Documents and Settings\Nic Williams

    Or combine: HOMEDRIVE=C: HOMEPATH=\Documents and Settings\Nic Williams

    Anyone have thoughts on which is best (and/or why HOMEPATH might be incorrect on my win32 laptop?)

    Nic

  • Dr Nic, about 20 hours later:

    Yeah, what yerejm said… :)

  • Chris Carter, about 23 hours later:

    I added a validations and a single_table_inheritcance one for all to enjoy.

  • Eric Anderson, 1 day later:

    I like to work at both the command line and in my text editor (JEdit). If you are using JEdit and want to access these cheat sheets right from your text editor I put together the following BeanShell script. It will execute the cheat command with the name you give it and put the output in a simple dialog box.

    My Java is quite rusty so this may not be the best implementation:

    String sheet = Macros.input(view, “Enter sheet name”); Process proc = Runtime.getRuntime().exec(“cheat “+sheet); BufferedReader output = new BufferedReader(new InputStreamReader(proc.getInputStream())); StringBuilder info = new StringBuilder(); while( (line = output.readLine()) != null ) { info.append(line+”\n”); } Macros.message(view, info.toString());

    Simply map this to a key command (I have it mapped to Ctrl-Shft-C) and you can quickly bring up your cheat sheet in Jedit.

  • Kent, 1 day later:

    Cool. What a nice idea!!!

  • John Nunemaker, 1 day later:

    These are flippin’ sweet. Absolutely a great idea. I can never remember strftime.

  • Chris Carter, 1 day later:

    Chris- I wrote up a blog post asking people to test the windows new windows cache code at (http://concentrationstudios.com/articles/2006/09/02/cheat-tests) I am going to try writing up some tests soon. At least I have some test stubs :)

  • TCS, 1 day later:

    Dugg! http://digg.com/programming/Ruby_Help_on_the_Command_Line

  • Dr Nic, 1 day later:

    v1.0.1 works great on Win32 now. Thx guys!

  • Ed Silva, 1 day later:

    Here’s a TextMate command I set up:

    word=${TM_SELECTED_TEXT:-$TM_CURRENT_WORD} echo “Cheat Sheet for $word

    ";
    /usr/local/bin/cheat $word;
    echo "
    ”;

  • Ed Silva, 1 day later:

    Ok, that got mangled. See my blog entry:

    http://weblogs.litmusgreen.com/ed/archives/002498.html

  • Dr Nic, 2 days later:

    Can you include the whole cheatsheet in the RSS feed?

  • Harriet, 3 days later:
    • What’s the password?
  • Chris, 3 days later:

    Harriet: The password is jalapeno.

    Dr Nic: Done!

  • Adam Sanderson, 4 days later:

    Very cool, I just scraped the relations docs for rails and dropped those in since I’m always lookin’ em up. Now to hook it up with TextMate (the one true $EDITOR)

  • Marius Popescu, 7 days later:

    Great stuff!

    Idea: would be nice to have an URL property for each cheat. Like where can we get the code. >cheat microformats_helper—url

  • blaine cook, 9 days later:

    Any reason it’s not up on rubyforge? appending that—source to the gem command line is way too much work :-p

  • Johannes, 9 days later:

    That’s cool!

  • zerohalo, 17 days later:

    Blaine, it’s on rubyforge. Just $gem install cheat :-)

  • nornagon, about 1 month later:
    --- /usr/lib/ruby/gems/1.8/gems/cheat-1.0.2/lib/cheat.rb        2006-10-04 16:23:11.000000000 +1000
    +++ cheat.rb    2006-10-15 12:24:49.000000000 +1000
    @@ -1,5 +1,5 @@
     $:.unshift File.dirname(__FILE__)
    -%w[rubygems fileutils net/http yaml open-uri wrap].each { |f| require f }
    +%w[rubygems tempfile fileutils net/http yaml open-uri wrap].each { |f| require f }
    
     module Cheat
       extend self
    @@ -19,6 +19,18 @@
           return if args.empty?
         end
    
    +    if (i = args.index('--add'))
    +      args.delete_at(i)
    +      add(args.shift)
    +      return
    +    end
    +
    +    edit = false
    +    if (i = args.index('--edit'))
    +      args.delete_at(i)
    +      edit = true
    +    end
    +
         sheet = args.shift
    
         cache_file = "#{cache_dir}/#{sheet}.yml" if cache_dir
    @@ -32,12 +44,14 @@
           return open(uri) { |body| show(body.read) }
         end
    
    -    return show(File.read(cache_file)) if File.exists?(cache_file) rescue clear_cache if cache_file
    +    unless edit
    +      return show(File.read(cache_file)) if File.exists?(cache_file) rescue clear_cache if cache_file
    +    end
    
         open(uri += sheet) do |body|
           sheet = body.read
           File.open(cache_file, 'w') { |f| f.write(sheet) } if cache_file
    -      show(sheet)
    +      edit ? edit(sheet) : show(sheet)
         end
       end
    
    @@ -48,6 +62,44 @@
         puts '  ' + sheet.last.gsub("\r",'').gsub("\n", "\n  ").wrap(80)
       end
    
    +  def edit(sheet_yaml)
    +    sheet = YAML.load(sheet_yaml).to_a.first
    +    sheet[-1] = sheet.last.gsub("\r", '')
    +    editor =  ENV['VISUAL'] || ENV['EDITOR'] || "vim"
    +    tf = Tempfile.new(sheet.first+'.cheat')
    +    tf.write(sheet.last)
    +    tf.close
    +    system(editor, tf.path)
    +    tf.open
    +    newsheet = tf.read
    +    tf.close
    +    if newsheet != sheet.last
    +      host   = HOST + ':' + PORT.to_s + SUFFIX
    +      uri    = "http://#{host}"
    +      res = Net::HTTP.post_form(URI.parse(uri + '/w/' + sheet.first), "sheet_title" => sheet.first,
    +                               "sheet_body" => newsheet)
    +      res.error! unless res.kind_of?(Net::HTTPSuccess) || res.kind_of?(Net::HTTPRedirection)
    +    end
    +  end
    +
    +  def add(name)
    +    editor = ENV['VISUAL'] || ENV['EDITOR'] || "vim"
    +    tf = Tempfile.new(name+'.cheat')
    +    tf.close
    +    system(editor, tf.path)
    +    tf.open
    +    body = tf.read
    +    tf.close
    +    res = Net::HTTP.post_form(URI.parse("http://#{HOST}:#{PORT}#{SUFFIX}/w/"),
    +                              "sheet_title" => name, "sheet_body" => body)
    +    if res.body =~ /<p class='error'>(.+?)<\/p>/m # please, please, please, someone fix this.
    +      puts $1.gsub(/\n/, '').gsub(/<.+?>/, '').squeeze(' ').wrap(80)
    +      puts
    +      puts "Here's what you wrote, so it isn't lost in the void:"
    +      puts body
    +    end
    +  end
    +
       def cache_dir
         PLATFORM =~ /win32/ ? win32_cache_dir : File.join(File.expand_path("~"), ".cheat")
       end
    

    cheat sheet—add cheat sheet—edit

    Someone please fix my horrible horrible hack :)

  • Randy Schmidt, about 1 month later:

    Thanks for making this! I have one question though, how do you get mac keyboard symbols to show up in the terminal? For example, some of the symbols in the textmate_rails cheat sheet? Thanks!

  • doug liveseey, 2 months later:

    Kick ass!

  • TonyC, 4 months later:

    Ok, now implement all of my MAN pages :)

  • JimOL, 5 months later:

    if you want to call cheat from within cygwin bash but you are using the windows version of ruby (don’t ask ;) then the following additions to your .bashrc will make it work without having to re-write the ruby:

    : ${HOMEDRIVE:=c:}; export HOMEDRIVE : ${HOMEPATH:=$(echo ~)}; export HOMEPATH alias cheat=’cheat.cmd’

  • Nimzter, 7 months later:

    I’m having issues getting cheat to work with Instant Rails. I was able to install it using the ‘gem install cheat’ command but when I run it mkdir seems to choke with a ‘No such file or directory error’ Any help will be appreciated. Thanks.

  • Autin, 7 months later:

    How to store in local?

  • Andrew Beacock, 10 months later:

    This is great! I’ve installed it successfully and ‘cheat migrations’ works a treat but ‘cheat cheat’ doesn’t:

    $ cheat Looking for help? Try http://cheat.errtheblog.com or `$ cheat cheat’

    $ cheat cheat Error!: Cheat sheet `cheat’ not found.

    Any ideas?

  • Keegan, 11 months later:

    man strftime ?? It is just calling the C function

  • Alexandru Ungur, about 1 year later:

    I love cheat :) and I love vim :) so there you go: a cheat wrapper for vim

    Cheers!

  • laszpio, about 1 year later:

    I added a cheat function to my ”.bashrc” file, so I got paging without typing “more”

    function cheat() { /usr/bin/cheat ”$@” | more; }

  • Thirty-six people have commented.
    Chime in.
    Sorry, no more comments :(
This is Err, the weblog of PJ Hyett and Chris Wanstrath.
All original content copyright ©2006-2008 the aforementioned.