irb_hacks 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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.