gvars 0.9.5 → 0.9.7
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/ext/gvars/extconf.rb +1 -1
- data/ext/gvars/gvars.c +249 -18
- data/gb +9 -0
- data/lib/gvars/version.rb +1 -1
- data/tmp.rb +34 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3f54223d6addde0cfe225b0894f2da28b43cfa6f679e786baceeee34aedf7238
|
|
4
|
+
data.tar.gz: 3fcc088c1798d3f303825e4ca5167e11b787ffde7f359101426df82b6bde96f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 98c348911582069c49ad6089837708b0479575ab2d176428d4099bb9c107cef7cadc8ce2173853268b4f442abd49385f63c7888ccb611aa9a4a7f5a94af4cdbf
|
|
7
|
+
data.tar.gz: 37ef3ebeefa4f341dc70e0fc393147e6b8feadc40a29e3edc4b8f7624e5836354f47c4f6801c53fe9301b871882b9a0ed45e872a6931fa05d80f8bc3db061c6c
|
data/ext/gvars/extconf.rb
CHANGED
data/ext/gvars/gvars.c
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#include "ruby.h"
|
|
2
|
+
#define dbg(...) (fprintf(stderr, "%s:%s:%d: ", __FILE__, __FUNCTION__, __LINE__), fprintf(stderr,__VA_ARGS__),fprintf(stderr,"\n"),fflush(stderr))
|
|
3
|
+
|
|
4
|
+
VALUE gvars_module;
|
|
2
5
|
|
|
3
6
|
// Converts `name` to a global variable name, ensures it's valid, and returns it.
|
|
4
7
|
//
|
|
@@ -42,7 +45,7 @@ gvars_f_global_variables(VALUE self)
|
|
|
42
45
|
static VALUE
|
|
43
46
|
gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
|
|
44
47
|
{
|
|
45
|
-
|
|
48
|
+
ID newid = rb_intern(get_global_name(&new));
|
|
46
49
|
rb_alias_variable(newid, rb_intern(get_global_name(&old)));
|
|
47
50
|
return ID2SYM(newid);
|
|
48
51
|
}
|
|
@@ -50,44 +53,268 @@ gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
|
|
|
50
53
|
static VALUE
|
|
51
54
|
gvars_enum_length(VALUE self, VALUE args, VALUE eobj)
|
|
52
55
|
{
|
|
53
|
-
|
|
56
|
+
return LONG2NUM(RARRAY_LEN(rb_f_global_variables()));
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
static VALUE
|
|
57
60
|
gvars_f_each(VALUE self)
|
|
58
61
|
{
|
|
59
|
-
|
|
62
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, gvars_enum_length);
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
VALUE gvars = gvars_f_global_variables(self);
|
|
65
|
+
for (long i = 0; i < RARRAY_LEN(gvars); i++) {
|
|
66
|
+
VALUE key = RARRAY_AREF(gvars, i);
|
|
67
|
+
rb_yield(rb_ary_new3(2, key, gvars_f_global_variable_get(self, key)));
|
|
68
|
+
}
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
return self;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
static VALUE
|
|
71
74
|
gvars_f_to_h(VALUE self)
|
|
72
75
|
{
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
VALUE gvars = gvars_f_global_variables(self);
|
|
77
|
+
VALUE hash = rb_hash_new_capa(RARRAY_LEN(gvars));
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
for (long i = 0; i < RARRAY_LEN(gvars); i++) {
|
|
80
|
+
VALUE key = RARRAY_AREF(gvars, i);
|
|
81
|
+
rb_hash_aset(hash, key, gvars_f_global_variable_get(self, key));
|
|
82
|
+
}
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
return hash;
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
struct value_ptr { VALUE *value; };
|
|
88
|
+
static void value_ptr_mark(void *ptr) { rb_gc_mark(*((struct value_ptr *) ptr)->value); }
|
|
89
|
+
static void value_ptr_free(void *ptr) { ruby_xfree(((struct value_ptr *) ptr)->value); }
|
|
90
|
+
static const rb_data_type_t value_ptr_data_type = {
|
|
91
|
+
.wrap_struct_name = "gvars/value_ptr",
|
|
92
|
+
.function = {
|
|
93
|
+
.dmark = value_ptr_mark,
|
|
94
|
+
.dfree = value_ptr_free,
|
|
95
|
+
.dsize = NULL // todo: not 0
|
|
96
|
+
},
|
|
97
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
struct gvars_virtual_var {
|
|
102
|
+
VALUE backing, getter, setter;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
static void gvars_virtual_var_mark(void *ptr) {
|
|
106
|
+
struct gvars_virtual_var *gv = ptr;
|
|
107
|
+
if (gv->backing != Qundef) rb_gc_mark(gv->backing);
|
|
108
|
+
rb_gc_mark(gv->getter);
|
|
109
|
+
rb_gc_mark(gv->setter);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static void gvars_virtual_var_free(void *ptr) {
|
|
113
|
+
xfree(ptr);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static const rb_data_type_t gvars_type = {
|
|
117
|
+
.wrap_struct_name = "gvars_var",
|
|
118
|
+
.function = {
|
|
119
|
+
.dmark = gvars_virtual_var_mark,
|
|
120
|
+
.dfree = gvars_virtual_var_free,
|
|
121
|
+
.dsize = NULL
|
|
122
|
+
},
|
|
123
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
static VALUE gvars_virtual_var_getter(ID id, VALUE *data) {
|
|
128
|
+
struct gvars_virtual_var *gv;
|
|
129
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
130
|
+
|
|
131
|
+
return rb_proc_call_kw(gv->getter, rb_ary_new(), RB_NO_KEYWORDS);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static void gvars_virtual_var_setter(VALUE val, ID id, VALUE *data) {
|
|
135
|
+
struct gvars_virtual_var *gv;
|
|
136
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
137
|
+
|
|
138
|
+
rb_proc_call_kw(gv->setter, rb_ary_new3(1, val), RB_NO_KEYWORDS);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
static VALUE gvars_hooked_state_var_getter(ID id, VALUE *data) {
|
|
142
|
+
struct gvars_virtual_var *gv;
|
|
143
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
144
|
+
|
|
145
|
+
return rb_proc_call_kw(gv->getter, rb_ary_new3(1, gv->backing), RB_NO_KEYWORDS);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static void gvars_hooked_state_var_setter_noproc(VALUE val, ID id, VALUE *data) {
|
|
149
|
+
struct gvars_virtual_var *gv;
|
|
150
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
151
|
+
|
|
152
|
+
gv->backing = val;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
static void gvars_hooked_state_var_setter_proc(VALUE val, ID id, VALUE *data) {
|
|
156
|
+
struct gvars_virtual_var *gv;
|
|
157
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
158
|
+
|
|
159
|
+
gv->backing = rb_proc_call_kw(gv->setter, rb_ary_new3(2, val, gv->backing), RB_NO_KEYWORDS);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static VALUE gvars_hooked_initial_var_getter(ID id, VALUE *data) {
|
|
163
|
+
struct gvars_virtual_var *gv;
|
|
164
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
165
|
+
|
|
166
|
+
gv->backing = rb_proc_call_kw(gv->getter, rb_ary_new3(1, gv->backing), RB_NO_KEYWORDS);
|
|
167
|
+
return gv->backing;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static void gvars_hooked_initial_var_setter_noproc(VALUE val, ID id, VALUE *data) {
|
|
171
|
+
struct gvars_virtual_var *gv;
|
|
172
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
173
|
+
|
|
174
|
+
gv->backing = val;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
static void gvars_hooked_initial_var_setter_proc(VALUE val, ID id, VALUE *data) {
|
|
178
|
+
struct gvars_virtual_var *gv;
|
|
179
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
180
|
+
|
|
181
|
+
gv->backing = rb_proc_call_kw(gv->setter, rb_ary_new3(2, val, gv->backing), RB_NO_KEYWORDS);
|
|
182
|
+
}
|
|
84
183
|
|
|
85
|
-
|
|
184
|
+
|
|
185
|
+
static VALUE gvars_virtual_var_alloc(VALUE backing, VALUE getter, VALUE setter) {
|
|
186
|
+
struct gvars_virtual_var *gv;
|
|
187
|
+
VALUE gvar_ty = TypedData_Make_Struct(rb_cObject, struct gvars_virtual_var, &gvars_type, gv);
|
|
188
|
+
gv->backing = backing;
|
|
189
|
+
gv->getter = getter;
|
|
190
|
+
gv->setter = setter;
|
|
191
|
+
return gvar_ty;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
enum virtual_kind {
|
|
195
|
+
GVARS_VIRTUAL_KIND_VIRTUAL,
|
|
196
|
+
GVARS_VIRTUAL_KIND_INITIAL,
|
|
197
|
+
GVARS_VIRTUAL_KIND_STATE,
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
static void
|
|
201
|
+
gvars_define_virtual_method(VALUE self, VALUE *name, VALUE backing, VALUE getter, VALUE setter, enum virtual_kind kind, int readonly_special)
|
|
202
|
+
{
|
|
203
|
+
char *name_str = get_global_name(name);
|
|
204
|
+
VALUE getter_proc, setter_proc;
|
|
205
|
+
|
|
206
|
+
getter_proc = rb_convert_type(getter, T_DATA, "Proc", "to_proc");
|
|
207
|
+
if (NIL_P(getter_proc) || !rb_obj_is_proc(getter_proc)) {
|
|
208
|
+
rb_raise(rb_eTypeError, "wrong getter type %s (expected Proc)", rb_obj_classname(getter_proc));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (NIL_P(setter)) {
|
|
212
|
+
setter_proc = Qnil;
|
|
213
|
+
} else {
|
|
214
|
+
setter_proc = rb_convert_type(setter, T_DATA, "Proc", "to_proc");
|
|
215
|
+
if (NIL_P(setter_proc) || !rb_obj_is_proc(setter_proc)) {
|
|
216
|
+
rb_raise(rb_eTypeError, "wrong setter type %s (expected Proc)", rb_obj_classname(setter_proc));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
struct value_ptr *vp;
|
|
221
|
+
VALUE vp_data = TypedData_Make_Struct(rb_cObject, struct value_ptr, &value_ptr_data_type, vp);
|
|
222
|
+
vp->value = RB_ALLOC(VALUE);
|
|
223
|
+
*vp->value = gvars_virtual_var_alloc(backing, getter, setter);
|
|
224
|
+
|
|
225
|
+
rb_gvar_getter_t *getter_meth;
|
|
226
|
+
rb_gvar_setter_t *setter_meth;
|
|
227
|
+
|
|
228
|
+
switch (kind) {
|
|
229
|
+
case GVARS_VIRTUAL_KIND_VIRTUAL:
|
|
230
|
+
getter_meth = gvars_virtual_var_getter;
|
|
231
|
+
setter_meth = setter_proc == Qnil ? rb_gvar_readonly_setter : gvars_virtual_var_setter;
|
|
232
|
+
break;
|
|
233
|
+
|
|
234
|
+
case GVARS_VIRTUAL_KIND_INITIAL:
|
|
235
|
+
getter_meth = gvars_hooked_initial_var_getter;
|
|
236
|
+
setter_meth = setter_proc == Qnil ? gvars_hooked_initial_var_setter_noproc : gvars_hooked_initial_var_setter_proc;
|
|
237
|
+
break;
|
|
238
|
+
|
|
239
|
+
case GVARS_VIRTUAL_KIND_STATE:
|
|
240
|
+
getter_meth = gvars_hooked_state_var_getter;
|
|
241
|
+
setter_meth = setter_proc == Qnil ? gvars_hooked_state_var_setter_noproc : gvars_hooked_state_var_setter_proc;
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
default:
|
|
245
|
+
rb_bug("oops");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (readonly_special) setter_meth = rb_gvar_readonly_setter;
|
|
249
|
+
|
|
250
|
+
rb_define_hooked_variable(name_str, vp->value, getter_meth, setter_meth);
|
|
251
|
+
|
|
252
|
+
VALUE hash = rb_iv_get(gvars_module, "@vars");
|
|
253
|
+
VALUE namesym = rb_str_new_cstr(name_str);
|
|
254
|
+
rb_hash_aset(hash, namesym, vp_data);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static VALUE
|
|
258
|
+
gvars_f_define_virtual_method(int argc, VALUE *argv, VALUE self)
|
|
259
|
+
{
|
|
260
|
+
VALUE name, backing = Qundef, getter, setter, opts_hash, opts[3];
|
|
261
|
+
ID keyword_ids[3];
|
|
262
|
+
keyword_ids[0] = rb_intern("initial");
|
|
263
|
+
keyword_ids[1] = rb_intern("state");
|
|
264
|
+
keyword_ids[2] = rb_intern("readonly");
|
|
265
|
+
|
|
266
|
+
switch (rb_scan_args(argc, argv, "12:", &name, &getter, &setter, &opts_hash)) {
|
|
267
|
+
case 1:
|
|
268
|
+
getter = (rb_need_block(), rb_block_proc());
|
|
269
|
+
setter = Qnil;
|
|
270
|
+
break;
|
|
271
|
+
|
|
272
|
+
case 2:
|
|
273
|
+
setter = Qnil;
|
|
274
|
+
|
|
275
|
+
case 3:
|
|
276
|
+
if (rb_block_given_p()) {
|
|
277
|
+
rb_warn("given block not used");
|
|
278
|
+
}
|
|
279
|
+
break;
|
|
280
|
+
default:
|
|
281
|
+
rb_bug("oops");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
enum virtual_kind kind = GVARS_VIRTUAL_KIND_VIRTUAL;
|
|
285
|
+
rb_get_kwargs(opts_hash, keyword_ids, 0, 3, opts);
|
|
286
|
+
|
|
287
|
+
if (opts[0] != Qundef) {
|
|
288
|
+
if (opts[1] != Qundef) {
|
|
289
|
+
rb_raise(rb_eArgError, "only one of 'initial' or 'state' may be supplied");
|
|
290
|
+
}
|
|
291
|
+
backing = opts[0];
|
|
292
|
+
kind = GVARS_VIRTUAL_KIND_INITIAL;
|
|
293
|
+
} else if (opts[1] != Qundef) {
|
|
294
|
+
backing = opts[1];
|
|
295
|
+
kind = GVARS_VIRTUAL_KIND_STATE;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
bool is_readonly = false;
|
|
299
|
+
if (opts[2] != Qundef && RTEST(opts[2])) { // sadly no bool expected :-/
|
|
300
|
+
if (setter != Qnil) {
|
|
301
|
+
rb_raise(rb_eArgError, "'readonly: true' may not be supplied when a setter proc is supplied");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
setter = Qnil;
|
|
305
|
+
is_readonly = true;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
gvars_define_virtual_method(self, &name, backing, getter, setter, kind, is_readonly);
|
|
309
|
+
|
|
310
|
+
return name; //TODO: ID2SYM(id)
|
|
311
|
+
}
|
|
86
312
|
|
|
87
313
|
void
|
|
88
314
|
Init_gvars(void)
|
|
89
315
|
{
|
|
90
316
|
gvars_module = rb_define_module("GVars");
|
|
317
|
+
rb_ivar_set(gvars_module, rb_intern("@vars"), rb_hash_new());
|
|
91
318
|
|
|
92
319
|
// Define module-level functions that can be used as mixins
|
|
93
320
|
rb_define_module_function(gvars_module, "global_variable_get", gvars_f_global_variable_get, 1);
|
|
@@ -97,8 +324,11 @@ Init_gvars(void)
|
|
|
97
324
|
// Don't make it an instance method, as it exists in Kernel
|
|
98
325
|
rb_define_singleton_method(gvars_module, "global_variables", gvars_f_global_variables, 0);
|
|
99
326
|
|
|
327
|
+
// Don't make it an instance method, cause we don't want it included
|
|
328
|
+
rb_define_singleton_method(gvars_module, "define_virtual_method", gvars_f_define_virtual_method, -1);
|
|
329
|
+
|
|
100
330
|
// Enumerable methods
|
|
101
|
-
|
|
331
|
+
rb_extend_object(gvars_module, rb_mEnumerable);
|
|
102
332
|
rb_define_singleton_method(gvars_module, "each", gvars_f_each, 0);
|
|
103
333
|
rb_define_singleton_method(gvars_module, "to_h", gvars_f_to_h, 0);
|
|
104
334
|
|
|
@@ -110,4 +340,5 @@ Init_gvars(void)
|
|
|
110
340
|
rb_define_alias(gvars_singleton, "[]=", "global_variable_set");
|
|
111
341
|
rb_define_alias(gvars_singleton, "alias", "alias_global_variable");
|
|
112
342
|
rb_define_alias(gvars_singleton, "list", "global_variables");
|
|
343
|
+
rb_define_alias(gvars_singleton, "virtual", "define_virtual_method");
|
|
113
344
|
}
|
data/gb
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
version = nil
|
|
4
|
+
File.open File.join __dir__, 'lib', 'gvars', 'version.rb' do |f|
|
|
5
|
+
f.read =~ /VERSION = '(.*)'/ and (version = $1; break)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
fail "cant find version" unless version
|
|
9
|
+
system('gem build gvars') && system("gem install ./gvars-#{version}.gem")
|
data/lib/gvars/version.rb
CHANGED
data/tmp.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'gvars'
|
|
2
|
+
p GVars::VERSION
|
|
3
|
+
|
|
4
|
+
100.times do
|
|
5
|
+
GVars.virtual(:$foo) { p "bar" }
|
|
6
|
+
# GVars.virtual(:$foo) { p "foo" }
|
|
7
|
+
# $foo
|
|
8
|
+
# p($foo)
|
|
9
|
+
# p GVars.instance_variable_get(:@vars)
|
|
10
|
+
GC.start
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
GVars.virtual(:$foo1) { "hello" }; fail unless 'hello' == $foo1
|
|
14
|
+
GVars.virtual(:$foo2, proc{ "hello" }); fail unless 'hello' == $foo2
|
|
15
|
+
GVars.virtual(:$foo3, proc{ "hello" }, proc { it + 1 }); fail unless ['hello', 3, 'hello'] == [$foo3, $foo3 = 3, $foo3]
|
|
16
|
+
|
|
17
|
+
GVars.virtual(:$bar1, initial: 0) { it + 1 }; fail unless [1, 2, 3] == [$bar1, $bar1, $bar1]
|
|
18
|
+
$bar1 = 10
|
|
19
|
+
fail unless 11 == $bar1
|
|
20
|
+
|
|
21
|
+
GVars.virtual(:$bar2, state: 'a') { it.succ!.dup }
|
|
22
|
+
fail unless ['b', 'c', 'd'] == [$bar2, $bar2, $bar2]
|
|
23
|
+
$bar2 = 10
|
|
24
|
+
fail unless 11 == $bar2
|
|
25
|
+
|
|
26
|
+
# GVars.virtual(:$bar, proc{ p "bar" })
|
|
27
|
+
# GVars.virtual(:$baz, proc{ p "bar" }, proc { p "baz: #{_1}"})
|
|
28
|
+
|
|
29
|
+
# 100.times do
|
|
30
|
+
# $foo
|
|
31
|
+
# $bar
|
|
32
|
+
# $baz
|
|
33
|
+
# GC.start
|
|
34
|
+
# end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gvars
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sam Westerman
|
|
@@ -25,9 +25,11 @@ files:
|
|
|
25
25
|
- ext/gvars/extconf.rb
|
|
26
26
|
- ext/gvars/gvars.c
|
|
27
27
|
- ext/gvars/gvars.c-old
|
|
28
|
+
- gb
|
|
28
29
|
- lib/gvars.rb
|
|
29
30
|
- lib/gvars/version.rb
|
|
30
31
|
- sig/gvars.rbs
|
|
32
|
+
- tmp.rb
|
|
31
33
|
homepage: https://github.com/sampersand/gvars
|
|
32
34
|
licenses:
|
|
33
35
|
- MIT
|