ruby_tree_sitter 1.3.0-x86_64-linux → 1.4.1-x86_64-linux

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0f7c51b289e769ad5701be586b28d61f41f0979ee6fd3c08f87481ae307f146
4
- data.tar.gz: 988052e5b5b5c41e9a9d974398c6c6cae401f2068a2ad4013d80198f3437c029
3
+ metadata.gz: 70e2391699fd48cf5f18b50df59b7c5929c09e07f18a366a94c24ce381754fe0
4
+ data.tar.gz: b66813822fe232322d4e4e841975a68d42d6454dcaf47b3b814875bed4f009a9
5
5
  SHA512:
6
- metadata.gz: 9ef62c5ea3bd4451b03b43e6efc2c3501191ffcd9ea96dfe12d2e66b249d1f16f58e82d6127d833a6c8105e3f910dda2ba898a138d5e6d2756615bf69fcb2e05
7
- data.tar.gz: 5bd46cc66e845c9091005a5eadeccb3db2984e0bbc5bf6d12e9fc4e3fd126f9ab6f1d37970fbe6760eee096ec2c011d4d328d5610a9e873ed313df3842caceb3
6
+ metadata.gz: 37dcb03d0061b0a019167924f2ded1c0291463e3a08d7e6ff58c9e8e121fcafa484d8effe77907fde05b47a1c77f1d5f71bb234c2ce44bce29e5a3d9c6c4dac9
7
+ data.tar.gz: b099f9953c709cc9edf745309e9b8a155b668947bc59c2abfe13e4bee7d0ba7ac9211facf654b0123eb5750cd04aeefc261a6904cae596a9f466def182c9618e
data/README.md CHANGED
@@ -200,4 +200,8 @@ To See a full list of the ruby-specific APIs, see [here](lib/README.md).
200
200
 
201
201
  ## Sponsors
202
202
 
