rib 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +6 -0
  2. data/.gitmodules +3 -0
  3. data/.travis.yml +9 -0
  4. data/2011-02-28.md +203 -0
  5. data/CHANGES +86 -0
  6. data/CONTRIBUTORS +2 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +201 -0
  9. data/README +190 -0
  10. data/README.md +190 -0
  11. data/Rakefile +20 -0
  12. data/TODO +6 -0
  13. data/lib/rib.rb +42 -0
  14. data/lib/rib/all.rb +4 -0
  15. data/lib/rib/api.rb +105 -0
  16. data/lib/rib/core.rb +5 -0
  17. data/lib/rib/core/completion.rb +22 -0
  18. data/lib/rib/core/history_file.rb +38 -0
  19. data/lib/rib/core/readline.rb +19 -0
  20. data/lib/rib/core/underscore.rb +53 -0
  21. data/lib/rib/debug.rb +3 -0
  22. data/lib/rib/more.rb +12 -0
  23. data/lib/rib/more/color.rb +98 -0
  24. data/lib/rib/more/multiline.rb +77 -0
  25. data/lib/rib/more/multiline_history.rb +31 -0
  26. data/lib/rib/more/multiline_history_file.rb +37 -0
  27. data/lib/rib/more/squeeze_history.rb +37 -0
  28. data/lib/rib/more/strip_backtrace.rb +43 -0
  29. data/lib/rib/plugin.rb +56 -0
  30. data/lib/rib/runner.rb +106 -0
  31. data/lib/rib/shell.rb +43 -0
  32. data/lib/rib/test.rb +25 -0
  33. data/lib/rib/version.rb +4 -0
  34. data/lib/rib/zore.rb +3 -0
  35. data/lib/rib/zore/anchor.rb +69 -0
  36. data/lib/rib/zore/edit.rb +33 -0
  37. data/rib.gemspec +104 -0
  38. data/screenshot.png +0 -0
  39. data/task/.gitignore +1 -0
  40. data/task/gemgem.rb +182 -0
  41. data/test/core/test_completion.rb +18 -0
  42. data/test/core/test_history_file.rb +57 -0
  43. data/test/core/test_readline.rb +21 -0
  44. data/test/core/test_underscore.rb +41 -0
  45. data/test/more/test_color.rb +28 -0
  46. data/test/more/test_squeeze_history.rb +43 -0
  47. data/test/test_api.rb +20 -0
  48. data/test/test_plugin.rb +38 -0
  49. data/test/test_shell.rb +82 -0
  50. 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,4 @@
1
+
2
+ module Rib
3
+ VERSION = '0.1.0'
4
+ end
@@ -0,0 +1,3 @@
1
+
2
+ require 'rib/zore/anchor'
3
+ require 'rib/zore/edit'
@@ -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