di 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/HISTORY +4 -0
  2. data/README.rdoc +1 -1
  3. data/Rakefile +1 -0
  4. data/VERSION +1 -1
  5. data/bin/di +217 -6
  6. data/di.gemspec +2 -1
  7. metadata +6 -4
data/HISTORY CHANGED
@@ -1,5 +1,9 @@
1
1
  * Add --[no-]pager and turn it on by default.
2
2
 
3
+ * Add --[no-]color and colorize diff output by default.
4
+
5
+ * Read user's preferred default options from DI_OPTIONS.
6
+
3
7
  * Do not choke on file names starting with a hyphen.
4
8
 
5
9
  == 0.1.3 2010-03-10
@@ -31,7 +31,7 @@ Run di --help for help.
31
31
 
32
32
  == REQUIREMENTS:
33
33
 
34
- - Ruby 1.8.6 or later
34
+ - Ruby 1.8.7 or later
35
35
 
36
36
  - GNU diff(1)
37
37
 
data/Rakefile CHANGED
@@ -13,6 +13,7 @@ EOS
13
13
  gem.email = "knu@idaemons.org"
14
14
  gem.homepage = "http://github.com/knu/di"
15
15
  gem.authors = ["Akinori MUSHA"]
16
+ gem.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
16
17
  gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
17
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
19
  gem.executables = ["di"]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.5
data/bin/di CHANGED
@@ -73,8 +73,24 @@ def setup
73
73
  $diff.include = []
74
74
  $diff.flags = []
75
75
  $diff.format_flags = []
76
+ $diff.format = :normal
76
77
  $diff.custom_format_p = false
77
78
  $diff.use_pager = false
79
+ $diff.colorize = false
80
+ $diff.highlight_whitespace = true
81
+ $diff.colors = {
82
+ :comment => "\033[1m",
83
+ :file1 => "\033[1m",
84
+ :file2 => "\033[1m",
85
+ :header => "\033[36m",
86
+ :function => "\033[m",
87
+ :new => "\033[32m",
88
+ :old => "\033[31m",
89
+ :changed => "\033[33m",
90
+ :unchanged => "",
91
+ :whitespace => "\033[41m",
92
+ :off => "\033[m",
93
+ }
78
94
  end
79
95
 
80
96
  def parse_args!(args)
@@ -94,8 +110,12 @@ usage: #{MYNAME} [flags] [files]
94
110
  opts.accept(miniTrueClass, hash) {|arg, val| val == nil or val}
95
111
 
96
112
  opts.on('--[no-]pager',
97
- 'Pipe output into $PAGER (or more(1) if not defined) if stdout is a terminal. [!][*]') { |val|
98
- $diff.use_pager = val
113
+ 'Pipe output into pager if stdout is a terminal. [!][*]') { |val|
114
+ $diff.use_pager = val if $stdout.tty?
115
+ }
116
+ opts.on('--[no-]color',
117
+ 'Colorize output if stdout is a terminal and the format is unified or context. [!][*]') { |val|
118
+ $diff.colorize = val if $stdout.tty?
99
119
  }
100
120
  opts.on('--[no-]rsync-exclude', '--[no-]cvs-exclude',
101
121
  'Exclude some kinds of files and directories a la rsync(1). [!][*]') { |val|
@@ -339,14 +359,26 @@ usage: #{MYNAME} [flags] [files]
339
359
  Options without the [*] sign will be passed through to diff(1).
340
360
  Options marked as [!] sign are turned on by default. To turn them off,
341
361
  specify -?- for short options and --no-??? for long options, respectively.
362
+
363
+ Environment variables:
364
+ DIFF Path to diff(1)
365
+ DI_OPTIONS User's preferred default options
366
+ PAGER Path to pager (more(1) is used if not defined)
342
367
  EOS
343
368
  exit 0
344
369
  }
345
370
  }
346
371
 
347
372
  begin
