rib 1.1.6 → 1.2.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.
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