irb_hacks 0.2.0 → 0.2.2

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.html CHANGED
@@ -31,14 +31,14 @@ irb> ae
31
31
 
32
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
33
 
34
- <p><code>irb_hacks</code> gem 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>
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
35
 
36
36
  <p>A very basic example:</p>
37
37
 
38
38
  <pre><code>irb&gt; ae
39
- (snippet)&gt;&gt; puts "Hello, world"
39
+ (snippet)&gt;&gt; puts "Hello, world!"
40
40
  irb&gt; a
41
- Hello, world
41
+ Hello, world!
42
42
  </code></pre>
43
43
 
44
44
  <p>Snippet arguments are supported. It’s an array called <code>args</code> in snippet context.</p>
@@ -61,7 +61,7 @@ charlie
61
61
  zulu
62
62
  </code></pre>
63
63
 
64
- <p>Snippets support code blocks. It’s a <code>Proc</code> called <code>block</code> in snippet context. Usage example follows (suppose you’re building a simplistic <code>/etc/passwd</code> parser).</p>
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
65
 
66
66
  <pre><code>irb&gt; ae
67
67
  (snippet)&gt;&gt; File.readlines("/etc/passwd").map(&amp;block).each {|s| p s}; nil
@@ -73,7 +73,7 @@ irb&gt; a {|s| ar = s.split(":"); {:name =&gt; ar[0], :uid =&gt; ar[2]}}
73
73
  ...
74
74
  </code></pre>
75
75
 
76
- <p>Snippets are <strong>persistent</strong> though IRB invocations. That’s quite handy, since not all stuff can be dynamically reloaded and sometimes one has to restart IRB to ensure a clean reload.</p>
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
77
 
78
78
  <pre><code>irb&gt; ae
79
79
  (snippet)&gt;&gt; puts "Snippets are persistent!"
@@ -83,9 +83,9 @@ irb&gt; a
83
83
  Snippets are persistent!
84
84
  </code></pre>
85
85
 
86
- <p>Just in case, snippet history file is called <code>.irb_snippet_history</code> in your <code>$HOME</code>.</p>
86
+ <p>Just in case, snippet history file is called <code>~/.irb_snippet_history</code> by default.</p>
87
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. Don’t retype the snippet you used yesterday – press [Up] a couple times and you’ll see it.</p>
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
89
 
90
90
  <pre><code>irb&gt; ae
91
91
  (snippet)&gt;&gt; puts "snippet one"
@@ -103,6 +103,8 @@ irb&gt; ae
103
103
  (snippet)&gt;&gt; puts "snippet one"
104
104
  </code></pre>
105
105
 
106
+ <p>You can configure some aspects of the snippets. Read “Configuration” chapter below.</p>
107
+
106
108
  <h3 id="browse-program-data-with-gnu-less">Browse program data with GNU <code>less</code></h3>
107
109
 
108
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>
@@ -113,7 +115,7 @@ irb&gt; ae
113
115
  irb&gt; files = Dir["/etc/*"].sort
114
116
  # Some bulky array...
115
117
  irb&gt; less files
116
- # ... which you browse interactively!
118
+ # ...which you browse interactively!
117
119
  </code></pre>
118
120
 
119
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>
@@ -133,16 +135,11 @@ STDERR.puts "to stderr"
133
135
  end
134
136
  </code></pre>
135
137
 
136
- <p>To specify another paging program or tweak <code>less</code> options, write in your <code>~/.irbrc</code>:</p>
137
-
138
- <pre><code>IrbHacks.less_cmd = "more"
139
- </code></pre>
140
-
141
- <p>, or something else you find appropriate.</p>
138
+ <p>You can configure which pager program to use and with which options. Read “Configuration” chapter below.</p>
142
139
 
143
140
  <h3 id="break-execution-and-return-instant-value">Break execution and return instant value</h3>
144
141
 
145
- <p>By using <code>IrbHacks.break(value)</code> you break snippet execution and make it return <code>value</code>. This is a simple yet powerful debugging technique.</p>
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>
146
143
 
147
144
  <p>Suppose you’re debugging the code which contains something like:</p>
148
145
 
