irb_hacks 0.1.0

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