ruby_tree_sitter 1.10.0-aarch64-linux-musl → 1.11.1-aarch64-linux-musl
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 +14 -0
- data/exe/print_matches +20 -0
- data/exe/rbts +83 -0
- data/lib/tree_sitter/3.0/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.1/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.2/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.3/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.4/tree_sitter.so +0 -0
- data/lib/tree_sitter/node.rb +90 -1
- data/lib/tree_sitter/version.rb +2 -2
- data/lib/tree_sitter.rb +2 -0
- data/lib/tree_stand/cli/options.rb +70 -0
- data/lib/tree_stand/cli.rb +16 -0
- data/lib/tree_stand/node.rb +7 -7
- data/lib/tree_stand.rb +2 -0
- data/tree_sitter.gemspec +4 -1
- metadata +26 -6
- data/lib/tree_stand/utils/printer.rb +0 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 954d29b7224f6149fe47913d1b0f7e5149aada3137cc1915756eab9a572e1962
|
4
|
+
data.tar.gz: 6b67777d6e9f6a698737235932d0e874f1bb3b36580e70b38c4adb6ad61127f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea24d4f850fda1d64d0fcb6352d3d0c795754e4d773460b320ec549937c05bf15738baae5c003bf34bf10be202748cca4d565879f3812e0f9ae51d08cccc6527
|
7
|
+
data.tar.gz: 96b7648e1c6f22edbff35a2850a49c9090e5e1a6d624d77dc340612ab94a192e7f4065ca05a8358c050ab14285f0247099a820acca063150661585788f449b7a
|
data/README.md
CHANGED
@@ -175,6 +175,20 @@ You will have to install parsers yourself, either by:
|
|
175
175
|
[Faveod/tree-sitter-parsers](https://github.com/Faveod/tree-sitter-parsers)
|
176
176
|
which supports numerous architectures.
|
177
177
|
|
178
|
+
### Utilities
|
179
|
+
|
180
|
+
`ruby_tree_sitter` ships with some useful utility programs to help work with parsers & queries.
|
181
|
+
|
182
|
+
#### `rbts`
|
183
|
+
|
184
|
+
```sh
|
185
|
+
$ rbts --source SOURCE --query QUERY --parser PARSER
|
186
|
+
```
|
187
|
+
|
188
|
+
Watches a source and a query file and prints the matches when one of the files are updated. Uses [entr](https://github.com/eradman/entr), if available, otherwise [watch(1)](https://man7.org/linux/man-pages/man1/watch.1.html) is used by default or if --watch is specified.
|
189
|
+
|
190
|
+
See `rbts --help` for more information.
|
191
|
+
|
178
192
|
## Examples
|
179
193
|
|
180
194
|
See `examples` directory.
|
data/exe/print_matches
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'tree_stand/cli'
|
6
|
+
|
7
|
+
program = TreeStand::Cli::Options.new
|
8
|
+
OptionParser.new do |parser|
|
9
|
+
program.define_options(parser)
|
10
|
+
parser.parse!(ARGV)
|
11
|
+
end
|
12
|
+
program.check!
|
13
|
+
|
14
|
+
def main(program)
|
15
|
+
program.tree.query(program.query).each do |match|
|
16
|
+
pp match.transform_values(&:text)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
main(program)
|
data/exe/rbts
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'tree_stand/cli'
|
6
|
+
|
7
|
+
BANNER = <<~BANNER
|
8
|
+
Usage: rbts --source SOURCE --query QUERY --parser PARSER
|
9
|
+
|
10
|
+
Watches a source and a query file and prints the matches when one of the
|
11
|
+
files are updated. Uses entr, if available, otherwise watch(1) is used by
|
12
|
+
default or if --watch is specified.
|
13
|
+
|
14
|
+
Check out the tree-sitter repository & documentation for information on how
|
15
|
+
to write S-expression queries.
|
16
|
+
|
17
|
+
Repo: https://github.com/tree-sitter/tree-sitter
|
18
|
+
Docs: https://tree-sitter.github.io/tree-sitter/using-parsers/queries
|
19
|
+
|
20
|
+
Example:
|
21
|
+
|
22
|
+
rbts --source tmp/rbts/code.rb \\
|
23
|
+
--query tmp/rbts/query.scm \\
|
24
|
+
--parser tmp/rbts/ruby.so
|
25
|
+
BANNER
|
26
|
+
|
27
|
+
program = TreeStand::Cli::Options.new
|
28
|
+
OptionParser.new do |parser|
|
29
|
+
parser.banner = BANNER
|
30
|
+
parser.separator('')
|
31
|
+
program.define_options(parser)
|
32
|
+
parser.separator('')
|
33
|
+
parser.on_tail(
|
34
|
+
'-w',
|
35
|
+
'--watch',
|
36
|
+
"use watch(1) to continuously print matches, by default entr is used if it's available",
|
37
|
+
TrueClass,
|
38
|
+
) do |watch|
|
39
|
+
program.watch = watch
|
40
|
+
end
|
41
|
+
|
42
|
+
parser.parse!(ARGV)
|
43
|
+
end
|
44
|
+
program.check!
|
45
|
+
|
46
|
+
def print_matches = File.join(__dir__, 'print_matches')
|
47
|
+
|
48
|
+
# ls -1 SOURCE QUERY |
|
49
|
+
# entr -c exe/print_matches
|
50
|
+
# --source SOURCE
|
51
|
+
# --query QUERY
|
52
|
+
# --parser PARSER
|
53
|
+
def entr_cmd(source, query, parser)
|
54
|
+
[
|
55
|
+
'ls', '-1', source, query, '|',
|
56
|
+
'entr', '-c',
|
57
|
+
print_matches,
|
58
|
+
'--source', source,
|
59
|
+
'--query', query,
|
60
|
+
'--parser', parser
|
61
|
+
].join(' ')
|
62
|
+
end
|
63
|
+
|
64
|
+
# watch 'exe/print_matches --source SOURCE --query QUERY --parser PARSER'
|
65
|
+
def watch_cmd(source, query, parser)
|
66
|
+
[
|
67
|
+
'watch',
|
68
|
+
"'#{print_matches} --source #{source} --query #{query} --parser #{parser}'",
|
69
|
+
].join(' ')
|
70
|
+
end
|
71
|
+
|
72
|
+
def main(program)
|
73
|
+
cmd = if !program.watch && system('which', 'entr')
|
74
|
+
entr_cmd(program.source_file, program.query_file, program.parser_file)
|
75
|
+
else
|
76
|
+
watch_cmd(program.source_file, program.query_file, program.parser_file)
|
77
|
+
end
|
78
|
+
|
79
|
+
program.logger.debug("Running `#{cmd}`")
|
80
|
+
exec(cmd)
|
81
|
+
end
|
82
|
+
|
83
|
+
main(program)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/tree_sitter/node.rb
CHANGED
@@ -56,7 +56,7 @@ module TreeSitter
|
|
56
56
|
case k = keys.first
|
57
57
|
when Integer then named_child(k)
|
58
58
|
when String, Symbol
|
59
|
-
raise IndexError, "Cannot find field #{k}. Available: #{fields}" unless fields.include?(k.to_sym)
|
59
|
+
raise IndexError, "Cannot find field #{k.to_sym}. Available: #{fields.to_a}" unless fields.include?(k.to_sym)
|
60
60
|
|
61
61
|
child_by_field_name(k.to_s)
|
62
62
|
else raise ArgumentError, <<~ERR
|
@@ -163,5 +163,94 @@ module TreeSitter
|
|
163
163
|
end
|
164
164
|
fields.values_at(*keys)
|
165
165
|
end
|
166
|
+
|
167
|
+
# Regex for line annotation extraction from sexpr with source.
|
168
|
+
#
|
169
|
+
# @!visibility private
|
170
|
+
LINE_ANNOTATION = /\0\{(.*?)\0\}/
|
171
|
+
|
172
|
+
# Pretty-prints the node's sexp.
|
173
|
+
#
|
174
|
+
# The default call to {to_s} or {to_string} calls tree-sitter's
|
175
|
+
# `ts_node_string`. It's displayed on a single line, so reading a rich node
|
176
|
+
# becomes tiresome.
|
177
|
+
#
|
178
|
+
# This provides a better sexpr where you can control the "screen" width to
|
179
|
+
# decide when to break.
|
180
|
+
#
|
181
|
+
# @param indent [Integer]
|
182
|
+
# indentation for nested nodes.
|
183
|
+
# @param width [Integer]
|
184
|
+
# the screen's width.
|
185
|
+
# @param source [Nil|String]
|
186
|
+
# display source on the margin if not `nil`.
|
187
|
+
# @param vertical [Nil|Boolean]
|
188
|
+
# fit as much sexpr on a single line if `false`, else, go vertical.
|
189
|
+
# This is always `true` if `source` is not `nil`.
|
190
|
+
#
|
191
|
+
# @return [String] the pretty-printed sexpr.
|
192
|
+
def sexpr(indent: 2, width: 120, source: nil, vertical: nil)
|
193
|
+
res =
|
194
|
+
sexpr_recur(
|
195
|
+
indent: indent,
|
196
|
+
width: width,
|
197
|
+
source: source,
|
198
|
+
vertical: !source.nil? || !!vertical,
|
199
|
+
).output
|
200
|
+
return res if source.nil?
|
201
|
+
|
202
|
+
max_width = 0
|
203
|
+
res
|
204
|
+
.lines
|
205
|
+
.map { |line|
|
206
|
+
extracted = line.scan(LINE_ANNOTATION).flatten.first || ''
|
207
|
+
base = line.gsub(LINE_ANNOTATION, '').rstrip
|
208
|
+
max_width = [max_width, base.length].max
|
209
|
+
[base, extracted]
|
210
|
+
}
|
211
|
+
.map { |base, extracted|
|
212
|
+
("%-#{max_width}s | %s" % [base, extracted]).rstrip
|
213
|
+
}
|
214
|
+
.join("\n")
|
215
|
+
end
|
216
|
+
|
217
|
+
# Helper function for {sexpr}.
|
218
|
+
#
|
219
|
+
# @!visibility private
|
220
|
+
def sexpr_recur(indent: 2, width: 120, out: nil, source: nil, vertical: false)
|
221
|
+
out ||= Oppen::Wadler.new(width: width)
|
222
|
+
out.group(indent) {
|
223
|
+
out.text "(#{type}"
|
224
|
+
if source.is_a?(String) && child_count.zero?
|
225
|
+
out.text "\0{#{source.byteslice(start_byte...end_byte)}\0}", width: 0
|
226
|
+
end
|
227
|
+
brk(out, vertical) if child_count.positive?
|
228
|
+
each.with_index do |child, index|
|
229
|
+
if field_name = field_name_for_child(index)
|
230
|
+
out.text "#{field_name}:"
|
231
|
+
out.group(indent) {
|
232
|
+
brk(out, vertical)
|
233
|
+
child.sexpr_recur(indent: indent, width: width, out: out, vertical: vertical, source: source)
|
234
|
+
}
|
235
|
+
else
|
236
|
+
child.sexpr_recur(indent: indent, width: width, out: out, vertical: vertical, source: source)
|
237
|
+
end
|
238
|
+
brk(out, vertical) if index < child_count - 1
|
239
|
+
end
|
240
|
+
out.text ')'
|
241
|
+
}
|
242
|
+
out
|
243
|
+
end
|
244
|
+
|
245
|
+
# Break helper
|
246
|
+
#
|
247
|
+
# !@visibility private
|
248
|
+
def brk(out, vertical)
|
249
|
+
if vertical
|
250
|
+
out.break
|
251
|
+
else
|
252
|
+
out.breakable
|
253
|
+
end
|
254
|
+
end
|
166
255
|
end
|
167
256
|
end
|
data/lib/tree_sitter/version.rb
CHANGED
data/lib/tree_sitter.rb
CHANGED
@@ -23,6 +23,8 @@ require 'tree_sitter/query_matches'
|
|
23
23
|
require 'tree_sitter/query_predicate'
|
24
24
|
require 'tree_sitter/text_predicate_capture'
|
25
25
|
|
26
|
+
require 'oppen'
|
27
|
+
|
26
28
|
# TreeSitter is a Ruby interface to the tree-sitter parsing library.
|
27
29
|
module TreeSitter
|
28
30
|
extend Mixins::Language
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module TreeStand
|
5
|
+
module Cli
|
6
|
+
# @!visibility private
|
7
|
+
class Options
|
8
|
+
attr_accessor :source_file, :query_file, :parser_file, :watch
|
9
|
+
|
10
|
+
attr_reader :logger, :progname
|
11
|
+
|
12
|
+
def initialize(progname = File.basename($PROGRAM_NAME))
|
13
|
+
@logger = Logger.new($stderr, level: T.unsafe(ENV.fetch('LOG_LEVEL', Logger::INFO)), progname: progname)
|
14
|
+
@progname = progname
|
15
|
+
end
|
16
|
+
|
17
|
+
# @!visibility private
|
18
|
+
def define_options(parser)
|
19
|
+
parser.on_tail('-v', '--verbose', 'Enable verbose logging') { logger.level -= 1 }
|
20
|
+
|
21
|
+
parser.separator('Required options:')
|
22
|
+
parser.on('-s', '--source SOURCE', 'The filepath to the source code to be parsed') do |filepath|
|
23
|
+
self.source_file = error_no_file(File.expand_path(filepath), "Source file not found: #{filepath}", 1)
|
24
|
+
end
|
25
|
+
parser.on('-q', '--query QUERY', 'The filepath to the query to be run against the source code') do |filepath|
|
26
|
+
self.query_file = error_no_file(File.expand_path(filepath), "Query file not found: #{filepath}", 2)
|
27
|
+
end
|
28
|
+
parser.on('-p', '--parser PARSER', 'The parser to use to parse the source code') do |filepath|
|
29
|
+
self.parser_file = error_no_file(File.expand_path(filepath), "Parser file not found: #{filepath}", 3)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @!visibility private
|
34
|
+
def check!
|
35
|
+
error!('No source file provided, specify with --source', 4) unless source_file
|
36
|
+
error!('No query file provided, specify with --query', 5) unless query_file
|
37
|
+
error!('No parser file provided, specify with --parser', 6) unless parser_file
|
38
|
+
|
39
|
+
parser_path = File.dirname(parser_file)
|
40
|
+
config = TreeStand.config
|
41
|
+
|
42
|
+
TreeStand.configure do
|
43
|
+
config.parser_path = parser_path
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @!visibility private
|
48
|
+
def source = @source ||= File.read(source_file)
|
49
|
+
# @!visibility private
|
50
|
+
def query = @query ||= File.read(query_file)
|
51
|
+
# @!visibility private
|
52
|
+
def parser = @parser ||= TreeStand::Parser.new(File.extname(source_file).delete_prefix('.'))
|
53
|
+
# @!visibility private
|
54
|
+
def tree = @tree ||= parser.parse_string(source)
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def error_no_file(filepath, message, code)
|
59
|
+
return filepath if File.exist?(filepath)
|
60
|
+
|
61
|
+
error!(message, code)
|
62
|
+
end
|
63
|
+
|
64
|
+
def error!(message, code = 1)
|
65
|
+
logger.error(message)
|
66
|
+
exit(code)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
require 'optparse'
|
6
|
+
require 'tree_stand'
|
7
|
+
|
8
|
+
require 'tree_stand/cli/options'
|
9
|
+
|
10
|
+
$stdout.sync = $stderr.sync = true
|
11
|
+
|
12
|
+
module TreeStand
|
13
|
+
# @!visibility private
|
14
|
+
module Cli
|
15
|
+
end
|
16
|
+
end
|
data/lib/tree_stand/node.rb
CHANGED
@@ -15,6 +15,8 @@ module TreeStand
|
|
15
15
|
# @return [Boolean] true if a syntax node has been edited.
|
16
16
|
# @!method child_count
|
17
17
|
# @return [Integer] the number of child nodes.
|
18
|
+
# @!method error?
|
19
|
+
# @return [bool] true if the node is an error node.
|
18
20
|
# @!method extra?
|
19
21
|
# @return [Boolean] true if the node is *extra* (e.g. comments).
|
20
22
|
# @!method has_error?
|
@@ -25,10 +27,10 @@ module TreeStand
|
|
25
27
|
# @return [Boolean] true if the node is not a literal in the grammar.
|
26
28
|
# @!method named_child_count
|
27
29
|
# @return [Integer] the number of *named* children.
|
30
|
+
# @!method sexpr
|
31
|
+
# @return [String] a pretty-printed sexpr.
|
28
32
|
# @!method type
|
29
33
|
# @return [Symbol] the type of the node in the tree-sitter grammar.
|
30
|
-
# @!method error?
|
31
|
-
# @return [bool] true if the node is an error node.
|
32
34
|
def_delegators(
|
33
35
|
:@ts_node,
|
34
36
|
:changed?,
|
@@ -39,6 +41,7 @@ module TreeStand
|
|
39
41
|
:missing?,
|
40
42
|
:named?,
|
41
43
|
:named_child_count,
|
44
|
+
:sexpr,
|
42
45
|
:type,
|
43
46
|
)
|
44
47
|
|
@@ -310,13 +313,10 @@ module TreeStand
|
|
310
313
|
T.must(range == other.range && type == other.type && text == other.text)
|
311
314
|
end
|
312
315
|
|
313
|
-
#
|
314
|
-
# Backed by {TreeStand::Utils::Printer}.
|
315
|
-
#
|
316
|
-
# @see TreeStand::Utils::Printer
|
316
|
+
# @see TreeSitter:Node::sexpr
|
317
317
|
sig { params(pp: PP).void }
|
318
318
|
def pretty_print(pp)
|
319
|
-
|
319
|
+
pp.output << sexpr(source: text)
|
320
320
|
end
|
321
321
|
|
322
322
|
private
|
data/lib/tree_stand.rb
CHANGED
@@ -10,6 +10,8 @@ require 'zeitwerk'
|
|
10
10
|
loader = Zeitwerk::Loader.for_gem
|
11
11
|
loader.ignore("#{__dir__}/tree_sitter")
|
12
12
|
loader.ignore("#{__dir__}/tree_sitter.rb")
|
13
|
+
loader.ignore("#{__dir__}/tree_stand/cli")
|
14
|
+
loader.ignore("#{__dir__}/tree_stand/cli.rb")
|
13
15
|
loader.setup
|
14
16
|
|
15
17
|
# TreeStand is a high-level Ruby wrapper for {https://tree-sitter.github.io/tree-sitter tree-sitter} bindings. It makes
|
data/tree_sitter.gemspec
CHANGED
@@ -6,7 +6,7 @@ $LOAD_PATH.unshift(lib) if !$LOAD_PATH.include?(lib)
|
|
6
6
|
require 'tree_sitter/version'
|
7
7
|
|
8
8
|
Gem::Specification.new do |spec|
|
9
|
-
spec.required_ruby_version = '>= 3.0'
|
9
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
|
10
10
|
|
11
11
|
spec.authors = ['Firas al-Khalil', 'Derek Stride']
|
12
12
|
spec.email = ['firasalkhalil@gmail.com', 'derek@stride.host']
|
@@ -27,8 +27,11 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.files = %w[LICENSE README.md tree_sitter.gemspec]
|
28
28
|
spec.files += Dir.glob('ext/**/*.{c,h,rb}')
|
29
29
|
spec.files += Dir.glob('lib/**/*.rb')
|
30
|
+
spec.bindir = 'exe'
|
31
|
+
spec.executables << 'rbts' << 'print_matches'
|
30
32
|
spec.require_paths = ['lib']
|
31
33
|
|
34
|
+
spec.add_dependency 'oppen', '0.9.8'
|
32
35
|
spec.add_dependency 'sorbet-runtime'
|
33
36
|
spec.add_dependency 'zeitwerk'
|
34
37
|
end
|
metadata
CHANGED
@@ -1,16 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_tree_sitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.11.1
|
5
5
|
platform: aarch64-linux-musl
|
6
6
|
authors:
|
7
7
|
- Firas al-Khalil
|
8
8
|
- Derek Stride
|
9
9
|
autorequire:
|
10
|
-
bindir:
|
10
|
+
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2025-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: oppen
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.9.8
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.9.8
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: sorbet-runtime
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,12 +57,16 @@ description:
|
|
43
57
|
email:
|
44
58
|
- firasalkhalil@gmail.com
|
45
59
|
- derek@stride.host
|
46
|
-
executables:
|
60
|
+
executables:
|
61
|
+
- rbts
|
62
|
+
- print_matches
|
47
63
|
extensions: []
|
48
64
|
extra_rdoc_files: []
|
49
65
|
files:
|
50
66
|
- LICENSE
|
51
67
|
- README.md
|
68
|
+
- exe/print_matches
|
69
|
+
- exe/rbts
|
52
70
|
- ext/tree_sitter/encoding.c
|
53
71
|
- ext/tree_sitter/extconf.rb
|
54
72
|
- ext/tree_sitter/input.c
|
@@ -78,6 +96,7 @@ files:
|
|
78
96
|
- lib/tree_sitter/3.1/tree_sitter.so
|
79
97
|
- lib/tree_sitter/3.2/tree_sitter.so
|
80
98
|
- lib/tree_sitter/3.3/tree_sitter.so
|
99
|
+
- lib/tree_sitter/3.4/tree_sitter.so
|
81
100
|
- lib/tree_sitter/error.rb
|
82
101
|
- lib/tree_sitter/helpers.rb
|
83
102
|
- lib/tree_sitter/mixins/language.rb
|
@@ -93,12 +112,13 @@ files:
|
|
93
112
|
- lib/tree_stand.rb
|
94
113
|
- lib/tree_stand/ast_modifier.rb
|
95
114
|
- lib/tree_stand/breadth_first_visitor.rb
|
115
|
+
- lib/tree_stand/cli.rb
|
116
|
+
- lib/tree_stand/cli/options.rb
|
96
117
|
- lib/tree_stand/config.rb
|
97
118
|
- lib/tree_stand/node.rb
|
98
119
|
- lib/tree_stand/parser.rb
|
99
120
|
- lib/tree_stand/range.rb
|
100
121
|
- lib/tree_stand/tree.rb
|
101
|
-
- lib/tree_stand/utils/printer.rb
|
102
122
|
- lib/tree_stand/version.rb
|
103
123
|
- lib/tree_stand/visitor.rb
|
104
124
|
- lib/tree_stand/visitors/tree_walker.rb
|
@@ -122,7 +142,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
142
|
version: '3.0'
|
123
143
|
- - "<"
|
124
144
|
- !ruby/object:Gem::Version
|
125
|
-
version: 3.
|
145
|
+
version: 3.5.dev
|
126
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
147
|
requirements:
|
128
148
|
- - ">="
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# typed: true
|
3
|
-
|
4
|
-
module TreeStand
|
5
|
-
# A collection of useful methods for working with syntax trees.
|
6
|
-
module Utils
|
7
|
-
# Used to {TreeStand::Node#pretty_print pretty-print} the node.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# pp node
|
11
|
-
# # (expression
|
12
|
-
# # (sum
|
13
|
-
# # left: (number) | 1
|
14
|
-
# # ("+") | +
|
15
|
-
# # right: (variable))) | x
|
16
|
-
class Printer
|
17
|
-
extend T::Sig
|
18
|
-
|
19
|
-
# @param ralign the right alignment for the text column.
|
20
|
-
sig { params(ralign: Integer).void }
|
21
|
-
def initialize(ralign:)
|
22
|
-
@ralign = ralign
|
23
|
-
end
|
24
|
-
|
25
|
-
# (see TreeStand::Utils::Printer)
|
26
|
-
sig { params(node: TreeStand::Node, io: T.any(IO, StringIO, String)).returns(T.any(IO, StringIO, String)) }
|
27
|
-
def print(node, io: StringIO.new)
|
28
|
-
lines = pretty_output_lines(node)
|
29
|
-
|
30
|
-
lines.each do |line|
|
31
|
-
if line.text.empty?
|
32
|
-
io << line.sexpr << "\n"
|
33
|
-
next
|
34
|
-
end
|
35
|
-
|
36
|
-
io << "#{line.sexpr}#{' ' * [(@ralign - line.sexpr.size), 0].max}| #{line.text}\n"
|
37
|
-
end
|
38
|
-
|
39
|
-
io
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
Line = Struct.new(:sexpr, :text)
|
45
|
-
private_constant :Line
|
46
|
-
|
47
|
-
def pretty_output_lines(node, prefix: '', depth: 0)
|
48
|
-
indent = ' ' * depth
|
49
|
-
ts_node = node.ts_node
|
50
|
-
if indent.size + prefix.size + ts_node.to_s.size < @ralign || ts_node.child_count.zero?
|
51
|
-
return [Line.new("#{indent}#{prefix}#{ts_node}", node.text)]
|
52
|
-
end
|
53
|
-
|
54
|
-
lines = T.let([Line.new("#{indent}#{prefix}(#{ts_node.type}", '')], T::Array[Line])
|
55
|
-
|
56
|
-
node.each.with_index do |child, index|
|
57
|
-
lines += if field_name = ts_node.field_name_for_child(index)
|
58
|
-
pretty_output_lines(
|
59
|
-
child,
|
60
|
-
prefix: "#{field_name}: ",
|
61
|
-
depth: depth + 1,
|
62
|
-
)
|
63
|
-
else
|
64
|
-
pretty_output_lines(child, depth: depth + 1)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
T.must(lines.last).sexpr << ')'
|
69
|
-
lines
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|