irb_hacks 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +1 -1
- data/README.md +118 -87
- data/Rakefile +1 -44
- data/irb_hacks.gemspec +15 -38
- data/lib/irb_hacks/break_exception.rb +7 -1
- data/lib/irb_hacks/snippet.rb +1 -2
- data/lib/irb_hacks/version.rb +4 -0
- data/lib/irb_hacks.rb +1 -1
- metadata +57 -33
- data/VERSION.yml +0 -5
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,30 +1,36 @@
|
|
1
|
-
Yet
|
1
|
+
Yet another set of IRB hacks
|
2
2
|
============================
|
3
3
|
|
4
4
|
Setup
|
5
5
|
-----
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
~~~
|
8
|
+
$ gem sources --add http://rubygems.org
|
9
|
+
$ gem install irb_hacks
|
10
|
+
~~~
|
9
11
|
|
10
12
|
Add to your `~/.irbrc`:
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
~~~
|
15
|
+
require "rubygems"
|
16
|
+
require "irb_hacks"
|
17
|
+
~~~
|
14
18
|
|
15
19
|
Now fire up IRB for a quick test:
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
~~~
|
22
|
+
$ irb
|
23
|
+
irb> ae
|
24
|
+
(snippet)>>
|
25
|
+
~~~
|
20
26
|
|
21
|
-
If you see
|
27
|
+
If you see `(snippet)`, you're ready to go.
|
22
28
|
|
23
29
|
|
24
|
-
The
|
30
|
+
The hacks
|
25
31
|
---------
|
26
32
|
|
27
|
-
### Code
|
33
|
+
### Code snippets -- `a` and `ae` ###
|
28
34
|
|
29
35
|
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
36
|
|
@@ -32,124 +38,148 @@ There's often a need to invoke our work-in-progress code a number of times using
|
|
32
38
|
|
33
39
|
A very basic example:
|
34
40
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
41
|
+
~~~
|
42
|
+
irb> ae
|
43
|
+
(snippet)>> puts "Hello, world!"
|
44
|
+
irb> a
|
45
|
+
Hello, world!
|
46
|
+
~~~
|
39
47
|
|
40
48
|
Snippet arguments are supported. It's an array called `args` in snippet context.
|
41
49
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
50
|
+
~~~
|
51
|
+
irb> ae
|
52
|
+
(snippet)>> p "args", args
|
53
|
+
irb> a 10, 1.0, "a string"
|
54
|
+
"args"
|
55
|
+
[10, 1.0, "a string"]
|
56
|
+
~~~
|
47
57
|
|
48
58
|
Snippets work just like normal Ruby methods -- they return the value of the last statement executed.
|
49
59
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
60
|
+
~~~
|
61
|
+
irb> ae
|
62
|
+
(snippet)>> ["alfa", "zulu", "bravo"] + args
|
63
|
+
irb> puts a("charlie").sort
|
64
|
+
alfa
|
65
|
+
bravo
|
66
|
+
charlie
|
67
|
+
zulu
|
68
|
+
~~~
|
57
69
|
|
58
70
|
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:
|
59
71
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
72
|
+
~~~
|
73
|
+
irb> ae
|
74
|
+
(snippet)>> File.readlines("/etc/passwd").map(&block).each {|s| p s}; nil
|
75
|
+
irb> a {|s| ar = s.split(":"); {:name => ar[0], :uid => ar[2]}}
|
76
|
+
{:uid=>"0", :name=>"root"}
|
77
|
+
{:uid=>"1", :name=>"bin"}
|
78
|
+
{:uid=>"2", :name=>"daemon"}
|
79
|
+
{:uid=>"3", :name=>"adm"}
|
80
|
+
...
|
81
|
+
~~~
|
68
82
|
|
69
83
|
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.
|
70
84
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
85
|
+
~~~
|
86
|
+
irb> ae
|
87
|
+
(snippet)>> puts "Snippets are persistent!"
|
88
|
+
irb> exit
|
89
|
+
$ irb
|
90
|
+
irb> a
|
91
|
+
Snippets are persistent!
|
92
|
+
~~~
|
77
93
|
|
78
94
|
Just in case, snippet history file is called `~/.irb_snippet_history` by default.
|
79
95
|
|
80
96
|
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.
|
81
97
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
98
|
+
~~~
|
99
|
+
irb> ae
|
100
|
+
(snippet)>> puts "snippet one"
|
101
|
+
irb> hala
|
102
|
+
irb> bala
|
103
|
+
irb> ae
|
104
|
+
(snippet)>> puts "snippet two"
|
105
|
+
irb> foo
|
106
|
+
irb> moo
|
107
|
+
irb> ae
|
108
|
+
(snippet)>>
|
109
|
+
# Pressing [Up] will give you...
|
110
|
+
(snippet)>> puts "snippet two"
|
111
|
+
# Pressing [Up] again will give you...
|
112
|
+
(snippet)>> puts "snippet one"
|
113
|
+
~~~
|
96
114
|
|
97
115
|
You can configure some aspects of the snippets. Read "Configuration" chapter below.
|
98
116
|
|
99
117
|
|
100
|
-
### Browse
|
118
|
+
### Browse program data with GNU `less` ###
|
101
119
|
|
102
120
|
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
121
|
|
104
122
|
To solve that, the greatest paging program of all times, GNU `less`, comes to the rescue.
|
105
123
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
124
|
+
~~~
|
125
|
+
$ irb
|
126
|
+
irb> files = Dir["/etc/*"].sort
|
127
|
+
# Some bulky array...
|
128
|
+
irb> less files
|
129
|
+
# ...which you browse interactively!
|
130
|
+
~~~
|
111
131
|
|
112
132
|
In block form, `less` hack intercepts everything output to `STDOUT` (and, optionally, to `STDERR`), and feeds it to the pager.
|
113
133
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
134
|
+
~~~
|
135
|
+
$ irb
|
136
|
+
irb> less do
|
137
|
+
puts "Hello, world"
|
138
|
+
end
|
139
|
+
~~~
|
118
140
|
|
119
141
|
Now with `STDERR` capture:
|
120
142
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
143
|
+
~~~
|
144
|
+
$ irb
|
145
|
+
irb> less(:stderr) do
|
146
|
+
puts "to stdout"
|
147
|
+
STDERR.puts "to stderr"
|
148
|
+
end
|
149
|
+
~~~
|
126
150
|
|
127
151
|
You can configure which pager program to use and with which options. Read "Configuration" chapter below.
|
128
152
|
|
129
153
|
|
130
|
-
### Break
|
154
|
+
### Break execution and return instant value ###
|
131
155
|
|
132
156
|
By using `IrbHacks.break(value)` you break snippet (`a`) execution and make it return `value`. This is a simple yet powerful debugging technique.
|
133
157
|
|
134
158
|
Suppose you're debugging the code which contains something like:
|
135
159
|
|
136
|
-
|
137
|
-
|
138
|
-
|
160
|
+
~~~
|
161
|
+
csv.each_with_index do |fc_row, i|
|
162
|
+
row = Hash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
|
163
|
+
...
|
164
|
+
~~~
|
139
165
|
|
140
166
|
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`:
|
141
167
|
|
142
|
-
|
143
|
-
|
144
|
-
|
168
|
+
~~~
|
169
|
+
csv.each_with_index do |fc_row, i|
|
170
|
+
row = Hash[*fc_row.map {|k, v| [(k.to_sym rescue k), (v.to_s.strip rescue v)]}.flatten(1)]
|
171
|
+
IrbHacks.break(row)
|
172
|
+
~~~
|
145
173
|
|
146
174
|
Now all you have to do is write an `ae` snippet and call it. `row` value will be available in IRB for inspection:
|
147
175
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
176
|
+
~~~
|
177
|
+
irb> ae
|
178
|
+
(snippet)>> Klass.new.method(args)
|
179
|
+
irb> row = a
|
180
|
+
# Back in IRB. Do whatever you want with `row` value now.
|
181
|
+
irb>
|
182
|
+
~~~
|
153
183
|
|
154
184
|
Each `IrbHacks.break` call raises an `IrbHacks::BreakException`. If you see them popping out runtime, find the appropriate `IrbHacks.break` calls and defuse them.
|
155
185
|
|
@@ -159,13 +189,14 @@ Configuration
|
|
159
189
|
|
160
190
|
Via `IrbHacks.conf` object you can configure various features of `irb_hacks`. Add `IrbHacks.conf` manipulation code to your `.irbrc`:
|
161
191
|
|
162
|
-
|
163
|
-
|
192
|
+
~~~
|
193
|
+
require "rubygems"
|
194
|
+
require "irb_hacks"
|
164
195
|
|
165
|
-
|
196
|
+
IrbHacks.conf.snippet_prompt = ">>> "
|
197
|
+
~~~
|
166
198
|
|
167
|
-
|
168
|
-
### Configuration Variables (`IrbHacks.conf.*`)###
|
199
|
+
### Configuration variables (`IrbHacks.conf.*`)###
|
169
200
|
|
170
201
|
* `less_cmd` -- System command to invoke pager for `less`.
|
171
202
|
* `snippet_history_file` -- Snippet (`a`, `ae`) history file.
|
data/Rakefile
CHANGED
@@ -1,44 +1 @@
|
|
1
|
-
require "
|
2
|
-
require "yaml"
|
3
|
-
|
4
|
-
GEM_NAME = "irb_hacks"
|
5
|
-
|
6
|
-
begin
|
7
|
-
require "jeweler"
|
8
|
-
Jeweler::Tasks.new do |gem|
|
9
|
-
gem.name = GEM_NAME
|
10
|
-
gem.summary = "Yet another set of IRB hacks"
|
11
|
-
gem.description = "Yet another set of IRB hacks"
|
12
|
-
gem.email = "alex.r@askit.org"
|
13
|
-
gem.homepage = "http://github.com/dadooda/irb_hacks"
|
14
|
-
gem.authors = ["Alex Fortuna"]
|
15
|
-
gem.files = FileList[
|
16
|
-
"[A-Z]*",
|
17
|
-
"*.gemspec",
|
18
|
-
"lib/**/*.rb",
|
19
|
-
]
|
20
|
-
end
|
21
|
-
rescue LoadError
|
22
|
-
STDERR.puts "This gem requires Jeweler to be built"
|
23
|
-
end
|
24
|
-
|
25
|
-
desc "Rebuild gemspec and package"
|
26
|
-
task :rebuild => [:gemspec, :build]
|
27
|
-
|
28
|
-
desc "Push (publish) gem to RubyGems.org"
|
29
|
-
task :push do
|
30
|
-
# NOTE: Yet found no way to ask Jeweler forge a complete version string for us.
|
31
|
-
vh = YAML.load(File.read("VERSION.yml"))
|
32
|
-
version = [vh[:major], vh[:minor], vh[:patch], vh[:build]].compact.join(".")
|
33
|
-
pkgfile = File.join("pkg", "#{GEM_NAME}-#{version}.gem")
|
34
|
-
Kernel.system("gem", "push", pkgfile)
|
35
|
-
end
|
36
|
-
|
37
|
-
desc "Generate RDoc documentation"
|
38
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
39
|
-
rdoc.rdoc_dir = "doc"
|
40
|
-
rdoc.title = "IrbHacks"
|
41
|
-
#rdoc.options << "--line-numbers"
|
42
|
-
#rdoc.options << "--inline-source"
|
43
|
-
rdoc.rdoc_files.include("lib/**/*.rb")
|
44
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
data/irb_hacks.gemspec
CHANGED
@@ -1,45 +1,22 @@
|
|
1
|
-
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
1
|
+
require File.expand_path("../lib/irb_hacks/version", __FILE__)
|
5
2
|
|
6
3
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version =
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
+
s.name = "irb_hacks"
|
5
|
+
s.version = IrbHacks::VERSION
|
11
6
|
s.authors = ["Alex Fortuna"]
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
|
15
|
-
s
|
16
|
-
"README.md"
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
"MIT-LICENSE",
|
20
|
-
"README.md",
|
21
|
-
"Rakefile",
|
22
|
-
"VERSION.yml",
|
23
|
-
"irb_hacks.gemspec",
|
24
|
-
"lib/irb_hacks.rb",
|
25
|
-
"lib/irb_hacks/break_exception.rb",
|
26
|
-
"lib/irb_hacks/config.rb",
|
27
|
-
"lib/irb_hacks/core_ext/kernel/a_and_ae.rb",
|
28
|
-
"lib/irb_hacks/core_ext/kernel/less.rb",
|
29
|
-
"lib/irb_hacks/snippet.rb"
|
30
|
-
]
|
31
|
-
s.homepage = %q{http://github.com/dadooda/irb_hacks}
|
32
|
-
s.require_paths = ["lib"]
|
33
|
-
s.rubygems_version = %q{1.6.2}
|
7
|
+
s.email = ["alex.r@askit.org"]
|
8
|
+
s.homepage = "http://github.com/dadooda/irb_hacks"
|
9
|
+
|
10
|
+
# Copy these from class's description, adjust markup.
|
34
11
|
s.summary = %q{Yet another set of IRB hacks}
|
12
|
+
s.description = %q{Yet another set of IRB hacks}
|
13
|
+
# end of s.description=
|
35
14
|
|
36
|
-
|
37
|
-
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map {|f| File.basename(f)}
|
18
|
+
s.require_paths = ["lib"]
|
38
19
|
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
else
|
43
|
-
end
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "yard"
|
44
22
|
end
|
45
|
-
|
data/lib/irb_hacks/snippet.rb
CHANGED
@@ -89,8 +89,7 @@ module IrbHacks
|
|
89
89
|
# NOTE: Passing `binding` is important to provide a better backtrace when exception occurs.
|
90
90
|
eval(code, binding, &block)
|
91
91
|
rescue IrbHacks::BreakException => e
|
92
|
-
|
93
|
-
e.message[0]
|
92
|
+
return e.value
|
94
93
|
end
|
95
94
|
end
|
96
95
|
end
|
data/lib/irb_hacks.rb
CHANGED
metadata
CHANGED
@@ -1,32 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: irb_hacks
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.4
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.3
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Alex Fortuna
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
date: 2012-05-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: yard
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
17
46
|
description: Yet another set of IRB hacks
|
18
|
-
email:
|
47
|
+
email:
|
48
|
+
- alex.r@askit.org
|
19
49
|
executables: []
|
20
|
-
|
21
50
|
extensions: []
|
22
|
-
|
23
|
-
|
24
|
-
-
|
25
|
-
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
26
55
|
- MIT-LICENSE
|
27
56
|
- README.md
|
28
57
|
- Rakefile
|
29
|
-
- VERSION.yml
|
30
58
|
- irb_hacks.gemspec
|
31
59
|
- lib/irb_hacks.rb
|
32
60
|
- lib/irb_hacks/break_exception.rb
|
@@ -34,33 +62,29 @@ files:
|
|
34
62
|
- lib/irb_hacks/core_ext/kernel/a_and_ae.rb
|
35
63
|
- lib/irb_hacks/core_ext/kernel/less.rb
|
36
64
|
- lib/irb_hacks/snippet.rb
|
37
|
-
|
65
|
+
- lib/irb_hacks/version.rb
|
38
66
|
homepage: http://github.com/dadooda/irb_hacks
|
39
67
|
licenses: []
|
40
|
-
|
41
68
|
post_install_message:
|
42
69
|
rdoc_options: []
|
43
|
-
|
44
|
-
require_paths:
|
70
|
+
require_paths:
|
45
71
|
- lib
|
46
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
73
|
none: false
|
48
|
-
requirements:
|
49
|
-
- -
|
50
|
-
- !ruby/object:Gem::Version
|
51
|
-
version:
|
52
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
79
|
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version:
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
58
84
|
requirements: []
|
59
|
-
|
60
85
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.
|
86
|
+
rubygems_version: 1.8.21
|
62
87
|
signing_key:
|
63
88
|
specification_version: 3
|
64
89
|
summary: Yet another set of IRB hacks
|
65
90
|
test_files: []
|
66
|
-
|