203
- <img src="img/faveod.jpg" width="75%">
203
+ - <a href="https://faveod.com">https://faveod.com</a>
204
+
205
+ <a href="https://faveod.com">
206
+ <img src="img/faveod.jpg" width="66%" />
207
+ </a>
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A colon-separated list of paths pointing to directories that can contain parsers.
5
+ # Order matters.
6
+ # Takes precedence over default lookup paths.
7
+ ENV_PARSERS =
8
+ ENV['TREE_SITTER_PARSERS']
9
+ &.split(':')
10
+ &.map { |v| Pathname(v) }
11
+ .freeze
12
+
13
+ # The default paths we use to lookup parsers.
14
+ # Order matters.
15
+ LIBDIRS = [
16
+ '.vendor/parsers',
17
+ '.vendor/tree-sitter-parsers',
18
+ 'vendor/parsers',
19
+ 'vendor/tree-sitter-parsers',
20
+ 'parsers',
21
+ 'tree-sitter-parsers',
22
+ '/opt/local/lib',
23
+ '/opt/lib',
24
+ '/usr/local/lib',
25
+ '/usr/lib',
26
+ ].map { |p| Pathname(p) }.freeze
27
+
28
+ # Mixins.
29
+ module Mixins
30
+ # Language Mixin.
31
+ module Language
32
+ # Load a language from configuration or default lookup paths.
33
+ #
34
+ # @example Load java from default paths
35
+ # # This will look for:
36
+ # #
37
+ # # .vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
38
+ # # .vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
39
+ # # vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
40
+ # # vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
41
+ # # parsers/(java/)?(libtree-sitter-)?java.{ext}
42
+ # # tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
43
+ # # /opt/local/lib/(java/)?(libtree-sitter-)?java.{ext}
44
+ # # /opt/lib/(java/)?(libtree-sitter-)?java.{ext}
45
+ # # /usr/local/lib/(java/)?(libtree-sitter-)?java.{ext}
46
+ # # /usr/lib/(java/)?(libtree-sitter-)?java.{ext}
47
+ # #
48
+ # java = TreeSitter.language('java')
49
+ #
50
+ # @example (TreeStand) Load java from a configured path
51
+ # # This will look for:
52
+ # #
53
+ # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
54
+ # #
55
+ # TreeStand.config.parser_path = '/my/path'
56
+ # java = TreeStand::Parser.language('java')
57
+ #
58
+ # @example (TreeStand) Load java from environment variables
59
+ # # This will look for:
60
+ # #
61
+ # # /my/forced/env/path/(java/)?(libtree-sitter-)?java.{ext}
62
+ # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
63
+ # #
64
+ # # … and the same works for the default paths if `TreeStand.config.parser_path`
65
+ # # was `nil`
66
+ # ENV['TREE_SITTER_PARSERS'] = '/my/forced/env/path'
67
+ # TreeStand.config.parser_path = '/my/path'
68
+ # java = TreeStand::Parser.language('java')
69
+ #
70
+ # @param name [String] the name of the parser.
71
+ # This name is used to load the symbol from the compiled parser, replacing `-` with `_`.
72
+ #
73
+ # @return [TreeSitter:language] a language object to use in your parsers.
74
+ #
75
+ # @raise [RuntimeError] if the parser was not found.
76
+ #
77
+ # @see search_for_lib
78
+ def language(name)
79
+ lib = search_for_lib(name)
80
+
81
+ if lib.nil?
82
+ raise <<~MSG.chomp
83
+ Failed to load a parser for #{name}.
84
+
85
+ #{search_lib_message}
86
+ MSG
87
+ end
88
+
89
+ # We know that the bindings will accept `lib`, but I don't know how to tell sorbet
90
+ # the types in ext/tree_sitter where `load` is defined.
91
+ TreeSitter::Language.load(name.tr('-', '_'), T.unsafe(lib))
92
+ end
93
+
94
+ # The platform-specific extension of the parser.
95
+ # @return [String] `dylib` or `so` for mac or linux.
96
+ def ext
97
+ case Gem::Platform.local.os
98
+ in /darwin/ then 'dylib'
99
+ else 'so'
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ # The library directories we need to look into.
106
+ #
107
+ # @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
108
+ #
109
+ # @see ENV_PARSERS
110
+ # @see LIBDIRS
111
+ def lib_dirs = [*TreeSitter::ENV_PARSERS, *TreeSitter::LIBDIRS]
112
+
113
+ # Lookup a parser by name.
114
+ #
115
+ # Precedence:
116
+ # 1. `Env['TREE_SITTER_PARSERS]`.
117
+ # 2. {TreeStand::Config#parser_path} if using {TreeStand}.
118
+ # 3. {LIBDIRS}.
119
+ #
120
+ # If a {TreeStand::Config#parser_path} is `nil`, {LIBDIRS} is used.
121
+ # If a {TreeStand::Config#parser_path} is a {::Pathname}, {LIBDIRS} is ignored.
122
+ def search_for_lib(name)
123
+ files = [
124
+ name,
125
+ "tree-sitter-#{name}",
126
+ "libtree-sitter-#{name}",
127
+ ].map { |v| "#{v}.#{ext}" }
128
+
129
+ lib_dirs
130
+ .product(files)
131
+ .find do |dir, so|
132
+ path = dir / so
133
+ path = dir / name / so if !path.exist?
134
+ break path.expand_path if path.exist?
135
+ end
136
+ end
137
+
138
+ # Generates a string message on where parser lookup happens.
139
+ #
140
+ # @return [String] A pretty message.
141
+ def search_lib_message
142
+ indent = 2
143
+ pretty = ->(arr) {
144
+ if arr
145
+ arr
146
+ .compact
147
+ .map { |v| "#{' ' * indent}#{v.expand_path}" }
148
+ .join("\n")
149
+ end
150
+ }
151
+ <<~MSG.chomp
152
+ From ENV['TREE_SITTER_PARSERS']:
153
+ #{pretty.call(ENV_PARSERS)}
154
+
155
+ From Defaults:
156
+ #{pretty.call(lib_dirs)}
157
+ MSG
158
+ end
159
+ end
160
+ end
161
+ end
@@ -3,6 +3,8 @@
3
3
  module TreeSitter
4
4
  # Node is a wrapper around a tree-sitter node.
5
5
  class Node
6
+ include Enumerable
7
+
6
8
  # @return [Array<Symbol>] the node's named fields
7
9
  def fields
8
10
  return @fields if @fields
@@ -87,10 +89,10 @@ module TreeSitter
87
89
  # Iterate over a node's children.
88
90
  #
89
91
  # @yieldparam child [Node] the child
90
- def each
92
+ def each(&_block)
91
93
  return enum_for __method__ if !block_given?
92
94
 
93
- (0...(child_count)).each do |i|
95
+ (0...child_count).each do |i|
94
96
  yield child(i)
95
97
  end
96
98
  end
