irb_hacks 0.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ 0.1.0 2010-01-14
2
+ ----------------
3
+
4
+ First public release.
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+ Yet another set of IRB hacks
2
+ ============================
3
+
4
+ Setup
5
+ -----
6
+
7
+ $ gem sources --add http://gemcutter.org
8
+ $ gem install irb_hacks
9
+
10
+ Add to your `~/.irbrc`:
11
+
12
+ require "rubygems"
13
+ require "irb_hacks"
14
+
15
+ Now fire up IRB for a quick test:
16
+
17
+ $ irb
18
+ irb> ae
19
+ (snippet)>>
20
+
21
+ If you see "(snippet)", you're ready to go.
22
+
23
+
24
+ The Hacks
25
+ ---------
26
+
27
+ ### Code snippets -- `a` and `ae` ###
28
+
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
+
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").
32
+
33
+ A very basic example:
34
+
35
+ irb> ae
36
+ (snippet)>> puts "Hello, world"
37
+ irb> a
38
+ Hello, world
39
+
40
+ Snippet arguments are supported. It's an array called `args` in snippet context.
41
+
42
+ irb> ae
43
+ (snippet)>> p "args", args
44
+ irb> a 10, 1.0, "a string"
45
+ "args"
46
+ [10, 1.0, "a string"]
47
+
48
+ Snippets work just like normal Ruby methods -- they return the value of the last statement executed.
49
+
50
+ irb> ae
51
+ (snippet)>> ["alfa", "zulu", "bravo"] + args
52
+ irb> puts a("charlie").sort
53
+ alfa
54
+ bravo
55
+ charlie
56
+ zulu
57
+
58
+ Snippets support code blocks. It's a `Proc` called `block` in snippet context. Usage example follows (suppose we're building a simplistic `/etc/passwd` parser).
59
+
60
+ irb> ae
61
+ (snippet)>> File.readlines("/etc/passwd").map(&block).each {|s| p s}; nil
62
+ irb> a {|s| ar = s.split(":"); {:name => ar[0], :uid => ar[2]}}
63
+ {:uid=>"0", :name=>"root"}
64
+ {:uid=>"1", :name=>"bin"}
65
+ {:uid=>"2", :name=>"daemon"}
66
+ {:uid=>"3", :name=>"adm"}
67
+ ...
68
+
69
+ Snippets are **persistent** though IRB invocations. That's quite handy, since not all stuff can be dynamically reloaded and sometimes we have to restart IRB to ensure clean reload.
70
+
71
+ irb> ae
72
+ (snippet)>> puts "Snippets are persistent!"
73
+ irb> exit
74
+ $ irb
75
+ irb> a
76
+ Snippets are persistent!
77
+
78
+ Just in case, snippet history file is called `.irb_snippet_history` in your `$HOME`.
79
+
80
+ Snippets maintain **their own** Realine 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.
81
+
82
+ irb> ae
83
+ (snippet)>> puts "snippet one"
84
+ irb> hala
85
+ irb> bala
86
+ irb> ae
87
+ (snippet)>> puts "snippet two"
88
+ irb> foo
89
+ irb> moo
90
+ irb> ae
91
+ (snippet)>>
92
+ ## Pressing [Up] will give you...
93
+ (snippet)>> puts "snippet two"
94
+ ## Pressing [Up] again will give you...
95
+ (snippet)>> puts "snippet one"
96
+
97
+ ### Browse program data with GNU `less` ###
98
+
99
+ 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.
100
+
101
+ To solve that, the greatest paging program of all times, GNU `less`, comes to the rescue.
102
+
103
+ $ irb
104
+ irb> files = Dir["/etc/*"].sort
105
+ ## Some bulky array...
106
+ irb> less files
107
+ ## ... which we browse interactively :).
108
+
109
+ In block form, `less` hack intercepts everything output to `STDOUT` (and, optionally, to `STDERR`), and feeds it to the pager.
110
+
111
+ $ irb
112
+ irb> less do
113
+ puts "Hello, world"
114
+ end
115
+
116
+ Now with `STDERR` capture:
117
+
118
+ $ irb
119
+ irb> less(:stderr) do
120
+ puts "to stdout"
121
+ STDERR.puts "to stderr"
122
+ end
123
+
124
+ To specify another paging program or tweak `less` options, write in your `~/.irbrc`:
125
+
126
+ IrbHacks.less_cmd = "more"
127
+
128
+ , or something else you find appropriate.
129
+
130
+
131
+ Feedback
132
+ --------
133
+
134
+ Send bug reports, suggestions and criticisms through [project's page on GitHub](http://github.com/dadooda/irb_hacks).
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 1
3
+ :patch: 0
4
+ :major: 0
data/irb_hacks.gemspec ADDED
@@ -0,0 +1,43 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{irb_hacks}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Alex Fortuna"]
12
+ s.date = %q{2010-01-14}
13
+ s.description = %q{Yet another set of IRB hacks}
14
+ s.email = %q{alex.r@askit.org}
15
+ s.extra_rdoc_files = [
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ "CHANGELOG.md",
20
+ "README.md",
21
+ "VERSION.yml",
22
+ "irb_hacks.gemspec",
23
+ "lib/irb_hacks.rb",
24
+ "lib/irb_hacks/core_ext/kernel/a_and_ae.rb",
25
+ "lib/irb_hacks/core_ext/kernel/less.rb",
26
+ "lib/irb_hacks/snippet.rb"
27
+ ]
28
+ s.homepage = %q{http://github.com/dadooda/irb_hacks}
29
+ s.rdoc_options = ["--charset=UTF-8"]
30
+ s.require_paths = ["lib"]
31
+ s.rubygems_version = %q{1.3.5}
32
+ s.summary = %q{Yet another set of IRB hacks}
33
+
34
+ if s.respond_to? :specification_version then
35
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
39
+ else
40
+ end
41
+ else
42
+ end
43
+ end
@@ -0,0 +1,33 @@
1
+ module IrbHacks #:nodoc:
2
+ module CoreExtensions #:nodoc:
3
+ module Kernel #:nodoc:
4
+ module SingletonMethods
5
+ # Run code snippet.
6
+ # See <tt>IrbHacks::Snippet.run</tt>.
7
+ def a(*args, &block)
8
+ IrbHacks::Snippet.run(*args, &block)
9
+ end
10
+
11
+ # Edit code snippet.
12
+ # See <tt>IrbHacks::Snippet.edit</tt>.
13
+ def ae(*args)
14
+ IrbHacks::Snippet.edit(*args)
15
+ end
16
+ end
17
+
18
+ ::Kernel.extend SingletonMethods
19
+ end
20
+ end
21
+ end
22
+
23
+ module Kernel #:nodoc:
24
+ private
25
+
26
+ def a(*args, &block)
27
+ ::Kernel.a(*args, &block)
28
+ end
29
+
30
+ def ae(*args)
31
+ ::Kernel.ae(*args)
32
+ end
33
+ end
@@ -0,0 +1,89 @@
1
+ module IrbHacks #:nodoc:
2
+ module CoreExtensions #:nodoc:
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.
27
+ def less(*args, &block)
28
+ less_cmd = IrbHacks.less_cmd
29
+
30
+ if not block
31
+ # Non-block invocation.
32
+ if args.size < 1
33
+ # We're interactive anyway. Why not give user a quick prompt?
34
+ STDERR.puts "Nothing to show. Invoke as less(args) or less(options, &block)."
35
+ else
36
+ File.popen(less_cmd, "w") do |f|
37
+ f.puts args
38
+ end
39
+ end
40
+ else
41
+ # Block invocation.
42
+
43
+ # Handle options.
44
+ options = {}
45
+
46
+ args.each do |arg|
47
+ if arg.is_a? Hash
48
+ ##p "arg hash", arg
49
+ options.merge! arg
50
+ elsif [Symbol, String].include? arg.class
51
+ ##p "arg sym/str", arg
52
+ options.merge! arg.to_sym => true
53
+ else
54
+ raise ArgumentError, "Unsupported argument #{arg.inspect}"
55
+ end
56
+ end
57
+
58
+ o_stderr = (v = options.delete(:stderr)).nil?? false : v
59
+
60
+ raise ArgumentError, "Unknown option(s): #{options.inspect}" if not options.empty?
61
+
62
+ old_stdout = STDOUT.clone
63
+ old_stderr = STDERR.clone if o_stderr
64
+
65
+ File.popen(less_cmd, "w") do |f|
66
+ STDOUT.reopen(f)
67
+ STDERR.reopen(f) if o_stderr
68
+ yield
69
+ STDOUT.reopen(old_stdout)
70
+ STDERR.reopen(old_stderr) if o_stderr
71
+ end
72
+ end # if block or no block.
73
+
74
+ nil
75
+ end # less
76
+ end # SingletonMethods
77
+
78
+ ::Kernel.extend SingletonMethods
79
+ end # Kernel
80
+ end # CoreExtensions
81
+ end
82
+
83
+ module Kernel #:nodoc:
84
+ private
85
+
86
+ def less(*args, &block)
87
+ ::Kernel.less(*args, &block)
88
+ end
89
+ end
@@ -0,0 +1,80 @@
1
+ require "readline"
2
+
3
+ module IrbHacks #:nodoc:
4
+ module Snippet
5
+ HISTORY_FILE = File.join(ENV["HOME"], ".irb_snippet_history")
6
+ HISTORY_SIZE = 20
7
+
8
+ # Edit code snippet.
9
+ def self.edit
10
+ ##p "R::H before", Readline::HISTORY.to_a
11
+ ##p "@history at inv", @history
12
+
13
+ # Push stuff into RL history.
14
+ npushed = @history.size
15
+ @history.each {|s| Readline::HISTORY.push s}
16
+
17
+ ##p "R::H after push", Readline::HISTORY.to_a
18
+
19
+ # NOTE: Readline help is missing. Copied from somewhere else.
20
+ input = Readline.readline("(snippet)>> ", true)
21
+
22
+ if not input.empty?
23
+ # Accept entry.
24
+ @history << input
25
+
26
+ # ["wan", "tew", "free", "tew"] should render into ["wan", "free", "tew"] with "tew" being the last input shippet.
27
+ @history = (@history.reverse.uniq).reverse
28
+ end
29
+
30
+ # Pop stuff out of RL history.
31
+ (npushed + 1).times {Readline::HISTORY.pop}
32
+
33
+ ##p "R::H after", Readline::HISTORY.to_a
34
+
35
+ # Save history -- we can't know when the session is going to end.
36
+ save_history
37
+
38
+ # Don't clutter IRB screen with anything extra.
39
+ nil
40
+ end
41
+
42
+ def self.history
43
+ @history
44
+ end
45
+
46
+ def self.history=(ar)
47
+ @history = ar
48
+ end
49
+
50
+ def self.load_history
51
+ @history = begin
52
+ content = File.read(HISTORY_FILE)
53
+ YAML.load(content)
54
+ rescue
55
+ nil
56
+ end
57
+
58
+ @history = [%{puts "YOUR test code here"}] if not @history.is_a? Array
59
+ end
60
+
61
+ # Run code snippet.
62
+ def self.run(*args, &block)
63
+ if (code = @history.last)
64
+ eval(code, &block)
65
+ end
66
+ end
67
+
68
+ def self.save_history
69
+ # Truncate a saved version of @history.
70
+ hist = @history.size > HISTORY_SIZE ? @history.slice(-HISTORY_SIZE..-1) : @history
71
+ File.open(HISTORY_FILE, "w") do |f|
72
+ f.write YAML.dump(hist)
73
+ end
74
+ end
75
+
76
+ #--------------------------------------- Init
77
+
78
+ load_history
79
+ end # Snippet
80
+ end # IrbHacks
data/lib/irb_hacks.rb ADDED
@@ -0,0 +1,15 @@
1
+ Dir[File.join(File.dirname(__FILE__), "irb_hacks/**/*.rb")].each {|fn| require fn}
2
+
3
+ module IrbHacks
4
+ def self.less_cmd
5
+ @less_cmd
6
+ end
7
+
8
+ def self.less_cmd=(cmd)
9
+ @less_cmd = cmd
10
+ end
11
+
12
+ #--------------------------------------- Defaults
13
+
14
+ self.less_cmd = "less -R"
15
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: irb_hacks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Fortuna
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-14 00:00:00 +03:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Yet another set of IRB hacks
17
+ email: alex.r@askit.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.md
24
+ files:
25
+ - CHANGELOG.md
26
+ - README.md
27
+ - VERSION.yml
28
+ - irb_hacks.gemspec
29
+ - lib/irb_hacks.rb
30
+ - lib/irb_hacks/core_ext/kernel/a_and_ae.rb
31
+ - lib/irb_hacks/core_ext/kernel/less.rb
32
+ - lib/irb_hacks/snippet.rb
33
+ has_rdoc: true
34
+ homepage: http://github.com/dadooda/irb_hacks
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Yet another set of IRB hacks
61
+ test_files: []
62
+