ruby-next 0.3.0 → 0.4.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 +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +11 -7
- metadata +3 -48
- data/bin/parse +0 -19
- data/bin/ruby-next +0 -16
- data/bin/transform +0 -21
- data/lib/ruby-next.rb +0 -37
- data/lib/ruby-next/cli.rb +0 -94
- data/lib/ruby-next/commands/base.rb +0 -42
- data/lib/ruby-next/commands/core_ext.rb +0 -166
- data/lib/ruby-next/commands/nextify.rb +0 -133
- data/lib/ruby-next/core.rb +0 -182
- data/lib/ruby-next/core/array/deconstruct.rb +0 -21
- data/lib/ruby-next/core/array/difference_union_intersection.rb +0 -25
- data/lib/ruby-next/core/constants/no_matching_pattern_error.rb +0 -17
- data/lib/ruby-next/core/enumerable/filter.rb +0 -25
- data/lib/ruby-next/core/enumerable/filter_map.rb +0 -38
- data/lib/ruby-next/core/enumerable/tally.rb +0 -14
- data/lib/ruby-next/core/enumerator/produce.rb +0 -20
- data/lib/ruby-next/core/hash/deconstruct_keys.rb +0 -21
- data/lib/ruby-next/core/hash/merge.rb +0 -14
- data/lib/ruby-next/core/kernel/then.rb +0 -10
- data/lib/ruby-next/core/proc/compose.rb +0 -19
- data/lib/ruby-next/core/runtime.rb +0 -10
- data/lib/ruby-next/core/string/split.rb +0 -11
- data/lib/ruby-next/core/struct/deconstruct.rb +0 -7
- data/lib/ruby-next/core/struct/deconstruct_keys.rb +0 -34
- data/lib/ruby-next/core/time/ceil.rb +0 -10
- data/lib/ruby-next/core/time/floor.rb +0 -9
- data/lib/ruby-next/core/unboundmethod/bind_call.rb +0 -9
- data/lib/ruby-next/core_ext.rb +0 -18
- data/lib/ruby-next/language.rb +0 -119
- data/lib/ruby-next/language/bootsnap.rb +0 -26
- data/lib/ruby-next/language/eval.rb +0 -64
- data/lib/ruby-next/language/parser.rb +0 -28
- data/lib/ruby-next/language/rewriters/args_forward.rb +0 -57
- data/lib/ruby-next/language/rewriters/base.rb +0 -105
- data/lib/ruby-next/language/rewriters/endless_range.rb +0 -60
- data/lib/ruby-next/language/rewriters/method_reference.rb +0 -33
- data/lib/ruby-next/language/rewriters/numbered_params.rb +0 -41
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +0 -541
- data/lib/ruby-next/language/runtime.rb +0 -95
- data/lib/ruby-next/language/setup.rb +0 -43
- data/lib/ruby-next/language/unparser.rb +0 -8
- data/lib/ruby-next/utils.rb +0 -36
- data/lib/ruby-next/version.rb +0 -5
- data/lib/uby-next.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cc67691b20d3fa1a528a3f42d306f634b4b23aa8d5d876c4441e5cfdc08bbd9
|
4
|
+
data.tar.gz: ba3efeed90aefc8ab2f50979792445e5dae7dc3447715bdc38155889459b8807
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fd55f852c960fe4230abb6ebd512bd0b22b084659486484bfc45b3b7ee987ff77fcc9ab5932e880175063ea492bb746dc88d2e0a230fd77b9dfee78b275d88f
|
7
|
+
data.tar.gz: 25c136bb7761113535006f1de10fe34fafd69520c633b7693b59afca63eb7b6b64593529f80c61b494325c3a6bd0864bfd30a011502dcbd4ff41fb54911d0f4e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.4.0 (2020-03-09)
|
6
|
+
|
7
|
+
- Optimize pattern matching transpiled code. ([@palkan][])
|
8
|
+
|
9
|
+
For array patterns, transpiled code is ~1.5-2x faster than native.
|
10
|
+
For hash patterns it's about the same.
|
11
|
+
|
12
|
+
- Pattern matching is 100% compatible with RubySpec. ([@palkan][])
|
13
|
+
|
14
|
+
- Add `Symbol#start_with?/end_with?`. ([@palkan][])
|
15
|
+
|
5
16
|
## 0.3.0 (2020-02-14) 💕
|
6
17
|
|
7
18
|
- Add `Time#floor` and `Time#ceil`. ([@palkan][])
|
@@ -48,7 +59,7 @@ You can still use this feature by enabling it explicitly (see Readme).
|
|
48
59
|
- Support in modifier. ([@palkan][])
|
49
60
|
|
50
61
|
```ruby
|
51
|
-
{a:1, b: 2} in {a:, **}
|
62
|
+
{a: 1, b: 2} in {a:, **}
|
52
63
|
p a #=> 1
|
53
64
|
```
|
54
65
|
|
data/README.md
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
|
4
4
|
# Ruby Next
|
5
5
|
|
6
|
-
|
6
|
+
<img align="right" height="184"
|
7
|
+
title="Ruby Next logo" src="./assets/images/logo.svg">
|
7
8
|
|
8
|
-
Ruby Next is a
|
9
|
+
Ruby Next is a **transpiler** and a collection of **polyfills** for supporting the latest and upcoming Ruby features (APIs and syntax) in older versions and alternative implementations. For example, you can use pattern matching and `Kernel#then` in Ruby 2.5 or [mruby][].
|
9
10
|
|
10
11
|
Who might be interested in Ruby Next?
|
11
12
|
|
@@ -14,9 +15,10 @@ Who might be interested in Ruby Next?
|
|
14
15
|
- **Users of non-MRI implementations** such as [mruby][], [JRuby][], [TruffleRuby][], [Opal][], [RubyMotion][], [Artichoke][], [Prism][].
|
15
16
|
|
16
17
|
Ruby Next also aims to help the community to assess new, _experimental_, MRI features by making it easier to play with them.
|
17
|
-
That's why Ruby Next implements the `
|
18
|
+
That's why Ruby Next implements the `master` features as fast as possible.
|
18
19
|
|
19
|
-
|
20
|
+
<a href="https://evilmartians.com/?utm_source=ruby-next">
|
21
|
+
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
20
22
|
|
21
23
|
## Links
|
22
24
|
|
@@ -92,7 +94,9 @@ gem "ruby-next"
|
|
92
94
|
|
93
95
|
# gemspec
|
94
96
|
spec.add_dependency "ruby-next"
|
97
|
+
```
|
95
98
|
|
99
|
+
```sh
|
96
100
|
# or install globally
|
97
101
|
gem install ruby-next
|
98
102
|
```
|
@@ -164,7 +168,7 @@ The behaviour depends on whether you transpile a single file or a directory:
|
|
164
168
|
|
165
169
|
```sh
|
166
170
|
$ ruby-next nextify my_ruby.rb -o my_ruby_next.rb -V
|
167
|
-
|
171
|
+
Ruby Next core strategy: refine
|
168
172
|
Generated: my_ruby_next.rb
|
169
173
|
```
|
170
174
|
|
@@ -298,7 +302,7 @@ Then, add to your Gemfile:
|
|
298
302
|
|
299
303
|
```ruby
|
300
304
|
source "https://rubygems.pkg.github.com/ruby-next" do
|
301
|
-
gem "parser", "2.7.0.100"
|
305
|
+
gem "parser", "~> 2.7.0.100", "< 2.7.1"
|
302
306
|
end
|
303
307
|
|
304
308
|
gem "ruby-next"
|
@@ -311,7 +315,7 @@ gem "ruby-next"
|
|
311
315
|
You can install `ruby-next` globally by running the following commands:
|
312
316
|
|
313
317
|
```sh
|
314
|
-
gem install parser -v "2.7.0.100" --source "https://USERNAME:ACCESS_TOKEN@rubygems.pkg.github.com/ruby-next"
|
318
|
+
gem install parser -v "~> 2.7.0.100" -v "< 2.7.1" --source "https://USERNAME:ACCESS_TOKEN@rubygems.pkg.github.com/ruby-next"
|
315
319
|
gem install ruby-next
|
316
320
|
```
|
317
321
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-next
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-next-core
|
@@ -57,58 +57,13 @@ description: "\n Ruby Next is a collection of polyfills and a transpiler for
|
|
57
57
|
(such as mruby, JRuby, Opal, Artichoke, RubyMotion, etc.).\n "
|
58
58
|
email:
|
59
59
|
- dementiev.vm@gmail.com
|
60
|
-
executables:
|
61
|
-
- ruby-next
|
60
|
+
executables: []
|
62
61
|
extensions: []
|
63
62
|
extra_rdoc_files: []
|
64
63
|
files:
|
65
64
|
- CHANGELOG.md
|
66
65
|
- LICENSE.txt
|
67
66
|
- README.md
|
68
|
-
- bin/parse
|
69
|
-
- bin/ruby-next
|
70
|
-
- bin/transform
|
71
|
-
- lib/ruby-next.rb
|
72
|
-
- lib/ruby-next/cli.rb
|
73
|
-
- lib/ruby-next/commands/base.rb
|
74
|
-
- lib/ruby-next/commands/core_ext.rb
|
75
|
-
- lib/ruby-next/commands/nextify.rb
|
76
|
-
- lib/ruby-next/core.rb
|
77
|
-
- lib/ruby-next/core/array/deconstruct.rb
|
78
|
-
- lib/ruby-next/core/array/difference_union_intersection.rb
|
79
|
-
- lib/ruby-next/core/constants/no_matching_pattern_error.rb
|
80
|
-
- lib/ruby-next/core/enumerable/filter.rb
|
81
|
-
- lib/ruby-next/core/enumerable/filter_map.rb
|
82
|
-
- lib/ruby-next/core/enumerable/tally.rb
|
83
|
-
- lib/ruby-next/core/enumerator/produce.rb
|
84
|
-
- lib/ruby-next/core/hash/deconstruct_keys.rb
|
85
|
-
- lib/ruby-next/core/hash/merge.rb
|
86
|
-
- lib/ruby-next/core/kernel/then.rb
|
87
|
-
- lib/ruby-next/core/proc/compose.rb
|
88
|
-
- lib/ruby-next/core/runtime.rb
|
89
|
-
- lib/ruby-next/core/string/split.rb
|
90
|
-
- lib/ruby-next/core/struct/deconstruct.rb
|
91
|
-
- lib/ruby-next/core/struct/deconstruct_keys.rb
|
92
|
-
- lib/ruby-next/core/time/ceil.rb
|
93
|
-
- lib/ruby-next/core/time/floor.rb
|
94
|
-
- lib/ruby-next/core/unboundmethod/bind_call.rb
|
95
|
-
- lib/ruby-next/core_ext.rb
|
96
|
-
- lib/ruby-next/language.rb
|
97
|
-
- lib/ruby-next/language/bootsnap.rb
|
98
|
-
- lib/ruby-next/language/eval.rb
|
99
|
-
- lib/ruby-next/language/parser.rb
|
100
|
-
- lib/ruby-next/language/rewriters/args_forward.rb
|
101
|
-
- lib/ruby-next/language/rewriters/base.rb
|
102
|
-
- lib/ruby-next/language/rewriters/endless_range.rb
|
103
|
-
- lib/ruby-next/language/rewriters/method_reference.rb
|
104
|
-
- lib/ruby-next/language/rewriters/numbered_params.rb
|
105
|
-
- lib/ruby-next/language/rewriters/pattern_matching.rb
|
106
|
-
- lib/ruby-next/language/runtime.rb
|
107
|
-
- lib/ruby-next/language/setup.rb
|
108
|
-
- lib/ruby-next/language/unparser.rb
|
109
|
-
- lib/ruby-next/utils.rb
|
110
|
-
- lib/ruby-next/version.rb
|
111
|
-
- lib/uby-next.rb
|
112
67
|
homepage: http://github.com/palkan/ruby-next
|
113
68
|
licenses:
|
114
69
|
- MIT
|
data/bin/parse
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
lib = File.expand_path("../../lib", __FILE__)
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
$VERBOSE = nil
|
6
|
-
|
7
|
-
require "bundler/setup"
|
8
|
-
|
9
|
-
require "ruby-next/language"
|
10
|
-
|
11
|
-
contents =
|
12
|
-
if File.exist?(ARGV[0])
|
13
|
-
File.read(ARGV[0])
|
14
|
-
else
|
15
|
-
ARGV[0]
|
16
|
-
end
|
17
|
-
|
18
|
-
ast = RubyNext::Language.parse(contents)
|
19
|
-
puts ast
|
data/bin/ruby-next
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
lib_path = File.expand_path("../lib", __dir__)
|
4
|
-
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
5
|
-
|
6
|
-
require "ruby-next/cli"
|
7
|
-
|
8
|
-
begin
|
9
|
-
cli = RubyNext::CLI.new
|
10
|
-
cli.run(ARGV)
|
11
|
-
rescue => e
|
12
|
-
raise e if $DEBUG
|
13
|
-
STDERR.puts e.message
|
14
|
-
STDERR.puts e.backtrace.join("\n") if ENV["RUBY_NEXT_DEBUG"] == "1"
|
15
|
-
exit 1
|
16
|
-
end
|
data/bin/transform
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
lib = File.expand_path("../../lib", __FILE__)
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
|
6
|
-
require "bundler/setup"
|
7
|
-
|
8
|
-
require "ruby-next/language"
|
9
|
-
|
10
|
-
# optional parsers
|
11
|
-
require "ruby-next/language/rewriters/method_reference"
|
12
|
-
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::MethodReference
|
13
|
-
|
14
|
-
contents =
|
15
|
-
if File.exist?(ARGV[0])
|
16
|
-
File.read(ARGV[0])
|
17
|
-
else
|
18
|
-
ARGV[0]
|
19
|
-
end
|
20
|
-
|
21
|
-
puts RubyNext::Language.transform(contents)
|
data/lib/ruby-next.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "ruby-next/version"
|
4
|
-
|
5
|
-
module RubyNext
|
6
|
-
# Mininum Ruby version supported by RubyNext
|
7
|
-
MIN_SUPPORTED_VERSION = Gem::Version.new("2.5.0")
|
8
|
-
|
9
|
-
# Where to store transpiled files (relative from the project LOAD_PATH, usually `lib/`)
|
10
|
-
RUBY_NEXT_DIR = ".rbnext"
|
11
|
-
|
12
|
-
# Defines last minor version for every major version
|
13
|
-
LAST_MINOR_VERSIONS = {
|
14
|
-
2 => 7
|
15
|
-
}.freeze
|
16
|
-
|
17
|
-
LATEST_VERSION = [2, 7].freeze
|
18
|
-
|
19
|
-
class << self
|
20
|
-
def next_version(version = RUBY_VERSION)
|
21
|
-
major, minor = Gem::Version.new(version).segments.map(&:to_i)
|
22
|
-
|
23
|
-
return if major >= LATEST_VERSION.first && minor >= LATEST_VERSION.last
|
24
|
-
|
25
|
-
nxt =
|
26
|
-
if LAST_MINOR_VERSIONS[major] == minor
|
27
|
-
"#{major + 1}.0.0"
|
28
|
-
else
|
29
|
-
"#{major}.#{minor + 1}.0"
|
30
|
-
end
|
31
|
-
|
32
|
-
Gem::Version.new(nxt)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
require_relative "ruby-next/core"
|
37
|
-
end
|
data/lib/ruby-next/cli.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "ruby-next"
|
4
|
-
require "ruby-next/language"
|
5
|
-
|
6
|
-
require "ruby-next/commands/base"
|
7
|
-
require "ruby-next/commands/nextify"
|
8
|
-
require "ruby-next/commands/core_ext"
|
9
|
-
|
10
|
-
module RubyNext
|
11
|
-
# Command line interface for RubyNext
|
12
|
-
class CLI
|
13
|
-
class << self
|
14
|
-
attr_accessor :verbose
|
15
|
-
end
|
16
|
-
|
17
|
-
self.verbose = false
|
18
|
-
|
19
|
-
COMMANDS = {
|
20
|
-
"nextify" => Commands::Nextify,
|
21
|
-
"core_ext" => Commands::CoreExt
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
def initialize
|
25
|
-
end
|
26
|
-
|
27
|
-
def run(args = ARGV)
|
28
|
-
maybe_print_version(args)
|
29
|
-
|
30
|
-
command = extract_command(args)
|
31
|
-
|
32
|
-
# Handle top-level help
|
33
|
-
unless command
|
34
|
-
maybe_print_help
|
35
|
-
raise "Command must be specified!"
|
36
|
-
end
|
37
|
-
|
38
|
-
args.delete(command)
|
39
|
-
|
40
|
-
COMMANDS.fetch(command) do
|
41
|
-
raise "Unknown command: #{command}. Available commands: #{COMMANDS.keys.join(",")}"
|
42
|
-
end.run(args)
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def maybe_print_version(args)
|
48
|
-
args = args.dup
|
49
|
-
begin
|
50
|
-
optparser.parse!(args)
|
51
|
-
rescue OptionParser::InvalidOption
|
52
|
-
# skip and pass all args to the command's parser
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def maybe_print_help
|
57
|
-
return unless @print_help
|
58
|
-
|
59
|
-
STDOUT.puts optparser.help
|
60
|
-
exit 0
|
61
|
-
end
|
62
|
-
|
63
|
-
def extract_command(source_args)
|
64
|
-
args = source_args.dup
|
65
|
-
unknown_args = []
|
66
|
-
command = nil
|
67
|
-
begin
|
68
|
-
command, = optparser.permute!(args)
|
69
|
-
rescue OptionParser::InvalidOption => e
|
70
|
-
unknown_args += e.args
|
71
|
-
args = source_args - unknown_args
|
72
|
-
retry
|
73
|
-
end
|
74
|
-
command
|
75
|
-
end
|
76
|
-
|
77
|
-
def optparser
|
78
|
-
@optparser ||= begin
|
79
|
-
OptionParser.new do |opts|
|
80
|
-
opts.banner = "Usage: ruby-next COMMAND [options]"
|
81
|
-
|
82
|
-
opts.on("-v", "--version", "Print version") do
|
83
|
-
STDOUT.puts RubyNext::VERSION
|
84
|
-
exit 0
|
85
|
-
end
|
86
|
-
|
87
|
-
opts.on("-h", "--help", "Print help") do
|
88
|
-
@print_help = true
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "optparse"
|
4
|
-
|
5
|
-
module RubyNext
|
6
|
-
module Commands
|
7
|
-
class Base
|
8
|
-
class << self
|
9
|
-
def run(args)
|
10
|
-
new(args).run
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(args)
|
15
|
-
parse! args
|
16
|
-
end
|
17
|
-
|
18
|
-
def parse!(*)
|
19
|
-
raise NotImplementedError
|
20
|
-
end
|
21
|
-
|
22
|
-
def run
|
23
|
-
raise NotImplementedError
|
24
|
-
end
|
25
|
-
|
26
|
-
def log(msg)
|
27
|
-
return unless CLI.verbose
|
28
|
-
$stdout.puts msg
|
29
|
-
end
|
30
|
-
|
31
|
-
def base_parser
|
32
|
-
OptionParser.new do |opts|
|
33
|
-
yield opts
|
34
|
-
|
35
|
-
opts.on("-V", "Turn on verbose mode") do
|
36
|
-
CLI.verbose = true
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,166 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "fileutils"
|
4
|
-
require "pathname"
|
5
|
-
|
6
|
-
module RubyNext
|
7
|
-
module Commands
|
8
|
-
class CoreExt < Base
|
9
|
-
using RubyNext
|
10
|
-
|
11
|
-
attr_reader :out_path, :min_version, :names, :list, :filter, :original_command
|
12
|
-
alias list? list
|
13
|
-
|
14
|
-
def run
|
15
|
-
log "Select core extensions for Ruby v#{min_version}" \
|
16
|
-
"#{filter ? " and matching #{filter.inspect}" : ""}"
|
17
|
-
|
18
|
-
matching_patches.then do |patches|
|
19
|
-
next print_list(patches) if list?
|
20
|
-
generate_core_ext(patches)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def parse!(args)
|
25
|
-
print_help = false
|
26
|
-
@min_version = MIN_SUPPORTED_VERSION
|
27
|
-
@original_command = "ruby-next core_ext #{args.join(" ")}"
|
28
|
-
@names = []
|
29
|
-
@list = false
|
30
|
-
@out_path = File.join(Dir.pwd, "core_ext.rb")
|
31
|
-
|
32
|
-
optparser = base_parser do |opts|
|
33
|
-
opts.banner = "Usage: ruby-next core_ext [options]"
|
34
|
-
|
35
|
-
opts.on("-o", "--output=OUTPUT", "Specify output file or stdout (default: ./core_ext.rb)") do |val|
|
36
|
-
@out_path = val
|
37
|
-
end
|
38
|
-
|
39
|
-
opts.on("-l", "--list", "List all available extensions") do
|
40
|
-
@list = true
|
41
|
-
end
|
42
|
-
|
43
|
-
opts.on("--min-version=VERSION", "Specify the minimum Ruby version to support") do |val|
|
44
|
-
@min_version = Gem::Version.new(val)
|
45
|
-
end
|
46
|
-
|
47
|
-
opts.on("-n", "--name=NAME", "Filter extensions by name") do |val|
|
48
|
-
names << val
|
49
|
-
end
|
50
|
-
|
51
|
-
opts.on("-h", "--help", "Print help") do
|
52
|
-
print_help = true
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
optparser.parse!(args)
|
57
|
-
|
58
|
-
if print_help
|
59
|
-
$stdout.puts optparser.help
|
60
|
-
exit 0
|
61
|
-
end
|
62
|
-
|
63
|
-
@filter = /(#{names.join("|")})/i unless names.empty?
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def matching_patches
|
69
|
-
RubyNext::Core.patches.extensions
|
70
|
-
.values
|
71
|
-
.flatten
|
72
|
-
.filter do |patch|
|
73
|
-
next if min_version && Gem::Version.new(patch.version) <= min_version
|
74
|
-
next if filter && !filter.match?(patch.name)
|
75
|
-
true
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def print_list(patches)
|
80
|
-
grouped_patches = patches.group_by(&:version).sort_by(&:first)
|
81
|
-
grouped_patches.each do |(group, patches)|
|
82
|
-
$stdout.puts "#{group} extensions:\n"
|
83
|
-
$stdout.puts patches.sort_by(&:name).map { |patch| " - #{patch.name}" }.join("\n")
|
84
|
-
$stdout.puts "\n"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def generate_core_ext(patches)
|
89
|
-
grouped_patches = patches.group_by(&:mod).sort_by { |(mod, patch)| mod.singleton_class? ? mod.inspect : mod.name }
|
90
|
-
|
91
|
-
buffer = []
|
92
|
-
|
93
|
-
buffer << "# frozen_string_literal: true\n"
|
94
|
-
|
95
|
-
buffer << generation_meta
|
96
|
-
|
97
|
-
grouped_patches.each do |mod, patches|
|
98
|
-
singleton = mod.singleton_class?
|
99
|
-
extend_name = singleton ? patches.first.singleton.name : mod.name
|
100
|
-
prepend_name = singleton ? "#{patches.first.singleton.name}.singleton_class" : mod.name
|
101
|
-
|
102
|
-
prepended, extended = patches.partition(&:prepend?)
|
103
|
-
|
104
|
-
prepended.map do |patch|
|
105
|
-
name = "RubyNext::Core::#{patch.name}"
|
106
|
-
|
107
|
-
buffer << <<~RUBY
|
108
|
-
module #{name}
|
109
|
-
#{indent_and_trim(patch.body)}
|
110
|
-
end
|
111
|
-
|
112
|
-
#{prepend_name}.prepend #{name}
|
113
|
-
RUBY
|
114
|
-
|
115
|
-
name
|
116
|
-
end
|
117
|
-
|
118
|
-
class_or_module = mod.is_a?(Class) ? "class" : "module"
|
119
|
-
|
120
|
-
buffer << "#{class_or_module} #{extend_name}"
|
121
|
-
|
122
|
-
buffer << " class << self" if singleton
|
123
|
-
|
124
|
-
indent_size = singleton ? 4 : 2
|
125
|
-
|
126
|
-
buffer << extended.map do |patch|
|
127
|
-
indent_and_trim(patch.body, indent_size)
|
128
|
-
end.join("\n\n")
|
129
|
-
|
130
|
-
buffer << " end" if singleton
|
131
|
-
|
132
|
-
buffer << "end\n"
|
133
|
-
end
|
134
|
-
|
135
|
-
contents = buffer.join("\n")
|
136
|
-
|
137
|
-
return $stdout.puts(contents) if out_path == "stdout"
|
138
|
-
|
139
|
-
FileUtils.mkdir_p File.dirname(out_path)
|
140
|
-
File.write(out_path, contents)
|
141
|
-
|
142
|
-
log "Generated: #{out_path}"
|
143
|
-
end
|
144
|
-
|
145
|
-
def generation_meta
|
146
|
-
<<~MSG
|
147
|
-
# Generated by RubyNext v#{RubyNext::VERSION} using the following command:
|
148
|
-
#
|
149
|
-
# #{original_command}
|
150
|
-
#
|
151
|
-
MSG
|
152
|
-
end
|
153
|
-
|
154
|
-
def indent_and_trim(src, size = 2)
|
155
|
-
new_src = src.dup
|
156
|
-
# indent code using <size> spaces
|
157
|
-
new_src.gsub!(/^/, " " * size)
|
158
|
-
# remove empty lines
|
159
|
-
new_src.gsub!(/^\s+$/, "")
|
160
|
-
# remove traling blank lines
|
161
|
-
new_src.gsub!(/\n\z/, "")
|
162
|
-
new_src
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|