irb_hacks 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +11 -5
- data/Rakefile +3 -22
- data/VERSION.yml +2 -2
- data/irb_hacks.gemspec +2 -4
- data/lib/irb_hacks/snippet.rb +2 -1
- data/lib/irb_hacks.rb +4 -18
- metadata +2 -4
- data/README.html +0 -192
data/README.md
CHANGED
@@ -24,7 +24,7 @@ If you see "(snippet)", you're ready to go.
|
|
24
24
|
The Hacks
|
25
25
|
---------
|
26
26
|
|
27
|
-
### Code
|
27
|
+
### Code Snippets -- `a` and `ae` ###
|
28
28
|
|
29
29
|
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.
|
30
30
|
|
@@ -97,7 +97,7 @@ Snippets maintain **their own** Readline history. When you press [Up] and [Down]
|
|
97
97
|
You can configure some aspects of the snippets. Read "Configuration" chapter below.
|
98
98
|
|
99
99
|
|
100
|
-
### Browse
|
100
|
+
### Browse Program Data With GNU `less` ###
|
101
101
|
|
102
102
|
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.
|
103
103
|
|
@@ -127,7 +127,7 @@ Now with `STDERR` capture:
|
|
127
127
|
You can configure which pager program to use and with which options. Read "Configuration" chapter below.
|
128
128
|
|
129
129
|
|
130
|
-
### Break
|
130
|
+
### Break Execution and Return Instant Value ###
|
131
131
|
|
132
132
|
By using `IrbHacks.break(value)` you break snippet (`a`) execution and make it return `value`. This is a simple yet powerful debugging technique.
|
133
133
|
|
@@ -173,9 +173,15 @@ Via `IrbHacks.conf` object you can configure various features of `irb_hacks`. Ad
|
|
173
173
|
* `snippet_prompt` -- Snippet input prompt.
|
174
174
|
|
175
175
|
|
176
|
+
Copyright
|
177
|
+
---------
|
178
|
+
|
179
|
+
Copyright © 2010-2012 Alex Fortuna.
|
180
|
+
|
181
|
+
Licensed under the MIT License.
|
182
|
+
|
183
|
+
|
176
184
|
Feedback
|
177
185
|
--------
|
178
186
|
|
179
187
|
Send bug reports, suggestions and criticisms through [project's page on GitHub](http://github.com/dadooda/irb_hacks).
|
180
|
-
|
181
|
-
Licensed under the MIT License.
|
data/Rakefile
CHANGED
@@ -27,10 +27,10 @@ task :rebuild => [:gemspec, :build]
|
|
27
27
|
|
28
28
|
desc "Push (publish) gem to RubyGems.org"
|
29
29
|
task :push do
|
30
|
-
# Yet found no way to ask Jeweler forge a complete version string for us.
|
30
|
+
# NOTE: Yet found no way to ask Jeweler forge a complete version string for us.
|
31
31
|
vh = YAML.load(File.read("VERSION.yml"))
|
32
|
-
version = [vh[:major], vh[:minor], vh[:patch],
|
33
|
-
pkgfile = File.join("pkg",
|
32
|
+
version = [vh[:major], vh[:minor], vh[:patch], vh[:build]].compact.join(".")
|
33
|
+
pkgfile = File.join("pkg", "#{GEM_NAME}-#{version}.gem")
|
34
34
|
Kernel.system("gem", "push", pkgfile)
|
35
35
|
end
|
36
36
|
|
@@ -42,22 +42,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
42
42
|
#rdoc.options << "--inline-source"
|
43
43
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
44
44
|
end
|
45
|
-
|
46
|
-
#Rake::GemPackageTask.new(spec) do |p|
|
47
|
-
# p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
48
|
-
#end
|
49
|
-
|
50
|
-
desc "Compile README preview"
|
51
|
-
task :readme do
|
52
|
-
require "kramdown"
|
53
|
-
|
54
|
-
doc = Kramdown::Document.new(File.read "README.md")
|
55
|
-
|
56
|
-
fn = "README.html"
|
57
|
-
puts "Writing '#{fn}'..."
|
58
|
-
File.open(fn, "w") do |f|
|
59
|
-
f.write(File.read "dev/head.html")
|
60
|
-
f.write(doc.to_html)
|
61
|
-
end
|
62
|
-
puts ": ok"
|
63
|
-
end
|
data/VERSION.yml
CHANGED
data/irb_hacks.gemspec
CHANGED
@@ -5,20 +5,18 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{irb_hacks}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alex Fortuna"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2012-02-10}
|
13
13
|
s.description = %q{Yet another set of IRB hacks}
|
14
14
|
s.email = %q{alex.r@askit.org}
|
15
15
|
s.extra_rdoc_files = [
|
16
|
-
"README.html",
|
17
16
|
"README.md"
|
18
17
|
]
|
19
18
|
s.files = [
|
20
19
|
"MIT-LICENSE",
|
21
|
-
"README.html",
|
22
20
|
"README.md",
|
23
21
|
"Rakefile",
|
24
22
|
"VERSION.yml",
|
data/lib/irb_hacks/snippet.rb
CHANGED
@@ -86,7 +86,8 @@ module IrbHacks
|
|
86
86
|
|
87
87
|
if (code = @history.last)
|
88
88
|
begin
|
89
|
-
|
89
|
+
# NOTE: Passing `binding` is important to provide a better backtrace when exception occurs.
|
90
|
+
eval(code, binding, &block)
|
90
91
|
rescue IrbHacks::BreakException => e
|
91
92
|
# If invoked as documented, `e.message` is always an array.
|
92
93
|
e.message[0]
|
data/lib/irb_hacks.rb
CHANGED
@@ -5,17 +5,17 @@ Dir[File.join(File.dirname(__FILE__), "irb_hacks/**/*.rb")].each {|fn| require f
|
|
5
5
|
# Summary of features brought to IRB:
|
6
6
|
#
|
7
7
|
# * <tt>a</tt> and <tt>ae</tt> methods to invoke or edit code snippets.
|
8
|
-
# * <tt>less</tt> method to interactively dump data with OS
|
8
|
+
# * <tt>less</tt> method to interactively dump data with OS pager program (e.g. <tt>less</tt>).
|
9
9
|
# * IrbHacks::break to instantly return value from code into IRB.
|
10
10
|
module IrbHacks #:doc:
|
11
|
-
# Break execution, instantly return value if caller is invoked from a snippet.
|
11
|
+
# Break execution, instantly return a value if caller is invoked from a snippet.
|
12
12
|
#
|
13
13
|
# def myfunc
|
14
14
|
# puts "Reading name..."
|
15
15
|
# name = File.read(...)
|
16
|
-
# IrbHacks.break name #
|
16
|
+
# IrbHacks.break name # Pass what's been read back to console.
|
17
17
|
#
|
18
|
-
#
|
18
|
+
# ...
|
19
19
|
# end
|
20
20
|
#
|
21
21
|
# irb> ae
|
@@ -35,17 +35,3 @@ module IrbHacks #:doc:
|
|
35
35
|
@conf ||= Config.new
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
#--------------------------------------- Junk
|
40
|
-
|
41
|
-
if false
|
42
|
-
def self.less_cmd #:nodoc:
|
43
|
-
@less_cmd
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.less_cmd=(cmd) #:nodoc:
|
47
|
-
@less_cmd = cmd
|
48
|
-
end
|
49
|
-
|
50
|
-
self.less_cmd = "less -R"
|
51
|
-
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: irb_hacks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Alex Fortuna
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2012-02-10 00:00:00 +04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -21,11 +21,9 @@ executables: []
|
|
21
21
|
extensions: []
|
22
22
|
|
23
23
|
extra_rdoc_files:
|
24
|
-
- README.html
|
25
24
|
- README.md
|
26
25
|
files:
|
27
26
|
- MIT-LICENSE
|
28
|
-
- README.html
|
29
27
|
- README.md
|
30
28
|
- Rakefile
|
31
29
|
- VERSION.yml
|
data/README.html
DELETED
@@ -1,192 +0,0 @@
|
|
1
|
-
<head>
|
2
|
-
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
3
|
-
<link href="dev/github.css" rel="stylesheet" type="text/css" />
|
4
|
-
</head>
|
5
|
-
<h1 id="yet-another-set-of-irb-hacks">Yet Another Set of IRB Hacks</h1>
|
6
|
-
|
7
|
-
<h2 id="setup">Setup</h2>
|
8
|
-
|
9
|
-
<pre><code>$ gem sources --add http://rubygems.org
|
10
|
-
$ gem install irb_hacks
|
11
|
-
</code></pre>
|
12
|
-
|
13
|
-
<p>Add to your <code>~/.irbrc</code>:</p>
|
14
|
-
|
15
|
-
<pre><code>require "rubygems"
|
16
|
-
require "irb_hacks"
|
17
|
-
</code></pre>
|
18
|
-
|
19
|
-
<p>Now fire up IRB for a quick test:</p>
|
20
|
-
|
21
|
-
<pre><code>$ irb
|
22
|
-
irb> ae
|
23
|
-
(snippet)>>
|
24
|
-
</code></pre>
|
25
|
-
|
26
|
-
<p>If you see “(snippet)”, you’re ready to go.</p>
|
27
|
-
|
28
|
-
<h2 id="the-hacks">The Hacks</h2>
|
29
|
-
|
30
|
-
<h3 id="code-snippets----a-and-ae">Code snippets – <code>a</code> and <code>ae</code></h3>
|
31
|
-
|
32
|
-
<p>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.</p>
|
33
|
-
|
34
|
-
<p><code>irb_hacks</code> provides the two methods with short, meaningless (and thus conflict-free) names – <code>a</code> and <code>ae</code>. <code>a</code> means nothing, it’s just the first letter of the alphabet. <code>a</code> <strong>invokes</strong> the last-edited snippet. <code>ae</code> <strong>lets you edit</strong> the actual snippet (it roughly stands for “a” + “edit”).</p>
|
35
|
-
|
36
|
-
<p>A very basic example:</p>
|
37
|
-
|
38
|
-
<pre><code>irb> ae
|
39
|
-
(snippet)>> puts "Hello, world!"
|
40
|
-
irb> a
|
41
|
-
Hello, world!
|
42
|
-
</code></pre>
|
43
|
-
|
44
|
-
<p>Snippet arguments are supported. It’s an array called <code>args</code> in snippet context.</p>
|
45
|
-
|
46
|
-
<pre><code>irb> ae
|
47
|
-
(snippet)>> p "args", args
|
48
|
-
irb> a 10, 1.0, "a string"
|
49
|
-
"args"
|
50
|
-
[10, 1.0, "a string"]
|
51
|
-
</code></pre>
|
52
|
-
|
53
|
-
<p>Snippets work just like normal Ruby methods – they return the value of the last statement executed.</p>
|
54
|
-
|
55
|
-
<pre><code>irb> ae
|
56
|
-
(snippet)>> ["alfa", "zulu", "bravo"] + args
|
57
|
-
irb> puts a("charlie").sort
|
58
|
-
alfa
|
59
|
-
bravo
|
60
|
-
charlie
|
61
|
-
zulu
|
62
|
-
</code></pre>
|
63
|
-
|
64
|
-
<p>Snippets support code blocks. It’s a <code>Proc</code> object called <code>block</code> in snippet context. Usage example follows. Suppose you’re building a simplistic <code>/etc/passwd</code> parser. You put the actual reading in the snippet, but do line data manipulation in a block:</p>
|
65
|
-
|
66
|
-
<pre><code>irb> ae
|
67
|
-
(snippet)>> File.readlines("/etc/passwd").map(&block).each {|s| p s}; nil
|
68
|
-
irb> a {|s| ar = s.split(":"); {:name => ar[0], :uid => ar[2]}}
|
69
|
-
{:uid=>"0", :name=>"root"}
|
70
|
-
{:uid=>"1", :name=>"bin"}
|
71
|
-
{:uid=>"2", :name=>"daemon"}
|
72
|
-
{:uid=>"3", :name=>"adm"}
|
73
|
-
...
|
74
|
-
</code></pre>
|
75
|
-
|
76
|
-
<p>Snippets are <strong>persistent</strong> 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.</p>
|
77
|
-
|
78
|
-
<pre><code>irb> ae
|
79
|
-
(snippet)>> puts "Snippets are persistent!"
|
80
|
-
irb> exit
|
81
|
-
$ irb
|
82
|
-
irb> a
|
83
|
-
Snippets are persistent!
|
84
|
-
</code></pre>
|
85
|
-
|
86
|
-
<p>Just in case, snippet history file is called <code>~/.irb_snippet_history</code> by default.</p>
|
87
|
-
|
88
|
-
<p>Snippets maintain <strong>their own</strong> Readline history. When you press [Up] and [Down] keys in <code>ae</code>, 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.</p>
|
89
|
-
|
90
|
-
<pre><code>irb> ae
|
91
|
-
(snippet)>> puts "snippet one"
|
92
|
-
irb> hala
|
93
|
-
irb> bala
|
94
|
-
irb> ae
|
95
|
-
(snippet)>> puts "snippet two"
|
96
|
-
irb> foo
|
97
|
-
irb> moo
|
98
|
-
irb> ae
|
99
|
-
(snippet)>>
|
100
|
-
# Pressing [Up] will give you...
|
101
|
-
(snippet)>> puts "snippet two"
|
102
|
-
# Pressing [Up] again will give you...
|
103
|
-
(snippet)>> puts "snippet one"
|
104
|
-
</code></pre>
|
105
|
-
|
106
|
-
<p>You can configure some aspects of the snippets. Read “Configuration” chapter below.</p>
|
107
|
-
|
108
|
-
<h3 id="browse-program-data-with-gnu-less">Browse program data with GNU <code>less</code></h3>
|
109
|
-
|
110
|
-
<p>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. <a href="http://github.com/whymirror/hpricot">Hpricot</a> documents/elements.</p>
|
111
|
-
|
112
|
-
<p>To solve that, the greatest paging program of all times, GNU <code>less</code>, comes to the rescue.</p>
|
113
|
-
|
114
|
-
<pre><code>$ irb
|
115
|
-
irb> files = Dir["/etc/*"].sort
|
116
|
-
# Some bulky array...
|
117
|
-
irb> less files
|
118
|
-
# ...which you browse interactively!
|
119
|
-
</code></pre>
|
120
|
-
|
121
|
-
<p>In block form, <code>less</code> hack intercepts everything output to <code>STDOUT</code> (and, optionally, to <code>STDERR</code>), and feeds it to the pager.</p>
|
122
|
-
|
123
|
-
<pre><code>$ irb
|
124
|
-
irb> less do
|
125
|
-
puts "Hello, world"
|
126
|
-
end
|
127
|
-
</code></pre>
|
128
|
-
|
129
|
-
<p>Now with <code>STDERR</code> capture:</p>
|
130
|
-
|
131
|
-
<pre><code>$ irb
|
132
|
-
irb> less(:stderr) do
|
133
|
-
puts "to stdout"
|
134
|
-
STDERR.puts "to stderr"
|
135
|
-
end
|
136
|
-
</code></pre>
|
137
|
-
|
138
|
-
<p>You can configure which pager program to use and with which options. Read “Configuration” chapter below.</p>
|
139
|
-
|
140
|
-
<h3 id="break-execution-and-return-instant-value">Break execution and return instant value</h3>
|
141
|
-
|
142
|
-
<p>By using <code>IrbHacks.break(value)</code> you break snippet (<code>a</code>) execution and make it return <code>value</code>. This is a simple yet powerful debugging technique.</p>
|
143
|
-
|
144
|
-
<p>Suppose you’re debugging the code which contains something like:</p>
|
145
|
-
|
146
|
-
<pre><code>csv.each_with_index do |fc_row, i|
|
147
|
-
row = OpenHash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
|
148
|
-
...
|
149
|
-
</code></pre>
|
150
|
-
|
151
|
-
<p>There’s something wrong with the code and you want to see if <code>row</code> is given the correct value. To do it, use <code>IrbHacks.break</code>:</p>
|
152
|
-
|
153
|
-
<pre><code>csv.each_with_index do |fc_row, i|
|
154
|
-
row = OpenHash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
|
155
|
-
IrbHacks.break(row)
|
156
|
-
</code></pre>
|
157
|
-
|
158
|
-
<p>Now all you have to do is write an <code>ae</code> snippet and call it. <code>row</code> value will be available in IRB for inspection:</p>
|
159
|
-
|
160
|
-
<pre><code>irb> ae
|
161
|
-
(snippet)>> Klass.new.method(args)
|
162
|
-
irb> row = a
|
163
|
-
# Back in IRB. Do whatever you want with `row` value now.
|
164
|
-
irb>
|
165
|
-
</code></pre>
|
166
|
-
|
167
|
-
<p>Each <code>IrbHacks.break</code> call raises an <code>IrbHacks::BreakException</code>. If you see them popping out runtime, find the appropriate <code>IrbHacks.break</code> calls and defuse them.</p>
|
168
|
-
|
169
|
-
<h2 id="configuration">Configuration</h2>
|
170
|
-
|
171
|
-
<p>Via <code>IrbHacks.conf</code> object you can configure various features of <code>irb_hacks</code>. Add <code>IrbHacks.conf</code> manipulation code to your <code>.irbrc</code>:</p>
|
172
|
-
|
173
|
-
<pre><code>require "rubygems"
|
174
|
-
require "irb_hacks"
|
175
|
-
|
176
|
-
IrbHacks.conf.snippet_prompt = ">>> "
|
177
|
-
</code></pre>
|
178
|
-
|
179
|
-
<h3 id="configuration-variables-irbhacksconf">Configuration Variables (<code>IrbHacks.conf.*</code>)</h3>
|
180
|
-
|
181
|
-
<ul>
|
182
|
-
<li><code>less_cmd</code> – System command to invoke pager for <code>less</code>.</li>
|
183
|
-
<li><code>snippet_history_file</code> – Snippet (<code>a</code>, <code>ae</code>) history file.</li>
|
184
|
-
<li><code>snippet_history_size</code> – Snippet history size.</li>
|
185
|
-
<li><code>snippet_prompt</code> – Snippet input prompt.</li>
|
186
|
-
</ul>
|
187
|
-
|
188
|
-
<h2 id="feedback">Feedback</h2>
|
189
|
-
|
190
|
-
<p>Send bug reports, suggestions and criticisms through <a href="http://github.com/dadooda/irb_hacks">project’s page on GitHub</a>.</p>
|
191
|
-
|
192
|
-
<p>Licensed under the MIT License.</p>
|