348
- opts.parse('--rsync-exclude', '--fignore-exclude', '--ignore-cvs-lines', '--pager',
373
+ opts.parse('--rsync-exclude', '--fignore-exclude', '--ignore-cvs-lines',
374
+ '--pager', '--color',
349
375
  '-U3', '-N', '-r', '-p', '-d')
376
+
377
+ if value = ENV['DI_OPTIONS']
378
+ require 'shellwords'
379
+ opts.parse(*value.shellsplit)
380
+ end
381
+
350
382
  opts.parse!(args)
351
383
 
352
384
  $diff.format_flags.each { |format_flag|
@@ -401,20 +433,28 @@ EOS
401
433
  end
402
434
 
403
435
  def invoke_pager
404
- invoke_pager! if $diff.use_pager && $stdout.tty?
436
+ invoke_pager! if $diff.use_pager
405
437
  end
406
438
 
407
439
  def invoke_pager!
408
440
  $stdout.flush
409
441
  $stderr.flush
410
442
  pr, pw = IO.pipe
443
+ ppid = Process.pid
411
444
  pid = fork {
412
445
  $stdin.reopen(pr)
413
446
  pr.close
414
447
  pw.close
415
448
  IO.select([$stdin], nil, [$stdin])
416
- exec(ENV['PAGER'] || 'more')
449
+ if system(ENV['PAGER'] || 'more')
450
+ Process.kill(:TERM, ppid)
451
+ else
452
+ $stderr.puts "Pager failed."
453
+ Process.kill(:INT, ppid)
454
+ end
417
455
  }
456
+ trap(:TERM) { exit(0) }
457
+ trap(:INT) { exit(130) }
418
458
  $stdout.reopen(pw)
419
459
  $stderr.reopen(pw) if $stderr.tty?
420
460
  pw.close
@@ -442,6 +482,24 @@ end
442
482
  def set_format_flag(flag, *val)
443
483
  $diff.format_flags.clear
444
484
  $diff.custom_format_p = false
485
+ case flag
486
+ when '-C'
487
+ $diff.format = :context
488
+ when '-U'
489
+ $diff.format = :unified
490
+ when '-e'
491
+ $diff.format = :ed
492
+ when '--normal'
493
+ $diff.format = :normal
494
+ when '-n'
495
+ $diff.format = :rcs
496
+ when '-y'
497
+ $diff.format = :side_by_side
498
+ when '-D'
499
+ $diff.format = :ifdef
500
+ else
501
+ $diff.format = :unknown
502
+ end
445
503
  $diff.format_flags.push([flag, *val])
446
504
  end
447
505
 
@@ -450,6 +508,7 @@ def set_custom_format_flag(flag, *val)
450
508
  $diff.format_flags.clear
451
509
  $diff.custom_format_p = true
452
510
  end
511
+ $diff.format = :custom
453
512
  $diff.format_flags.push([flag, *val])
454
513
  end
455
514
 
@@ -509,7 +568,21 @@ def diff_files(file1, file2)
509
568
  end
510
569
 
511
570
  def call_diff(*args)
512
- system(*[DIFF_CMD, $diff.flags, args].flatten)
571
+ command_args = [DIFF_CMD, $diff.flags, args].flatten
572
+ if $diff.colorize
573
+ case $diff.format
574
+ when :unified
575
+ filter = method(:colorize_unified_diff)
576
+ when :context
577
+ filter = method(:colorize_context_diff)
578
+ end
579
+ end
580
+ if filter
581
+ require 'shellwords'
582
+ filter.call(IO.popen(command_args.shelljoin, 'r'))
583
+ else
584
+ system(*command_args)
585
+ end
513
586
  status = $? >> 8
514
587
  $status = status if $status < status
515
588
  return status
@@ -594,4 +667,142 @@ def diff_exclude?(basename)
594
667
  return false
595
668
  end
596
669
 
670
+ def colorize_unified_diff(io)
671
+ colors = $diff.colors
672
+
673
+ state = :comment
674
+ hunk_left = nil
675
+ io.each_line { |line|
676
+ case state
677
+ when :comment
678
+ case line
679
+ when /^\+{3} /
680
+ color = colors[:file1]
681
+ when /^-{3} /
682
+ color = colors[:file2]
683
+ when /^@@ -[0-9]+,([0-9]+)/
684
+ state = :hunk
685
+ hunk_left = $1.to_i
686
+ line.sub!(/^(@@ .*? @@)( )?/) {
687
+ $1 + ($2 ? colors[:off] + $2 + colors[:function] : '')
688
+ }
689
+ color = colors[:header]
690
+ else
691
+ color = colors[:comment]
692
+ end
693
+ when :hunk
694
+ check = false
695
+ case line
696
+ when /^\+/
697
+ color = colors[:new]
698
+ check = $diff.highlight_whitespace
699
+ when /^-/
700
+ color = colors[:old]
701
+ hunk_left -= 1
702
+ check = $diff.highlight_whitespace
703
+ when /^ /
704
+ color = colors[:unchanged]
705
+ hunk_left -= 1
706
+ else
707
+ # error
708
+ color = colors[:comment]
709
+ end
710
+ if check
711
+ line.sub!(/([ \t]+)$/) {
712
+ colors[:off] + colors[:whitespace] + $1
713
+ }
714
+ end
715
+ if hunk_left <= 0
716
+ state = :comment
717
+ hunk_left = nil
718
+ end
719
+ end
720
+
721
+ line.sub!(/^/, color)
722
+ line.sub!(/$/, colors[:off])
723
+
724
+ print line
725
+ }
726
+
727
+ io.close
728
+ end
729
+
730
+ def colorize_context_diff(io)
731
+ colors = $diff.colors
732
+
733
+ state = :comment
734
+ hunk_part = nil
735
+ io.each_line { |line|
736
+ case state
737
+ when :comment
738
+ case line
739
+ when /^\*{3} /
740
+ color = colors[:file1]
741
+ when /^-{3} /
742
+ color = colors[:file2]
743
+ when /^\*{15}/
744
+ state = :hunk
745
+ hunk_part = 0
746
+ line.sub!(/^(\*{15})( )?/) {
747
+ $1 + ($2 ? colors[:off] + $2 + colors[:function] : '')
748
+ }
749
+ color = colors[:header]
750
+ end
751
+ when :hunk
752
+ case hunk_part
753
+ when 0
754
+ case line
755
+ when /^\*{3} /
756
+ hunk_part = 1
757
+ color = colors[:header]
758
+ else
759
+ # error
760
+ color = colors[:comment]
761
+ end
762
+ when 1, 2
763
+ check = false
764
+ case line
765
+ when /^\-{3} /
766
+ if hunk_part == 1
767
+ hunk_part = 2
768
+ color = colors[:header]
769
+ else
770
+ #error
771
+ color = colors[:comment]
772
+ end
773
+ when /^\*{3} /, /^\*{15} /
774
+ state = :comment
775
+ redo
776
+ when /^\+ /
777
+ color = colors[:new]
778
+ check = $diff.highlight_whitespace
779
+ when /^- /
780
+ color = colors[:old]
781
+ check = $diff.highlight_whitespace
782
+ when /^! /
783
+ color = colors[:changed]
784
+ check = $diff.highlight_whitespace
785
+ when /^ /
786
+ color = colors[:unchanged]
787
+ else
788
+ # error
789
+ color = colors[:comment]
790
+ end
791
+ if check
792
+ line.sub!(/^(...*)([ \t]+)$/) {
793
+ $1 + colors[:off] + colors[:whitespace] + $2
794
+ }
795
+ end
796
+ end
797
+ end
798
+
799
+ line.sub!(/^/, color)
800
+ line.sub!(/$/, colors[:off])
801
+
802
+ print line
803
+ }
804
+
805
+ io.close
806
+ end
807
+
597
808
  main(ARGV)
data/di.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{di}
8
- s.version = "0.1.4"
8
+ s.version = "0.1.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Akinori MUSHA"]
@@ -36,6 +36,7 @@ default settings and some original features.
36
36
  s.homepage = %q{http://github.com/knu/di}
37
37
  s.rdoc_options = ["--charset=UTF-8"]
38
38
  s.require_paths = ["lib"]
39
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
39
40
  s.rubygems_version = %q{1.3.6}
40
41
  s.summary = %q{A wrapper around GNU diff(1)}
41
42
  s.test_files = [
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 4
9
- version: 0.1.4
8
+ - 5
9
+ version: 0.1.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Akinori MUSHA
@@ -67,8 +67,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  segments:
70
- - 0
71
- version: "0"
70
+ - 1
71
+ - 8
72
+ - 7
73
+ version: 1.8.7
72
74
  required_rubygems_version: !ruby/object:Gem::Requirement
73
75
  requirements:
74
76
  - - ">="