<commit_before>:- module(
  dot,
  [
    dot_hash/2, % +Term, -Hash
    dot_node/3, % +Out, +Id, +Label
    graphviz/3, % +Method, -ProcIn, +Format
    graphviz/4  % +Method, -ProcIn, +Format, -ProcOut
  ]
).

/** <module> DOT

@author <NAME>
@version 2017/08-2017/09
*/

:- use_module(library(call_ext)).
:- use_module(library(debug)).
:- use_module(library(hash_ext)).
:- use_module(library(process)).

:- discontiguous
    output_format/1,
    output_format/2.





%! dot_hash(@Term, -Hash:atom) is det.
%
% GraphViz-friendly hash.

dot_hash(Term, Hash2) :-
  md5(Term, Hash1),
  atomic_concat(n, Hash1, Hash2).



%! dot_node(+Out:stream, +Id:atom, +Label:string) is det.

dot_node(Out, Id, Label) :-
  format(Out, '  ~a [label=<~s>];\n', [Id,Label]),
  debug(dot, '  ~a [label=<~s>];\n', [Id,Label]).



%! graphviz(+Method:atom, -ProcIn:stream, +Format:atom) is det.

graphviz(Method, ProcIn, Format) :-
  call_must_be(method, Method),
  call_must_be(output_format_none, Format),
  process_create(path(Method), ['-T',Format], [stdin(pipe(ProcIn))]).

output_format_none(Format) :-
  output_format(Format, none).



%! graphviz(+Method:atom, -ProcIn:stream, +Format:atom,
%!          -ProcOut:stream) is det.
%
% @arg Method The algorithm used by GraphViz for positioning the tree
%             nodes.
%
% @arg Format The file type of the GraphViz output file.
%
% @type_error if Method is not a value of method/1.
%
% @type_error if Format is not a value of output_format/1.

graphviz(Method, ProcIn, Format, ProcOut) :-
  call_must_be(method, Method),
  call_must_be(output_format_not_none, Format),
  output_format(Format, Type),<commit_msg>ENHANCED: Allow arbitrary DOT attributes to be set on nodes.<commit_after>:- module(
  dot,
  [
    dot_hash/2, % +Term, -Hash
    dot_node/3, % +Out, +Id, +Options
    graphviz/3, % +Method, -ProcIn, +Format
    graphviz/4  % +Method, -ProcIn, +Format, -ProcOut
  ]
).

/** <module> DOT

@author <NAME>
@version 2017/08-2017/09
*/

:- use_module(library(call_ext)).
:- use_module(library(debug)).
:- use_module(library(hash_ext)).
:- use_module(library(option)).
:- use_module(library(process)).

:- discontiguous
    output_format/1,
    output_format/2.





%! dot_hash(@Term, -Hash:atom) is det.
%
% GraphViz-friendly hash.

dot_hash(Term, Hash2) :-
  md5(Term, Hash1),
  atomic_concat(n, Hash1, Hash2).



%! dot_node(+Out:stream, +Id:atom, +Options:list(compound)) is det.
%
% The following Options are supported:
%
%   * label(+string)
%
%     Is printed as a DOT HTML label to allow Unicode characters.
%
%   * Other options are written as DOT attributes.

dot_node(Out, Id, Options1) :-
  maplist(dot_attribute, Options1, Options2),
  atomic_list_concat(Options2, ',', Options3),
  format(Out, '  ~a [~a];\n', [Id,Options3]),
  debug(dot, '  ~a [~a];\n', [Id,Options3]).

dot_attribute(Option, Atom) :-
  Option =.. [Name,Value],
  dot_attribute(Name, Value, Atom).

dot_attribute(label, Value, Atom) :- !,
  format(atom(Atom), 'label=<~a>', [Value]).
dot_attribute(Name, Value, Atom) :-
  format(atom(Atom), '~a="~a"', [Name,Value]).



%! graphviz(+Method:atom, -ProcIn:stream, +Format:atom) is det.

graphviz(Method, ProcIn, Format) :-
  call_must_be(method, Method),
  call_must_be(output_format_none, Format),
  process_create(path(Method), ['-T',Format], [stdin(pipe(ProcIn))]).

output_format_none(Format) :-
  output_format(Format, none).



%! graphviz(+Method:atom, -ProcIn:stream, +Format:atom,
%!          -ProcOut:stream) is det.
%
% @arg Method The algorithm used by GraphViz for positioning the tree
%             nodes.
%
% @arg Format The file type of the GraphViz output file.
%
% @type_error if Method is not a value of method/1.
%
% @type_error if Format is not a value of output_format/1.

graphviz(Method, ProcIn, Format, ProcOut) :-
  call_must_be(method, Method),
  call_must_be(output_format_not_none, Format),
  output_format(Format, Type),
{'fraction_non_alphanumeric': 0.16938359653591442, 'fraction_numerical': 0.014518593988792664, 'mean_word_length': 4.160315374507228, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3175532', 'n_tokens_mistral': 1546, 'n_tokens_neox': 1473, 'n_words': 327}