mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	Add support for showing code context lines (#181)
* Add support for showing code context lines * Show context lines only in ExplainFormatter * Add spec coverage for context_lines option
This commit is contained in:
		
							parent
							
								
									9bc6c13d11
								
							
						
					
					
						commit
						c4d34d74d8
					
				
					 3 changed files with 96 additions and 13 deletions
				
			
		| 
						 | 
					@ -22,7 +22,38 @@ module Ameba::Formatter
 | 
				
			||||||
          a = 1
 | 
					          a = 1
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        location = Crystal::Location.new("filename", 1, 1)
 | 
					        location = Crystal::Location.new("filename", 1, 1)
 | 
				
			||||||
        subject.affected_code(source, location).should eq "> a = 1\n  \e[33m^\e[0m"
 | 
					        subject.deansify(subject.affected_code(source, location))
 | 
				
			||||||
 | 
					          .should eq "> a = 1\n  ^"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "returns correct line if it is found" do
 | 
				
			||||||
 | 
					        source = Source.new <<-EOF
 | 
				
			||||||
 | 
					          # pre:1
 | 
				
			||||||
 | 
					            # pre:2
 | 
				
			||||||
 | 
					              # pre:3
 | 
				
			||||||
 | 
					                # pre:4
 | 
				
			||||||
 | 
					                  # pre:5
 | 
				
			||||||
 | 
					          a = 1
 | 
				
			||||||
 | 
					                  # post:1
 | 
				
			||||||
 | 
					                # post:2
 | 
				
			||||||
 | 
					              # post:3
 | 
				
			||||||
 | 
					            # post:4
 | 
				
			||||||
 | 
					          # post:5
 | 
				
			||||||
 | 
					          EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        location = Crystal::Location.new("filename", 6, 1)
 | 
				
			||||||
 | 
					        subject.deansify(subject.affected_code(source, location, context_lines: 3))
 | 
				
			||||||
 | 
					          .should eq <<-STR
 | 
				
			||||||
 | 
					            >     # pre:3
 | 
				
			||||||
 | 
					            >       # pre:4
 | 
				
			||||||
 | 
					            >         # pre:5
 | 
				
			||||||
 | 
					            > a = 1
 | 
				
			||||||
 | 
					              ^
 | 
				
			||||||
 | 
					            >         # post:1
 | 
				
			||||||
 | 
					            >       # post:2
 | 
				
			||||||
 | 
					            >     # post:3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            STR
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ module Ameba::Formatter
 | 
				
			||||||
        @location.to_s.colorize(:cyan).to_s,
 | 
					        @location.to_s.colorize(:cyan).to_s,
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if affected_code = affected_code(source, @location)
 | 
					      if affected_code = affected_code(source, @location, context_lines: 3)
 | 
				
			||||||
        output_title "AFFECTED CODE"
 | 
					        output_title "AFFECTED CODE"
 | 
				
			||||||
        output_paragraph affected_code
 | 
					        output_paragraph affected_code
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,75 @@
 | 
				
			||||||
module Ameba::Formatter
 | 
					module Ameba::Formatter
 | 
				
			||||||
  module Util
 | 
					  module Util
 | 
				
			||||||
    def affected_code(source, location, max_length = 100, placeholder = " ...", prompt = "> ")
 | 
					    def deansify(message : String?) : String?
 | 
				
			||||||
      line, column = location.line_number, location.column_number
 | 
					      message.try &.gsub(/\x1b[^m]*m/, "").presence
 | 
				
			||||||
      affected_line = source.lines[line - 1]?.presence
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return unless affected_line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if affected_line.size > max_length && column < max_length
 | 
					 | 
				
			||||||
        affected_line = affected_line[0, max_length - placeholder.size - 1] + placeholder
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def affected_code(source, location, context_lines = 0, max_length = 100, placeholder = " ...", prompt = "> ")
 | 
				
			||||||
 | 
					      lines = source.lines
 | 
				
			||||||
 | 
					      lineno, column =
 | 
				
			||||||
 | 
					        location.line_number, location.column_number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return unless affected_line = lines[lineno - 1]?.presence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      trim_line = Proc(String, String).new do |line|
 | 
				
			||||||
 | 
					        if line.size > max_length
 | 
				
			||||||
 | 
					          line = line[0, max_length - placeholder.size - 1] + placeholder
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        line
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if column < max_length
 | 
				
			||||||
 | 
					        affected_line = trim_line.call(affected_line)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      show_context = context_lines > 0
 | 
				
			||||||
 | 
					      if show_context
 | 
				
			||||||
 | 
					        pre_context, post_context = %w[], %w[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lines.each_with_index do |line, i|
 | 
				
			||||||
 | 
					          case i + 1
 | 
				
			||||||
 | 
					          when lineno - context_lines...lineno
 | 
				
			||||||
 | 
					            pre_context << trim_line.call(line)
 | 
				
			||||||
 | 
					          when lineno
 | 
				
			||||||
 | 
					            #
 | 
				
			||||||
 | 
					          when lineno + 1..lineno + context_lines
 | 
				
			||||||
 | 
					            post_context << trim_line.call(line)
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # remove empty lines at the beginning/end
 | 
				
			||||||
 | 
					        pre_context.shift? unless pre_context.first?.presence
 | 
				
			||||||
 | 
					        post_context.pop? unless post_context.last?.presence
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      String.build do |str|
 | 
				
			||||||
 | 
					        if show_context
 | 
				
			||||||
 | 
					          pre_context.try &.each do |line|
 | 
				
			||||||
 | 
					            str << prompt
 | 
				
			||||||
 | 
					            str.puts(line.colorize(:dark_gray))
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          str << prompt
 | 
				
			||||||
 | 
					          str.puts(affected_line.colorize(:white))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          str << " " * (prompt.size + column - 1)
 | 
				
			||||||
 | 
					          str.puts("^".colorize(:yellow))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          post_context.try &.each do |line|
 | 
				
			||||||
 | 
					            str << prompt
 | 
				
			||||||
 | 
					            str.puts(line.colorize(:dark_gray))
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
          stripped = affected_line.lstrip
 | 
					          stripped = affected_line.lstrip
 | 
				
			||||||
          position = column - (affected_line.size - stripped.size) + prompt.size
 | 
					          position = column - (affected_line.size - stripped.size) + prompt.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      String.build do |str|
 | 
					          str << prompt
 | 
				
			||||||
        str << prompt << stripped << '\n'
 | 
					          str.puts(stripped)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          str << " " * (position - 1)
 | 
					          str << " " * (position - 1)
 | 
				
			||||||
          str << "^".colorize(:yellow)
 | 
					          str << "^".colorize(:yellow)
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue