Class | CodeRay::Scanners::Diff |
In: |
lib/coderay/scanners/diff.rb
|
Parent: | Scanner |
Scanner for output of the diff command.
Alias: patch
DEFAULT_OPTIONS | = | { :highlight_code => true, :inline_diff => true, } |
# File lib/coderay/scanners/diff.rb, line 19 19: def scan_tokens encoder, options 20: 21: line_kind = nil 22: state = :initial 23: deleted_lines = 0 24: scanners = Hash.new do |h, lang| 25: h[lang] = Scanners[lang].new '', :keep_tokens => true, :keep_state => true 26: end 27: content_scanner = scanners[:plain] 28: content_scanner_entry_state = nil 29: 30: until eos? 31: 32: if match = scan(/\n/) 33: deleted_lines = 0 unless line_kind == :delete 34: if line_kind 35: encoder.end_line line_kind 36: line_kind = nil 37: end 38: encoder.text_token match, :space 39: next 40: end 41: 42: case state 43: 44: when :initial 45: if match = scan(/--- |\+\+\+ |=+|_+/) 46: encoder.begin_line line_kind = :head 47: encoder.text_token match, :head 48: if match = scan(/.*?(?=$|[\t\n\x00]| \(revision)/) 49: encoder.text_token match, :filename 50: if options[:highlight_code] && match != '/dev/null' 51: file_type = CodeRay::FileType.fetch(match, :text) 52: file_type = :text if file_type == :diff 53: content_scanner = scanners[file_type] 54: content_scanner_entry_state = nil 55: end 56: end 57: next unless match = scan(/.+/) 58: encoder.text_token match, :plain 59: elsif match = scan(/Index: |Property changes on: /) 60: encoder.begin_line line_kind = :head 61: encoder.text_token match, :head 62: next unless match = scan(/.+/) 63: encoder.text_token match, :plain 64: elsif match = scan(/Added: /) 65: encoder.begin_line line_kind = :head 66: encoder.text_token match, :head 67: next unless match = scan(/.+/) 68: encoder.text_token match, :plain 69: state = :added 70: elsif match = scan(/\\ .*/) 71: encoder.text_token match, :comment 72: elsif match = scan(/@@(?>[^@\n]*)@@/) 73: content_scanner.state = :initial unless match?(/\n\+/) 74: content_scanner_entry_state = nil 75: if check(/\n|$/) 76: encoder.begin_line line_kind = :change 77: else 78: encoder.begin_group :change 79: end 80: encoder.text_token match[0,2], :change 81: encoder.text_token match[2...-2], :plain 82: encoder.text_token match[-2,2], :change 83: encoder.end_group :change unless line_kind 84: next unless match = scan(/.+/) 85: if options[:highlight_code] 86: content_scanner.tokenize match, :tokens => encoder 87: else 88: encoder.text_token match, :plain 89: end 90: next 91: elsif match = scan(/\+/) 92: encoder.begin_line line_kind = :insert 93: encoder.text_token match, :insert 94: next unless match = scan(/.+/) 95: if options[:highlight_code] 96: content_scanner.tokenize match, :tokens => encoder 97: else 98: encoder.text_token match, :plain 99: end 100: next 101: elsif match = scan(/-/) 102: deleted_lines += 1 103: encoder.begin_line line_kind = :delete 104: encoder.text_token match, :delete 105: if options[:inline_diff] && deleted_lines == 1 && check(/(?>.*)\n\+(?>.*)$(?!\n\+)/) 106: content_scanner_entry_state = content_scanner.state 107: skip(/(.*)\n\+(.*)$/) 108: head, deletion, insertion, tail = diff self[1], self[2] 109: pre, deleted, post = content_scanner.tokenize [head, deletion, tail], :tokens => Tokens.new 110: encoder.tokens pre 111: unless deleted.empty? 112: encoder.begin_group :eyecatcher 113: encoder.tokens deleted 114: encoder.end_group :eyecatcher 115: end 116: encoder.tokens post 117: encoder.end_line line_kind 118: encoder.text_token "\n", :space 119: encoder.begin_line line_kind = :insert 120: encoder.text_token '+', :insert 121: content_scanner.state = content_scanner_entry_state || :initial 122: pre, inserted, post = content_scanner.tokenize [head, insertion, tail], :tokens => Tokens.new 123: encoder.tokens pre 124: unless inserted.empty? 125: encoder.begin_group :eyecatcher 126: encoder.tokens inserted 127: encoder.end_group :eyecatcher 128: end 129: encoder.tokens post 130: elsif match = scan(/.*/) 131: if options[:highlight_code] 132: if deleted_lines == 1 133: content_scanner_entry_state = content_scanner.state 134: end 135: content_scanner.tokenize match, :tokens => encoder unless match.empty? 136: if !match?(/\n-/) 137: if match?(/\n\+/) 138: content_scanner.state = content_scanner_entry_state || :initial 139: end 140: content_scanner_entry_state = nil 141: end 142: else 143: encoder.text_token match, :plain 144: end 145: end 146: next 147: elsif match = scan(/ .*/) 148: if options[:highlight_code] 149: content_scanner.tokenize match, :tokens => encoder 150: else 151: encoder.text_token match, :plain 152: end 153: next 154: elsif match = scan(/.+/) 155: encoder.begin_line line_kind = :comment 156: encoder.text_token match, :plain 157: else 158: raise_inspect 'else case rached' 159: end 160: 161: when :added 162: if match = scan(/ \+/) 163: encoder.begin_line line_kind = :insert 164: encoder.text_token match, :insert 165: next unless match = scan(/.+/) 166: encoder.text_token match, :plain 167: else 168: state = :initial 169: next 170: end 171: end 172: 173: end 174: 175: encoder.end_line line_kind if line_kind 176: 177: encoder 178: end