Skip to content

Commit

Permalink
Use colored diff output by default. Fix printing.
Browse files Browse the repository at this point in the history
  • Loading branch information
rvantonder authored Jun 6, 2019
1 parent 716c8f1 commit 7d789a5
Show file tree
Hide file tree
Showing 11 changed files with 465 additions and 83 deletions.
2 changes: 1 addition & 1 deletion lib/match/match.mli
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ val pp_json_pretty : Format.formatter -> string option * t list -> unit

val pp_json_lines : Format.formatter -> string option * t list -> unit

val pp_match_result : Format.formatter -> string option * t list -> unit
val pp_match_count : Format.formatter -> string option * t list -> unit
2 changes: 1 addition & 1 deletion lib/match/match_context.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ let pp_json_pretty ppf (source_path, matches) =
let pp_json_lines ppf (source_path, matches) =
Format.fprintf ppf "%s" @@ yojson_to_string `Lines @@ to_json source_path matches

let pp_match_result ppf (source_path, matches) =
let pp_match_count ppf (source_path, matches) =
let pp_source_path ppf source_path =
match source_path with
| Some path -> Format.fprintf ppf " in %s " path
Expand Down
44 changes: 40 additions & 4 deletions lib/replacement/diff_configuration.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,51 @@ open Patdiff_lib

open Configuration

(* This is the default patdiff configuration. *)
let default =
sprintf
{|;; -*- scheme -*-
;; patdiff Configuration file

(
(context 16)

(line_same
((prefix ((text " |") (style ((bg bright_black) (fg black)))))))

(line_old
((prefix ((text "-|") (style ((bg red)(fg black)))))
(style ((fg red)))
(word_same (dim))))

(line_new
((prefix ((text "+|") (style ((bg green)(fg black)))))
(style ((fg green)))))

(line_unified
((prefix ((text "!|") (style ((bg yellow)(fg black)))))))

(header_old
((prefix ((text "------ ") (style ((fg red)))))
(style (bold))))

(header_new
((prefix ((text "++++++ ") (style ((fg green)))))
(style (bold))))

(hunk
((prefix ((text "@|") (style ((bg bright_black) (fg black)))))
(suffix ((text " ============================================================") (style ())))
(style (bold))))
)|}

let terminal () =
Config.t_of_sexp (Sexp.of_string default)
|> parse

(* Needs (unrefined true), otherwise it just prints without colors. Unrefined true
will diff on a line basis. line_unified is ignored for unrefined, but
will still create a prefix width of 2 in the diff if it is "!|" *)
let plain_configuration =
{|;; -*- scheme -*-
;; patdiff Configuration file
Expand All @@ -28,9 +68,6 @@ let plain_configuration =
((prefix ((text "+") (style ())))
(style ())))

(line_unified
((prefix ((text "!|") (style ())))))

(header_old
((prefix ((text "--- ") (style ())))
(style ())))
Expand All @@ -39,7 +76,6 @@ let plain_configuration =
((prefix ((text "+++ ") (style ())))
(style ())))


(hunk
((prefix ((text "@@ ") (style ())))
(suffix ((text " @@") (style ())))
Expand Down
29 changes: 2 additions & 27 deletions lib/replacement/replacement.ml
Original file line number Diff line number Diff line change
Expand Up @@ -40,38 +40,13 @@ let to_json replacements path diff result =
; ("diff", diff)
]

let get_diff source_path source_content result =
let open Patdiff_lib in
let source_path =
match source_path with
| Some path -> path
| None -> "/dev/null"
in
let configuration = Diff_configuration.plain () in
let prev = Patdiff_core.{ name = source_path; text = source_content } in
let next = Patdiff_core.{ name = source_path; text = result } in
Compare_core.diff_strings
~print_global_header:true
configuration
~prev
~next
|> function
| `Different diff -> Some diff
| `Same -> None

let yojson_to_string kind json =
match kind with
| `Pretty -> Yojson.Safe.pretty_to_string json
| `Lines -> Yojson.Safe.to_string json

let pp_json_pretty ppf (source_path, source_content, replacements, replacement_content) =
let diff = get_diff source_path source_content replacement_content in
let pp_json_pretty ppf (source_path, replacements, replacement_content, diff) =
Format.fprintf ppf "%s" @@ yojson_to_string `Pretty @@ to_json replacements source_path diff replacement_content

