rib 1.1.6 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 36e9907e98417b88befb05f1493f23737418dd34
4
- data.tar.gz: a3b24ca77822b8f6aa5877a173303cde0b329127
3
+ metadata.gz: 727360f1321ba8190d0b2316745c26d5b1e26897
4
+ data.tar.gz: 1ae6ffef657e408088ee7778cd764e85a90f7697
5
5
  SHA512:
6
- metadata.gz: 9bc4ead99bd2d24251849fabd4c03005fbd2ddb71dd704710dc6ebdbe22e867677c39ee665d18e27bae8f07b224bbcfee9fdb1b681a7121a17a90b3ca7692e59
7
- data.tar.gz: 66c7f94e4549d4f63509ab8848f9227cd32660f31b98bc3ce380ff9b9431cbf6ea28c56b50a6fec9052fbf07f7f1643a161cc8a81d4ce97130fa69250e18fd16
6
+ metadata.gz: 50beef0233c1d1ef514f19f660be5a3941bf564041f69fa740c2e4663cda721e09c7310d59732dacb5d4c12f0f475160f1ebb84b36aaaa5aceb91d39078792db
7
+ data.tar.gz: 1c68d1f84c0d2c5b26e6302b75fac4aebcdc4a549b8037feab9dda1e38d0d8bf2e0e1dbd8d03b56bca5664a8d212e86b5f1229945fc512ae2d13c4bf6481ac23
data/.gitignore CHANGED
@@ -1,2 +1 @@
1
- pkg
2
- *.rbc
1
+ /pkg/
@@ -1,11 +1,13 @@
1
1
  before_install: 'git submodule update --init'
2
2
  script: 'ruby -r bundler/setup -S rake test'
3
3
 
4
- env:
5
- - 'RBXOPT=-X19'
6
-
7
4
  rvm:
8
5
  - 1.9.3
9
6
  - 2.0.0
10
- - rbx-head
11
- - jruby-head
7
+ - 2.1.0
8
+ - rbx
9
+ - jruby
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: jruby
data/CHANGES.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # CHANGES
2
2
 
3
+ ## Rib 1.2.0 -- 2014-01-17
4
+
5
+ * We no longer really eval on TOPLEVEL_BINDING, but a private binding
6
+ derived from TOPLEVEL_BINDING. This is due to RubyGems bin stub would
7
+ actually pollute TOPLEVEL_BINDING, leaving `str` and `version` as
8
+ local variables. I would like to avoid them, thus introducing this change.
9
+ Please let me know if this breaks anything, thanks!
10
+
11
+ * [core/multiline] Fixed a multiline detection for Rubinius.
12
+
3
13
  ## Rib 1.1.6 -- 2013-08-14
4
14
 
5
15
  * [more/color] Fixed inspecting recursive array and hash.
data/Gemfile CHANGED
@@ -10,6 +10,11 @@ gem 'muack'
10
10
  gem 'bond'
11
11
  gem 'hirb'
12
12
 
13
- platforms(:ruby) do
13
+ platforms :ruby do
14
14
  gem 'readline_buffer'
15
15
  end
16
+
17
+ platforms :rbx do
18
+ gem 'rubysl-singleton' # used in rake
19
+ gem 'rubysl-readline' # we need readline extension
20
+ end
data/README.md CHANGED
@@ -228,7 +228,7 @@ simple, simpler than rib-rails.
228
228
 
229
229
  Apache License 2.0
230
230
 
231
- Copyright (c) 2011-2012, Lin Jen-Shin (godfat)
231
+ Copyright (c) 2011-2014, Lin Jen-Shin (godfat)
232
232
 
233
233
  Licensed under the Apache License, Version 2.0 (the "License");
234
234
  you may not use this file except in compliance with the License.
data/Rakefile CHANGED
@@ -1,18 +1,14 @@
1
1
 
2
- require "#{dir = File.dirname(__FILE__)}/task/gemgem"
3
- Gemgem.dir = dir
4
-
5
- ($LOAD_PATH << File.expand_path("#{Gemgem.dir}/lib")).uniq!
6
-
7
- desc 'Generate gemspec'
8
- task 'gem:spec' do
9
- Gemgem.spec = Gemgem.create do |s|
10
- require 'rib/version'
11
- s.name = 'rib'
12
- s.version = Rib::VERSION
13
-
14
- %w[].each{ |g| s.add_runtime_dependency(g) }
15
- end
2
+ begin
3
+ require "#{dir = File.dirname(__FILE__)}/task/gemgem"
4
+ rescue LoadError
5
+ sh 'git submodule update --init'
6
+ exec Gem.ruby, '-S', $PROGRAM_NAME, *ARGV
7
+ end
16
8
 
17
- Gemgem.write
9
+ Gemgem.init(dir) do |s|
10
+ require 'rib/version'
11
+ s.name = 'rib'
12
+ s.version = Rib::VERSION
13
+ %w[].each{ |g| s.add_runtime_dependency(g) }
18
14
  end
@@ -15,7 +15,7 @@ module Rib::Rack
15
15
  Rib.abort("Error: Cannot find config.ru") unless rack?
16
16
  app, _ = Rack::Builder.parse_file('config.ru')
17
17
  self.app = app
18
- Rib.shell.config[:binding].eval('def app; Rib::Rack.app; end')
18
+ Rib.shell.eval_binding.eval('def app; Rib::Rack.app; end')
19
19
  Rib.say("Access your app via :app method")
20
20
  end
21
21
 
@@ -101,7 +101,7 @@ module Rib::Rails
101
101
 
102
102
  # rails 3.2
103
103
  if ::Rails.const_defined?(:ConsoleMethods)
104
- Rib.shell.config[:binding].eval('extend ::Rails::ConsoleMethods')
104
+ Rib.shell.eval_binding.eval('extend ::Rails::ConsoleMethods')
105
105
  end
106
106
  end
107
107
 
@@ -48,6 +48,7 @@ module Rib::Multiline
48
48
  # mri and rubinius
49
49
  "syntax error, unexpected \\$end" ,
50
50
  # rubinius
51
+ "expecting keyword_end" ,
51
52
  "expecting \\$end" ,
