Mercurial > hg > soundsoftware-site
view vendor/gems/coderay-1.0.0/lib/coderay/scanners/diff.rb @ 1082:997f6d7738f7 bug_531
In repo controller entry action, show the page for the file even if it's binary (so user still has access to history etc links). This makes it possible to use the entry action as the default when a file is clicked on
author | Chris Cannam <chris.cannam@soundsoftware.ac.uk> |
---|---|
date | Thu, 22 Nov 2012 18:04:17 +0000 |
parents | cbb26bc654de |
children |
line wrap: on
line source
module CodeRay module Scanners # Scanner for output of the diff command. # # Alias: +patch+ class Diff < Scanner register_for :diff title 'diff output' DEFAULT_OPTIONS = { :highlight_code => true, :inline_diff => true, } protected require 'coderay/helpers/file_type' def scan_tokens encoder, options line_kind = nil state = :initial deleted_lines = 0 scanners = Hash.new do |h, lang| h[lang] = Scanners[lang].new '', :keep_tokens => true, :keep_state => true end content_scanner = scanners[:plain] content_scanner_entry_state = nil until eos? if match = scan(/\n/) deleted_lines = 0 unless line_kind == :delete if line_kind encoder.end_line line_kind line_kind = nil end encoder.text_token match, :space next end case state when :initial if match = scan(/--- |\+\+\+ |=+|_+/) encoder.begin_line line_kind = :head encoder.text_token match, :head if match = scan(/.*?(?=$|[\t\n\x00]| \(revision)/) encoder.text_token match, :filename if options[:highlight_code] file_type = FileType.fetch(match, :text) file_type = :text if file_type == :diff content_scanner = scanners[file_type] content_scanner_entry_state = nil end end next unless match = scan(/.+/) encoder.text_token match, :plain elsif match = scan(/Index: |Property changes on: /) encoder.begin_line line_kind = :head encoder.text_token match, :head next unless match = scan(/.+/) encoder.text_token match, :plain elsif match = scan(/Added: /) encoder.begin_line line_kind = :head encoder.text_token match, :head next unless match = scan(/.+/) encoder.text_token match, :plain state = :added elsif match = scan(/\\ .*/) encoder.text_token match, :comment elsif match = scan(/@@(?>[^@\n]*)@@/) content_scanner.state = :initial unless match?(/\n\+/) content_scanner_entry_state = nil if check(/\n|$/) encoder.begin_line line_kind = :change else encoder.begin_group :change end encoder.text_token match[0,2], :change encoder.text_token match[2...-2], :plain encoder.text_token match[-2,2], :change encoder.end_group :change unless line_kind next unless match = scan(/.+/) if options[:highlight_code] content_scanner.tokenize match, :tokens => encoder else encoder.text_token match, :plain end next elsif match = scan(/\+/) encoder.begin_line line_kind = :insert encoder.text_token match, :insert next unless match = scan(/.+/) if options[:highlight_code] content_scanner.tokenize match, :tokens => encoder else encoder.text_token match, :plain end next elsif match = scan(/-/) deleted_lines += 1 encoder.begin_line line_kind = :delete encoder.text_token match, :delete if options[:inline_diff] && deleted_lines == 1 && check(/(?>.*)\n\+(?>.*)$(?!\n\+)/) content_scanner_entry_state = content_scanner.state skip(/(.*)\n\+(.*)$/) head, deletion, insertion, tail = diff self[1], self[2] pre, deleted, post = content_scanner.tokenize [head, deletion, tail], :tokens => Tokens.new encoder.tokens pre unless deleted.empty? encoder.begin_group :eyecatcher encoder.tokens deleted encoder.end_group :eyecatcher end encoder.tokens post encoder.end_line line_kind encoder.text_token "\n", :space encoder.begin_line line_kind = :insert encoder.text_token '+', :insert content_scanner.state = content_scanner_entry_state || :initial pre, inserted, post = content_scanner.tokenize [head, insertion, tail], :tokens => Tokens.new encoder.tokens pre unless inserted.empty? encoder.begin_group :eyecatcher encoder.tokens inserted encoder.end_group :eyecatcher end encoder.tokens post elsif match = scan(/.*/) if options[:highlight_code] if deleted_lines == 1 content_scanner_entry_state = content_scanner.state end content_scanner.tokenize match, :tokens => encoder unless match.empty? if !match?(/\n-/) if match?(/\n\+/) content_scanner.state = content_scanner_entry_state || :initial end content_scanner_entry_state = nil end else encoder.text_token match, :plain end end next elsif match = scan(/ .*/) if options[:highlight_code] content_scanner.tokenize match, :tokens => encoder else encoder.text_token match, :plain end next elsif match = scan(/.+/) encoder.begin_line line_kind = :comment encoder.text_token match, :plain else raise_inspect 'else case rached' end when :added if match = scan(/ \+/) encoder.begin_line line_kind = :insert encoder.text_token match, :insert next unless match = scan(/.+/) encoder.text_token match, :plain else state = :initial next end end end encoder.end_line line_kind if line_kind encoder end private def diff a, b # i will be the index of the leftmost difference from the left. i_max = [a.size, b.size].min i = 0 i += 1 while i < i_max && a[i] == b[i] # j_min will be the index of the leftmost difference from the right. j_min = i - i_max # j will be the index of the rightmost difference from the right which # does not precede the leftmost one from the left. j = -1 j -= 1 while j >= j_min && a[j] == b[j] return a[0...i], a[i..j], b[i..j], (j < -1) ? a[j+1..-1] : '' end end end end