README.md in irb_hacks-0.2.3 vs README.md in irb_hacks-0.2.4
- old
+ new
@@ -1,172 +1,203 @@
-Yet Another Set of IRB Hacks
+Yet another set of IRB hacks
============================
Setup
-----
- $ gem sources --add http://rubygems.org
- $ gem install irb_hacks
+~~~
+$ gem sources --add http://rubygems.org
+$ gem install irb_hacks
+~~~
Add to your `~/.irbrc`:
- require "rubygems"
- require "irb_hacks"
+~~~
+require "rubygems"
+require "irb_hacks"
+~~~
Now fire up IRB for a quick test:
- $ irb
- irb> ae
- (snippet)>>
+~~~
+$ irb
+irb> ae
+(snippet)>>
+~~~
-If you see "(snippet)", you're ready to go.
+If you see `(snippet)`, you're ready to go.
-The Hacks
+The hacks
---------
-### Code Snippets -- `a` and `ae` ###
+### Code snippets -- `a` and `ae` ###
There's often a need to invoke our work-in-progress code a number of times using the same arguments, wrapping block, etc. For that, "code snippets" feature is quite handy.
`irb_hacks` provides the two methods with short, meaningless (and thus conflict-free) names -- `a` and `ae`. `a` means nothing, it's just the first letter of the alphabet. `a` **invokes** the last-edited snippet. `ae` **lets you edit** the actual snippet (it roughly stands for "a" + "edit").
A very basic example:
- irb> ae
- (snippet)>> puts "Hello, world!"
- irb> a
- Hello, world!
+~~~
+irb> ae
+(snippet)>> puts "Hello, world!"
+irb> a
+Hello, world!
+~~~
Snippet arguments are supported. It's an array called `args` in snippet context.
- irb> ae
- (snippet)>> p "args", args
- irb> a 10, 1.0, "a string"
- "args"
- [10, 1.0, "a string"]
+~~~
+irb> ae
+(snippet)>> p "args", args
+irb> a 10, 1.0, "a string"
+"args"
+[10, 1.0, "a string"]
+~~~
Snippets work just like normal Ruby methods -- they return the value of the last statement executed.
- irb> ae
- (snippet)>> ["alfa", "zulu", "bravo"] + args
- irb> puts a("charlie").sort
- alfa
- bravo
- charlie
- zulu
+~~~
+irb> ae
+(snippet)>> ["alfa", "zulu", "bravo"] + args
+irb> puts a("charlie").sort
+alfa
+bravo
+charlie
+zulu
+~~~
Snippets support code blocks. It's a `Proc` object called `block` in snippet context. Usage example follows. Suppose you're building a simplistic `/etc/passwd` parser. You put the actual reading in the snippet, but do line data manipulation in a block:
- irb> ae
- (snippet)>> File.readlines("/etc/passwd").map(&block).each {|s| p s}; nil
- irb> a {|s| ar = s.split(":"); {:name => ar[0], :uid => ar[2]}}
- {:uid=>"0", :name=>"root"}
- {:uid=>"1", :name=>"bin"}
- {:uid=>"2", :name=>"daemon"}
- {:uid=>"3", :name=>"adm"}
- ...
+~~~
+irb> ae
+(snippet)>> File.readlines("/etc/passwd").map(&block).each {|s| p s}; nil
+irb> a {|s| ar = s.split(":"); {:name => ar[0], :uid => ar[2]}}
+{:uid=>"0", :name=>"root"}
+{:uid=>"1", :name=>"bin"}
+{:uid=>"2", :name=>"daemon"}
+{:uid=>"3", :name=>"adm"}
+...
+~~~
Snippets are **persistent** thoughout IRB invocations. That's quite handy, since not all stuff can be dynamically reloaded and sometimes we have to restart IRB to ensure a clean reload.
- irb> ae
- (snippet)>> puts "Snippets are persistent!"
- irb> exit
- $ irb
- irb> a
- Snippets are persistent!
+~~~
+irb> ae
+(snippet)>> puts "Snippets are persistent!"
+irb> exit
+$ irb
+irb> a
+Snippets are persistent!
+~~~
Just in case, snippet history file is called `~/.irb_snippet_history` by default.
Snippets maintain **their own** Readline history. When you press [Up] and [Down] keys in `ae`, you browse the previously used snippets, not just your previous IRB input. So don't retype the snippet you used yesterday -- press [Up] a few times and you'll see it.
- irb> ae
- (snippet)>> puts "snippet one"
- irb> hala
- irb> bala
- irb> ae
- (snippet)>> puts "snippet two"
- irb> foo
- irb> moo
- irb> ae
- (snippet)>>
- # Pressing [Up] will give you...
- (snippet)>> puts "snippet two"
- # Pressing [Up] again will give you...
- (snippet)>> puts "snippet one"
+~~~
+irb> ae
+(snippet)>> puts "snippet one"
+irb> hala
+irb> bala
+irb> ae
+(snippet)>> puts "snippet two"
+irb> foo
+irb> moo
+irb> ae
+(snippet)>>
+# Pressing [Up] will give you...
+(snippet)>> puts "snippet two"
+# Pressing [Up] again will give you...
+(snippet)>> puts "snippet one"
+~~~
You can configure some aspects of the snippets. Read "Configuration" chapter below.
-### Browse Program Data With GNU `less` ###
+### Browse program data with GNU `less` ###
Sometimes the data your code works with is too long to fit in a console window. The clearest example of this are variables filled with text content, e.g. [Hpricot](http://github.com/whymirror/hpricot) documents/elements.
To solve that, the greatest paging program of all times, GNU `less`, comes to the rescue.
- $ irb
- irb> files = Dir["/etc/*"].sort
- # Some bulky array...
- irb> less files
- # ...which you browse interactively!
+~~~
+$ irb
+irb> files = Dir["/etc/*"].sort
+# Some bulky array...
+irb> less files
+# ...which you browse interactively!
+~~~
In block form, `less` hack intercepts everything output to `STDOUT` (and, optionally, to `STDERR`), and feeds it to the pager.
- $ irb
- irb> less do
- puts "Hello, world"
- end
+~~~
+$ irb
+irb> less do
+puts "Hello, world"
+end
+~~~
Now with `STDERR` capture:
- $ irb
- irb> less(:stderr) do
- puts "to stdout"
- STDERR.puts "to stderr"
- end
+~~~
+$ irb
+irb> less(:stderr) do
+puts "to stdout"
+STDERR.puts "to stderr"
+end
+~~~
You can configure which pager program to use and with which options. Read "Configuration" chapter below.
-### Break Execution and Return Instant Value ###
+### Break execution and return instant value ###
By using `IrbHacks.break(value)` you break snippet (`a`) execution and make it return `value`. This is a simple yet powerful debugging technique.
Suppose you're debugging the code which contains something like:
- csv.each_with_index do |fc_row, i|
- row = OpenHash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
- ...
+~~~
+csv.each_with_index do |fc_row, i|
+ row = Hash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
+ ...
+~~~
There's something wrong with the code and you want to see if `row` is given the correct value. To do it, use `IrbHacks.break`:
- csv.each_with_index do |fc_row, i|
- row = OpenHash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
- IrbHacks.break(row)
+~~~
+csv.each_with_index do |fc_row, i|
+ row = Hash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
+ IrbHacks.break(row)
+~~~
Now all you have to do is write an `ae` snippet and call it. `row` value will be available in IRB for inspection:
- irb> ae
- (snippet)>> Klass.new.method(args)
- irb> row = a
- # Back in IRB. Do whatever you want with `row` value now.
- irb>
+~~~
+irb> ae
+(snippet)>> Klass.new.method(args)
+irb> row = a
+# Back in IRB. Do whatever you want with `row` value now.
+irb>
+~~~
Each `IrbHacks.break` call raises an `IrbHacks::BreakException`. If you see them popping out runtime, find the appropriate `IrbHacks.break` calls and defuse them.
Configuration
-------------
Via `IrbHacks.conf` object you can configure various features of `irb_hacks`. Add `IrbHacks.conf` manipulation code to your `.irbrc`:
- require "rubygems"
- require "irb_hacks"
+~~~
+require "rubygems"
+require "irb_hacks"
- IrbHacks.conf.snippet_prompt = ">>> "
+IrbHacks.conf.snippet_prompt = ">>> "
+~~~
-
-### Configuration Variables (`IrbHacks.conf.*`)###
+### Configuration variables (`IrbHacks.conf.*`)###
* `less_cmd` -- System command to invoke pager for `less`.
* `snippet_history_file` -- Snippet (`a`, `ae`) history file.
* `snippet_history_size` -- Snippet history size.
* `snippet_prompt` -- Snippet input prompt.