rib 0.0.1 → 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/.gitignore +6 -0
- data/.gitmodules +3 -0
- data/.travis.yml +9 -0
- data/2011-02-28.md +203 -0
- data/CHANGES +86 -0
- data/CONTRIBUTORS +2 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/README +190 -0
- data/README.md +190 -0
- data/Rakefile +20 -0
- data/TODO +6 -0
- data/lib/rib.rb +42 -0
- data/lib/rib/all.rb +4 -0
- data/lib/rib/api.rb +105 -0
- data/lib/rib/core.rb +5 -0
- data/lib/rib/core/completion.rb +22 -0
- data/lib/rib/core/history_file.rb +38 -0
- data/lib/rib/core/readline.rb +19 -0
- data/lib/rib/core/underscore.rb +53 -0
- data/lib/rib/debug.rb +3 -0
- data/lib/rib/more.rb +12 -0
- data/lib/rib/more/color.rb +98 -0
- data/lib/rib/more/multiline.rb +77 -0
- data/lib/rib/more/multiline_history.rb +31 -0
- data/lib/rib/more/multiline_history_file.rb +37 -0
- data/lib/rib/more/squeeze_history.rb +37 -0
- data/lib/rib/more/strip_backtrace.rb +43 -0
- data/lib/rib/plugin.rb +56 -0
- data/lib/rib/runner.rb +106 -0
- data/lib/rib/shell.rb +43 -0
- data/lib/rib/test.rb +25 -0
- data/lib/rib/version.rb +4 -0
- data/lib/rib/zore.rb +3 -0
- data/lib/rib/zore/anchor.rb +69 -0
- data/lib/rib/zore/edit.rb +33 -0
- data/rib.gemspec +104 -0
- data/screenshot.png +0 -0
- data/task/.gitignore +1 -0
- data/task/gemgem.rb +182 -0
- data/test/core/test_completion.rb +18 -0
- data/test/core/test_history_file.rb +57 -0
- data/test/core/test_readline.rb +21 -0
- data/test/core/test_underscore.rb +41 -0
- data/test/more/test_color.rb +28 -0
- data/test/more/test_squeeze_history.rb +43 -0
- data/test/test_api.rb +20 -0
- data/test/test_plugin.rb +38 -0
- data/test/test_shell.rb +82 -0
- metadata +77 -13
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
require 'rib/more/multiline' # dependency
|
3
|
+
|
4
|
+
module Rib::MultilineHistory
|
5
|
+
include Rib::Plugin
|
6
|
+
Shell.use(self)
|
7
|
+
|
8
|
+
def loop_eval input
|
9
|
+
return super if MultilineHistory.disabled?
|
10
|
+
value = super
|
11
|
+
rescue Exception
|
12
|
+
# might be multiline editing, ignore
|
13
|
+
raise
|
14
|
+
else
|
15
|
+
if multiline_buffer.size > 1
|
16
|
+
# so multiline editing is considering done here
|
17
|
+
(multiline_buffer.size + (@multiline_trash || 0)).times{ history.pop }
|
18
|
+
history << "\n" + multiline_buffer.join("\n")
|
19
|
+
end
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_interrupt
|
24
|
+
return super if MultilineHistory.disabled?
|
25
|
+
if multiline_buffer.size > 1
|
26
|
+
@multiline_trash ||= 0
|
27
|
+
@multiline_trash += 1
|
28
|
+
end
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'rib/more/multiline_history'
|
3
|
+
|
4
|
+
module Rib::MultilineHistoryFile
|
5
|
+
include Rib::Plugin
|
6
|
+
Shell.use(self)
|
7
|
+
|
8
|
+
def before_loop
|
9
|
+
return super if MultilineHistoryFile.disabled?
|
10
|
+
config[:multiline_history_file_token] ||= ' '
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def read_history
|
15
|
+
return super if MultilineHistoryFile.disabled?
|
16
|
+
buffer = []
|
17
|
+
File.exist?(history_file) && history.empty? &&
|
18
|
+
IO.readlines(history_file).each{ |line|
|
19
|
+
if line.end_with?(
|
20
|
+
"#{config[:multiline_history_file_token]}\n")
|
21
|
+
buffer << line[0...
|
22
|
+
-config[:multiline_history_file_token].size-1] + "\n"
|
23
|
+
else
|
24
|
+
history << (buffer.join + line).chomp
|
25
|
+
buffer = []
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def write_history
|
31
|
+
return super if MultilineHistoryFile.disabled?
|
32
|
+
@history = history.to_a.map{ |line|
|
33
|
+
line.gsub("\n", "#{config[:multiline_history_file_token]}\n")
|
34
|
+
}
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'rib/core/history_file'
|
3
|
+
|
4
|
+
module Rib::SqueezeHistory
|
5
|
+
include Rib::Plugin
|
6
|
+
Shell.use(self)
|
7
|
+
|
8
|
+
# squeeze history on memory too
|
9
|
+
def eval_input input
|
10
|
+
return super if SqueezeHistory.disabled?
|
11
|
+
history.pop if input.strip == '' ||
|
12
|
+
(history.size > 1 && input == history.to_a[-2])
|
13
|
+
# EditLine is really broken, to_a is needed for it
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
# write squeezed history
|
18
|
+
def write_history
|
19
|
+
return super if SqueezeHistory.disabled?
|
20
|
+
@history = P.squeeze_history(history)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
module Imp
|
25
|
+
def squeeze_history history
|
26
|
+
history.to_a.inject([]){ |result, item|
|
27
|
+
if result.last == item || item.strip == ''
|
28
|
+
result
|
29
|
+
else
|
30
|
+
result << item
|
31
|
+
end
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Plugin.extend(Imp)
|
37
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
require 'rib'
|
3
|
+
|
4
|
+
module Rib::StripBacktrace
|
5
|
+
include Rib::Plugin
|
6
|
+
Shell.use(self)
|
7
|
+
|
8
|
+
# strip backtrace until ripl
|
9
|
+
def format_error e
|
10
|
+
return super if StripBacktrace.disabled?
|
11
|
+
message, backtrace = get_error(e, P.strip_backtrace(e, config[:name]))
|
12
|
+
"#{message}\n #{backtrace.join("\n ")}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_error e, backtrace=e.backtrace
|
16
|
+
return super if StripBacktrace.disabled?
|
17
|
+
["#{e.class}: #{e.message}", backtrace]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
module Imp
|
22
|
+
def strip_backtrace e, name
|
23
|
+
home(cwd(snip(e, name)))
|
24
|
+
end
|
25
|
+
|
26
|
+
def home b
|
27
|
+
b.map{ |p| p.sub(ENV['HOME'], '~') }
|
28
|
+
end
|
29
|
+
|
30
|
+
def cwd b
|
31
|
+
b.map{ |p| p.sub(Dir.pwd, '.') }
|
32
|
+
end
|
33
|
+
|
34
|
+
def snip e, name
|
35
|
+
return [] if e.kind_of?(SyntaxError)
|
36
|
+
e.backtrace[
|
37
|
+
0..
|
38
|
+
e.backtrace.rindex{ |l| l =~ /\(#{name}\):\d+:in `.+?'/ } || -1]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Plugin.extend(Imp)
|
43
|
+
end
|
data/lib/rib/plugin.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
module Rib; end
|
3
|
+
module Rib::Plugin
|
4
|
+
Rib::P = self
|
5
|
+
|
6
|
+
def self.included mod
|
7
|
+
mod.send(:include, Rib)
|
8
|
+
|
9
|
+
class << mod
|
10
|
+
attr_accessor :disabled
|
11
|
+
|
12
|
+
def enable
|
13
|
+
self.disabled = false
|
14
|
+
if block_given? then yield else enabled? end
|
15
|
+
end
|
16
|
+
|
17
|
+
def disable
|
18
|
+
self.disabled = true
|
19
|
+
if block_given? then yield else enabled? end
|
20
|
+
end
|
21
|
+
|
22
|
+
def enabled?
|
23
|
+
!disabled
|
24
|
+
end
|
25
|
+
|
26
|
+
def disabled?
|
27
|
+
!!disabled
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
snake_name = mod.name[/::\w+$/].tr(':', ''). # remove namespaces
|
32
|
+
gsub(/([A-Z][a-z]*)/, '\\1_').downcase[0..-2]
|
33
|
+
|
34
|
+
code = (%w[enable disable].map{ |meth|
|
35
|
+
<<-RUBY
|
36
|
+
def #{meth}_#{snake_name} &block
|
37
|
+
#{mod.name}.#{meth}(&block)
|
38
|
+
end
|
39
|
+
RUBY
|
40
|
+
} + %w[enabled? disabled?].map{ |meth|
|
41
|
+
<<-RUBY
|
42
|
+
def #{snake_name}_#{meth} &block
|
43
|
+
#{mod.name}.#{meth}(&block)
|
44
|
+
end
|
45
|
+
RUBY
|
46
|
+
}).join("\n")
|
47
|
+
|
48
|
+
meta_rib = if respond_to?(:singleton_class)
|
49
|
+
Rib.singleton_class
|
50
|
+
else
|
51
|
+
class << Rib; self; end
|
52
|
+
end
|
53
|
+
|
54
|
+
meta_rib.module_eval(code, __FILE__, __LINE__)
|
55
|
+
end
|
56
|
+
end
|
data/lib/rib/runner.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
|
2
|
+
require 'rib'
|
3
|
+
|
4
|
+
module Rib::Runner
|
5
|
+
module_function
|
6
|
+
def name
|
7
|
+
File.basename($PROGRAM_NAME)
|
8
|
+
end
|
9
|
+
|
10
|
+
def options
|
11
|
+
{ # Ruby OPTIONS
|
12
|
+
'-e, --eval LINE' =>
|
13
|
+
'Evaluate a LINE of code' ,
|
14
|
+
|
15
|
+
'-d, --debug' =>
|
16
|
+
'Set debugging flags (set $DEBUG to true)' ,
|
17
|
+
|
18
|
+
'-w, --warn' =>
|
19
|
+
'Turn warnings on for your script (set $-w to true)' ,
|
20
|
+
|
21
|
+
'-I, --include PATH' =>
|
22
|
+
'Specify $LOAD_PATH (may be used more than once)' ,
|
23
|
+
|
24
|
+
'-r, --require LIBRARY' =>
|
25
|
+
'Require the library, before executing your script' ,
|
26
|
+
|
27
|
+
# Rib OPTIONS
|
28
|
+
'-c, --config FILE' => 'Load config from FILE' ,
|
29
|
+
'-n, --no-config' => 'Suppress loading ~/.config/rib/config.rb',
|
30
|
+
'-h, --help' => 'Print this message' ,
|
31
|
+
'-v, --version' => 'Print the version' }
|
32
|
+
end
|
33
|
+
|
34
|
+
def run argv=ARGV
|
35
|
+
if command = argv.find{ |a| a =~ /^[^-]/ }
|
36
|
+
argv.delete(command)
|
37
|
+
plugin = "rib-#{command}"
|
38
|
+
path = `which #{plugin}`.strip
|
39
|
+
if path == ''
|
40
|
+
puts("Can't find `#{plugin}' in $PATH.\n" \
|
41
|
+
"Please make sure `#{plugin}' is installed.\n" \
|
42
|
+
"e.g. run `gem install #{plugin}`")
|
43
|
+
else
|
44
|
+
load(path)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
start(*argv)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def start *argv
|
52
|
+
unused = parse(argv.dup)
|
53
|
+
warn "#{name}: Unused arguments: #{unused.inspect}" unless unused.empty?
|
54
|
+
Rib.shell.loop
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse argv
|
58
|
+
unused = []
|
59
|
+
until argv.empty?
|
60
|
+
case arg = argv.shift
|
61
|
+
when /-e=?(.*)/, /--eval=?(.*)/
|
62
|
+
eval($1 || argv.shift, __FILE__, __LINE__)
|
63
|
+
|
64
|
+
when '-d', '--debug'
|
65
|
+
$DEBUG = true
|
66
|
+
|
67
|
+
when '-w', '--warn'
|
68
|
+
$-w = true
|
69
|
+
|
70
|
+
when /-I=?(.*)/, /--include=?(.*)/
|
71
|
+
paths = ($1 || argv.shift).split(':')
|
72
|
+
$LOAD_PATH.unshift(*paths)
|
73
|
+
|
74
|
+
when /-r=?(.*)/, /--require=?(.*)/
|
75
|
+
require($1 || argv.shift)
|
76
|
+
|
77
|
+
when /-c=?(.*)/, /--config=?(.*)/
|
78
|
+
Rib.config[:config] = $1 || argv.shift
|
79
|
+
|
80
|
+
when '-n', '--no-config'
|
81
|
+
Rib.config.delete(:config)
|
82
|
+
|
83
|
+
when '-h', '--help'
|
84
|
+
puts(help)
|
85
|
+
exit
|
86
|
+
|
87
|
+
when '-v', '--version'
|
88
|
+
require 'rib/version'
|
89
|
+
puts(Rib::VERSION)
|
90
|
+
exit
|
91
|
+
|
92
|
+
else
|
93
|
+
unused << arg
|
94
|
+
end
|
95
|
+
end
|
96
|
+
unused
|
97
|
+
end
|
98
|
+
|
99
|
+
def help
|
100
|
+
maxn = options.keys .map(&:size).max
|
101
|
+
maxd = options.values.map(&:size).max
|
102
|
+
"Usage: #{name} [Ruby OPTIONS] [Rib COMMAND] [Rib OPTIONS]\n" +
|
103
|
+
options.map{ |name, desc|
|
104
|
+
sprintf(" %-*s %-*s", maxn, name, maxd, desc) }.join("\n")
|
105
|
+
end
|
106
|
+
end
|
data/lib/rib/shell.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
require 'rib/plugin'
|
3
|
+
require 'rib/api'
|
4
|
+
|
5
|
+
class Rib::Shell
|
6
|
+
include Rib::API
|
7
|
+
trap('INT'){ raise Interrupt }
|
8
|
+
|
9
|
+
def self.use mod
|
10
|
+
include mod
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :config
|
14
|
+
def initialize(config={})
|
15
|
+
self.config = {
|
16
|
+
:name => 'rib' ,
|
17
|
+
:result_prompt => '=> ' ,
|
18
|
+
:prompt => '>> ' ,
|
19
|
+
:binding => TOPLEVEL_BINDING ,
|
20
|
+
:exit => [nil, 'exit', 'quit'] ,
|
21
|
+
:line => 1
|
22
|
+
}.merge(config)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Loops shell until user exits
|
26
|
+
def loop
|
27
|
+
before_loop
|
28
|
+
@running = true
|
29
|
+
in_loop
|
30
|
+
self
|
31
|
+
ensure
|
32
|
+
@running = false
|
33
|
+
after_loop
|
34
|
+
end
|
35
|
+
|
36
|
+
def running?
|
37
|
+
!!@running
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
attr_writer :config
|
42
|
+
attr_accessor :error_raised
|
43
|
+
end
|
data/lib/rib/test.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
require 'bacon'
|
3
|
+
require 'rr'
|
4
|
+
require 'fileutils'
|
5
|
+
Bacon.summary_on_exit
|
6
|
+
include RR::Adapters::RRMethods
|
7
|
+
|
8
|
+
require 'rib'
|
9
|
+
|
10
|
+
shared :rib do
|
11
|
+
before do
|
12
|
+
Rib.disable_plugins
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
RR.verify
|
17
|
+
Rib.enable_plugins
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Kernel
|
22
|
+
def eq? rhs
|
23
|
+
self == rhs
|
24
|
+
end
|
25
|
+
end
|
data/lib/rib/version.rb
ADDED
data/lib/rib/zore.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
require 'rib'
|
3
|
+
|
4
|
+
module Rib::Anchor
|
5
|
+
include Rib::Plugin
|
6
|
+
Shell.use(self)
|
7
|
+
|
8
|
+
def loop_eval(str)
|
9
|
+
case obj_or_binding = (Rib.vars[:anchor] ||= []).last
|
10
|
+
when NilClass
|
11
|
+
super
|
12
|
+
|
13
|
+
when Binding
|
14
|
+
@binding = obj_or_binding
|
15
|
+
super
|
16
|
+
|
17
|
+
else
|
18
|
+
obj_or_binding.instance_eval(str, "(#{config[:name]})", config[:line])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def prompt
|
23
|
+
if Rib.const_defined?(:Color) && kind_of?(Rib::Color) &&
|
24
|
+
obj_or_binding = (Rib.vars[:anchor] ||= []).last
|
25
|
+
|
26
|
+
super.sub(config[:name], format_color(obj_or_binding, config[:name]))
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# if the object is the same, then we're exiting from an anchor,
|
33
|
+
# so don't print anything.
|
34
|
+
def print_result result
|
35
|
+
super unless !result.nil? &&
|
36
|
+
result.object_id == Rib.vars[:anchor_last].object_id
|
37
|
+
end
|
38
|
+
|
39
|
+
module Imp
|
40
|
+
def short_inspect obj_or_binding
|
41
|
+
obj_or_binding.inspect[0..9]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module AnchorImp
|
46
|
+
def anchor obj_or_binding
|
47
|
+
return if Rib::Anchor.disabled?
|
48
|
+
|
49
|
+
(Rib.vars[:anchor] ||= []) << obj_or_binding
|
50
|
+
name = Rib::P.short_inspect(obj_or_binding)
|
51
|
+
|
52
|
+
Rib.shells <<
|
53
|
+
Rib::Shell.new(Rib.config.merge(
|
54
|
+
:name => name,
|
55
|
+
:prompt => "#{name}(#{Rib.vars[:anchor].size})" +
|
56
|
+
(Rib.config[:prompt] || '>> ')))
|
57
|
+
|
58
|
+
Rib.shell.loop
|
59
|
+
|
60
|
+
ensure
|
61
|
+
# stores to check if we're exiting from an anchor
|
62
|
+
Rib.vars[:anchor_last] = Rib.vars[:anchor].pop
|
63
|
+
Rib.shells.pop
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Plugin.extend(Imp)
|
68
|
+
Rib .extend(AnchorImp)
|
69
|
+
end
|