spoom 1.0.4 → 1.0.5
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/README.md +253 -1
- data/Rakefile +1 -0
- data/lib/spoom.rb +2 -1
- data/lib/spoom/cli.rb +42 -7
- data/lib/spoom/cli/bump.rb +59 -0
- data/lib/spoom/cli/config.rb +51 -0
- data/lib/spoom/cli/coverage.rb +191 -0
- data/lib/spoom/cli/helper.rb +70 -0
- data/lib/spoom/cli/lsp.rb +165 -0
- data/lib/spoom/cli/run.rb +79 -0
- data/lib/spoom/config.rb +1 -1
- data/lib/spoom/coverage.rb +73 -0
- data/lib/spoom/coverage/d3.rb +110 -0
- data/lib/spoom/coverage/d3/base.rb +50 -0
- data/lib/spoom/coverage/d3/circle_map.rb +195 -0
- data/lib/spoom/coverage/d3/pie.rb +175 -0
- data/lib/spoom/coverage/d3/timeline.rb +486 -0
- data/lib/spoom/coverage/report.rb +308 -0
- data/lib/spoom/coverage/snapshot.rb +132 -0
- data/lib/spoom/file_tree.rb +196 -0
- data/lib/spoom/git.rb +98 -0
- data/lib/spoom/printer.rb +81 -0
- data/lib/spoom/sorbet.rb +15 -2
- data/lib/spoom/sorbet/errors.rb +25 -15
- data/lib/spoom/sorbet/lsp.rb +4 -2
- data/lib/spoom/sorbet/lsp/structures.rb +108 -14
- data/lib/spoom/sorbet/metrics.rb +10 -79
- data/lib/spoom/sorbet/sigils.rb +98 -0
- data/lib/spoom/test_helpers/project.rb +103 -0
- data/lib/spoom/timeline.rb +53 -0
- data/lib/spoom/version.rb +1 -1
- metadata +25 -10
- data/lib/spoom/cli/commands/base.rb +0 -36
- data/lib/spoom/cli/commands/config.rb +0 -67
- data/lib/spoom/cli/commands/lsp.rb +0 -156
- data/lib/spoom/cli/commands/run.rb +0 -92
- data/lib/spoom/cli/symbol_printer.rb +0 -71
data/lib/spoom/git.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
module Spoom
|
7
|
+
# Execute git commands
|
8
|
+
module Git
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
# Execute a `command`
|
12
|
+
sig { params(command: String, arg: String, path: String).returns([String, String, T::Boolean]) }
|
13
|
+
def self.exec(command, *arg, path: '.')
|
14
|
+
return "", "Error: `#{path}` is not a directory.", false unless File.directory?(path)
|
15
|
+
opts = {}
|
16
|
+
opts[:chdir] = path
|
17
|
+
_, o, e, s = Open3.popen3(*T.unsafe([command, *T.unsafe(arg), opts]))
|
18
|
+
out = o.read.to_s
|
19
|
+
o.close
|
20
|
+
err = e.read.to_s
|
21
|
+
e.close
|
22
|
+
[out, err, T.cast(s.value, Process::Status).success?]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Git commands
|
26
|
+
|
27
|
+
sig { params(arg: String, path: String).returns([String, String, T::Boolean]) }
|
28
|
+
def self.checkout(*arg, path: ".")
|
29
|
+
exec("git checkout -q #{arg.join(' ')}", path: path)
|
30
|
+
end
|
31
|
+
|
32
|
+
sig { params(arg: String, path: String).returns([String, String, T::Boolean]) }
|
33
|
+
def self.diff(*arg, path: ".")
|
34
|
+
exec("git diff #{arg.join(' ')}", path: path)
|
35
|
+
end
|
36
|
+
|
37
|
+
sig { params(arg: String, path: String).returns([String, String, T::Boolean]) }
|
38
|
+
def self.log(*arg, path: ".")
|
39
|
+
exec("git log #{arg.join(' ')}", path: path)
|
40
|
+
end
|
41
|
+
|
42
|
+
sig { params(arg: String, path: String).returns([String, String, T::Boolean]) }
|
43
|
+
def self.rev_parse(*arg, path: ".")
|
44
|
+
exec("git rev-parse --short #{arg.join(' ')}", path: path)
|
45
|
+
end
|
46
|
+
|
47
|
+
sig { params(arg: String, path: String).returns([String, String, T::Boolean]) }
|
48
|
+
def self.show(*arg, path: ".")
|
49
|
+
exec("git show #{arg.join(' ')}", path: path)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Utils
|
53
|
+
|
54
|
+
# Get the commit epoch timestamp for a `sha`
|
55
|
+
sig { params(sha: String, path: String).returns(T.nilable(Integer)) }
|
56
|
+
def self.commit_timestamp(sha, path: ".")
|
57
|
+
out, _, status = show("--no-notes --no-patch --pretty=%at #{sha}", path: path)
|
58
|
+
return nil unless status
|
59
|
+
out.strip.to_i
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get the commit Time for a `sha`
|
63
|
+
sig { params(sha: String, path: String).returns(T.nilable(Time)) }
|
64
|
+
def self.commit_time(sha, path: ".")
|
65
|
+
timestamp = commit_timestamp(sha, path: path)
|
66
|
+
return nil unless timestamp
|
67
|
+
epoch_to_time(timestamp.to_s)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get the last commit sha
|
71
|
+
sig { params(path: String).returns(T.nilable(String)) }
|
72
|
+
def self.last_commit(path: ".")
|
73
|
+
out, _, status = rev_parse("HEAD", path: path)
|
74
|
+
return nil unless status
|
75
|
+
out.strip
|
76
|
+
end
|
77
|
+
|
78
|
+
# Translate a git epoch timestamp into a Time
|
79
|
+
sig { params(timestamp: String).returns(Time) }
|
80
|
+
def self.epoch_to_time(timestamp)
|
81
|
+
Time.strptime(timestamp, "%s")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Is there uncommited changes in `path`?
|
85
|
+
sig { params(path: String).returns(T::Boolean) }
|
86
|
+
def self.workdir_clean?(path: ".")
|
87
|
+
diff("HEAD", path: path).first.empty?
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get the hash of the commit introducing the `sorbet/config` file
|
91
|
+
sig { params(path: String).returns(T.nilable(String)) }
|
92
|
+
def self.sorbet_intro_commit(path: ".")
|
93
|
+
res, _, status = Spoom::Git.log("--diff-filter=A --format='%h' -1 -- sorbet/config", path: path)
|
94
|
+
return nil unless status
|
95
|
+
res.strip
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "colorize"
|
5
|
+
require "stringio"
|
6
|
+
|
7
|
+
module Spoom
|
8
|
+
class Printer
|
9
|
+
extend T::Sig
|
10
|
+
extend T::Helpers
|
11
|
+
|
12
|
+
abstract!
|
13
|
+
|
14
|
+
sig { returns(T.any(IO, StringIO)) }
|
15
|
+
attr_accessor :out
|
16
|
+
|
17
|
+
sig { params(out: T.any(IO, StringIO), colors: T::Boolean, indent_level: Integer).void }
|
18
|
+
def initialize(out: $stdout, colors: true, indent_level: 0)
|
19
|
+
@out = out
|
20
|
+
@colors = colors
|
21
|
+
@indent_level = indent_level
|
22
|
+
end
|
23
|
+
|
24
|
+
# Increase indent level
|
25
|
+
sig { void }
|
26
|
+
def indent
|
27
|
+
@indent_level += 2
|
28
|
+
end
|
29
|
+
|
30
|
+
# Decrease indent level
|
31
|
+
sig { void }
|
32
|
+
def dedent
|
33
|
+
@indent_level -= 2
|
34
|
+
end
|
35
|
+
|
36
|
+
# Print `string` into `out`
|
37
|
+
sig { params(string: T.nilable(String)).void }
|
38
|
+
def print(string)
|
39
|
+
return unless string
|
40
|
+
@out.print(string)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Print `string` colored with `color` into `out`
|
44
|
+
#
|
45
|
+
# Does not use colors unless `@colors`.
|
46
|
+
sig { params(string: T.nilable(String), color: Symbol, colors: Symbol).void }
|
47
|
+
def print_colored(string, color, *colors)
|
48
|
+
return unless string
|
49
|
+
string = colorize(string, color)
|
50
|
+
colors.each { |c| string = colorize(string, c) }
|
51
|
+
@out.print(string)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Print a new line into `out`
|
55
|
+
sig { void }
|
56
|
+
def printn
|
57
|
+
print("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
# Print `string` with indent and newline
|
61
|
+
sig { params(string: T.nilable(String)).void }
|
62
|
+
def printl(string)
|
63
|
+
return unless string
|
64
|
+
printt
|
65
|
+
print(string)
|
66
|
+
printn
|
67
|
+
end
|
68
|
+
|
69
|
+
# Print an indent space into `out`
|
70
|
+
sig { void }
|
71
|
+
def printt
|
72
|
+
print(" " * @indent_level)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Colorize `string` with color if `@colors`
|
76
|
+
sig { params(string: String, color: Symbol).returns(String) }
|
77
|
+
def colorize(string, color)
|
78
|
+
@colors ? string.colorize(color) : string
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/spoom/sorbet.rb
CHANGED
@@ -5,6 +5,7 @@ require "spoom/sorbet/config"
|
|
5
5
|
require "spoom/sorbet/errors"
|
6
6
|
require "spoom/sorbet/lsp"
|
7
7
|
require "spoom/sorbet/metrics"
|
8
|
+
require "spoom/sorbet/sigils"
|
8
9
|
|
9
10
|
require "open3"
|
10
11
|
|
@@ -54,17 +55,29 @@ module Spoom
|
|
54
55
|
out.split(" ")[2]
|
55
56
|
end
|
56
57
|
|
57
|
-
sig { params(arg: String, path: String, capture_err: T::Boolean).returns(T.nilable(
|
58
|
+
sig { params(arg: String, path: String, capture_err: T::Boolean).returns(T.nilable(T::Hash[String, Integer])) }
|
58
59
|
def self.srb_metrics(*arg, path: '.', capture_err: false)
|
59
60
|
metrics_file = "metrics.tmp"
|
60
61
|
metrics_path = "#{path}/#{metrics_file}"
|
61
62
|
srb_tc(*T.unsafe(["--metrics-file=#{metrics_file}", *arg]), path: path, capture_err: capture_err)
|
62
63
|
if File.exist?(metrics_path)
|
63
|
-
metrics = Spoom::Sorbet::
|
64
|
+
metrics = Spoom::Sorbet::MetricsParser.parse_file(metrics_path)
|
64
65
|
File.delete(metrics_path)
|
65
66
|
return metrics
|
66
67
|
end
|
67
68
|
nil
|
68
69
|
end
|
70
|
+
|
71
|
+
# Get `gem` version from the `Gemfile.lock` content
|
72
|
+
#
|
73
|
+
# Returns `nil` if `gem` cannot be found in the Gemfile.
|
74
|
+
sig { params(gem: String, path: String).returns(T.nilable(String)) }
|
75
|
+
def self.version_from_gemfile_lock(gem: 'sorbet', path: '.')
|
76
|
+
gemfile_path = "#{path}/Gemfile.lock"
|
77
|
+
return nil unless File.exist?(gemfile_path)
|
78
|
+
content = File.read(gemfile_path).match(/^ #{gem} \(.*(\d+\.\d+\.\d+).*\)/)
|
79
|
+
return nil unless content
|
80
|
+
content[1]
|
81
|
+
end
|
69
82
|
end
|
70
83
|
end
|
data/lib/spoom/sorbet/errors.rb
CHANGED
@@ -16,6 +16,19 @@ module Spoom
|
|
16
16
|
"or set SORBET_SILENCE_DEV_MESSAGE=1 in your shell environment.",
|
17
17
|
]
|
18
18
|
|
19
|
+
ERROR_LINE_MATCH_REGEX = %r{
|
20
|
+
^ # match beginning of line
|
21
|
+
(\S[^:]*) # capture filename as something that starts with a non-space character
|
22
|
+
# followed by anything that is not a colon character
|
23
|
+
: # match the filename - line number seperator
|
24
|
+
(\d+) # capture the line number
|
25
|
+
:\s # match the line number - error message separator
|
26
|
+
(.*) # capture the error message
|
27
|
+
\shttps://srb.help/ # match the error code url prefix
|
28
|
+
(\d+) # capture the error code
|
29
|
+
$ # match end of line
|
30
|
+
}x.freeze
|
31
|
+
|
19
32
|
sig { params(output: String).returns(T::Array[Error]) }
|
20
33
|
def self.parse_string(output)
|
21
34
|
parser = Spoom::Sorbet::Errors::Parser.new
|
@@ -37,9 +50,9 @@ module Spoom
|
|
37
50
|
|
38
51
|
next if line == "\n"
|
39
52
|
|
40
|
-
if
|
53
|
+
if (error = match_error_line(line))
|
41
54
|
close_error if @current_error
|
42
|
-
open_error(
|
55
|
+
open_error(error)
|
43
56
|
next
|
44
57
|
end
|
45
58
|
|
@@ -51,15 +64,19 @@ module Spoom
|
|
51
64
|
|
52
65
|
private
|
53
66
|
|
54
|
-
sig { params(line: String).returns(T.nilable(
|
55
|
-
def
|
56
|
-
line.
|
67
|
+
sig { params(line: String).returns(T.nilable(Error)) }
|
68
|
+
def match_error_line(line)
|
69
|
+
match = line.match(ERROR_LINE_MATCH_REGEX)
|
70
|
+
return unless match
|
71
|
+
|
72
|
+
file, line, message, code = match.captures
|
73
|
+
Error.new(file, line&.to_i, message, code&.to_i)
|
57
74
|
end
|
58
75
|
|
59
|
-
sig { params(
|
60
|
-
def open_error(
|
76
|
+
sig { params(error: Error).void }
|
77
|
+
def open_error(error)
|
61
78
|
raise "Error: Already parsing an error!" if @current_error
|
62
|
-
@current_error =
|
79
|
+
@current_error = error
|
63
80
|
end
|
64
81
|
|
65
82
|
sig { void }
|
@@ -106,13 +123,6 @@ module Spoom
|
|
106
123
|
@more = more
|
107
124
|
end
|
108
125
|
|
109
|
-
sig { params(line: String).returns(Error) }
|
110
|
-
def self.from_error_line(line)
|
111
|
-
file, line, rest = line.split(/: ?/, 3)
|
112
|
-
message, code = rest&.split(%r{ https://srb\.help/}, 2)
|
113
|
-
Error.new(file, line&.to_i, message, code&.to_i)
|
114
|
-
end
|
115
|
-
|
116
126
|
sig { params(other: T.untyped).returns(Integer) }
|
117
127
|
def <=>(other)
|
118
128
|
return 0 unless other.is_a?(Error)
|
data/lib/spoom/sorbet/lsp.rb
CHANGED
@@ -11,10 +11,12 @@ require_relative 'lsp/errors'
|
|
11
11
|
module Spoom
|
12
12
|
module LSP
|
13
13
|
class Client
|
14
|
-
def initialize(sorbet_cmd, *sorbet_args)
|
14
|
+
def initialize(sorbet_cmd, *sorbet_args, path: ".")
|
15
15
|
@id = 0
|
16
16
|
Bundler.with_clean_env do
|
17
|
-
|
17
|
+
opts = {}
|
18
|
+
opts[:chdir] = path
|
19
|
+
@in, @out, @err, @status = Open3.popen3([sorbet_cmd, *sorbet_args].join(" "), opts)
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -1,9 +1,24 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require_relative "../../printer"
|
5
|
+
|
4
6
|
module Spoom
|
5
7
|
module LSP
|
8
|
+
module PrintableSymbol
|
9
|
+
extend T::Sig
|
10
|
+
extend T::Helpers
|
11
|
+
|
12
|
+
interface!
|
13
|
+
|
14
|
+
sig { abstract.params(printer: SymbolPrinter).void }
|
15
|
+
def accept_printer(printer); end
|
16
|
+
end
|
17
|
+
|
6
18
|
class Hover < T::Struct
|
19
|
+
extend T::Sig
|
20
|
+
include PrintableSymbol
|
21
|
+
|
7
22
|
const :contents, String
|
8
23
|
const :range, T.nilable(Range)
|
9
24
|
|
@@ -14,9 +29,10 @@ module Spoom
|
|
14
29
|
)
|
15
30
|
end
|
16
31
|
|
32
|
+
sig { override.params(printer: SymbolPrinter).void }
|
17
33
|
def accept_printer(printer)
|
18
34
|
printer.print("#{contents}\n")
|
19
|
-
printer.
|
35
|
+
printer.print_object(range) if range
|
20
36
|
end
|
21
37
|
|
22
38
|
def to_s
|
@@ -25,6 +41,9 @@ module Spoom
|
|
25
41
|
end
|
26
42
|
|
27
43
|
class Position < T::Struct
|
44
|
+
extend T::Sig
|
45
|
+
include PrintableSymbol
|
46
|
+
|
28
47
|
const :line, Integer
|
29
48
|
const :char, Integer
|
30
49
|
|
@@ -35,8 +54,9 @@ module Spoom
|
|
35
54
|
)
|
36
55
|
end
|
37
56
|
|
57
|
+
sig { override.params(printer: SymbolPrinter).void }
|
38
58
|
def accept_printer(printer)
|
39
|
-
printer.
|
59
|
+
printer.print_colored("#{line}:#{char}", :light_black)
|
40
60
|
end
|
41
61
|
|
42
62
|
def to_s
|
@@ -45,6 +65,9 @@ module Spoom
|
|
45
65
|
end
|
46
66
|
|
47
67
|
class Range < T::Struct
|
68
|
+
extend T::Sig
|
69
|
+
include PrintableSymbol
|
70
|
+
|
48
71
|
const :start, Position
|
49
72
|
const :end, Position
|
50
73
|
|
@@ -55,10 +78,11 @@ module Spoom
|
|
55
78
|
)
|
56
79
|
end
|
57
80
|
|
81
|
+
sig { override.params(printer: SymbolPrinter).void }
|
58
82
|
def accept_printer(printer)
|
59
|
-
printer.
|
60
|
-
printer.
|
61
|
-
printer.
|
83
|
+
printer.print_object(start)
|
84
|
+
printer.print_colored("-", :light_black)
|
85
|
+
printer.print_object(self.end)
|
62
86
|
end
|
63
87
|
|
64
88
|
def to_s
|
@@ -67,6 +91,9 @@ module Spoom
|
|
67
91
|
end
|
68
92
|
|
69
93
|
class Location < T::Struct
|
94
|
+
extend T::Sig
|
95
|
+
include PrintableSymbol
|
96
|
+
|
70
97
|
const :uri, String
|
71
98
|
const :range, LSP::Range
|
72
99
|
|
@@ -77,17 +104,21 @@ module Spoom
|
|
77
104
|
)
|
78
105
|
end
|
79
106
|
|
107
|
+
sig { override.params(printer: SymbolPrinter).void }
|
80
108
|
def accept_printer(printer)
|
81
|
-
printer.
|
82
|
-
printer.
|
109
|
+
printer.print_colored("#{printer.clean_uri(uri)}:", :light_black)
|
110
|
+
printer.print_object(range)
|
83
111
|
end
|
84
112
|
|
85
113
|
def to_s
|
86
|
-
"#{uri}:#{range}
|
114
|
+
"#{uri}:#{range}"
|
87
115
|
end
|
88
116
|
end
|
89
117
|
|
90
118
|
class SignatureHelp < T::Struct
|
119
|
+
extend T::Sig
|
120
|
+
include PrintableSymbol
|
121
|
+
|
91
122
|
const :label, T.nilable(String)
|
92
123
|
const :doc, Object # TODO
|
93
124
|
const :params, T::Array[T.untyped] # TODO
|
@@ -100,6 +131,7 @@ module Spoom
|
|
100
131
|
)
|
101
132
|
end
|
102
133
|
|
134
|
+
sig { override.params(printer: SymbolPrinter).void }
|
103
135
|
def accept_printer(printer)
|
104
136
|
printer.print(label)
|
105
137
|
printer.print("(")
|
@@ -113,6 +145,9 @@ module Spoom
|
|
113
145
|
end
|
114
146
|
|
115
147
|
class Diagnostic < T::Struct
|
148
|
+
extend T::Sig
|
149
|
+
include PrintableSymbol
|
150
|
+
|
116
151
|
const :range, LSP::Range
|
117
152
|
const :code, Integer
|
118
153
|
const :message, String
|
@@ -127,12 +162,20 @@ module Spoom
|
|
127
162
|
)
|
128
163
|
end
|
129
164
|
|
165
|
+
sig { override.params(printer: SymbolPrinter).void }
|
166
|
+
def accept_printer(printer)
|
167
|
+
printer.print(to_s)
|
168
|
+
end
|
169
|
+
|
130
170
|
def to_s
|
131
171
|
"Error: #{message} (#{code})."
|
132
172
|
end
|
133
173
|
end
|
134
174
|
|
135
175
|
class DocumentSymbol < T::Struct
|
176
|
+
extend T::Sig
|
177
|
+
include PrintableSymbol
|
178
|
+
|
136
179
|
const :name, String
|
137
180
|
const :detail, T.nilable(String)
|
138
181
|
const :kind, Integer
|
@@ -151,6 +194,7 @@ module Spoom
|
|
151
194
|
)
|
152
195
|
end
|
153
196
|
|
197
|
+
sig { override.params(printer: SymbolPrinter).void }
|
154
198
|
def accept_printer(printer)
|
155
199
|
h = serialize.hash
|
156
200
|
return if printer.seen.include?(h)
|
@@ -159,18 +203,18 @@ module Spoom
|
|
159
203
|
printer.printt
|
160
204
|
printer.print(kind_string)
|
161
205
|
printer.print(' ')
|
162
|
-
printer.
|
163
|
-
printer.
|
206
|
+
printer.print_colored(name, :blue, :bold)
|
207
|
+
printer.print_colored(' (', :light_black)
|
164
208
|
if range
|
165
|
-
printer.
|
209
|
+
printer.print_object(range)
|
166
210
|
elsif location
|
167
|
-
printer.
|
211
|
+
printer.print_object(location)
|
168
212
|
end
|
169
|
-
printer.
|
213
|
+
printer.print_colored(')', :light_black)
|
170
214
|
printer.printn
|
171
215
|
unless children.empty?
|
172
216
|
printer.indent
|
173
|
-
printer.
|
217
|
+
printer.print_objects(children)
|
174
218
|
printer.dedent
|
175
219
|
end
|
176
220
|
# TODO: also display details?
|
@@ -214,5 +258,55 @@ module Spoom
|
|
214
258
|
26 => "type_parameter",
|
215
259
|
}
|
216
260
|
end
|
261
|
+
|
262
|
+
class SymbolPrinter < Printer
|
263
|
+
extend T::Sig
|
264
|
+
|
265
|
+
attr_accessor :seen, :prefix
|
266
|
+
|
267
|
+
sig do
|
268
|
+
params(
|
269
|
+
out: T.any(IO, StringIO),
|
270
|
+
colors: T::Boolean,
|
271
|
+
indent_level: Integer,
|
272
|
+
prefix: T.nilable(String)
|
273
|
+
).void
|
274
|
+
end
|
275
|
+
def initialize(out: $stdout, colors: true, indent_level: 0, prefix: nil)
|
276
|
+
super(out: out, colors: colors, indent_level: indent_level)
|
277
|
+
@seen = Set.new
|
278
|
+
@out = out
|
279
|
+
@colors = colors
|
280
|
+
@indent_level = indent_level
|
281
|
+
@prefix = prefix
|
282
|
+
end
|
283
|
+
|
284
|
+
sig { params(object: T.nilable(PrintableSymbol)).void }
|
285
|
+
def print_object(object)
|
286
|
+
return unless object
|
287
|
+
object.accept_printer(self)
|
288
|
+
end
|
289
|
+
|
290
|
+
sig { params(objects: T::Array[PrintableSymbol]).void }
|
291
|
+
def print_objects(objects)
|
292
|
+
objects.each { |object| print_object(object) }
|
293
|
+
end
|
294
|
+
|
295
|
+
sig { params(uri: String).returns(String) }
|
296
|
+
def clean_uri(uri)
|
297
|
+
return uri unless prefix
|
298
|
+
uri.delete_prefix(prefix)
|
299
|
+
end
|
300
|
+
|
301
|
+
sig { params(objects: T::Array[PrintableSymbol]).void }
|
302
|
+
def print_list(objects)
|
303
|
+
objects.each do |object|
|
304
|
+
printt
|
305
|
+
print "* "
|
306
|
+
print_object(object)
|
307
|
+
printn
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
217
311
|
end
|
218
312
|
end
|