Sha256: 09b37e2172a8a7ee9dee6863ba64e4f0eeb175871111bf6005a59f99b5a239b6

Contents?: true

Size: 1.98 KB

Versions: 85

Compression:

Stored size: 1.98 KB

Contents

# frozen_string_literal: true

module Parser

  class Lexer::Dedenter
    # Tab (\t) counts as 8 spaces
    TAB_WIDTH = 8

    def initialize(dedent_level)
      @dedent_level = dedent_level
      @at_line_begin = true
      @indent_level  = 0
    end

    # For a heredoc like
    #   <<-HERE
    #     a
    #     b
    #   HERE
    # this method gets called with "  a\n" and "  b\n"
    #
    # However, the following heredoc:
    #
    #   <<-HERE
    #     a\
    #     b
    #   HERE
    # calls this method only once with a string "  a\\\n  b\n"
    #
    # This is important because technically it's a single line,
    # but it has to be concatenated __after__ dedenting.
    #
    # It has no effect for non-squiggly heredocs, i.e. it simply removes "\\\n"
    # Of course, lexer could do it but once again: it's all because of dedenting.
    #
    def dedent(string)
      original_encoding = string.encoding
      # Prevent the following error when processing binary encoded source.
      # "\xC0".split # => ArgumentError (invalid byte sequence in UTF-8)
      lines = string.force_encoding(Encoding::BINARY).split("\\\n")
      lines.map! {|s| s.force_encoding(original_encoding) }

      if @at_line_begin
        lines_to_dedent = lines
      else
        _first, *lines_to_dedent = lines
      end

      lines_to_dedent.each do |line|
        left_to_remove = @dedent_level
        remove = 0

        line.each_char do |char|
          break if left_to_remove <= 0
          case char
          when ?\s
            remove += 1
            left_to_remove -= 1
          when ?\t
            break if TAB_WIDTH * (remove / TAB_WIDTH + 1) > @dedent_level
            remove += 1
            left_to_remove -= TAB_WIDTH
          else
            # no more spaces or tabs
            break
          end
        end

        line.slice!(0, remove)
      end

      string.replace(lines.join)

      @at_line_begin = string.end_with?("\n")
    end

    def interrupt
      @at_line_begin = false
    end
  end

end

Version data entries

85 entries across 79 versions & 14 rubygems

Version Path
plaid-14.12.1 vendor/bundle/ruby/3.0.0/gems/parser-2.7.2.0/lib/parser/lexer/dedenter.rb
plaid-14.12.0 vendor/bundle/ruby/2.6.0/gems/parser-2.7.2.0/lib/parser/lexer/dedenter.rb
plaid-14.11.1 vendor/bundle/ruby/2.6.0/gems/parser-2.7.2.0/lib/parser/lexer/dedenter.rb
plaid-14.10.0 vendor/bundle/ruby/2.6.0/gems/parser-2.7.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.4.0 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.3.0 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.2.0 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.1.0 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
ory-client-0.0.1.alpha29 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.0.6 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
ory-client-0.0.1.alpha28 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.0.5 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
ory-client-0.0.1.alpha27 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
ory-client-0.0.1.alpha24 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.0.4 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
primary_connect_proto-0.0.3 vendor/bundle/ruby/2.6.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
ory-client-0.0.1.alpha23 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
plaid-14.7.0 vendor/bundle/ruby/2.6.0/gems/parser-2.7.2.0/lib/parser/lexer/dedenter.rb
ory-kratos-client-0.8.0.alpha2 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb
ory-client-0.0.1.alpha21 vendor/bundle/ruby/2.5.0/gems/parser-3.0.2.0/lib/parser/lexer/dedenter.rb