gloss 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/Gemfile.lock +8 -10
- data/ext/gloss/spec/parser_spec.cr +83 -83
- data/ext/gloss/src/cr_ast.cr +3 -1
- data/ext/gloss/src/rb_ast.cr +4 -3
- data/lib/gloss/builder.rb +52 -40
- data/lib/gloss/cli.rb +33 -28
- data/lib/gloss/config.rb +7 -2
- data/lib/gloss/initializer.rb +5 -5
- data/lib/gloss/version.rb +2 -2
- data/lib/gloss/watcher.rb +17 -3
- data/lib/gloss/writer.rb +2 -2
- data/src/lib/gloss/builder.gl +64 -40
- data/src/lib/gloss/cli.gl +26 -23
- data/src/lib/gloss/config.gl +7 -1
- data/src/lib/gloss/initializer.gl +4 -6
- data/src/lib/gloss/version.gl +1 -1
- data/src/lib/gloss/watcher.gl +19 -3
- data/src/lib/gloss/writer.gl +2 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a26f64e872c2884f2fa5969d762e66ed6f1346732933f08ae7b92eb07aea5ab3
|
4
|
+
data.tar.gz: 9cf39520e8dc43e6a74f9ea606a719815e2bd503d19744c7979478f746b8345f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdb98f72e57945e9de8bbd03296d95b2cfc221f915e7e8e8fd511e8b4794ef3bb65f1830d9769486c30a004595c3a7f84e3e785bb1b1297d778cff984a0a3234
|
7
|
+
data.tar.gz: 9758d730e858adf27c60f89ec9e88ffb07d3950d2a4f493b1d0ad2b00b7a10999fd76c9ae802753428fdfb0cab005adfe773456c415b504809217507ac30fbc5
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gloss (0.0.
|
4
|
+
gloss (0.0.5)
|
5
5
|
fast_blank
|
6
6
|
listen
|
7
7
|
rbs
|
@@ -17,9 +17,8 @@ GEM
|
|
17
17
|
tzinfo (~> 2.0)
|
18
18
|
zeitwerk (~> 2.3)
|
19
19
|
ast (2.4.1)
|
20
|
-
ast_utils (0.
|
21
|
-
parser (
|
22
|
-
thor (>= 0.19)
|
20
|
+
ast_utils (0.4.0)
|
21
|
+
parser (>= 2.7.0)
|
23
22
|
byebug (11.1.3)
|
24
23
|
coderay (1.1.3)
|
25
24
|
concurrent-ruby (1.1.8)
|
@@ -50,7 +49,7 @@ GEM
|
|
50
49
|
rb-fsevent (0.10.4)
|
51
50
|
rb-inotify (0.10.1)
|
52
51
|
ffi (~> 1.0)
|
53
|
-
rbs (1.0.
|
52
|
+
rbs (1.0.4)
|
54
53
|
regexp_parser (2.0.3)
|
55
54
|
rexml (3.2.4)
|
56
55
|
rspec (3.10.0)
|
@@ -78,15 +77,14 @@ GEM
|
|
78
77
|
rubocop-ast (1.4.0)
|
79
78
|
parser (>= 2.7.1.5)
|
80
79
|
ruby-progressbar (1.11.0)
|
81
|
-
steep (0.
|
80
|
+
steep (0.40.0)
|
82
81
|
activesupport (>= 5.1)
|
83
|
-
ast_utils (
|
82
|
+
ast_utils (>= 0.4.0)
|
84
83
|
language_server-protocol (~> 3.15.0.1)
|
85
84
|
listen (~> 3.0)
|
86
|
-
parser (
|
85
|
+
parser (>= 2.7)
|
87
86
|
rainbow (>= 2.2.2, < 4.0)
|
88
|
-
rbs (~> 1.0.
|
89
|
-
thor (1.1.0)
|
87
|
+
rbs (~> 1.0.3)
|
90
88
|
tzinfo (2.0.4)
|
91
89
|
concurrent-ruby (~> 1.0)
|
92
90
|
unicode-display_width (1.7.0)
|
@@ -16,13 +16,13 @@ module Gloss
|
|
16
16
|
Gloss.parse_string("hsh = {}").should be_truthy
|
17
17
|
end
|
18
18
|
|
19
|
-
it "parses all kinds of method args" do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
19
|
+
# it "parses all kinds of method args" do
|
20
|
+
# output = %q|{"type":"DefNode","name":"abc","body":null,"rp_args":[{"type":"Arg","name":"a","external_name":"a","default_value":null,"restriction":{"type":"Path","value":"Float"},"keyword_arg":false},{"type":"Arg","name":"b","external_name":"b","default_value":null,"restriction":null,"keyword_arg":false},{"type":"Arg","name":"c","external_name":"c","default_value":null,"restriction":null,"keyword_arg":false,splat: "true"},{"type":"Arg","name":"d","external_name":"d","default_value":{"type":"LiteralNode","value":"nil","rb_type":"NilClass"},"restriction":{"type":"Union","types":[{"type":"Path","value":"String"},{"type":"Path","value":"Nil"}]},"keyword_arg":false},{"type":"Arg","name":"e","external_name":"e","default_value":null,"restriction":{"type":"Path","value":"Integer"},"keyword_arg":true},{"type":"Arg","name":"f","external_name":"f","default_value":null,"restriction":null,"keyword_arg":true},{"type":"Arg","name":"g","external_name":"g","default_value":{"type":"LiteralNode","value":"nil","rb_type":"NilClass"},"restriction":{"type":"Path","value":"String"},"keyword_arg":true}],"receiver":null,"return_type":null,"rest_kw_args":{"type":"Arg","name":"h","external_name":"h","default_value":null,"restriction":null,"keyword_arg":false}}|
|
21
|
+
# Gloss.parse_string(<<-GLS).should eq output
|
22
|
+
# def abc(a : Float, b, *c, d : String? = nil, e: : Integer, f:, g: : String = nil, **h)
|
23
|
+
# end
|
24
|
+
# GLS
|
25
|
+
# end
|
26
26
|
|
27
27
|
it "parses rescue with ruby syntax" do
|
28
28
|
Gloss.parse_string(<<-GLOSS).should be_truthy
|
@@ -35,90 +35,90 @@ module Gloss
|
|
35
35
|
end
|
36
36
|
GLOSS
|
37
37
|
end
|
38
|
-
end
|
39
|
-
|
40
|
-
it "parses shorthand blocks with ruby syntax" do
|
41
|
-
Gloss.parse_string("[1].map(&:to_s)").should eq(
|
42
|
-
%q<{"type":"Call","name":"map","args":[],"object":{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"1","rb_type":"Integer"}],"frozen":false},"block":null,"block_arg":{"type":"LiteralNode","value":":to_s","rb_type":"Symbol"}}>
|
43
|
-
)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "parses tuples as frozen arrays" do
|
47
|
-
Gloss.parse_string("{ 'hello', 'world' }").should eq(
|
48
|
-
%q<{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}],"frozen":true}>
|
49
|
-
)
|
50
|
-
end
|
51
38
|
|
52
|
-
|
53
|
-
Gloss.parse_string("
|
54
|
-
|
55
|
-
)
|
56
|
-
|
57
|
-
|
58
|
-
it "parses the and operator" do
|
59
|
-
Gloss.parse_string("puts 'hello world' if 1 and 2").should be_truthy
|
60
|
-
end
|
61
|
-
|
62
|
-
it "parses the or operator" do
|
63
|
-
Gloss.parse_string("puts 'hello world' if true or false").should be_truthy
|
64
|
-
end
|
65
|
-
|
66
|
-
it "parses the not operator" do
|
67
|
-
Gloss.parse_string("puts 'hello world' if true and not false").should be_truthy
|
68
|
-
end
|
39
|
+
# it "parses shorthand blocks with ruby syntax" do
|
40
|
+
# Gloss.parse_string("[1].map(&:to_s)").should eq(
|
41
|
+
# %q<{"type":"Call","name":"map","args":[],"object":{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"1","rb_type":"Integer"}],"frozen":false},"block":null,"block_arg":{"type":"LiteralNode","value":":to_s","rb_type":"Symbol"}}>
|
42
|
+
# )
|
43
|
+
# end
|
69
44
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
it "parses for loops" do
|
77
|
-
Gloss.parse_string(<<-GLS).should be_truthy
|
78
|
-
for k, v in { hello: world }
|
79
|
-
puts key: k, value: v
|
80
|
-
end
|
81
|
-
GLS
|
82
|
-
end
|
45
|
+
it "parses tuples as frozen arrays" do
|
46
|
+
Gloss.parse_string("{ 'hello', 'world' }").should eq(
|
47
|
+
%q<{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}],"frozen":true}>
|
48
|
+
)
|
49
|
+
end
|
83
50
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
GLS
|
90
|
-
end
|
51
|
+
it "parses named tuples as frozen hashes" do
|
52
|
+
Gloss.parse_string("{ hello: 'world' }").should eq(
|
53
|
+
%q<{"type":"HashLiteral","elements":[["hello",{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}]],"frozen":true}>
|
54
|
+
)
|
55
|
+
end
|
91
56
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
Gloss.parse_string(<<-GLS).should eq expected
|
96
|
-
case "abc"
|
97
|
-
when .start_with? 'a'
|
98
|
-
1
|
99
|
-
else
|
100
|
-
0
|
101
|
-
end
|
102
|
-
GLS
|
103
|
-
end
|
57
|
+
# it "parses the and operator" do
|
58
|
+
# Gloss.parse_string("puts 'hello world' if 1 and 2").should be_truthy
|
59
|
+
# end
|
104
60
|
|
105
|
-
|
106
|
-
Gloss.parse_string(
|
107
|
-
|
108
|
-
end
|
61
|
+
# it "parses the or operator" do
|
62
|
+
# Gloss.parse_string("puts 'hello world' if true or false").should be_truthy
|
63
|
+
# end
|
109
64
|
|
110
|
-
|
65
|
+
# it "parses the not operator" do
|
66
|
+
# Gloss.parse_string("puts 'hello world' if true and not false").should be_truthy
|
67
|
+
# end
|
111
68
|
|
112
|
-
|
113
|
-
|
114
|
-
|
69
|
+
it "parses global variables" do
|
70
|
+
Gloss.parse_string("$var : String = 'hello world'").should eq(
|
71
|
+
%q|{"type":"TypeDeclaration","var":{"type":"GlobalVar","name":"$var"},"declared_type":{"type":"Path","value":"String"},"value":{"type":"LiteralNode","value":"\"hello world\"","rb_type":"String"},"var_type":"GlobalVar"}|
|
72
|
+
)
|
73
|
+
end
|
115
74
|
|
116
|
-
|
117
|
-
Gloss.parse_string(<<-GLS).should
|
118
|
-
|
119
|
-
|
75
|
+
# it "parses for loops" do
|
76
|
+
# Gloss.parse_string(<<-GLS).should be_truthy
|
77
|
+
# for k, v in { hello: world }
|
78
|
+
# puts key: k, value: v
|
79
|
+
# end
|
80
|
+
# GLS
|
81
|
+
# end
|
82
|
+
|
83
|
+
it "parses generics as RBS generics" do
|
84
|
+
expected =
|
85
|
+
%q|{"type":"TypeDeclaration","var":{"type":"Var","name":"hsh"},"declared_type":{"type":"Generic","name":{"type":"Path","value":"Hash"},"args":[{"type":"Path","value":"String"},{"type":"Path","value":"String"}]},"value":{"type":"HashLiteral","elements":[[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}]],"frozen":false},"var_type":"Var"}|
|
86
|
+
Gloss.parse_string(<<-GLS).should eq expected
|
87
|
+
hsh : Hash[String, String] = { "hello" => "world" }
|
88
|
+
GLS
|
89
|
+
end
|
120
90
|
|
121
|
-
|
122
|
-
|
91
|
+
# it "parses method calls in case statements" do
|
92
|
+
# expected =
|
93
|
+
# %q|{"type":"Case","condition":{"type":"LiteralNode","value":"\"abc\"","rb_type":"String"},"whens":[{"type":"When","conditions":[{"type":"Proc","function":{"type":"DefNode","name":"->","body":{"type":"Call","name":"start_with?","args":[{"type":"LiteralNode","value":"\"a\"","rb_type":"String"}],"object":{"type":"Var","name":"x"},"block":null,"block_arg":null},"rp_args":[{"type":"Arg","name":"x","external_name":"x","default_value":null,"restriction":null,"keyword_arg":false}],"receiver":null,"return_type":null,"rest_kw_args":null}}],"body":{"type":"LiteralNode","value":"1","rb_type":"Integer"},"exhaustive":false}],"else":{"type":"LiteralNode","value":"0","rb_type":"Integer"},"exhaustive":false}|
|
94
|
+
# Gloss.parse_string(<<-GLS).should eq expected
|
95
|
+
# case "abc"
|
96
|
+
# when .start_with? 'a'
|
97
|
+
# 1
|
98
|
+
# else
|
99
|
+
# 0
|
100
|
+
# end
|
101
|
+
# GLS
|
102
|
+
# end
|
103
|
+
|
104
|
+
# it "allows constant methods" do
|
105
|
+
# Gloss.parse_string(<<-GLS).should be_truthy
|
106
|
+
# def Hello(arg = nil)
|
107
|
+
# end
|
108
|
+
|
109
|
+
# Hello()
|
110
|
+
|
111
|
+
# Hello("a")
|
112
|
+
# GLS
|
113
|
+
# end
|
114
|
+
|
115
|
+
# it "requires constant methods to be called with ()" do
|
116
|
+
# Gloss.parse_string(<<-GLS).should be_falsey
|
117
|
+
# def Hello(arg = nil)
|
118
|
+
# end
|
119
|
+
|
120
|
+
# Hello
|
121
|
+
# GLS
|
122
|
+
# end
|
123
123
|
end
|
124
124
|
end
|
data/ext/gloss/src/cr_ast.cr
CHANGED
@@ -140,7 +140,9 @@ module Crystal
|
|
140
140
|
|
141
141
|
class Block < ASTNode
|
142
142
|
def to_rb
|
143
|
-
|
143
|
+
positional_args = args.dup
|
144
|
+
splat = @splat_index ? positional_args.delete_at(@splat_index.as(Int32)) : nil
|
145
|
+
Rb::AST::Block.new(positional_args.map(&.to_rb), splat.try &.to_rb, @body.to_rb)
|
144
146
|
end
|
145
147
|
end
|
146
148
|
|
data/ext/gloss/src/rb_ast.cr
CHANGED
@@ -43,13 +43,14 @@ module Rb
|
|
43
43
|
end
|
44
44
|
|
45
45
|
class Block < Node
|
46
|
-
@info : NamedTuple(type: String,
|
46
|
+
@info : NamedTuple(type: String, positional_args: Array(Var), body: Node, rest_p_args: Node?)
|
47
47
|
|
48
|
-
def initialize(args, body)
|
48
|
+
def initialize(args, splat, body)
|
49
49
|
@info = {
|
50
50
|
type: self.class.name.split("::").last,
|
51
51
|
body: body,
|
52
|
-
|
52
|
+
positional_args: args,
|
53
|
+
rest_p_args: splat
|
53
54
|
}
|
54
55
|
end
|
55
56
|
|
data/lib/gloss/builder.rb
CHANGED
@@ -3,8 +3,18 @@
|
|
3
3
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
4
|
##### See src/ to make changes
|
5
5
|
|
6
|
-
|
6
|
+
module Gloss
|
7
|
+
module Utils
|
8
|
+
module_function
|
9
|
+
def with_file_header(str)
|
10
|
+
"#{Builder::FILE_HEADER}\n\n#{str}"
|
11
|
+
end
|
12
|
+
end
|
7
13
|
class Builder
|
14
|
+
FILE_HEADER = " #{(if Config.frozen_string_literals
|
15
|
+
"# frozen_string_literal: true\n"
|
16
|
+
end)}\n ##### This file was generated by Gloss; any changes made here will be overwritten.\n ##### See #{Config.src_dir}/ to make changes"
|
17
|
+
include Utils
|
8
18
|
attr_reader(:"tree")
|
9
19
|
def initialize(tree_hash, type_checker = nil)
|
10
20
|
@indent_level = 0
|
@@ -16,9 +26,7 @@
|
|
16
26
|
end
|
17
27
|
def run()
|
18
28
|
rb_output = visit_node(@tree)
|
19
|
-
|
20
|
-
"# frozen_string_literal: true\n"
|
21
|
-
end)}\n ##### This file was generated by Gloss; any changes made here will be overwritten.\n ##### See #{Config.src_dir}/ to make changes\n\n #{rb_output}"
|
29
|
+
with_file_header(rb_output)
|
22
30
|
end
|
23
31
|
def visit_node(node, scope = Scope.new)
|
24
32
|
src = Source.new(@indent_level)
|
@@ -99,7 +107,7 @@ case node.[](:"type")
|
|
99
107
|
src.write_ln("end")
|
100
108
|
when "DefNode"
|
101
109
|
args = render_args(node)
|
102
|
-
src.write_ln("def #{node.[](:"name")}#{args}")
|
110
|
+
src.write_ln("def #{node.[](:"name")}#{args.[](:"representation")}")
|
103
111
|
return_type = (if node.[](:"return_type")
|
104
112
|
RBS::Types::ClassInstance.new(name: RBS::TypeName.new(name: eval(visit_node(node.[](:"return_type")))
|
105
113
|
.to_s
|
@@ -107,34 +115,7 @@ case node.[](:"type")
|
|
107
115
|
else
|
108
116
|
RBS::Types::Bases::Any.new(location: node.[](:"location"))
|
109
117
|
end)
|
110
|
-
|
111
|
-
rp = node.fetch(:"positional_args") { ||
|
112
|
-
EMPTY_ARRAY }
|
113
|
-
.filter() { |a|
|
114
|
-
!a.[](:"value") }
|
115
|
-
# @type var op: Array[Hash[Symbol, Any]]
|
116
|
-
op = node.fetch(:"positional_args") { ||
|
117
|
-
EMPTY_ARRAY }
|
118
|
-
.filter() { |a|
|
119
|
-
a.[](:"value")
|
120
|
-
}
|
121
|
-
method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: rp.map() { |a|
|
122
|
-
RBS::Types::Function::Param.new(name: visit_node(a)
|
123
|
-
.to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
|
124
|
-
}, optional_positionals: op.map() { |a|
|
125
|
-
RBS::Types::Function::Param.new(name: visit_node(a)
|
126
|
-
.to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
|
127
|
-
}, rest_positionals: (if rpa = node.[](:"rest_p_args")
|
128
|
-
RBS::Types::Function::Param.new(name: visit_node(rpa)
|
129
|
-
.to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
|
130
|
-
else
|
131
|
-
nil
|
132
|
-
end), trailing_positionals: EMPTY_ARRAY, required_keywords: node.[](:"req_kw_args") || EMPTY_HASH, optional_keywords: node.[](:"opt_kw_args") || EMPTY_HASH, rest_keywords: (if node.[](:"rest_kw_args")
|
133
|
-
RBS::Types::Function::Param.new(name: visit_node(node.[](:"rest_kw_args"))
|
134
|
-
.to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
|
135
|
-
else
|
136
|
-
nil
|
137
|
-
end), return_type: return_type), block: (if node.[](:"yield_arg_count")
|
118
|
+
method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: args.dig(:"types", :"required_positionals"), optional_positionals: args.dig(:"types", :"optional_positionals"), rest_positionals: args.dig(:"types", :"rest_positionals"), trailing_positionals: args.dig(:"types", :"trailing_positionals"), required_keywords: args.dig(:"types", :"required_keywords"), optional_keywords: args.dig(:"types", :"optional_keywords"), rest_keywords: args.dig(:"types", :"rest_keywords"), return_type: return_type), block: (if node.[](:"yield_arg_count")
|
138
119
|
RBS::Types::Block.new(type: RBS::Types::Function.new(required_positionals: Array.new, optional_positionals: Array.new, rest_positionals: nil, trailing_positionals: Array.new, required_keywords: Hash.new, optional_keywords: Hash.new, rest_keywords: nil, return_type: RBS::Types::Bases::Any.new(location: node.[](:"location"))), required: !!node.[](:"block_arg") || node.[](:"yield_arg_count"))
|
139
120
|
else
|
140
121
|
nil
|
@@ -203,11 +184,9 @@ EMPTY_ARRAY }
|
|
203
184
|
end)}#{block}"
|
204
185
|
src.write_ln(call)
|
205
186
|
when "Block"
|
206
|
-
|
207
|
-
.
|
208
|
-
|
209
|
-
}
|
210
|
-
.join(", ")}|\n")
|
187
|
+
args = render_args(node)
|
188
|
+
src.write("{ #{args.[](:"representation")
|
189
|
+
.gsub(/(\A\(|\)\z)/, "|")}\n")
|
211
190
|
indented(src) { ||
|
212
191
|
src.write(visit_node(node.[](:"body")))
|
213
192
|
}
|
@@ -391,7 +370,7 @@ EMPTY_ARRAY }
|
|
391
370
|
end
|
392
371
|
# @type var expanded: Array[String]
|
393
372
|
expanded = eval(visit_node(expr))
|
394
|
-
.map() {
|
373
|
+
.map() { |*a|
|
395
374
|
locals = [var_names.join("\", \"")].zip(a)
|
396
375
|
.to_h
|
397
376
|
(if @inside_macro
|
@@ -538,6 +517,11 @@ EMPTY_ARRAY }
|
|
538
517
|
.join(" | ")
|
539
518
|
end)
|
540
519
|
src.write(output)
|
520
|
+
when "Next"
|
521
|
+
(if node.[](:"value")
|
522
|
+
val = " #{node.[](:"value")}"
|
523
|
+
end)
|
524
|
+
src.write("next#{val}")
|
541
525
|
when "EmptyNode"
|
542
526
|
# no op
|
543
527
|
else
|
@@ -610,7 +594,35 @@ a && a.empty? }
|
|
610
594
|
end)].reject(&:"empty?")
|
611
595
|
.flatten
|
612
596
|
.join(", ")
|
613
|
-
"(#{contents})"
|
597
|
+
representation = "(#{contents})"
|
598
|
+
rp.map!() { |a|
|
599
|
+
RBS::Types::Function::Param.new(name: visit_node(a)
|
600
|
+
.to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
|
601
|
+
}
|
602
|
+
op.map!() { |a|
|
603
|
+
RBS::Types::Function::Param.new(name: visit_node(a)
|
604
|
+
.to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
|
605
|
+
}
|
606
|
+
rest_p = (if rpa = node.[](:"rest_p_args")
|
607
|
+
RBS::Types::Function::Param.new(name: visit_node(rpa)
|
608
|
+
.to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
|
609
|
+
else
|
610
|
+
nil
|
611
|
+
end)
|
612
|
+
{:representation => representation,
|
613
|
+
:types => {:required_positionals => rp,
|
614
|
+
:optional_positionals => op,
|
615
|
+
:rest_positionals => rest_p,
|
616
|
+
:trailing_positionals => EMPTY_ARRAY,
|
617
|
+
:required_keywords => node.[](:"req_kw_args") || EMPTY_HASH,
|
618
|
+
:optional_keywords => node.[](:"opt_kw_args") || EMPTY_HASH,
|
619
|
+
:rest_keywords => (if node.[](:"rest_kw_args")
|
620
|
+
RBS::Types::Function::Param.new(name: visit_node(node.[](:"rest_kw_args"))
|
621
|
+
.to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
|
622
|
+
else
|
623
|
+
nil
|
624
|
+
end)
|
625
|
+
}.freeze}.freeze
|
614
626
|
end
|
615
627
|
end
|
616
628
|
end
|
data/lib/gloss/cli.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
4
|
##### See src/ to make changes
|
5
5
|
|
6
|
-
|
6
|
+
require "optparse"
|
7
7
|
module Gloss
|
8
8
|
class CLI
|
9
9
|
def initialize(argv)
|
@@ -12,42 +12,47 @@ module Gloss
|
|
12
12
|
def run()
|
13
13
|
command = @argv.first
|
14
14
|
files = @argv.[]((1..-1))
|
15
|
+
err_msg = catch(:"error") { ||
|
15
16
|
case command
|
16
|
-
|
17
|
-
|
17
|
+
when "watch"
|
18
|
+
Watcher.new(files)
|
18
19
|
.watch
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
when "build"
|
21
|
+
(if files.empty?
|
22
|
+
Dir.glob("#{Config.src_dir}/**/*.gl")
|
23
|
+
else
|
24
|
+
files
|
25
|
+
end)
|
25
26
|
.each() { |fp|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
puts("=====> Building #{fp}")
|
28
|
+
content = File.read(fp)
|
29
|
+
tree_hash = Parser.new(content)
|
29
30
|
.run
|
30
|
-
|
31
|
-
|
31
|
+
type_checker = TypeChecker.new
|
32
|
+
rb_output = Builder.new(tree_hash, type_checker)
|
32
33
|
.run
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
type_checker.run(rb_output)
|
35
|
+
puts("=====> Writing #{fp}")
|
36
|
+
Writer.new(rb_output, fp)
|
36
37
|
.run
|
37
|
-
}
|
38
|
-
when "init"
|
39
|
-
force = false
|
40
|
-
OptionParser.new() { |opt|
|
41
|
-
opt.on("--force", "-f") { ||
|
42
|
-
force = true
|
43
38
|
}
|
44
|
-
|
39
|
+
when "init"
|
40
|
+
force = false
|
41
|
+
OptionParser.new() { |opt|
|
42
|
+
opt.on("--force", "-f") { ||
|
43
|
+
force = true
|
44
|
+
}
|
45
|
+
}
|
45
46
|
.parse(@argv)
|
46
|
-
|
47
|
+
Initializer.new(force)
|
47
48
|
.run
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
else
|
50
|
+
throw(:"error", "Gloss doesn't know how to #{command}")
|
51
|
+
end
|
52
|
+
nil }
|
53
|
+
(if err_msg
|
54
|
+
abort(err_msg)
|
55
|
+
end)
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
data/lib/gloss/config.rb
CHANGED
@@ -3,12 +3,17 @@
|
|
3
3
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
4
|
##### See src/ to make changes
|
5
5
|
|
6
|
-
|
6
|
+
require "ostruct"
|
7
7
|
require "yaml"
|
8
8
|
module Gloss
|
9
|
-
|
9
|
+
CONFIG_PATH = ".gloss.yml"
|
10
10
|
Config = OpenStruct.new(default_config: {:frozen_string_literals => true,
|
11
11
|
:src_dir => "src"}.freeze)
|
12
|
+
user_config = (if File.exist?(CONFIG_PATH)
|
13
|
+
YAML.safe_load(File.read(CONFIG_PATH))
|
14
|
+
else
|
15
|
+
Config.default_config
|
16
|
+
end)
|
12
17
|
Config.default_config
|
13
18
|
.each() { |k, v|
|
14
19
|
Config.send(:"#{k}=", user_config.[](k.to_s) || v)
|
data/lib/gloss/initializer.rb
CHANGED
@@ -3,22 +3,22 @@
|
|
3
3
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
4
|
##### See src/ to make changes
|
5
5
|
|
6
|
-
|
6
|
+
require "yaml"
|
7
7
|
module Gloss
|
8
8
|
class Initializer
|
9
9
|
def initialize(force)
|
10
10
|
@force = force
|
11
11
|
end
|
12
12
|
def run()
|
13
|
-
(if File.exist?(
|
14
|
-
|
13
|
+
(if File.exist?(CONFIG_PATH) && !@force
|
14
|
+
throw(:"error", "#{CONFIG_PATH} file already exists - aborting. Use --force to override.")
|
15
15
|
end)
|
16
|
-
File.open(
|
16
|
+
File.open(CONFIG_PATH, "wb") { |file|
|
17
17
|
file.puts(Config.default_config
|
18
18
|
.transform_keys(&:"to_s")
|
19
19
|
.to_yaml)
|
20
20
|
}
|
21
|
-
puts("Created
|
21
|
+
puts("Created #{CONFIG_PATH} with default preferences")
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/gloss/version.rb
CHANGED
data/lib/gloss/watcher.rb
CHANGED
@@ -6,24 +6,38 @@
|
|
6
6
|
require "listen"
|
7
7
|
module Gloss
|
8
8
|
class Watcher
|
9
|
-
def initialize()
|
10
|
-
@paths =
|
9
|
+
def initialize(paths)
|
10
|
+
@paths = paths
|
11
|
+
(if @paths.empty?
|
12
|
+
@paths = [File.join(Dir.pwd, Config.src_dir)]
|
13
|
+
end)
|
11
14
|
end
|
12
15
|
def watch()
|
13
16
|
puts("=====> Now listening for changes in #{@paths.join(", ")}")
|
14
17
|
listener = Listen.to(*@paths, latency: 2) { |modified, added, removed|
|
15
18
|
modified.+(added)
|
16
19
|
.each() { |f|
|
20
|
+
unless f.end_with?(".gl")
|
21
|
+
next
|
22
|
+
end
|
23
|
+
puts("====> Rewriting #{f}")
|
17
24
|
content = File.read(f)
|
18
|
-
Writer.new(Builder.new(content)
|
25
|
+
Writer.new(Builder.new(Parser.new(content)
|
26
|
+
.run)
|
19
27
|
.run, f)
|
20
28
|
.run
|
29
|
+
puts("====> Done")
|
21
30
|
}
|
22
31
|
removed.each() { |f|
|
32
|
+
unless f.end_with?(".gl")
|
33
|
+
next
|
34
|
+
end
|
23
35
|
out_path = Utils.src_path_to_output_path(f)
|
36
|
+
puts("====> Removing #{out_path}")
|
24
37
|
(if File.exist?(out_path)
|
25
38
|
File.delete(out_path)
|
26
39
|
end)
|
40
|
+
puts("====> Done")
|
27
41
|
}
|
28
42
|
}
|
29
43
|
listener.start
|
data/lib/gloss/writer.rb
CHANGED
@@ -9,7 +9,7 @@ module Gloss
|
|
9
9
|
module Utils
|
10
10
|
module_function
|
11
11
|
def src_path_to_output_path(src_path)
|
12
|
-
src_path.sub(
|
12
|
+
src_path.sub("#{Config.src_dir}/", "")
|
13
13
|
.sub(/\.gl$/, ".rb")
|
14
14
|
end
|
15
15
|
end
|
@@ -25,7 +25,7 @@ module Gloss
|
|
25
25
|
FileUtils.mkdir_p(@output_path.parent)
|
26
26
|
end
|
27
27
|
File.open(@output_path, "wb") { |file|
|
28
|
-
file
|
28
|
+
file.puts(@content)
|
29
29
|
}
|
30
30
|
end
|
31
31
|
end
|
data/src/lib/gloss/builder.gl
CHANGED
@@ -1,7 +1,21 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Gloss
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def with_file_header(str)
|
6
|
+
"#{Builder::FILE_HEADER}\n\n#{str}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
4
10
|
class Builder
|
11
|
+
FILE_HEADER = <<~RUBY
|
12
|
+
#{"# frozen_string_literal: true\n" if Config.frozen_string_literals}
|
13
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
14
|
+
##### See #{Config.src_dir}/ to make changes
|
15
|
+
RUBY
|
16
|
+
|
17
|
+
include Utils
|
18
|
+
|
5
19
|
attr_reader :tree
|
6
20
|
|
7
21
|
def initialize(tree_hash, type_checker = nil)
|
@@ -15,13 +29,7 @@ module Gloss
|
|
15
29
|
|
16
30
|
def run
|
17
31
|
rb_output = visit_node(@tree)
|
18
|
-
|
19
|
-
#{"# frozen_string_literal: true\n" if Config.frozen_string_literals}
|
20
|
-
##### This file was generated by Gloss; any changes made here will be overwritten.
|
21
|
-
##### See #{Config.src_dir}/ to make changes
|
22
|
-
|
23
|
-
#{rb_output}
|
24
|
-
RUBY
|
32
|
+
with_file_header(rb_output)
|
25
33
|
end
|
26
34
|
|
27
35
|
# type node = Hash[Symbol, String | Array[String | node] | Hash[Symbol, node]] | true | false
|
@@ -105,7 +113,7 @@ module Gloss
|
|
105
113
|
src.write_ln "end"
|
106
114
|
when "DefNode"
|
107
115
|
args = render_args(node)
|
108
|
-
src.write_ln "def #{node[:name]}#{args}"
|
116
|
+
src.write_ln "def #{node[:name]}#{args[:representation]}"
|
109
117
|
|
110
118
|
return_type = if node[:return_type]
|
111
119
|
RBS::Types::ClassInstance.new(
|
@@ -122,36 +130,17 @@ module Gloss
|
|
122
130
|
)
|
123
131
|
end
|
124
132
|
|
125
|
-
rp : Array[Hash[Symbol, Any]] = node.fetch(:positional_args) { EMPTY_ARRAY }.filter { |a| !a[:value] }
|
126
|
-
op : Array[Hash[Symbol, Any]] = node.fetch(:positional_args) { EMPTY_ARRAY }.filter { |a| a[:value] }
|
127
|
-
|
128
133
|
method_types = [
|
129
134
|
RBS::MethodType.new(
|
130
135
|
type_params: EMPTY_ARRAY, # TODO
|
131
136
|
type: RBS::Types::Function.new(
|
132
|
-
required_positionals:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end,
|
140
|
-
optional_positionals: op.map do |a|
|
141
|
-
RBS::Types::Function::Param.new(
|
142
|
-
name: visit_node(a).to_sym,
|
143
|
-
type: RBS::Types::Bases::Any.new(location: a[:location])
|
144
|
-
)
|
145
|
-
end,
|
146
|
-
rest_positionals: (rpa = node[:rest_p_args]) ? RBS::Types::Function::Param.new(name: visit_node(rpa).to_sym, type: RBS::Types::Bases::Any.new(location: node[:location])) : nil,
|
147
|
-
trailing_positionals: EMPTY_ARRAY, # TODO
|
148
|
-
required_keywords: node[:req_kw_args] || EMPTY_HASH,
|
149
|
-
optional_keywords: node[:opt_kw_args] || EMPTY_HASH,
|
150
|
-
rest_keywords: node[:rest_kw_args] ?
|
151
|
-
RBS::Types::Function::Param.new(
|
152
|
-
name: visit_node(node[:rest_kw_args]).to_sym,
|
153
|
-
type: RBS::Types::Bases::Any.new(location: node[:location])
|
154
|
-
) : nil,
|
137
|
+
required_positionals: args.dig(:types, :required_positionals),
|
138
|
+
optional_positionals: args.dig(:types, :optional_positionals),
|
139
|
+
rest_positionals: args.dig(:types, :rest_positionals),
|
140
|
+
trailing_positionals: args.dig(:types, :trailing_positionals),
|
141
|
+
required_keywords: args.dig(:types, :required_keywords),
|
142
|
+
optional_keywords: args.dig(:types, :optional_keywords),
|
143
|
+
rest_keywords: args.dig(:types, :rest_keywords),
|
155
144
|
return_type: return_type
|
156
145
|
),
|
157
146
|
block: node[:yield_arg_count] ?
|
@@ -216,8 +205,8 @@ module Gloss
|
|
216
205
|
src.write_ln(call)
|
217
206
|
|
218
207
|
when "Block"
|
219
|
-
|
220
|
-
src.write "{
|
208
|
+
args = render_args node
|
209
|
+
src.write "{ #{args[:representation].gsub(/(\A\(|\)\z)/,'|')}\n"
|
221
210
|
|
222
211
|
indented(src) { src.write visit_node(node[:body]) }
|
223
212
|
|
@@ -466,6 +455,9 @@ module Gloss
|
|
466
455
|
types.map { |t| visit_node(t) }.join(" | ")
|
467
456
|
end
|
468
457
|
src.write output
|
458
|
+
when "Next"
|
459
|
+
val = " #{node[:value]}" if node[:value]
|
460
|
+
src.write "next#{val}"
|
469
461
|
when "EmptyNode"
|
470
462
|
# pass
|
471
463
|
else
|
@@ -497,7 +489,8 @@ module Gloss
|
|
497
489
|
src.decrement_indent
|
498
490
|
end
|
499
491
|
|
500
|
-
|
492
|
+
# TODO: allow NamedTuple as return type
|
493
|
+
private def render_args(node)# : { representation: String, types: Hash[Symbol, Any] }
|
501
494
|
rp : Array[Hash[Symbol, Any]] = node.fetch(:positional_args) { EMPTY_ARRAY }.filter { |a| !a[:value] }
|
502
495
|
op : Array[Hash[Symbol, Any]] = node.fetch(:positional_args) { EMPTY_ARRAY }.filter { |a| a[:value] }
|
503
496
|
rkw : Hash[Symbol, Any] = node.fetch(:req_kw_args) { EMPTY_HASH }
|
@@ -514,7 +507,38 @@ module Gloss
|
|
514
507
|
rest_p ? "*#{rest_p}" : "",
|
515
508
|
rest_kw ? "**#{visit_node(rest_kw)}" : ""
|
516
509
|
].reject(&:empty?).flatten.join(", ")
|
517
|
-
"(#{contents})"
|
510
|
+
representation = "(#{contents})"
|
511
|
+
rp.map! do |a|
|
512
|
+
RBS::Types::Function::Param.new(
|
513
|
+
name: visit_node(a).to_sym,
|
514
|
+
type: RBS::Types::Bases::Any.new(
|
515
|
+
location: a[:location]
|
516
|
+
)
|
517
|
+
)
|
518
|
+
end
|
519
|
+
op.map! do |a|
|
520
|
+
RBS::Types::Function::Param.new(
|
521
|
+
name: visit_node(a).to_sym,
|
522
|
+
type: RBS::Types::Bases::Any.new(location: a[:location])
|
523
|
+
)
|
524
|
+
end
|
525
|
+
rest_p = (rpa = node[:rest_p_args]) ? RBS::Types::Function::Param.new(name: visit_node(rpa).to_sym, type: RBS::Types::Bases::Any.new(location: node[:location])) : nil
|
526
|
+
{
|
527
|
+
representation: representation,
|
528
|
+
types: {
|
529
|
+
required_positionals: rp,
|
530
|
+
optional_positionals: op,
|
531
|
+
rest_positionals: rest_p,
|
532
|
+
trailing_positionals: EMPTY_ARRAY, # TODO
|
533
|
+
required_keywords: node[:req_kw_args] || EMPTY_HASH,
|
534
|
+
optional_keywords: node[:opt_kw_args] || EMPTY_HASH,
|
535
|
+
rest_keywords: node[:rest_kw_args] ?
|
536
|
+
RBS::Types::Function::Param.new(
|
537
|
+
name: visit_node(node[:rest_kw_args]).to_sym,
|
538
|
+
type: RBS::Types::Bases::Any.new(location: node[:location])
|
539
|
+
) : nil
|
540
|
+
}
|
541
|
+
}
|
518
542
|
end
|
519
543
|
end
|
520
544
|
end
|
data/src/lib/gloss/cli.gl
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "optparse"
|
4
2
|
|
5
3
|
module Gloss
|
@@ -12,30 +10,35 @@ module Gloss
|
|
12
10
|
# TODO: allow destructuring: command, *files = @argv
|
13
11
|
command = @argv.first
|
14
12
|
files = @argv[1..-1]
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
13
|
+
err_msg = catch :error do
|
14
|
+
case command
|
15
|
+
when "watch"
|
16
|
+
Watcher.new(files).watch
|
17
|
+
when "build"
|
18
|
+
(files.empty? ? Dir.glob("#{Config.src_dir}/**/*.gl") : files).each do |fp|
|
19
|
+
puts "=====> Building #{fp}"
|
20
|
+
content = File.read(fp)
|
21
|
+
tree_hash = Parser.new(content).run
|
22
|
+
type_checker = TypeChecker.new
|
23
|
+
rb_output = Builder.new(tree_hash, type_checker).run
|
24
|
+
type_checker.run(rb_output)
|
26
25
|
|
27
|
-
|
28
|
-
|
26
|
+
puts "=====> Writing #{fp}"
|
27
|
+
Writer.new(rb_output, fp).run
|
28
|
+
end
|
29
|
+
when "init"
|
30
|
+
force = false
|
31
|
+
OptionParser.new do |opt|
|
32
|
+
opt.on("--force", "-f") { force = true }
|
33
|
+
end.parse(@argv)
|
34
|
+
Initializer.new(force).run
|
35
|
+
else
|
36
|
+
throw :error, "Gloss doesn't know how to #{command}"
|
29
37
|
end
|
30
|
-
|
31
|
-
force = false
|
32
|
-
OptionParser.new do |opt|
|
33
|
-
opt.on("--force", "-f") { force = true }
|
34
|
-
end.parse(@argv)
|
35
|
-
Initializer.new(force).run
|
36
|
-
else
|
37
|
-
abort "Gloss doesn't know how to #{command}"
|
38
|
+
nil
|
38
39
|
end
|
40
|
+
|
41
|
+
abort err_msg if err_msg
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
data/src/lib/gloss/config.gl
CHANGED
@@ -4,12 +4,18 @@ require "ostruct"
|
|
4
4
|
require "yaml"
|
5
5
|
|
6
6
|
module Gloss
|
7
|
-
|
7
|
+
CONFIG_PATH = ".gloss.yml"
|
8
8
|
Config = OpenStruct.new(
|
9
9
|
default_config: {
|
10
10
|
frozen_string_literals: true,
|
11
11
|
src_dir: "src",
|
12
12
|
}
|
13
13
|
)
|
14
|
+
|
15
|
+
user_config = if File.exist?(CONFIG_PATH)
|
16
|
+
YAML.safe_load(File.read(CONFIG_PATH))
|
17
|
+
else
|
18
|
+
Config.default_config
|
19
|
+
end
|
14
20
|
Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
|
15
21
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "yaml"
|
4
2
|
|
5
3
|
module Gloss
|
@@ -8,15 +6,15 @@ module Gloss
|
|
8
6
|
end
|
9
7
|
|
10
8
|
def run
|
11
|
-
if File.exist?(
|
12
|
-
|
9
|
+
if File.exist?(CONFIG_PATH) && !@force
|
10
|
+
throw :error, "#{CONFIG_PATH} file already exists - aborting. Use --force to override."
|
13
11
|
end
|
14
12
|
|
15
|
-
File.open(
|
13
|
+
File.open(CONFIG_PATH, "wb") do |file|
|
16
14
|
file.puts Config.default_config.transform_keys(&:to_s).to_yaml
|
17
15
|
end
|
18
16
|
|
19
|
-
puts "Created
|
17
|
+
puts "Created #{CONFIG_PATH} with default preferences"
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
data/src/lib/gloss/version.gl
CHANGED
data/src/lib/gloss/watcher.gl
CHANGED
@@ -4,20 +4,36 @@ require "listen"
|
|
4
4
|
|
5
5
|
module Gloss
|
6
6
|
class Watcher
|
7
|
-
def initialize
|
8
|
-
@paths =
|
7
|
+
def initialize(@paths : Array[String])
|
8
|
+
@paths = [File.join(Dir.pwd, Config.src_dir)] if @paths.empty?
|
9
9
|
end
|
10
10
|
|
11
11
|
def watch
|
12
12
|
puts "=====> Now listening for changes in #{@paths.join(', ')}"
|
13
13
|
listener = Listen.to(*@paths, latency: 2) do |modified, added, removed|
|
14
14
|
(modified + added).each do |f|
|
15
|
+
next unless f.end_with? ".gl"
|
16
|
+
|
17
|
+
puts "====> Rewriting #{f}"
|
15
18
|
content = File.read(f)
|
16
|
-
Writer.new(
|
19
|
+
Writer.new(
|
20
|
+
Builder.new(
|
21
|
+
Parser.new(
|
22
|
+
content
|
23
|
+
).run
|
24
|
+
).run, f
|
25
|
+
).run
|
26
|
+
|
27
|
+
puts "====> Done"
|
17
28
|
end
|
18
29
|
removed.each do |f|
|
30
|
+
next unless f.end_with? ".gl"
|
31
|
+
|
19
32
|
out_path = Utils.src_path_to_output_path(f)
|
33
|
+
puts "====> Removing #{out_path}"
|
20
34
|
File.delete out_path if File.exist? out_path
|
35
|
+
|
36
|
+
puts "====> Done"
|
21
37
|
end
|
22
38
|
end
|
23
39
|
listener.start
|
data/src/lib/gloss/writer.gl
CHANGED
@@ -8,7 +8,7 @@ module Gloss
|
|
8
8
|
module_function
|
9
9
|
|
10
10
|
def src_path_to_output_path(src_path : String) : String
|
11
|
-
src_path.sub(
|
11
|
+
src_path.sub("#{Config.src_dir}/", "")
|
12
12
|
.sub(/\.gl$/, ".rb")
|
13
13
|
end
|
14
14
|
end
|
@@ -26,7 +26,7 @@ module Gloss
|
|
26
26
|
def run
|
27
27
|
FileUtils.mkdir_p(@output_path.parent) unless @output_path.parent.exist?
|
28
28
|
File.open(@output_path, "wb") do |file|
|
29
|
-
file
|
29
|
+
file.puts @content
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gloss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- johansenja
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fast_blank
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- ".github/workflows/ruby.yml"
|
136
136
|
- ".gitignore"
|
137
137
|
- ".gloss.yml"
|
138
|
+
- ".rspec"
|
138
139
|
- ".rubocop.yml"
|
139
140
|
- Gemfile
|
140
141
|
- Gemfile.lock
|
@@ -202,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
202
203
|
- !ruby/object:Gem::Version
|
203
204
|
version: '0'
|
204
205
|
requirements: []
|
205
|
-
rubygems_version: 3.2
|
206
|
+
rubygems_version: 3.1.2
|
206
207
|
signing_key:
|
207
208
|
specification_version: 4
|
208
209
|
summary: A superset of ruby
|