@@ -3,6 +3,8 @@
3
3
  module TreeSitter
4
4
  # A sequence of {TreeSitter::QueryCapture} associated with a given {TreeSitter::QueryCursor}.
5
5
  class QueryCaptures
6
+ include Enumerable
7
+
6
8
  def initialize(cursor, query, src)
7
9
  @cursor = cursor
8
10
  @query = query
@@ -13,7 +15,7 @@ module TreeSitter
13
15
  #
14
16
  # @yieldparam match [TreeSitter::QueryMatch]
15
17
  # @yieldparam capture_index [Integer]
16
- def each
18
+ def each(&_block)
17
19
  return enum_for __method__ if !block_given?
18
20
 
19
21
  while (capture_index, match = @cursor.next_capture)
@@ -3,6 +3,8 @@
3
3
  module TreeSitter
4
4
  # A sequence of {QueryMatch} associated with a given {QueryCursor}.
5
5
  class QueryMatches
6
+ include Enumerable
7
+
6
8
  def initialize(cursor, query, src)
7
9
  @cursor = cursor
8
10
  @query = query
@@ -12,7 +14,7 @@ module TreeSitter
12
14
  # Iterator over matches.
13
15
  #
14
16
  # @yieldparam match [TreeSitter::QueryMatch]
15
- def each
17
+ def each(&_block)
16
18
  return enum_for __method__ if !block_given?
17
19
 
18
20
  while match = @cursor.next_match
@@ -21,5 +23,17 @@ module TreeSitter
21
23
  end
22
24
  end
23
25
  end
26
+
27
+ # Iterate over all the results presented as hashes of `capture name => node`.
28
+ #
29
+ # @yieldparam match [Hash<String, TreeSitter::Node>]
30
+ def each_capture_hash(&_block)
31
+ # TODO: should we return [Array<Hash<Symbol, TreeSitter::Node]>>] instead?
32
+ return enum_for __method__ if !block_given?
33
+
34
+ each do |match|
35
+ yield match.captures.to_h { |cap| [@query.capture_name_for_id(cap.index), cap.node] }
36
+ end
37
+ end
24
38
  end
25
39
  end
Binary file
@@ -4,5 +4,5 @@ module TreeSitter
4
4
  # The version of the tree-sitter library.
5
5
  TREESITTER_VERSION = '0.22.6'
6
6
  # The current version of the gem.
7
- VERSION = '1.3.0'
7
+ VERSION = '1.4.1'
8
8
  end
data/lib/tree_sitter.rb CHANGED
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # TreeSitter is a Ruby interface to the tree-sitter parsing library.
4
- module TreeSitter
5
- end
6
-
7
3
  require 'set'
8
4
 
9
5
  require 'tree_sitter/tree_sitter'
10
6
  require 'tree_sitter/version'
11
7
 
8
+ require 'tree_sitter/mixins/language'
9
+
12
10
  require 'tree_sitter/node'
13
11
  require 'tree_sitter/query'
14
12
  require 'tree_sitter/query_captures'
@@ -18,4 +16,13 @@ require 'tree_sitter/query_matches'
18
16
  require 'tree_sitter/query_predicate'
19
17
  require 'tree_sitter/text_predicate_capture'
20
18
 
19
+ # TreeSitter is a Ruby interface to the tree-sitter parsing library.
20
+ module TreeSitter
21
+ extend Mixins::Language
22
+
23
+ class << self
24
+ alias_method :lang, :language
25
+ end
26
+ end
27
+
21
28
  ObjectSpace.define_finalizer(TreeSitter::Tree.class, proc { TreeSitter::Tree.finalizer })
@@ -97,19 +97,11 @@ module TreeStand
97
97
  sig { params(query_string: String).returns(T::Array[T::Hash[String, TreeStand::Node]]) }
98
98
  def query(query_string)
99
99
  ts_query = TreeSitter::Query.new(@tree.parser.ts_language, query_string)
100
- ts_cursor = TreeSitter::QueryCursor.exec(ts_query, ts_node)
101
- matches = []
102
- while ts_match = ts_cursor.next_match
103
- captures = {}
104
-
105
- ts_match.captures.each do |ts_capture|
106
- capture_name = ts_query.capture_name_for_id(ts_capture.index)
107
- captures[capture_name] = TreeStand::Node.new(@tree, ts_capture.node)
108
- end
109
-
110
- matches << captures
111
- end
112
- matches
100
+ TreeSitter::QueryCursor
101
+ .new
102
+ .matches(ts_query, @tree.ts_tree.root_node, @tree.document)
103
+ .each_capture_hash
104
+ .map { |h| h.transform_values! { |n| TreeStand::Node.new(@tree, n) } }
113
105
  end
114
106
 
115
107
  # Returns the first captured node that matches the query string or nil if
@@ -26,6 +26,7 @@ module TreeStand
26
26
  # @see LIBDIRS
27
27
  class Parser
28
28
  extend T::Sig
29
+ extend TreeSitter::Mixins::Language
29
30
 
30
31
  sig { returns(TreeSitter::Language) }
31
32
  attr_reader :ts_language
@@ -33,156 +34,6 @@ module TreeStand
33
34
  sig { returns(TreeSitter::Parser) }
34
35
  attr_reader :ts_parser
35
36
 
36
- # A colon-seprated list of paths pointing to directories that can contain parsers.
37
- # Order matters.
38
- # Takes precedence over default lookup paths.
39
- ENV_PARSERS =
40
- ENV['TREE_SITTER_PARSERS']
41
- &.split(':')
42
- &.map { |v| Pathname(v) }
43
- .freeze
44
-
45
- # The default paths we use to lookup parsers when no specific
46
- # {TreeStand::Config#parser_path} is `nil`.
47
- # Order matters.
48
- LIBDIRS = [
49
- 'tree-sitter-parsers',
50
- '/opt/local/lib',
51
- '/opt/lib',
52
- '/usr/local/lib',
53
- '/usr/lib',
54
- ].map { |p| Pathname(p) }.freeze
55
-
56
- # The library directories we need to look into.
57
- #
58
- # @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
59
- #
60
- # @see ENV_PARSERS
61
- # @see LIBDIRS
62
- sig { returns(T::Array[Pathname]) }
63
- def self.lib_dirs = [
64
- *ENV_PARSERS,
65
- *(TreeStand.config.parser_path ? [TreeStand.config.parser_path] : LIBDIRS),
66
- ].compact
67
-
68
- # The platform-specific extension of the parser.
69
- # @return [String] `dylib` or `so` for mac or linux.
70
- sig { returns(String) }
71
- def self.ext
72
- case Gem::Platform.local.os
73
- in /darwin/ then 'dylib'
74
- else 'so'
75
- end
76
- end
77
-
78
- # Lookup a parser by name.
79
- #
80
- # Precedence:
81
- # 1. `Env['TREE_SITTER_PARSERS]`
82
- # 2. {TreeStand::Config#parser_path}
83
- # 3. {LIBDIRS}
84
- #
85
- # If a {TreeStand::Config#parser_path} is `nil`, {LIBDIRS} is used.
86
- # If a {TreeStand::Config#parser_path} is a {::Pathname}, {LIBDIRS} is ignored.
87
- sig { params(name: String).returns(T.nilable(Pathname)) }
88
- def self.search_for_lib(name)
89
- files = [
90
- name,
91
- "tree-sitter-#{name}",
92
- "libtree-sitter-#{name}",
93
- ].map { |v| "#{v}.#{ext}" }
94
-
95
- res = lib_dirs
96
- .product(files)
97
- .find do |dir, so|
98
- path = dir / so
99
- path = dir / name / so if !path.exist?
100
- break path.expand_path if path.exist?
101
- end
102
- res.is_a?(Array) ? nil : res
103
- end
104
-
105
- # Generates a string message on where parser lookup happens.
106
- #
107
- # @return [String] A pretty message.
108
- sig { returns(String) }
109
- def self.search_lib_message
110
- indent = 2
111
- pretty = ->(arr) {
112
- if arr
113
- arr
114
- .compact
115
- .map { |v| "#{' ' * indent}#{v.expand_path}" }
116
- .join("\n")
117
- end
118
- }
119
- <<~MSG
120
- From ENV['TREE_SITTER_PARSERS']:
121
- #{pretty.call(ENV_PARSERS)}
122
-
123
- From TreeStand.config.parser_path:
124
- #{pretty.call([TreeStand.config.parser_path])}
125
-
126
- From Defaults:
127
- #{pretty.call(LIBDIRS)}
128
- MSG
129
- end
130
-
131
- # Load a language from configuration or default lookup paths.
132
- #
133
- # @example Load java from default paths
134
- # # This will look for:
135
- # #
136
- # # tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
137
- # # /opt/local/lib/(java/)?(libtree-sitter-)?java.{ext}
138
- # # /opt/lib/(java/)?(libtree-sitter-)?java.{ext}
139
- # # /usr/local/lib/(java/)?(libtree-sitter-)?java.{ext}
140
- # # /usr/lib/(java/)?(libtree-sitter-)?java.{ext}
141
- # #
142
- # java = TreeStand::Parser.language('java')
143
- #
144
- # @example Load java from a configured path
145
- # # This will look for:
146
- # #
147
- # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
148
- # #
149
- # TreeStand.config.parser_path = '/my/path'
150
- # java = TreeStand::Parser.language('java')
151
- #
152
- # @example Load java from environment variables
153
- # # This will look for:
154
- # #
155
- # # /my/forced/env/path/(java/)?(libtree-sitter-)?java.{ext}
156
- # # /my/path/(java/)?(libtree-sitter-)?java.{ext}
157
- # #
158
- # # … and the same works for the default paths if `TreeStand.config.parser_path`
159
- # # was `nil`
160
- # ENV['TREE_SITTER_PARSERS'] = '/my/forced/env/path'
161
- # TreeStand.config.parser_path = '/my/path'
162
- # java = TreeStand::Parser.language('java')
163
- #
164
- # @param name [String] the name of the parser.
165
- # This name is used to load the symbol from the compiled parser, replacing `-` with `_`.
166
- # @return [TreeSitter:language] a language object to use in your parsers.
167
- # @raise [RuntimeError] if the parser was not found.
168
- # @see search_for_lib
169
- sig { params(name: String).returns(TreeSitter::Language) }
170
- def self.language(name)
171
- lib = search_for_lib(name)
172
-
173
- if lib.nil?
174
- raise <<~MSG
175
- Failed to load a parser for #{name}.
176
-
177
- #{search_lib_message}
178
- MSG
179
- end
180
-
181
- # We know that the bindings will accept `lib`, but I don't know how to tell sorbet
182
- # the types in ext/tree_sitter where `load` is defined.
183
- TreeSitter::Language.load(name.tr('-', '_'), T.unsafe(lib))
184
- end
185
-
186
37
  # @param language [String]