52
53
  "expecting '.+'( or '.+')*" ,
53
54
  "missing '.+' for '.+' started on line \\d+"].join('|'))
@@ -19,3 +19,9 @@ module Rib::Readline
19
19
  ::Readline.readline(prompt, true)
20
20
  end
21
21
  end
22
+
23
+ unless ::Readline::HISTORY.respond_to?(:last)
24
+ def (::Readline::HISTORY).last
25
+ self[-1]
26
+ end
27
+ end
@@ -11,7 +11,6 @@ module Rib::SqueezeHistory
11
11
  def loop_once
12
12
  return super if SqueezeHistory.disabled?
13
13
  begin
14
- # TODO: history[-1] is MRI 1.9+
15
14
  input, last_input = history[-1], history[-2]
16
15
  rescue IndexError # EditLine is really broken, to_a is needed for it
17
16
  array = history.to_a
@@ -35,7 +34,6 @@ module Rib::SqueezeHistory
35
34
 
36
35
  private
37
36
  def squeezed_history
38
- # TODO: history.inject is MRI 1.9+
39
37
  history.to_a.inject([]){ |result, item|
40
38
  if result.last == item || item.strip == ''
41
39
  result
@@ -7,12 +7,12 @@ module Rib::Anchor
7
7
 
8
8
  # --------------- Rib API ---------------
9
9
 
10
- def loop_eval str
10
+ def loop_eval input
11
11
  return super if Rib::Anchor.disabled?
12
12
  if eval_binding.kind_of?(Binding)
13
13
  super
14
14
  else
15
- eval_binding.instance_eval(str, "(#{name})", line)
15
+ eval_binding.instance_eval(input, "(#{name})", line)
16
16
  end
17
17
  end
18
18
 
@@ -53,6 +53,18 @@ module Rib::Anchor
53
53
  end
54
54
 
55
55
  module Imp
56
+ # Enter an interactive Rib shell based on a particular context.
57
+ #
58
+ # @api public
59
+ # @param obj_or_binding [Object, Binding] The context of the shell.
60
+ # @param opts [Hash] The config hash passed to the newly created shell.
61
+ # See {Rib::Shell#initialize} for all possible options.
62
+ # @return [Rib::Skip] This is the mark telling Rib do not print anything.
63
+ # It's only used internally in Rib.
64
+ # @see Rib::Shell#initialize
65
+ # @example
66
+ # Rib.anchor binding
67
+ # Rib.anchor 123
56
68
  def anchor obj_or_binding, opts={}
57
69
  return if Rib::Anchor.disabled?
58
70
 
@@ -66,7 +66,7 @@ module Rib::Runner
66
66
 
67
67
  def run argv=ARGV
68
68
  (@running_commands ||= []) << Rib.config[:name]
69
- unused = parse(argv)
69
+ unused, e = parse(argv)
70
70
  # if it's running a Rib command, the loop would be inside Rib itself
71
71
  # so here we only parse args for the command
72
72
  return if @running_commands.pop != 'rib'
@@ -74,12 +74,13 @@ module Rib::Runner
74
74
  # not any other Rib command
75
75
  Rib.warn("Unused arguments: #{unused.inspect}") unless unused.empty?
76
76
  require 'rib/core' if Rib.config.delete(:mimic_irb)
77
+ Rib.shell.eval_binding.eval(e, __FILE__, __LINE__)
77
78
  loop
78
79
  end
79
80
 
80
81
  def loop retry_times=5
81
82
  Rib.shell.loop
82
- rescue Exception => e
83
+ rescue => e
83
84
  if retry_times <= 0
84
85
  Rib.warn("Error: #{e}. Too many retries, give up.")
85
86
  elsif Rib.shells.last.running?
@@ -96,19 +97,19 @@ module Rib::Runner
96
97
  end
97
98
 
98
99
  def parse argv
99
- unused = []
100
+ unused, e = [], ''
100
101
  until argv.empty?
101
102
  case arg = argv.shift
102
103
  when /^-e=?(.+)?/, /^--eval=?(.+)?/
103
- eval($1 || argv.shift, TOPLEVEL_BINDING, __FILE__, __LINE__)
104
+ e = $1 || argv.shift || ''
104
105
 
105
106
  when /^-d/, '--debug'
106
107
  $DEBUG = true
107
- argv.unshift("-#{arg[2..-1]}") if arg.size > 2
108
+ parse_next(argv, arg)
108
109
 
109
110
  when /^-w/, '--warn'
110
111
  $-w, $VERBOSE = true, true
111
- argv.unshift("-#{arg[2..-1]}") if arg.size > 2
112
+ parse_next(argv, arg)
112
113
 
113
114
  when /^-I=?(.+)?/, /^--include=?(.+)?/
114
115
  paths = ($1 || argv.shift).split(':')
@@ -122,7 +123,7 @@ module Rib::Runner
122
123
 
123
124
  when /^-n/, '--no-config'
124
125
  Rib.config.delete(:config)
125
- argv.unshift("-#{arg[2..-1]}") if arg.size > 2
126
+ parse_next(argv, arg)
126
127
 
127
128
  when /^-h/, '--help'
128
129
  puts(help)
@@ -140,12 +141,17 @@ module Rib::Runner
140
141
  unused << arg
141
142
  end
142
143
  end
143
- unused
144
+ [unused, e]
145
+ end
146
+
147
+ def parse_next argv, arg
148
+ argv.unshift("-#{arg[2..-1]}") if arg.size > 2
144
149
  end
145
150
 
146
151
  def help
147
- maxn = options.transpose.first.map(&:size).max
148
- maxd = options.transpose.last .map(&:size).max
152
+ optt = options.transpose
153
+ maxn = optt.first.map(&:size).max
154
+ maxd = optt.last .map(&:size).max
149
155
  "Usage: #{Rib.config[:name]}" \
150
156
  " [ruby OPTIONS] [rib OPTIONS] [rib COMMANDS]\n" +
151
157
  options.map{ |(name, desc)|
@@ -11,13 +11,36 @@ class Rib::Shell
11
11
  end
12
12
 
13
13
  attr_reader :config
14
+
15
+ # Create a new shell.
16
+ #
17
+ # @api public
18
+ # @param config [Hash] The config of the shell.
19
+ # @option config [String] :config ('~/.rib/config.rb')
20
+ # The path to Rib config file.
21
+ # @option config [String] :name ('rib')
22
+ # The name of the shell. Used for Rib application.
23
+ # @option config [String] :result_prompt ('=> ')
24
+ # @option config [String] :prompt ('>> ')
25
+ # @option config [Binding, Object] :binding (new_private_binding)
26
+ # The context of the shell. Could be an Object.
27
+ # @option config [Array<String>] :exit ([nil])
28
+ # The keywords to exit the shell. `nil` means EOF (ctrl+d).
29
+ # @option config [Fixnum] :line (1) The beginning of line number.
30
+ # @option config [String] :history_file ('~/.rib/config/history.rb')
31
+ # (Only if {Rib::History} plugin is used) The path to history file.
32
+ # @option config [Fixnum] :history_size (500)
33
+ # (Only if {Rib::History} plugin is used) Maximum numbers of history.
34
+ # @option config [Hash<Class, Symbol>] :color (...)
35
+ # (Only if {Rib::Color} plugin is used) Data type colors mapping.
36
+ # @option config [String] :autoindent_spaces (' ')
37
+ # (Only if {Rib::Autoindent} plugin is used) The indented string.
14
38
  def initialize(config={})
15
- self.config = {
16
- :result_prompt => '=> ' ,
17
- :prompt => '>> ' ,
18
- :binding => TOPLEVEL_BINDING,
19
- :exit => [nil] ,
20
- :line => 1 }.merge(config)
39
+ config[:binding] ||= new_private_binding
40
+ self.config = {:result_prompt => '=> ',
41
+ :prompt => '>> ',
42
+ :exit => [nil],
43
+ :line => 1 }.merge(config)
21
44
  @running = false
22
45
  end
23
46
 
@@ -41,4 +64,16 @@ class Rib::Shell
41
64
 
42
65
  protected
43
66
  attr_writer :config
67
+
68
+ private
69
+ # Avoid namespace pollution from rubygems bin stub.
70
+ # To be specific, version and str.
71
+ def new_private_binding
72
+ TOPLEVEL_BINDING.eval <<-RUBY
73
+ def main; binding; end # anyway to define <main> method?
74
+ ret = main
75
+ Object.send(:remove_method, 'main') # never pollute anything
76
+ ret
77
+ RUBY
78
+ end
44
79
  end
@@ -66,18 +66,9 @@ shared :rib do
66
66
 
67
67
  def stub_readline
68
68
  stub(::Readline).readline(is_a(String), true){
69
- (::Readline::HISTORY << str.chomp)[-1]
69
+ (::Readline::HISTORY << str.chomp).last
70
70
  }
71
71
  end
72
-
73
- # TODO: history.clear is MRI 1.9+
74
- def clear_history history
75
- if history.respond_to?(:clear)
76
- history.clear
77
- else
78
- history.pop until history.empty?
79
- end
80
- end
81
72
  end
82
73
 
83
74
  module Kernel
@@ -89,4 +80,5 @@ end
89
80
  Rib::Blackhole = Object.new
90
81
  b = Rib::Blackhole.singleton_class
91
82
  b.instance_methods(true).each{ |m|
92
- b.send(:undef_method, m) unless [:object_id, :__send__].include?(m) }
83
+ b.send(:undef_method, m) unless
84
+ [:object_id, :__send__, :__id__].include?(m) }
@@ -3,8 +3,8 @@ shared :setup_multiline do
3
3
  def setup_shell
4
4
  @shell = Rib::Shell.new(
5
5
  :binding => Object.new.instance_eval{binding}).before_loop
6
- stub(@shell).print.with_any_args
7
- stub(@shell).puts .with_any_args
6
+ stub(@shell).print{}.with_any_args
7
+ stub(@shell).puts{} .with_any_args
8
8
  end
9
9
 
10
10
  def setup_input str
@@ -19,15 +19,15 @@ shared :setup_multiline do
19
19
 
20
20
  def input str
21
21
  setup_input(str)
22
- mock(@shell).throw(:rib_multiline).proxy
22
+ mock(@shell).throw(:rib_multiline)
23
23
  end
24
24
 
25
25
  def input_done str, err=nil
26
26
  setup_input(str)
27
27
  if err
28
- mock(@shell).print_eval_error(is_a(err))
28
+ mock(@shell).print_eval_error(is_a(err)){}
29
29
  else
30
- mock(@shell).print_result(is_a(Object))
30
+ mock(@shell).print_result(is_a(Object)){}
31
31
  end
32
32
  @shell.loop_once
33
33
  true.should.eq true
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Rib
3
- VERSION = '1.1.6'
3
+ VERSION = '1.2.0'
4
4
  end
@@ -1,12 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # stub: rib 1.2.0 ruby lib
2
3
 
3
4
  Gem::Specification.new do |s|
4
5
  s.name = "rib"
5
- s.version = "1.1.6"
6
+ s.version = "1.2.0"
6
7
 
7
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib"]
8
10
  s.authors = ["Lin Jen-Shin (godfat)"]
9
- s.date = "2013-08-14"
11
+ s.date = "2014-01-17"
10
12
  s.description = "Ruby-Interactive-ruBy -- Yet another interactive Ruby shell\n\nRib is based on the design of [ripl][] and the work of [ripl-rc][], some of\nthe features are also inspired by [pry][]. The aim of Rib is to be fully\nfeatured and yet very easy to opt-out or opt-in other features. It shall\nbe simple, lightweight and modular so that everyone could customize Rib.\n\n[ripl]: https://github.com/cldwalker/ripl\n[ripl-rc]: https://github.com/godfat/ripl-rc\n[pry]: https://github.com/pry/pry"
11
13
  s.email = ["godfat (XD) godfat.org"]
12
14
  s.executables = [
@@ -69,7 +71,7 @@ Gem::Specification.new do |s|
69
71
  "lib/rib/version.rb",
70
72
  "rib.gemspec",
71
73
  "screenshot.png",
72
- "task/.gitignore",
74
+ "task/README.md",
73
75
  "task/gemgem.rb",
74
76
  "test/core/test_completion.rb",
75
77
  "test/core/test_history.rb",
@@ -81,11 +83,11 @@ Gem::Specification.new do |s|
81
83
  "test/more/test_multiline_history.rb",
82
84
  "test/test_api.rb",
83
85
  "test/test_plugin.rb",
86
+ "test/test_runner.rb",
84
87
  "test/test_shell.rb"]
85
88
  s.homepage = "https://github.com/godfat/rib"
86
89
  s.licenses = ["Apache License 2.0"]
87
- s.require_paths = ["lib"]
88
- s.rubygems_version = "2.0.6"
90
+ s.rubygems_version = "2.2.1"
89
91
  s.summary = "Ruby-Interactive-ruBy -- Yet another interactive Ruby shell"
90
92
  s.test_files = [
91
93
  "test/core/test_completion.rb",
@@ -98,5 +100,6 @@ Gem::Specification.new do |s|
98
100
  "test/more/test_multiline_history.rb",
99
101
  "test/test_api.rb",
100
102
  "test/test_plugin.rb",
103
+ "test/test_runner.rb",
101
104
  "test/test_shell.rb"]
102
105
  end
@@ -0,0 +1,54 @@
1
+ # Gemgem
2
+
3
+ ## DESCRIPTION:
4
+
5
+ Provided tasks:
6
+
7
+ rake clean # Remove ignored files
8
+ rake gem:build # Build gem
9
+ rake gem:install # Install gem
10
+ rake gem:release # Release gem
11
+ rake gem:spec # Generate gemspec
12
+ rake test # Run tests in memory
13
+
14
+ ## REQUIREMENTS:
15
+
16
+ * Tested with MRI (official CRuby) 1.9.3, 2.0.0, Rubinius and JRuby.
17
+
18
+ ## INSTALLATION:
19
+
20
+ git submodule add git://github.com/godfat/gemgem.git task
21
+
22
+ And in Rakefile:
23
+
24
+ ``` ruby
25
+ begin
26
+ require "#{dir = File.dirname(__FILE__)}/task/gemgem"
27
+ rescue LoadError
28
+ sh 'git submodule update --init'
29
+ exec Gem.ruby, '-S', $PROGRAM_NAME, *ARGV
30
+ end
31
+
32
+ Gemgem.init(dir) do |s|
33
+ s.name = 'your-gem'
34
+ s.version = '0.1.0'
35
+ end
36
+ ```
37
+
38
+ ## LICENSE:
39
+
40
+ Apache License 2.0
41
+
42
+ Copyright (c) 2011-2013, Lin Jen-Shin (godfat)
43
+
44
+ Licensed under the Apache License, Version 2.0 (the "License");
45
+ you may not use this file except in compliance with the License.
46
+ You may obtain a copy of the License at
47
+
48
+ <http://www.apache.org/licenses/LICENSE-2.0>
49
+
50
+ Unless required by applicable law or agreed to in writing, software
51
+ distributed under the License is distributed on an "AS IS" BASIS,
52
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
53
+ See the License for the specific language governing permissions and
54
+ limitations under the License.
@@ -1,14 +1,26 @@
1
1
 
2
- require 'pathname'
3
-
4
2
  module Gemgem
5
3
  class << self
6
- attr_accessor :dir, :spec
4
+ attr_accessor :dir, :spec, :spec_create
7
5
  end
8
6
 
9
7
  module_function
8
+ def gem_tag ; "#{spec.name}-#{spec.version}" ; end
9
+ def gem_path ; "#{pkg_dir}/#{gem_tag}.gem" ; end
10
+ def spec_path ; "#{dir}/#{spec.name}.gemspec" ; end
11
+ def pkg_dir ; "#{dir}/pkg" ; end
12
+ def escaped_dir; @escaped_dir ||= Regexp.escape(dir); end
13
+
14
+ def init dir, &block
15
+ self.dir = dir
16
+ $LOAD_PATH.unshift("#{dir}/lib")
17
+ ENV['RUBYLIB'] = "#{dir}/lib:#{ENV['RUBYLIB']}"
18
+ ENV['PATH'] = "#{dir}/bin:#{ENV['PATH']}"
19
+ self.spec_create = block
20
+ end
21
+
10
22
  def create
11
- yield(spec = Gem::Specification.new{ |s|
23
+ spec = Gem::Specification.new do |s|
12
24
  s.authors = ['Lin Jen-Shin (godfat)']
13
25
  s.email = ['godfat (XD) godfat.org']
14
26
 
@@ -16,163 +28,144 @@ module Gemgem
16
28
  s.summary = description.first
17
29
  s.license = readme['LICENSE'].sub(/.+\n\n/, '').lines.first.strip
18
30
 
19
- s.rubygems_version = Gem::VERSION
20
- s.date = Time.now.strftime('%Y-%m-%d')
21
- s.files = gem_files
22
- s.test_files = gem_files.grep(%r{^test/(.+?/)*test_.+?\.rb$})
23
- s.executables = Dir['bin/*'].map{ |f| File.basename(f) }
24
- s.require_paths = %w[lib]
25
- })
26
- spec.homepage ||= "https://github.com/godfat/#{spec.name}"
27
- spec
31
+ s.date = Time.now.strftime('%Y-%m-%d')
32
+ s.files = gem_files
33
+ s.test_files = test_files
34
+ s.executables = bin_files
35
+ end
36
+ spec_create.call(spec)
37
+ spec.homepage = "https://github.com/godfat/#{spec.name}"
38
+ self.spec = spec
28
39
  end
29
40
 
30
- def readme
31
- path = %w[README.md README].find{ |name|
32
- File.exist?("#{Gemgem.dir}/#{name}")
33
- }
34
- @readme ||=
35
- if path
36
- ps = "##{File.read(path)}".
37
- scan(/((#+)[^\n]+\n\n.+?(?=(\n\n\2[^#\n]+\n)|\Z))/m).map(&:first)
38
- ps.inject('HEADER' => ps.first){ |r, s, i|
39
- r[s[/\w+/]] = s
40
- r
41
- }
41
+ def write
42
+ File.open(spec_path, 'w'){ |f| f << split_lines(spec.to_ruby) }
43
+ end
44
+
45
+ def split_lines ruby
46
+ ruby.gsub(/(.+?)\s*=\s*\[(.+?)\]/){ |s|
47
+ if $2.index(',')
48
+ "#{$1} = [\n #{$2.split(',').map(&:strip).join(",\n ")}]"
42
49
  else
43
- {}
50
+ s
44
51
  end
52
+ }
45
53
  end
46
54
 
47
- def description
48
- @description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines
55
+ def strip_path path
56
+ strip_home_path(strip_cwd_path(path))
49
57
  end
50
58
 
51
- def changes
52
- path = %w[CHANGES.md CHANGES].find{ |name|
53
- File.exist?("#{Gemgem.dir}/#{name}")
54
- }
55
- @changes ||=
56
- if path
57
- date = '\d+{4}\-\d+{2}\-\d{2}'
58
- File.read(path).match(
59
- /([^\n]+#{date}\n\n(.+?))(?=\n\n[^\n]+#{date}\n|\Z)/m)[1]
60
- else
61
- ''
62
- end
59
+ def strip_home_path path
60
+ path.sub(ENV['HOME'], '~')
63
61
  end
64
62
 
65
- def ann_md
66
- "#{readme['HEADER'].sub(/([\w\-]+)/, "[\\1](#{spec.homepage})")}\n\n" \
67
- "##{readme['DESCRIPTION'][/[^\n]+\n\n[^\n]+/]}\n\n" \
68
- "### CHANGES:\n\n" \
69
- "###{changes}\n\n" \
70
- "##{readme['INSTALLATION']}\n\n" +
71
- if readme['SYNOPSIS'] then "##{readme['SYNOPSIS'][/[^\n]+\n\n[^\n]+/]}"
72
- else '' end
63
+ def strip_cwd_path path
64
+ path.sub(Dir.pwd, '.')
73
65
  end
74
66
 
75
- def ann_html
76
- gem 'nokogiri'
77
- gem 'kramdown'
78
-
79
- IO.popen('kramdown', 'r+') do |md|
80
- md.puts Gemgem.ann_md
81
- md.close_write
82
- require 'nokogiri'
83
- html = Nokogiri::XML.parse("<gemgem>#{md.read}</gemgem>")
84
- html.css('*').each{ |n| n.delete('id') }
85
- html.root.children.to_html
86
- end
67
+ def git *args
68
+ `git --git-dir=#{dir}/.git #{args.join(' ')}`
87
69
  end
88
70
 
89
- def ann_email
90
- "#{readme['HEADER'].sub(/([\w\-]+)/, "\\1 <#{spec.homepage}>")}\n\n" \
91
- "#{readme['DESCRIPTION']}\n\n" \
92
- "#{readme['INSTALLATION']}\n\n" +
93
- if readme['SYNOPSIS'] then "##{readme['SYNOPSIS']}\n\n" else '' end +
94
- "## CHANGES:\n\n" \
95
- "##{changes}\n\n"
71
+ def sh_git *args
72
+ Rake.sh('git', "--git-dir=#{dir}/.git", *args)
96
73
  end
97
74
 
98
- def gem_tag
99
- "#{spec.name}-#{spec.version}"
75
+ def sh_gem *args
76
+ Rake.sh(Gem.ruby, '-S', 'gem', *args)
100
77
  end
101
78
 
102
- def write
103
- File.open("#{dir}/#{spec.name}.gemspec", 'w'){ |f|
104
- f << split_lines(spec.to_ruby) }
79
+ def glob path=dir
80
+ Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
105
81
  end
106
82
 
107
- def split_lines ruby
108
- ruby.gsub(/(.+?)\s*=\s*\[(.+?)\]/){ |s|
109
- if $2.index(',')
110
- "#{$1} = [\n #{$2.split(',').map(&:strip).join(",\n ")}]"
83
+ def readme
84
+ @readme ||=
85
+ if (path = "#{Gemgem.dir}/README.md") && File.exist?(path)
86
+ ps = "##{File.read(path)}".
87
+ scan(/((#+)[^\n]+\n\n.+?(?=(\n\n\2[^#\n]+\n)|\Z))/m).map(&:first)
88
+ ps.inject('HEADER' => ps.first){ |r, s, i|
89
+ r[s[/\w+/]] = s
90
+ r
91
+ }
111
92
  else
112
- s
93
+ {}
113
94
  end
114
- }
95
+ end
96
+
97
+ def description
98
+ # JRuby String#lines is returning an enumerator
99
+ @description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines.to_a
115
100
  end
116
101
 
117
102
  def all_files
118
- @all_files ||= find_files(Pathname.new(dir)).map{ |file|
119
- if file.to_s =~ %r{\.git/|\.git$}
120
- nil
103
+ @all_files ||= fold_files(glob).sort
104
+ end
105
+
106
+ def fold_files files
107
+ files.inject([]){ |r, path|
108
+ if File.file?(path) && path !~ %r{/\.git(/|$)} &&
109
+ (rpath = path[%r{^#{escaped_dir}/(.*$)}, 1])
110
+ r << rpath
111
+ elsif File.symlink?(path) # walk into symlinks...
112
+ r.concat(fold_files(glob(File.expand_path(path,
113
+ File.readlink(path)))))
121
114
  else
122
- file.to_s
115
+ r
123
116
  end
124
- }.compact.sort
117
+ }
125
118
  end
126
119
 
127
120
  def gem_files
128
- @gem_files ||= all_files - ignored_files
121
+ @gem_files ||= all_files.reject{ |f|
122
+ f =~ ignored_pattern && !git_files.include?(f)
123
+ }
129
124
  end
130
125
 
131
- def ignored_files
132
- @ignored_file ||= all_files.select{ |path| ignore_patterns.find{ |ignore|
133
- path =~ ignore && !git_files.include?(path)}}
126
+ def test_files
127
+ @test_files ||= gem_files.grep(%r{^test/(.+?/)*test_.+?\.rb$})
128
+ end
129
+
130
+ def bin_files
131
+ @bin_files ||= gem_files.grep(%r{^bin/}).map{ |f| File.basename(f) }
134
132
  end
135
133
 
136
134
  def git_files
137
135
  @git_files ||= if File.exist?("#{dir}/.git")
138
- `git ls-files`.split("\n")
136
+ git('ls-files').split("\n")
139
137
  else
140
138
  []
141
139
  end
142
140
  end
143
141
 
144
- # protected
145
- def find_files path
146
- path.children.select(&:file?).map{|file| file.to_s[(dir.size+1)..-1]} +
147
- path.children.select(&:directory?).map{|dir| find_files(dir)}.flatten
142
+ def ignored_files
143
+ @ignored_files ||= all_files.grep(ignored_pattern)
148
144
  end
149
145
 
150
- def ignore_patterns
151
- @ignore_files ||= expand_patterns(
152
- gitignore.split("\n").reject{ |pattern|
153
- pattern.strip == ''
154
- }).map{ |pattern| %r{^([^/]+/)*?#{Regexp.escape(pattern)}(/[^/]+)*?$} }
146
+ def ignored_pattern
147
+ @ignored_pattern ||= if gitignore.empty?
148
+ /^$/
149
+ else
150
+ Regexp.new(expand_patterns(gitignore).join('|'))
151
+ end
155
152
  end
156
153
 
157
154
  def expand_patterns pathes
158
- pathes.map{ |path|
159
- if path !~ /\*/
160
- path
161
- else
162
- expand_patterns(
163
- Dir[path] +
164
- Pathname.new(File.dirname(path)).children.select(&:directory?).
165
- map{ |prefix| "#{prefix}/#{File.basename(path)}" })
166
- end
167
- }.flatten
155
+ # http://git-scm.com/docs/gitignore
156
+ pathes.flat_map{ |path|
157
+ # we didn't implement negative pattern for now
158
+ Regexp.escape(path).sub(%r{^/}, '^').gsub(/\\\*/, '[^/]*')
159
+ }
168
160
  end
169
161
 
170
162
  def gitignore
171
- if File.exist?(path = "#{dir}/.gitignore")
172
- File.read(path)
173
- else
174
- ''
175
- end
163
+ @gitignore ||= if File.exist?(path = "#{dir}/.gitignore")
164
+ File.read(path).lines.
165
+ reject{ |l| l == /^\s*(#|\s+$)/ }.map(&:strip)
166
+ else
167
+ []
168
+ end
176
169
  end
177
170
  end
178
171
 
@@ -180,22 +173,37 @@ namespace :gem do
180
173
 
181
174
  desc 'Install gem'
182
175
  task :install => [:build] do
183
- sh("#{Gem.ruby} -S gem install pkg/#{Gemgem.gem_tag}.gem")
176
+ Gemgem.sh_gem('install', Gemgem.gem_path)
184
177
  end
185
178
 
186
179
  desc 'Build gem'
187
180
  task :build => [:spec] do
188
- sh("#{Gem.ruby} -S gem build #{Gemgem.spec.name}.gemspec")
189
- sh("mkdir -p pkg")
190
- sh("mv #{Gemgem.gem_tag}.gem pkg/")
181
+ require 'fileutils'
182
+ require 'rubygems/package'
183
+ gem = nil
184
+ Dir.chdir(Gemgem.dir) do
185
+ gem = Gem::Package.build(Gem::Specification.load(Gemgem.spec_path))
186
+ FileUtils.mkdir_p(Gemgem.pkg_dir)
187
+ FileUtils.mv(gem, Gemgem.pkg_dir) # gem is relative path, but might be ok
188
+ end
189
+ puts "\e[35mGem built: \e[33m" \
190
+ "#{Gemgem.strip_path("#{Gemgem.pkg_dir}/#{gem}")}\e[0m"
191
+ end
192
+
193
+ desc 'Generate gemspec'
194
+ task :spec do
195
+ Gemgem.create
196
+ Gemgem.write
191
197
  end
192
198
 
193
199
  desc 'Release gem'
194
200
  task :release => [:spec, :check, :build] do
195
- sh("git tag #{Gemgem.gem_tag}")
196
- sh("git push")
197
- sh("git push --tags")
198
- sh("#{Gem.ruby} -S gem push pkg/#{Gemgem.gem_tag}.gem")
201
+ Gemgem.module_eval do
202
+ sh_git('tag', Gemgem.gem_tag)
203
+ sh_git('push')
204
+ sh_git('push', '--tags')
205
+ sh_gem('push', Gemgem.gem_path)
206
+ end
199
207
  end
200
208
 
201
209
  task :check do
@@ -216,53 +224,39 @@ end
216
224
 
217
225
  end # of gem namespace
218
226
 
219
- desc 'Run tests in memory'
227
+ desc 'Run tests'
220
228
  task :test do
229
+ next if Gemgem.test_files.empty?
230
+
221
231
  require 'bacon'
222
232
  Bacon.extend(Bacon::TestUnitOutput)
223
233
  Bacon.summary_on_exit
224
- $LOAD_PATH.unshift('lib')
225
- Dir['./test/**/test_*.rb'].each{ |file| require file[0..-4] }
234
+ Gemgem.test_files.each{ |file| require "#{Gemgem.dir}/#{file[0..-4]}" }
226
235
  end
227
236
 
228
- desc 'Run tests with shell'
229
- task 'test:shell', :RUBY_OPTS do |t, args|
230
- files = Dir['test/**/test_*.rb'].join(' ')
231
-
232
- cmd = [Gem.ruby, args[:RUBY_OPTS],
233
- '-I', 'lib', '-S', 'bacon', '--quiet', files]
234
-
235
- sh(cmd.compact.join(' '))
236
- end
237
+ desc 'Trash ignored files'
238
+ task :clean => ['gem:spec'] do
239
+ next if Gemgem.ignored_files.empty?
237
240
 
238
- desc 'Generate ann markdown'
239
- task 'ann:md' => ['gem:spec'] do
240
- puts Gemgem.ann_md
241
- end
241
+ require 'fileutils'
242
+ trash = File.expand_path("~/.Trash/#{Gemgem.spec.name}")
243
+ puts "Move the following files into:" \
244
+ " \e[35m#{Gemgem.strip_path(trash)}\e[33m"
242
245
 
243
- desc 'Generate ann html'
244
- task 'ann:html' => ['gem:spec'] do
245
- puts Gemgem.ann_html
246
- end
246
+ Gemgem.ignored_files.each do |file|
247
+ from = "#{Gemgem.dir}/#{file}"
248
+ to = "#{trash}/#{File.dirname(file)}"
249
+ puts Gemgem.strip_path(from)
247
250
 
248
- desc 'Generate ann email'
249
- task 'ann:email' => ['gem:spec'] do
250
- puts Gemgem.ann_email
251
- end
252
-
253
- desc 'Generate rdoc'
254
- task :doc => ['gem:spec'] do
255
- sh("yardoc -o rdoc --main README.md" \
256
- " --files #{Gemgem.spec.extra_rdoc_files.join(',')}")
257
- end
251
+ FileUtils.mkdir_p(to)
252
+ FileUtils.mv(from, to)
253
+ end
258
254
 
259
- desc 'Remove ignored files'
260
- task :clean => ['gem:spec'] do
261
- trash = "~/.Trash/#{Gemgem.spec.name}/"
262
- sh "mkdir -p #{trash}" unless File.exist?(File.expand_path(trash))
263
- Gemgem.ignored_files.each{ |file| sh "mv #{file} #{trash}" }
255
+ print "\e[0m"
264
256
  end
265
257
 
266
258
  task :default do
267
- puts `#{Gem.ruby} -S #{$PROGRAM_NAME} -T`
259
+ # Is there a reliable way to do this in the current process?
260
+ # It failed miserably before between Rake versions...
261
+ exec "#{Gem.ruby} -S #{$PROGRAM_NAME} -f #{Rake.application.rakefile} -T"
268
262
  end
@@ -5,8 +5,7 @@ require 'rib/core/history'
5
5
  shared :history do
6
6
  should '#after_loop save history' do
7
7
  inputs = %w[blih blah]
8
- # TODO: history.replace(input) is MRI 1.9+
9
- clear_history(@shell.history)
8
+ @shell.history.clear
10
9
  @shell.history.push(*inputs)
11
10
 
12
11
  @shell.after_loop
@@ -52,7 +51,7 @@ describe Rib::History do
52
51
 
53
52
  before do
54
53
  if readline?
55
- clear_history(::Readline::HISTORY)
54
+ ::Readline::HISTORY.clear
56
55
  stub_readline
57
56
  end
58
57
  @history_file = "/tmp/test_rib_#{rand}"
@@ -11,21 +11,21 @@ shared :squeeze_history do
11
11
 
12
12
  should 'loop_once squeeze history' do
13
13
  times = @input.size
14
- stub(@shell).get_input{ (@shell.history << "'#{@input.shift}'")[-1] }
15
- stub(@shell).print_result.with_any_args
14
+ stub(@shell).get_input{ (@shell.history << "'#{@input.shift}'").last }
15
+ stub(@shell).print_result{}.with_any_args
16
16
  times.times{ @shell.loop_once }
17
17
  @shell.history.to_a.should.eq %w[foo bar foo bar].map{ |i| "'#{i}'" }
18
18
  end
19
19
 
20
20
  should 'be disabled if disabled' do
21
- Rib::SqueezeHistory.disable
22
- times = @input.size
23
- input = @input.dup
24
- stub(@shell).get_input{ (@shell.history << "'#{@input.shift}'")[-1] }
25
- stub(@shell).print_result.with_any_args
26
- times.times{ @shell.loop_once }
27
- @shell.history.to_a.should.eq input.map{ |i| "'#{i}'" }
28
- Rib::SqueezeHistory.enable
21
+ Rib::SqueezeHistory.disable do
22
+ times = @input.size
23
+ input = @input.dup
24
+ stub(@shell).get_input{ (@shell.history << "'#{@input.shift}'").last }
25
+ stub(@shell).print_result{}.with_any_args
26
+ times.times{ @shell.loop_once }
27
+ @shell.history.to_a.should.eq input.map{ |i| "'#{i}'" }
28
+ end
29
29
  end
30
30
  end
31
31
 
@@ -36,7 +36,7 @@ describe Rib::SqueezeHistory do
36
36
  @history = "/tmp/test_rib_#{rand}"
37
37
  @shell = Rib::Shell.new(:history_file => @history).before_loop
38
38
  @input = %w[foo bar bar foo bar]
39
- clear_history(@shell.history)
39
+ @shell.history.clear
40
40
  end
41
41
 
42
42
  after do
@@ -29,7 +29,7 @@ shared :underscore do
29
29
 
30
30
  should 'set __' do
31
31
  setup
32
- stub(@shell).puts.with_any_args
32
+ stub(@shell).puts{}.with_any_args
33
33
  mock(@shell).get_input{'XD'}
34
34
  mock(@shell).get_input{'__'}
35
35
  @shell.loop_once
@@ -43,7 +43,7 @@ describe Rib::Underscore do
43
43
  def setup bound=Object.new
44
44
  @shell = Rib::Shell.new(
45
45
  :binding => bound.instance_eval{binding}).before_loop
46
- stub(@shell).puts(is_a(String))
46
+ stub(@shell).puts(is_a(String)){}
47
47
  end
48
48
 
49
49
  test_for Rib::Underscore do
@@ -8,12 +8,12 @@ describe Rib::MultilineHistory do
8
8
  behaves_like :setup_multiline
9
9
 
10
10
  def check str, err=nil
11
- clear_history(@shell.history)
11
+ @shell.history.clear
12
12
  with_history(str, err)
13
13
 
14
14
  setup_shell
15
15
 
16
- clear_history(@shell.history)
16
+ @shell.history.clear
17
17
  @shell.history << 'old history'
18
18
  with_history(str, err, 'old history')
19
19
  end
@@ -0,0 +1,35 @@
1
+
2
+ require 'rib/test'
3
+ require 'rib/runner'
4
+
5
+ describe Rib::Runner do
6
+ behaves_like :rib
7
+
8
+ before do
9
+ Rib.disable_plugins
10
+ @shell = Rib::Shell.new
11
+ mock(Rib).shell{ @shell }.times(2)
12
+ end
13
+
14
+ def input *args
15
+ args.each{ |item| mock(@shell).get_input{ item } }
16
+ mock(@shell).get_input{}
17
+ end
18
+
19
+ def output *args
20
+ args.each{ |item| mock(@shell).puts("=> #{item}"){} }
21
+ mock(@shell).puts{}
22
+ end
23
+
24
+ should '-e' do
25
+ input('a')
26
+ output('1')
27
+ Rib::Runner.run(%w[-ea=1]).should.eq @shell
28
+ end
29
+
30
+ should '-e nothing' do
31
+ input
32
+ output
33
+ Rib::Runner.run(%w[-e]).should.eq @shell
34
+ end
35
+ end
@@ -18,7 +18,7 @@ describe Rib::Shell do
18
18
  end
19
19
  should 'exit' do input('exit' ) end
20
20
  should 'also exit' do input(' exit') end
21
- should 'ctrl+d' do mock(@shell).puts ; input(nil) end
21
+ should 'ctrl+d' do mock(@shell).puts{} ; input(nil) end
22
22
  should ':q' do @shell.config[:exit] << ':q'; input(':q') end
23
23
  should '\q' do @shell.config[:exit] << '\q'; input('\q') end
24
24
  end
@@ -35,27 +35,27 @@ describe Rib::Shell do
35
35
  end
36
36
 
37
37
  should 'handles ctrl+c' do
38
- mock(@shell).handle_interrupt
38
+ mock(@shell).handle_interrupt{}
39
39
  input{ raise Interrupt }
40
40
  end
41
41
 
42
42
  should 'prints result' do
43
- mock(@shell).puts('=> "mm"')
43
+ mock(@shell).puts('=> "mm"'){}
44
44
  input('"m" * 2')
45
45
  end
46
46
 
47
47
  should 'error in print_result' do
48
- mock(Rib).warn(match(/Error while printing result.*BOOM/m))
48
+ mock(Rib).warn(match(/Error while printing result.*BOOM/m)){}
49
49
  input('obj = Object.new; def obj.inspect; raise "BOOM"; end; obj')
50
50
  end
51
51
 
52
52
  should 'not crash if user input is a blackhole' do
53
- mock(Rib).warn(match(/Error while printing result/))
53
+ mock(Rib).warn(match(/Error while printing result/)){}
54
54
  input('Rib::Blackhole')
55
55
  end
56
56
 
57
57
  should 'print error from eval' do
58
- mock(@shell).puts(match(/RuntimeError/))
58
+ mock(@shell).puts(match(/RuntimeError/)){}
59
59
  input('raise "blah"')
60
60
  end
61
61
  end
@@ -87,8 +87,12 @@ describe Rib::Shell do
87
87
 
88
88
  should 'call after_loop even if in_loop raises' do
89
89
  mock(@shell).loop_once{ raise 'boom' }
90
- mock(Rib).warn(is_a(String))
91
- mock(@shell).after_loop
90
+ mock(Rib).warn(is_a(String)){}
91
+ mock(@shell).after_loop{}
92
92
  lambda{@shell.loop}.should.raise(RuntimeError)
93
93
  end
94
+
95
+ should 'have empty binding' do
96
+ @shell.eval_input('local_variables').first.should.empty
97
+ end
94
98
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rib
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lin Jen-Shin (godfat)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-14 00:00:00.000000000 Z
11
+ date: 2014-01-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |-
14
14
  Ruby-Interactive-ruBy -- Yet another interactive Ruby shell
@@ -34,9 +34,9 @@ executables:
34
34
  extensions: []
35
35
  extra_rdoc_files: []
36
36
  files:
37
- - .gitignore
38
- - .gitmodules
39
- - .travis.yml
37
+ - ".gitignore"
38
+ - ".gitmodules"
39
+ - ".travis.yml"
40
40
  - CHANGES.md
41
41
  - Gemfile
42
42
  - LICENSE
@@ -85,7 +85,7 @@ files:
85
85
  - lib/rib/version.rb
86
86
  - rib.gemspec
87
87
  - screenshot.png
88
- - task/.gitignore
88
+ - task/README.md
89
89
  - task/gemgem.rb
90
90
  - test/core/test_completion.rb
91
91
  - test/core/test_history.rb
@@ -97,6 +97,7 @@ files:
97
97
  - test/more/test_multiline_history.rb
98
98
  - test/test_api.rb
99
99
  - test/test_plugin.rb
100
+ - test/test_runner.rb
100
101
  - test/test_shell.rb
101
102
  homepage: https://github.com/godfat/rib
102
103
  licenses:
@@ -108,17 +109,17 @@ require_paths:
108
109
  - lib
109
110
  required_ruby_version: !ruby/object:Gem::Requirement
110
111
  requirements:
111
- - - '>='
112
+ - - ">="
112
113
  - !ruby/object:Gem::Version
113
114
  version: '0'
114
115
  required_rubygems_version: !ruby/object:Gem::Requirement
115
116
  requirements:
116
- - - '>='
117
+ - - ">="
117
118
  - !ruby/object:Gem::Version
118
119
  version: '0'
119
120
  requirements: []
120
121
  rubyforge_project:
121
- rubygems_version: 2.0.6
122
+ rubygems_version: 2.2.1
122
123
  signing_key:
123
124
  specification_version: 4
124
125
  summary: Ruby-Interactive-ruBy -- Yet another interactive Ruby shell
@@ -133,4 +134,5 @@ test_files:
133
134
  - test/more/test_multiline_history.rb
134
135
  - test/test_api.rb
135
136
  - test/test_plugin.rb
137
+ - test/test_runner.rb
136
138
  - test/test_shell.rb
@@ -1 +0,0 @@
1
- *.rbc