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
         |