187
38
  sig { params(language: String).void }
188
39
  def initialize(language)
@@ -192,6 +43,19 @@ module TreeStand
192
43
  end
193
44
  end
194
45
 
46
+ # The library directories we need to look into.
47
+ #
48
+ # @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
49
+ #
50
+ # @see ENV_PARSERS
51
+ # @see LIBDIRS
52
+ def self.lib_dirs
53
+ [
54
+ *TreeSitter::ENV_PARSERS,
55
+ *(TreeStand.config.parser_path ? [TreeStand.config.parser_path] : TreeSitter::LIBDIRS),
56
+ ]
57
+ end
58
+
195
59
  # Parse the provided document with the TreeSitter parser.
196
60
  # @param tree [TreeStand::Tree, nil] providing the old tree will allow the
197
61
  # parser to take advantage of incremental parsing and improve performance
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_tree_sitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.1
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Firas al-Khalil
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-06-26 00:00:00.000000000 Z
12
+ date: 2024-07-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sorbet-runtime
@@ -75,6 +75,7 @@ files:
75
75
  - ext/tree_sitter/tree_sitter.h
76
76
  - lib/tree_sitter.rb
77
77
  - lib/tree_sitter/helpers.rb
78
+ - lib/tree_sitter/mixins/language.rb
78
79
  - lib/tree_sitter/node.rb
79
80
  - lib/tree_sitter/query.rb
80
81
  - lib/tree_sitter/query_captures.rb
@@ -115,17 +116,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
116
  requirements:
116
117
  - - ">="
117
118
  - !ruby/object:Gem::Version
118
- version: '3.2'
119
+ version: '3.3'
119
120
  - - "<"
120
121
  - !ruby/object:Gem::Version
121
- version: 3.3.dev
122
+ version: 3.4.dev
122
123
  required_rubygems_version: !ruby/object:Gem::Requirement
123
124
  requirements:
124
125
  - - ">="
125
126
  - !ruby/object:Gem::Version
126
127
  version: '0'
127
128
  requirements: []
128
- rubygems_version: 3.4.19
129
+ rubygems_version: 3.5.11
129
130
  signing_key:
130
131
  specification_version: 4
131
132
  summary: Ruby bindings for Tree-Sitter