Now that you know everything about writing visualizers, it might be worth
having a look at the code of the built-in visualizers,
fdbg_show/2
and fdbg_label_show/3
.
fdbg_show(Constraint, Actions) :- fdbg_annotate(Constraint, Actions, AnnotC, CVars), print(fdbg_output, AnnotC), nl(fdbg_output), fdbg_legend(CVars, Actions), nl(fdbg_output). fdbg_label_show(start, I, Var) :- fdbg_annotate(Var, AVar, _), ( AVar = fdvar(Name, _, Set) -> fdset_to_range(Set, Range), format(fdbg_output, 'Labeling [~p, <~p>]: starting in range ~p.~n', [I,Name,Range]) ; format(fdbg_output, 'Labeling [~p, <>]: starting.~n', [I]) ). fdbg_label_show(fail, I, Var) :- ( var(Var) -> lookup_or_set_name(Var, Name), format(fdbg_output, 'Labeling [~p, <~p>]: failed.~n~n', [I,Name]) ; format(fdbg_output, 'Labeling [~p, <>]: failed.~n~n', [I]) ). fdbg_label_show(step(Step), I, Var) :- ( var(Var) -> lookup_or_set_name(Var, Name), format(fdbg_output, 'Labeling [~p, <~p>]: ~p~n~n', [I,Name,Step]) ; format(fdbg_output, 'Labeling [~p, <>]: ~p~n~n', [I,Step]) ). lookup_or_set_name(Term, Name) :- fdbg_get_name(Term, Name), !. lookup_or_set_name(Term, Name) :- fdbg_assign_name(Term, Name).
As you can see, they are quite simple, thanks to the extensive set of support predicates also available to the user.