@@ -167,7 +164,26 @@ irb&gt; row = a
167
164
  irb&gt;
168
165
  </code></pre>
169
166
 
170
- <p>Each <code>IrbHacks.break</code> call raises an <code>IrbHacks::BreakException</code>. If you see them popping out during runtime, find the appropriate <code>IrbHacks.break</code> calls and defuse them.</p>
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 = "&gt;&gt;&gt; "
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>
171
187
 
172
188
  <h2 id="feedback">Feedback</h2>
173
189
 
data/README.md CHANGED
@@ -28,14 +28,14 @@ The Hacks
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
 
31
- `irb_hacks` gem 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").
31
+ `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").
32
32
 
33
33
  A very basic example:
34
34
 
35
35
  irb> ae
36
- (snippet)>> puts "Hello, world"
36
+ (snippet)>> puts "Hello, world!"
37
37
  irb> a
38
- Hello, world
38
+ Hello, world!
39
39
 
40
40
  Snippet arguments are supported. It's an array called `args` in snippet context.
41
41
 
@@ -55,7 +55,7 @@ Snippets work just like normal Ruby methods -- they return the value of the last
55
55
  charlie
56
56
  zulu
57
57
 
58
- Snippets support code blocks. It's a `Proc` called `block` in snippet context. Usage example follows (suppose you're building a simplistic `/etc/passwd` parser).
58
+ 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
59
 
60
60
  irb> ae
61
61
  (snippet)>> File.readlines("/etc/passwd").map(&block).each {|s| p s}; nil
@@ -66,7 +66,7 @@ Snippets support code blocks. It's a `Proc` called `block` in snippet context. U
66
66
  {:uid=>"3", :name=>"adm"}
67
67
  ...
68
68
 
69
- Snippets are **persistent** though IRB invocations. That's quite handy, since not all stuff can be dynamically reloaded and sometimes one has to restart IRB to ensure a clean reload.
69
+ 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
70
 
71
71
  irb> ae
72
72
  (snippet)>> puts "Snippets are persistent!"
@@ -75,9 +75,9 @@ Snippets are **persistent** though IRB invocations. That's quite handy, since no
75
75
  irb> a
76
76
  Snippets are persistent!
77
77
 
78
- Just in case, snippet history file is called `.irb_snippet_history` in your `$HOME`.
78
+ Just in case, snippet history file is called `~/.irb_snippet_history` by default.
79
79
 
80
- 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. Don't retype the snippet you used yesterday -- press [Up] a couple times and you'll see it.
80
+ 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
81
 
82
82
  irb> ae
83
83
  (snippet)>> puts "snippet one"
@@ -94,6 +94,8 @@ Snippets maintain **their own** Readline history. When you press [Up] and [Down]
94
94
  # Pressing [Up] again will give you...
95
95
  (snippet)>> puts "snippet one"
96
96
 
97
+ You can configure some aspects of the snippets. Read "Configuration" chapter below.
98
+
97
99
 
98
100
  ### Browse program data with GNU `less` ###
99
101
 
@@ -105,7 +107,7 @@ To solve that, the greatest paging program of all times, GNU `less`, comes to th
105
107
  irb> files = Dir["/etc/*"].sort
106
108
  # Some bulky array...
107
109
  irb> less files
108
- # ... which you browse interactively!
110
+ # ...which you browse interactively!
109
111
 
110
112
  In block form, `less` hack intercepts everything output to `STDOUT` (and, optionally, to `STDERR`), and feeds it to the pager.
111
113
 
@@ -122,16 +124,12 @@ Now with `STDERR` capture:
122
124
  STDERR.puts "to stderr"
123
125
  end
124
126
 
125
- To specify another paging program or tweak `less` options, write in your `~/.irbrc`:
126
-
127
- IrbHacks.less_cmd = "more"
128
-
129
- , or something else you find appropriate.
127
+ You can configure which pager program to use and with which options. Read "Configuration" chapter below.
130
128
 
131
129
 
132
130
  ### Break execution and return instant value ###
133
131
 
134
- By using `IrbHacks.break(value)` you break snippet execution and make it return `value`. This is a simple yet powerful debugging technique.
132
+ By using `IrbHacks.break(value)` you break snippet (`a`) execution and make it return `value`. This is a simple yet powerful debugging technique.
135
133
 
136
134
  Suppose you're debugging the code which contains something like:
137
135
 
@@ -153,7 +151,26 @@ Now all you have to do is write an `ae` snippet and call it. `row` value will be
153
151
  # Back in IRB. Do whatever you want with `row` value now.
154
152
  irb>
155
153
 
156
- Each `IrbHacks.break` call raises an `IrbHacks::BreakException`. If you see them popping out during runtime, find the appropriate `IrbHacks.break` calls and defuse them.
154
+ 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
+
156
+
157
+ Configuration
158
+ -------------
159
+
160
+ Via `IrbHacks.conf` object you can configure various features of `irb_hacks`. Add `IrbHacks.conf` manipulation code to your `.irbrc`:
161
+
162
+ require "rubygems"
163
+ require "irb_hacks"
164
+
165
+ IrbHacks.conf.snippet_prompt = ">>> "
166
+
167
+
168
+ ### Configuration Variables (`IrbHacks.conf.*`)###
169
+
170
+ * `less_cmd` -- System command to invoke pager for `less`.
171
+ * `snippet_history_file` -- Snippet (`a`, `ae`) history file.
172
+ * `snippet_history_size` -- Snippet history size.
173
+ * `snippet_prompt` -- Snippet input prompt.
157
174
 
158
175
 
159
176
  Feedback
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
+ require "rake/rdoctask"
1
2
  require "yaml"
2
- #require 'rake/gempackagetask'
3
3
 
4
4
  GEM_NAME = "irb_hacks"
5
5
 
@@ -25,15 +25,24 @@ end
25
25
  desc "Rebuild gemspec and package"
26
26
  task :rebuild => [:gemspec, :build]
27
27
 
28
- desc "Push (publish) gem to Gemcutter"
28
+ desc "Push (publish) gem to RubyGems.org"
29
29
  task :push do
30
30
  # 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]].join(".")
33
- pkgfile = File.join("pkg", [GEM_NAME, "-", version, ".gem"].to_s)
32
+ version = [vh[:major], vh[:minor], vh[:patch], (if (v = vh[:build]); v; end)].compact.join(".")
33
+ pkgfile = File.join("pkg", [GEM_NAME, "-", version, ".gem"].join)
34
34
  Kernel.system("gem", "push", pkgfile)
35
35
  end
36
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
45
+
37
46
  #Rake::GemPackageTask.new(spec) do |p|
38
47
  # p.need_tar = true if RUBY_PLATFORM !~ /mswin/
39
48
  #end
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 2
4
- :patch: 0
5
- #:build: pre
4
+ :patch: 2
5
+ #:build: pre2
data/irb_hacks.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{irb_hacks}
8
- s.version = "0.2.0"
8
+ s.version = "0.2.2"
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{2010-12-13}
12
+ s.date = %q{2011-07-12}
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 = [
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
17
17
  "README.md"
18
18
  ]
19
19
  s.files = [
20
- "CHANGELOG.md",
21
20
  "MIT-LICENSE",
22
21
  "README.html",
23
22
  "README.md",
@@ -25,17 +24,18 @@ Gem::Specification.new do |s|
25
24
  "VERSION.yml",
26
25
  "irb_hacks.gemspec",
27
26
  "lib/irb_hacks.rb",
27
+ "lib/irb_hacks/break_exception.rb",
28
+ "lib/irb_hacks/config.rb",
28
29
  "lib/irb_hacks/core_ext/kernel/a_and_ae.rb",
29
30
  "lib/irb_hacks/core_ext/kernel/less.rb",
30
31
  "lib/irb_hacks/snippet.rb"
31
32
  ]
32
33
  s.homepage = %q{http://github.com/dadooda/irb_hacks}
33
34
  s.require_paths = ["lib"]
34
- s.rubygems_version = %q{1.3.7}
35
+ s.rubygems_version = %q{1.6.2}
35
36
  s.summary = %q{Yet another set of IRB hacks}
36
37
 
37
38
  if s.respond_to? :specification_version then
38
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
39
39
  s.specification_version = 3
40
40
 
41
41
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -0,0 +1,4 @@
1
+ module IrbHacks
2
+ # Exception class used by IrbHacks::break.
3
+ class BreakException < Exception; end
4
+ end
@@ -0,0 +1,33 @@
1
+ module IrbHacks
2
+ # IrbHacks configuration object.
3
+ class Config
4
+ # System command to invoke pager for <tt>less</tt>. Default:
5
+ #
6
+ # less -R
7
+ attr_accessor :less_cmd
8
+
9
+ # Snippet (<tt>a</tt>, <tt>ae</tt>) history file. Default:
10
+ #
11
+ # ~/.irb_snippet_history
12
+ attr_accessor :snippet_history_file
13
+
14
+ # Snippet history size. Default is <tt>100</tt>.
15
+ attr_accessor :snippet_history_size
16
+
17
+ # Snippet input prompt. Default:
18
+ #
19
+ # (snippet)>>
20
+ attr_accessor :snippet_prompt
21
+
22
+ def initialize(attrs = {})
23
+ defaults = {
24
+ :less_cmd => "less -R",
25
+ :snippet_history_file => "~/.irb_snippet_history",
26
+ :snippet_history_size => 100,
27
+ :snippet_prompt => "(snippet)>> ",
28
+ }
29
+
30
+ defaults.merge(attrs).each {|k, v| send("#{k}=", v)}
31
+ end
32
+ end
33
+ end
@@ -1,27 +1,25 @@
1
- module IrbHacks #:nodoc:
1
+ module IrbHacks
2
2
  module CoreExtensions #:nodoc:
3
3
  module Kernel #:nodoc:
4
- module SingletonMethods
5
- # Run code snippet.
6
- # See <tt>IrbHacks::Snippet.run</tt>.
4
+ module SingletonMethods #:nodoc:
7
5
  def a(*args, &block)
8
- IrbHacks::Snippet.run(*args, &block)
6
+ Snippet.run(*args, &block)
9
7
  end
10
8
 
11
- # Edit code snippet.
12
- # See <tt>IrbHacks::Snippet.edit</tt>.
13
9
  def ae(*args)
14
- IrbHacks::Snippet.edit(*args)
10
+ Snippet.edit(*args)
15
11
  end
16
12
  end # SingletonMethods
17
13
 
18
14
  module InstanceMethods
19
15
  private
20
16
 
17
+ # Run code snippet. See IrbHacks::Snippet::run.
21
18
  def a(*args, &block)
22
19
  ::Kernel.a(*args, &block)
23
20
  end
24
21
 
22
+ # Interactively edit code snippet. See IrbHacks::Snippet::edit.
25
23
  def ae(*args)
26
24
  ::Kernel.ae(*args)
27
25
  end
@@ -1,39 +1,16 @@
1
- module IrbHacks #:nodoc:
1
+ module IrbHacks
2
2
  module CoreExtensions #:nodoc:
3
3
  module Kernel #:nodoc:
4
- module SingletonMethods
5
- # Dump program data with GNU <tt>less</tt>.
6
- #
7
- # Plain form:
8
- # less "hello", "world"
9
- # less mydata
10
- #
11
- # Block form:
12
- # less do
13
- # puts "hello, world"
14
- # end
15
- #
16
- # less(:stderr => true) do
17
- # puts "to stdout"
18
- # STDERR.puts "to stderr"
19
- # end
20
- #
21
- # Block form options:
22
- # :stderr => T|F # Redirect STDERR too.
23
- #
24
- # If block form option is <tt>String</tt> or <tt>Symbol</tt>, it's automatically
25
- # converted to a hash like <tt>{:var => true}</tt>. Thus, <tt>less(:stderr => true)</tt>
26
- # and <tt>less(:stderr)</tt> are identical.
4
+ module SingletonMethods #:nodoc:
5
+ # See InstanceMethods for documentation.
27
6
  def less(*args, &block)
28
- less_cmd = IrbHacks.less_cmd
29
-
30
7
  if not block
31
8
  # Non-block invocation.
32
9
  if args.size < 1
33
10
  # We're interactive anyway. Why not give user a quick prompt?
34
11
  STDERR.puts "Nothing to show. Invoke as less(args) or less(options, &block)"
35
12
  else
36
- File.popen(less_cmd, "w") do |f|
13
+ File.popen(IrbHacks.conf.less_cmd, "w") do |f|
37
14
  f.puts args
38
15
  end
39
16
  end
@@ -62,7 +39,7 @@ module IrbHacks #:nodoc:
62
39
  old_stdout = STDOUT.clone
63
40
  old_stderr = STDERR.clone if o_stderr
64
41
 
65
- File.popen(less_cmd, "w") do |f|
42
+ File.popen(IrbHacks.conf.less_cmd, "w") do |f|
66
43
  STDOUT.reopen(f)
67
44
  STDERR.reopen(f) if o_stderr
68
45
  yield
@@ -78,6 +55,33 @@ module IrbHacks #:nodoc:
78
55
  module InstanceMethods
79
56
  private
80
57
 
58
+ # Dump program data with GNU <tt>less</tt> or the other configured OS pager.
59
+ #
60
+ # Plain form:
61
+ #
62
+ # less "hello", "world"
63
+ # less mydata
64
+ #
65
+ # Block form:
66
+ #
67
+ # less do
68
+ # puts "hello, world"
69
+ # end
70
+ #
71
+ # less(:stderr => true) do
72
+ # puts "to stdout"
73
+ # STDERR.puts "to stderr"
74
+ # end
75
+ #
76
+ # Block form options:
77
+ #
78
+ # :stderr => T|F # Redirect STDERR too.
79
+ #
80
+ # If block form option is String or Symbol, it's automatically
81
+ # converted to Hash like <tt>{:var => true}</tt>. Thus, you can write <tt>less(:stderr)</tt>
82
+ # for <tt>less(:stderr => true)</tt>, they are functionally identical.
83
+ #
84
+ # See also IrbHacks::Config::less_cmd.
81
85
  def less(*args, &block)
82
86
  ::Kernel.less(*args, &block)
83
87
  end
@@ -1,43 +1,66 @@
1
1
  require "readline"
2
2
 
3
- module IrbHacks #:nodoc:
3
+ module IrbHacks
4
+ # Snippet manipulation internals.
4
5
  module Snippet
5
- #TODO: Configured values. Config is common for entire IrbHacks.
6
- HISTORY_FILE = File.join(ENV["HOME"], ".irb_snippet_history")
7
- HISTORY_SIZE = 500
6
+ # Initializer.
7
+ def self._initialize #:nodoc:
8
+ load_history
9
+ end
10
+
11
+ # On-the-fly initializer.
12
+ def self._otf_init #:nodoc:
13
+ # Consider job done, replace self with a blank.
14
+ class_eval {
15
+ def self._otf_init #:nodoc:
16
+ end
17
+ }
8
18
 
9
- # Edit code snippet.
19
+ _initialize
20
+ end
21
+
22
+ # Interactively edit code snippet.
10
23
  def self.edit
11
- ##p "R::H before", Readline::HISTORY.to_a
24
+ _otf_init
25
+
26
+ # Gracefully catch Ctrl-C.
27
+ old_sigint = trap("INT") do
28
+ puts "\nAborted"
29
+ return nil
30
+ end
31
+
32
+ #DEBUG
33
+ ##p "RH at inv", Readline::HISTORY.to_a
12
34
  ##p "@history at inv", @history
13
35
 
14
- # Push stuff into RL history.
15
- npushed = @history.size
16
- @history.each {|s| Readline::HISTORY.push s}
36
+ rl_history = _replace_rl_history(@history)
17
37
 
18
- ##p "R::H after push", Readline::HISTORY.to_a
38
+ ##p "RH at cp 1", Readline::HISTORY.to_a #DEBUG
19
39
 
20
- # NOTE: Readline help is missing. Copied from somewhere else.
21
- input = Readline.readline("(snippet)>> ", true)
40
+ # Read input.
41
+ # NOTE: Readline help is missing.
42
+ input = Readline.readline(IrbHacks.conf.snippet_prompt, true).strip
22
43
 
23
- if not input.empty?
24
- # Accept entry.
25
- @history << input
44
+ return nil if input.empty?
26
45
 
27
- # ["wan", "tew", "free", "tew"] should render into ["wan", "free", "tew"] with "tew" being the last input shippet.
28
- @history = (@history.reverse.uniq).reverse
29
- end
46
+ # Accept input.
47
+ @history << input
30
48
 
31
- # Pop stuff out of RL history.
32
- (npushed + 1).times {Readline::HISTORY.pop}
49
+ # Remove duplicates. Most recent bubble up.
50
+ # [1, 2, 3, 2] will render into [1, 3, 2] with 2 being the last snippet.
51
+ @history = (@history.reverse.uniq).reverse
33
52
 
34
- ##p "R::H after", Readline::HISTORY.to_a
53
+ ##p "RH after restore", Readline::HISTORY.to_a #DEBUG
35
54
 
36
- # Save history -- we can't know when the session is going to end.
55
+ # Save our history now.
37
56
  save_history
38
57
 
39
58
  # Don't clutter IRB screen with anything extra.
40
59
  nil
60
+ ensure
61
+ ##puts "-- ensure" #DEBUG
62
+ trap("INT", &old_sigint) if old_sigint
63
+ _replace_rl_history(rl_history) if rl_history
41
64
  end
42
65
 
43
66
  def self.history
@@ -48,20 +71,19 @@ module IrbHacks #:nodoc:
48
71
  @history = ar
49
72
  end
50
73
 
74
+ # Load history from a file.
51
75
  def self.load_history
52
76
  @history = begin
53
- content = File.read(HISTORY_FILE)
54
- YAML.load(content)
77
+ File.readlines(File.expand_path(IrbHacks.conf.snippet_history_file)).map(&:chomp)
55
78
  rescue
56
- nil
79
+ [%{puts "YOUR test code here"}]
57
80
  end
58
-
59
- @history = [%{puts "YOUR test code here"}] if not @history
60
81
  end
61
82
 
62
- # Run code snippet.
63
- # If <tt>IrbHacks.break</tt> is called anywhere, immediately return its argument.
83
+ # Run latest edited code snippet. If IrbHacks::break is called anywhere, immediately return its argument.
64
84
  def self.run(*args, &block)
85
+ _otf_init
86
+
65
87
  if (code = @history.last)
66
88
  begin
67
89
  eval(code, &block)
@@ -72,16 +94,25 @@ module IrbHacks #:nodoc:
72
94
  end
73
95
  end
74
96
 
97
+ # Save history to a file.
75
98
  def self.save_history
76
- # Truncate a saved version of @history.
77
- hist = @history.size > HISTORY_SIZE ? @history.slice(-HISTORY_SIZE..-1) : @history
78
- File.open(HISTORY_FILE, "w") do |f|
79
- f.write YAML.dump(hist)
99
+ # Truncate and save history.
100
+ # NOTE: It's more logical (WYSIWYG) to truncate @history live, not its copy. Thus the user will see what's going to be saved & restored.
101
+ @history.slice!(0..-(IrbHacks.conf.snippet_history_size + 1))
102
+ File.open(File.expand_path(IrbHacks.conf.snippet_history_file), "w") do |f|
103
+ f.puts @history
80
104
  end
81
105
  end
82
106
 
83
- #--------------------------------------- Init
107
+ #---------------------------------------
84
108
 
85
- load_history
109
+ # Clear Readline history and optionally replace it with new content.
110
+ # Return previous content.
111
+ def self._replace_rl_history(ar = nil) #:nodoc:
112
+ out = []
113
+ while (s = Readline::HISTORY.shift); out << s; end
114
+ ar.each {|s| Readline::HISTORY << s} if ar
115
+ out
116
+ end
86
117
  end # Snippet
87
118
  end # IrbHacks
data/lib/irb_hacks.rb CHANGED
@@ -1,27 +1,51 @@
1
- require "yaml"
2
-
3
1
  Dir[File.join(File.dirname(__FILE__), "irb_hacks/**/*.rb")].each {|fn| require fn}
4
2
 
5
- module IrbHacks
6
- # Break execution, return value if invoked from `a`.
3
+ # Yet another set of IRB hacks.
4
+ #
5
+ # Summary of features brought to IRB:
6
+ #
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 pages like <tt>less</tt>.
9
+ # * IrbHacks::break to instantly return value from code into IRB.
10
+ module IrbHacks #:doc:
11
+ # Break execution, instantly return value if caller is invoked from a snippet.
12
+ #
13
+ # def myfunc
14
+ # puts "Reading name..."
15
+ # name = File.read(...)
16
+ # IrbHacks.break name #DEBUG: See what's been read.
17
+ #
18
+ # # Other code...
19
+ # end
7
20
  #
8
- # IrbHacks.break
9
- # IrbHacks.break("hi")
21
+ # irb> ae
22
+ # snippet>> myfunc
23
+ # irb> a
24
+ # Reading name...
25
+ # => "John Smith"
10
26
  def self.break(value = nil)
11
27
  raise BreakException, [value]
12
28
  end
13
29
 
14
- def self.less_cmd
30
+ # Access configuration object. See IrbHacks::Config.
31
+ #
32
+ # IrbHacks.conf
33
+ # IrbHacks.conf.snippet_history_size = 200
34
+ def self.conf
35
+ @conf ||= Config.new
36
+ end
37
+ end
38
+
39
+ #--------------------------------------- Junk
40
+
41
+ if false
42
+ def self.less_cmd #:nodoc:
15
43
  @less_cmd
16
44
  end
17
45
 
18
- def self.less_cmd=(cmd)
46
+ def self.less_cmd=(cmd) #:nodoc:
19
47
  @less_cmd = cmd
20
48
  end
21
49
 
22
- class BreakException < Exception; end
23
-
24
- #--------------------------------------- Defaults
25
-
26
50
  self.less_cmd = "less -R"
27
51
  end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: irb_hacks
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 0
9
- version: 0.2.0
4
+ prerelease:
5
+ version: 0.2.2
10
6
  platform: ruby
11
7
  authors:
12
8
  - Alex Fortuna
@@ -14,7 +10,7 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2010-12-13 00:00:00 +03:00
13
+ date: 2011-07-12 00:00:00 +04:00
18
14
  default_executable:
19
15
  dependencies: []
20
16
 
@@ -28,7 +24,6 @@ extra_rdoc_files:
28
24
  - README.html
29
25
  - README.md
30
26
  files:
31
- - CHANGELOG.md
32
27
  - MIT-LICENSE
33
28
  - README.html
34
29
  - README.md
@@ -36,6 +31,8 @@ files:
36
31
  - VERSION.yml
37
32
  - irb_hacks.gemspec
38
33
  - lib/irb_hacks.rb
34
+ - lib/irb_hacks/break_exception.rb
35
+ - lib/irb_hacks/config.rb
39
36
  - lib/irb_hacks/core_ext/kernel/a_and_ae.rb
40
37
  - lib/irb_hacks/core_ext/kernel/less.rb
41
38
  - lib/irb_hacks/snippet.rb
@@ -53,21 +50,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
50
  requirements:
54
51
  - - ">="
55
52
  - !ruby/object:Gem::Version
56
- segments:
57
- - 0
58
53
  version: "0"
59
54
  required_rubygems_version: !ruby/object:Gem::Requirement
60
55
  none: false
61
56
  requirements:
62
57
  - - ">="
63
58
  - !ruby/object:Gem::Version
64
- segments:
65
- - 0
66
59
  version: "0"
67
60
  requirements: []
68
61
 
69
62
  rubyforge_project:
70
- rubygems_version: 1.3.7
63
+ rubygems_version: 1.6.2
71
64
  signing_key:
72
65
  specification_version: 3
73
66
  summary: Yet another set of IRB hacks
data/CHANGELOG.md DELETED
@@ -1,10 +0,0 @@
1
- 0.1.1 2010-01-18
2
- ----------------
3
-
4
- Fixed YAML issue for Ruby 1.9.1.
5
-
6
-
7
- 0.1.0 2010-01-14
8
- ----------------
9
-
10
- First public release.