superscript 0.4.2 → 0.8.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/Gemfile.lock +1 -1
- data/e2e/dsls/go.rb +17 -1
- data/e2e/test.rb +2 -3
- data/exe/superscript +17 -8
- data/lib/superscript/ctx.rb +0 -3
- data/lib/superscript/runner.rb +101 -42
- data/lib/superscript/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bc0b05122c192f2a84ec91cadc082732fed684193b8188f8199bba45028325a
|
4
|
+
data.tar.gz: d984d3bf79427a748d7eff8fe5eb52e9be1b79cf8fa4eb2c296876d1e86619e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35ae9ec98919157414db881ab46c8f37038bba5464592539ecb51459d1769d183fa9c734412ca26935444819c0281a8f444d5acbb262bc981511c585a05a439c
|
7
|
+
data.tar.gz: 3d17e452859eaea0861b5971dd7f04077689e7920c446a504b6ecacb4034d4092520ba32f99f2b674071376d736cc0f227575f860ca9622eb06b8d27f74e5aee
|
data/Gemfile.lock
CHANGED
data/e2e/dsls/go.rb
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
class Go < Superscript::Dsl
|
2
2
|
def go(*args)
|
3
|
-
|
3
|
+
self.say "Go #{args.join(" ")}!"
|
4
|
+
end
|
5
|
+
|
6
|
+
def hang
|
7
|
+
sleep 9999
|
8
|
+
end
|
9
|
+
|
10
|
+
def say(message)
|
11
|
+
puts message
|
12
|
+
end
|
13
|
+
|
14
|
+
def struct
|
15
|
+
Struct.new(:name).new("joe")
|
16
|
+
end
|
17
|
+
|
18
|
+
def now
|
19
|
+
Time.now
|
4
20
|
end
|
5
21
|
|
6
22
|
def explode!
|
data/e2e/test.rb
CHANGED
@@ -1,3 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
explode!
|
1
|
+
a = struct
|
2
|
+
go a.name
|
data/exe/superscript
CHANGED
@@ -4,11 +4,18 @@ $stdout.sync = true
|
|
4
4
|
|
5
5
|
require "bundler/setup"
|
6
6
|
require "superscript"
|
7
|
+
require "optparse"
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
options = {
|
10
|
+
methods: false,
|
11
|
+
on_error_exec: nil
|
12
|
+
}
|
13
|
+
ARGV << "-h" if ARGV.empty?
|
14
|
+
|
15
|
+
optparse = OptionParser.new do |opt|
|
16
|
+
opt.on('--allow-methods') { |o| options[:methods] = true }
|
17
|
+
opt.on('--on-error-exec CMD') { |o| options[:on_error_exec] = o }
|
18
|
+
end.parse!
|
12
19
|
|
13
20
|
best_guess_path = if ARGV[0].start_with? "/"
|
14
21
|
ARGV[0]
|
@@ -22,13 +29,15 @@ ctx_classname = File.basename(ARGV[0]).split(".").first.capitalize
|
|
22
29
|
ctx = (eval "#{ctx_classname}").new
|
23
30
|
|
24
31
|
if ARGV[1]
|
25
|
-
runner = Superscript::Runner.new ARGV[1]
|
32
|
+
runner = Superscript::Runner.new ARGV[1], options
|
26
33
|
runner.run! ctx
|
27
34
|
else
|
28
|
-
|
35
|
+
require "readline"
|
36
|
+
|
37
|
+
runner = Superscript::Runner.new nil, options
|
29
38
|
loop do
|
30
|
-
|
31
|
-
|
39
|
+
contents = Readline.readline "> ", true
|
40
|
+
|
32
41
|
value = runner.run! ctx, contents: contents
|
33
42
|
puts " => #{value.inspect}"
|
34
43
|
end
|
data/lib/superscript/ctx.rb
CHANGED
data/lib/superscript/runner.rb
CHANGED
@@ -1,31 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
error_message = ""
|
5
|
-
case where
|
6
|
-
when :exception
|
7
|
-
exception = args.first
|
8
|
-
pp exception
|
9
|
-
pp exception.backtrace_locations
|
10
|
-
error_message = exception
|
11
|
-
when :ctx_method_missing, :tp_singleton_method_added, :tp_command_not_found
|
12
|
-
error_message = args.first
|
13
|
-
when :tp_class_define, :tp_module_define
|
14
|
-
error_message = args.first
|
15
|
-
else
|
16
|
-
pp [:unknown_where, where, args]
|
17
|
-
error_message = args.join(" ")
|
18
|
-
end
|
1
|
+
Signal.trap "TERM" do
|
2
|
+
exit 0
|
3
|
+
end
|
19
4
|
|
20
|
-
|
21
|
-
if ENV["SUPERSCRIPT_ERROR_EXEC"]
|
22
|
-
error_exec_pid = spawn ENV["SUPERSCRIPT_ERROR_EXEC"], error_message
|
23
|
-
Process.wait error_exec_pid
|
24
|
-
end
|
25
|
-
exit 1
|
26
|
-
end
|
5
|
+
module Superscript
|
27
6
|
class Runner
|
28
|
-
def initialize path=nil
|
7
|
+
def initialize path=nil, opts={}
|
8
|
+
@methods = opts[:methods] || false
|
9
|
+
@on_error_exec = opts[:on_error_exec]
|
10
|
+
|
11
|
+
@armed = false
|
29
12
|
@path = if path
|
30
13
|
path
|
31
14
|
else
|
@@ -33,32 +16,77 @@ module Superscript
|
|
33
16
|
end
|
34
17
|
end
|
35
18
|
|
19
|
+
def error!(where, *args)
|
20
|
+
puts "-- [ superscript error ] --"
|
21
|
+
error_message = ""
|
22
|
+
case where
|
23
|
+
when :exception
|
24
|
+
exception = args.first
|
25
|
+
error_message = exception
|
26
|
+
when :tp_call_superscript, :tp_call_superscript_global
|
27
|
+
error_message = "Can't touch this"
|
28
|
+
when :ctx_method_missing, :tp_singleton_method_added, :tp_command_not_found
|
29
|
+
error_message = args.first
|
30
|
+
when :tp_class_define, :tp_module_define
|
31
|
+
error_message = args.first
|
32
|
+
else
|
33
|
+
pp [:unknown_where, where, args]
|
34
|
+
error_message = args.join(" ")
|
35
|
+
end
|
36
|
+
|
37
|
+
puts error_message
|
38
|
+
if @on_error_exec
|
39
|
+
system("#{@on_error_exec} #{error_message}")
|
40
|
+
end
|
41
|
+
|
42
|
+
unless @path == "<interactive>"
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def arm!(reason=nil)
|
48
|
+
p [:arm!, reason] if ENV["SUPERSCRIPT_DEBUG"]
|
49
|
+
@armed = true
|
50
|
+
end
|
51
|
+
def disarm!(reason=nil)
|
52
|
+
p [:disarm!, reason] if ENV["SUPERSCRIPT_DEBUG"]
|
53
|
+
@armed = false
|
54
|
+
end
|
55
|
+
|
36
56
|
def run!(ctx, contents:nil)
|
37
57
|
contents = File.read(@path) unless contents
|
58
|
+
$__superscript_none_of_yer_business = self
|
59
|
+
ctx.define_singleton_method "method_missing" do |*args|
|
60
|
+
$__superscript_none_of_yer_business.error! :ctx_method_missing, "No such command or variable '#{args.first}'"
|
61
|
+
end
|
38
62
|
|
39
|
-
|
63
|
+
disarm! :at_start
|
40
64
|
trace = TracePoint.new do |tp|
|
41
65
|
if ENV["SUPERSCRIPT_DEBUG"]
|
42
66
|
p [@armed, tp.path, tp.lineno, tp.method_id, tp.event, tp.defined_class]
|
43
67
|
end
|
44
68
|
|
69
|
+
if tp.event == :line && tp.path == @path && !@armed
|
70
|
+
arm!
|
71
|
+
end
|
72
|
+
|
45
73
|
if tp.defined_class&.name == "BasicObject" && tp.method_id == :instance_eval
|
46
74
|
if tp.event == :script_compiled
|
47
|
-
|
75
|
+
arm! :script_compiled
|
48
76
|
elsif tp.event == :c_return
|
49
|
-
|
77
|
+
disarm! :script_done
|
50
78
|
end
|
51
79
|
end
|
52
80
|
|
53
|
-
if tp.event == :return && tp.defined_class.ancestors.include?(Superscript::Ctx)
|
54
|
-
|
81
|
+
if tp.path == @path && tp.event == :return && tp.defined_class.ancestors.include?(Superscript::Ctx)
|
82
|
+
arm! :return_to_script_from_dsl_calling_another_dsl_method
|
55
83
|
end
|
56
84
|
|
57
85
|
next unless @armed
|
58
86
|
|
59
87
|
case tp.event
|
60
88
|
when :class
|
61
|
-
|
89
|
+
error! :tp_module_define, "Defining modules is not allowed"
|
62
90
|
when :line
|
63
91
|
lines = if tp.path == "<interactive>"
|
64
92
|
contents.split("\n")
|
@@ -69,19 +97,36 @@ module Superscript
|
|
69
97
|
line = lines[tp.lineno-1].lstrip
|
70
98
|
puts "< #{tp.path}:#{tp.lineno-1}"
|
71
99
|
puts line
|
100
|
+
|
101
|
+
if line.match(/\$__superscript_none_of_yer_business/)
|
102
|
+
tp.disable
|
103
|
+
error! :tp_call_superscript_global
|
104
|
+
end
|
72
105
|
when :c_call
|
73
|
-
# allow calls to these
|
74
|
-
|
106
|
+
# allow calls to these instances
|
107
|
+
if tp.defined_class.ancestors.at(1) == Struct
|
108
|
+
disarm! :safe_instance
|
109
|
+
next
|
110
|
+
end
|
111
|
+
if ["Array", "String","Float", "Integer"].include? tp.defined_class.name
|
112
|
+
disarm! :safe_instance
|
113
|
+
next
|
114
|
+
end
|
75
115
|
|
76
116
|
case tp.method_id
|
77
117
|
when :singleton_method_added
|
118
|
+
if @methods
|
119
|
+
next
|
120
|
+
end
|
121
|
+
trace.disable
|
122
|
+
error! :tp_singleton_method_added, "Deffining methods is not allowed"
|
123
|
+
when :method_missing
|
78
124
|
trace.disable
|
79
|
-
::Superscript.error :tp_singleton_method_added, "Deffining methods is not allowed"
|
80
125
|
else
|
81
126
|
trace.disable
|
82
127
|
case tp.defined_class.name
|
83
128
|
when "Class"
|
84
|
-
|
129
|
+
error! :tp_class_define, "Defining classes is not allowed"
|
85
130
|
else
|
86
131
|
class_name = case tp.defined_class.inspect
|
87
132
|
when "Kernel"
|
@@ -102,17 +147,31 @@ module Superscript
|
|
102
147
|
"#{class_name}.#{tp.method_id}"
|
103
148
|
end
|
104
149
|
|
105
|
-
|
150
|
+
error! :tp_command_not_found, "Command not found '#{command_name}'"
|
106
151
|
end
|
107
152
|
end
|
108
153
|
when :call
|
154
|
+
if tp.method_id == :method_missing
|
155
|
+
tp.disable
|
156
|
+
next
|
157
|
+
end
|
158
|
+
|
159
|
+
if tp.defined_class.ancestors.first.to_s == "#<Class:Superscript>"
|
160
|
+
tp.disable
|
161
|
+
error! :tp_call_superscript
|
162
|
+
end
|
109
163
|
# disable if calling some other file
|
110
|
-
|
111
|
-
|
164
|
+
# but do not allow call to Superscript.error etc
|
165
|
+
if tp.path != @path
|
166
|
+
disarm! :calling_other_file
|
112
167
|
end
|
113
|
-
|
114
|
-
|
168
|
+
tp.defined_class.ancestors.each do |ancestor|
|
169
|
+
if ancestor.to_s == "Superscript::Dsl"
|
170
|
+
disarm! :dsl_method
|
171
|
+
break
|
172
|
+
end
|
115
173
|
end
|
174
|
+
|
116
175
|
end
|
117
176
|
end
|
118
177
|
|
@@ -129,7 +188,7 @@ module Superscript
|
|
129
188
|
print "#{@path}:#{ex.backtrace_locations.first.lineno} "
|
130
189
|
puts ex.message.split(" for ").first
|
131
190
|
else
|
132
|
-
|
191
|
+
error! :exception, ex
|
133
192
|
end
|
134
193
|
ensure
|
135
194
|
trace.disable
|
data/lib/superscript/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: superscript
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matti Paksula
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-05-
|
11
|
+
date: 2020-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|