let pp_json_lines ppf (source_path, source_content, replacements, replacement_content) =
let diff = get_diff source_path source_content replacement_content in
let pp_json_line ppf (source_path, replacements, replacement_content, diff) =
Format.fprintf ppf "%s" @@ Yojson.Safe.to_string @@ to_json replacements source_path diff replacement_content

let pp_diff ppf (source_path, source_content, replacement_content) =
let diff = get_diff source_path source_content replacement_content in
Option.value_map diff ~default:() ~f:(fun diff -> Format.fprintf ppf "%s@." diff)
6 changes: 2 additions & 4 deletions lib/replacement/replacement.mli
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ type result =

val empty_result : result

val pp_json_pretty : Format.formatter -> string option * string * t list * string -> unit
val pp_json_pretty : Format.formatter -> string option * t list * string * string option -> unit

val pp_json_lines : Format.formatter -> string option * string * t list * string -> unit

val pp_diff : Format.formatter -> string option * string * string -> unit
val pp_json_line : Format.formatter -> string option * t list * string * string option -> unit
102 changes: 76 additions & 26 deletions src/command_configuration.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ let parse_source_directories ?(file_extensions = []) target_directory =
ls_rec target_directory

type output_options =
{ json_pretty : bool
{ color : bool
; json_pretty : bool
; json_lines : bool
; in_place : bool
; diff : bool
; stdout : bool
; count : bool
}

type anonymous_arguments =
Expand Down Expand Up @@ -109,84 +111,116 @@ module Printer = struct

module Match : sig

type match_only_kind =
| Colored
| Count

type match_output =
| Json_lines
| Json_pretty
| Diff
| Number_of_matches
| Match_only of match_only_kind

val convert : output_options -> match_output

val print : match_output -> string option -> Match.t list -> unit

end = struct

type match_only_kind =
| Colored
| Count

type match_output =
| Json_lines
| Json_pretty
| Diff
| Number_of_matches
| Match_only of match_only_kind

let convert output_options =
match output_options with
| { json_pretty = true; json_lines = true; _ }
| { json_pretty = true; json_lines = false; _ } -> Json_pretty
| { json_pretty = false; json_lines = true; _ } -> Json_lines
| _ -> Number_of_matches
| { count = true; _ } -> Match_only Count
| _ -> Match_only Colored

let print (match_output : match_output) source_path matches =
let ppf = Format.std_formatter in
match match_output with
| Json_lines -> Format.fprintf ppf "%a" Match.pp_json_lines (source_path, matches)
| Json_pretty -> Format.fprintf ppf "%a" Match.pp_json_pretty (source_path, matches)
| Number_of_matches -> Format.fprintf ppf "%a" Match.pp_match_result (source_path, matches)
| Diff -> assert false
| Match_only _ -> Format.fprintf ppf "%a" Match.pp_match_count (source_path, matches)

end

module Rewrite : sig

type diff_kind =
| Plain
| Colored

type replacement_output =
| In_place
| Stdout
| Json_lines
| Json_pretty
| Diff
| Diff of diff_kind
| Match_only

val convert : output_options -> replacement_output


val print : replacement_output -> string option -> Replacement.t list -> string -> string -> unit

end = struct

type diff_kind =
| Plain
| Colored

type replacement_output =
| In_place
| Stdout
| Json_lines
| Json_pretty
| Diff
| Diff of diff_kind
| Match_only

let convert output_options : replacement_output =
match output_options with
| { json_pretty = false; json_lines = false; stdout = false; in_place = true; _ } -> In_place
| { in_place = true; _ } -> In_place
| { json_pretty = true; in_place = false; _ } -> Json_pretty
| { json_lines = true; in_place = false; _ } -> Json_lines
| { diff = true; _ } -> Diff
| { stdout = true; _ } -> Stdout
| _ -> Diff
| { diff = true; color = false; _ } -> Diff Plain
| { color = true; _ }
| _ -> Diff Colored

let print replacement_output path replacements replacement_content source_content =
let ppf = Format.std_formatter in
match path, replacement_output with
| Some path, In_place -> Out_channel.write_all path ~data:replacement_content
| _, Stdout -> Format.fprintf ppf "%s" replacement_content
| Some path, Json_pretty ->
Format.fprintf ppf "%a" Replacement.pp_json_pretty (Some path, source_content, replacements, replacement_content)
| Some path, Json_lines -> Format.fprintf ppf "%a" Replacement.pp_json_lines (Some path, source_content, replacements, replacement_content)
| None, Json_pretty -> Format.fprintf ppf "%a" Replacement.pp_json_pretty (path, source_content, replacements, replacement_content)
| None, Json_lines -> Format.fprintf ppf "%a" Replacement.pp_json_lines (path, source_content, replacements, replacement_content)
| Some in_, Diff -> Format.fprintf ppf "%a" Replacement.pp_diff (Some in_, source_content, replacement_content)
| None, _ -> Format.printf "%s" replacement_content
match replacement_output with
| Stdout ->
Format.fprintf ppf "%s" replacement_content
| Json_pretty ->
let diff = Diff_configuration.get_diff Plain path source_content replacement_content in
let print diff = Format.fprintf ppf "%a@." Replacement.pp_json_pretty (path, replacements, replacement_content, diff) in
Option.value_map diff ~default:() ~f:(fun diff -> print (Some diff))
| Json_lines ->
let diff = Diff_configuration.get_diff Plain path source_content replacement_content in
let print diff = Format.fprintf ppf "%a@." Replacement.pp_json_line (path, replacements, replacement_content, diff) in
Option.value_map diff ~default:() ~f:(fun diff -> print (Some diff))
| Diff Plain ->
let diff = Diff_configuration.get_diff Plain path source_content replacement_content in
Option.value_map diff ~default:() ~f:(fun diff -> Format.fprintf ppf "%s@." diff)
| Diff Colored ->
let diff = Diff_configuration.get_diff Colored path source_content replacement_content in
Option.value_map diff ~default:() ~f:(fun diff -> Format.fprintf ppf "%s@." diff)
| Match_only ->
let diff = Diff_configuration.get_diff Match_only path replacement_content source_content in
Option.value_map diff ~default:() ~f:(fun diff -> Format.fprintf ppf "%s@." diff)
| In_place ->
match path with
| Some path -> Out_channel.write_all path ~data:replacement_content
(* This should be impossible since we checked in validate_errors. Leaving the code path explicit. *)
| None -> failwith "Error: could not write to file."
end
end

Expand Down Expand Up @@ -255,6 +289,14 @@ let emit_warnings { input_options; output_options; _ } =
and rewrite templates on the command line and only using those in directories."
; output_options.json_lines = true && output_options.json_pretty = true,
"Both -json-lines and -json-pretty specified. Using -json-pretty."
; output_options.color
&& (output_options.stdout
|| output_options.json_pretty
|| output_options.json_lines
|| output_options.in_place)
, "-color only works with -diff or -match-only"
; output_options.count && not input_options.match_only
, "-count only works with -match-only. Ignoring -count."
]
in
List.iter warn_on ~f:(function
Expand Down Expand Up @@ -282,6 +324,7 @@ let create
}
; output_options =
({ in_place
; color
; _
} as output_options)
} as configuration)
Expand All @@ -293,7 +336,11 @@ let create
match specification_directories, anonymous_arguments with
| None, Some { match_template; rewrite_template; _ } ->
if match_only then
[ Specification.create ~match_template ~match_rule:rule () ]
if color then
(* Fake a replacement with empty to get a nice colored match output. More expensive though. *)
[ Specification.create ~match_template ~match_rule:rule ~rewrite_template:"" () ]
else
[ Specification.create ~match_template ~match_rule:rule () ]
else
[ Specification.create ~match_template ~rewrite_template ~match_rule:rule ~rewrite_rule:rule () ]
| Some specification_directories, _ ->
Expand Down Expand Up @@ -330,7 +377,10 @@ let create
| Replacements { source_path; replacements; result; source_content } ->
Printer.Rewrite.convert output_options
|> fun replacement_output ->
Printer.Rewrite.print replacement_output source_path replacements result source_content
if match_only && color then
Printer.Rewrite.print Match_only source_path replacements result source_content
else
Printer.Rewrite.print replacement_output source_path replacements result source_content
in
return
{ sources
Expand Down
4 changes: 3 additions & 1 deletion src/command_configuration.mli
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ end


type output_options =
{ json_pretty : bool
{ color : bool
; json_pretty : bool
; json_lines : bool
; in_place : bool
; diff : bool
; stdout : bool
; count : bool
}

type anonymous_arguments =
Expand Down
Loading

0 comments on commit 7d789a5

Please sign in to comment.