diff --git a/.gitignore b/.gitignore index 3099d3e..061a5ce 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,6 @@ nativecode lambda_example simple_example test_easy_format - +easy_format_example.html +easy_format_example.ml +ocamldoc diff --git a/easy_format.ml b/easy_format.ml index 785c099..24e6a28 100644 --- a/easy_format.ml +++ b/easy_format.ml @@ -1,12 +1,20 @@ open Format -type wrap = - [ `Wrap_atoms - | `Always_wrap - | `Never_wrap - | `Force_breaks - | `Force_breaks_rec - | `No_breaks ] +type wrap = [ + | `Wrap_atoms + | `Always_wrap + | `Never_wrap + | `Force_breaks + | `Force_breaks_rec + | `No_breaks +] + +type label_break = [ + | `Auto + | `Always + | `Always_rec + | `Never +] type style_name = string type style = { @@ -57,12 +65,14 @@ let list = { } type label_param = { + label_break: label_break; space_after_label : bool; indent_after_label : int; label_style : style_name option; } let label = { + label_break = `Auto; space_after_label = true; indent_after_label = 2; label_style = None; @@ -118,12 +128,13 @@ let propagate_from_leaf_to_root has the attribute wrap_body = `Force_breaks_rec. *) let propagate_forced_breaks x = - (* acc = whether to force breaks in wrappable lists *) + (* acc = whether to force breaks in wrappable lists or labels *) let init_acc = function + | List ((_, _, _, { wrap_body = `Force_breaks_rec }), _) + | Label ((_, { label_break = `Always_rec }), _) -> true | Atom _ | Label _ - | Custom _ -> false - | List ((_, _, _, { wrap_body = `Force_breaks_rec }), _) -> true + | Custom _ | List _ -> false in let merge_acc force_breaks1 force_breaks2 = @@ -144,9 +155,16 @@ let propagate_forced_breaks x = else x, false + | Label ((a, ({ label_break = `Auto } as lp)), b) -> + if force_breaks then + let lp = { lp with label_break = `Always } in + Label ((a, lp), b), true + else + x, false + | List ((_, _, _, { wrap_body = `No_breaks }), _) + | Label ((_, { label_break = (`Always | `Always_rec | `Never) }), _) | Atom _ - | Label _ | Custom _ -> x, force_breaks in let new_x, forced_breaks = @@ -492,10 +510,22 @@ struct fprint_t fmt lab; close_tag fmt lp.label_style; - if lp.space_after_label then - pp_print_break fmt 1 indent - else - pp_print_break fmt 0 indent; + (match lp.label_break with + | `Auto -> + if lp.space_after_label then + pp_print_break fmt 1 indent + else + pp_print_break fmt 0 indent + | `Always + | `Always_rec -> + pp_force_newline fmt (); + pp_print_string fmt (String.make indent ' ') + | `Never -> + if lp.space_after_label then + pp_print_char fmt ' ' + else + () + ); fprint_t fmt x; pp_close_box fmt () @@ -620,12 +650,14 @@ struct } let label_true = { + label_break = `Auto; space_after_label = true; indent_after_label = 2; label_style = None; } let label_false = { + label_break = `Auto; space_after_label = false; indent_after_label = 2; label_style = None; diff --git a/easy_format.mli b/easy_format.mli index ce706a6..0aeb629 100644 --- a/easy_format.mli +++ b/easy_format.mli @@ -39,6 +39,19 @@ type wrap = i.e. never break line between list items *) +type label_break = [ + | `Auto + | `Always + | `Always_rec + | `Never +] +(** When to break the line after a [Label]: + - [Auto]: break after the label if there's not enough room + - [Always]: always break after the label + - [Always_rec]: always break after the label and force breaks in all parent + lists and labels, similarly to [`Force_breaks_rec] for lists. + - [Never]: never break after the label +*) type style_name = string @@ -116,14 +129,22 @@ val list : list_param See {!Easy_format.label}. *) type label_param = { - space_after_label : bool; (** Whether there must be some whitespace - after the label. - Default: [true] *) - indent_after_label : int; (** Extra indentation before the item - that comes after a label. - Default: [2] - *) - label_style : style_name option; (** Default: [None] *) + label_break: label_break; + (** Whether to break the line after the label. + Introduced in version 1.2.0. + Default: [`Auto] *) + + space_after_label : bool; + (** Whether there must be some whitespace after the label. + Default: [true] *) + + indent_after_label : int; + (** Extra indentation before the item that comes after a label. + Default: [2] + *) + + label_style : style_name option; + (** Default: [None] *) } val label : label_param diff --git a/simple_example.ml b/simple_example.ml index 4febdfb..56abc67 100644 --- a/simple_example.ml +++ b/simple_example.ml @@ -126,18 +126,18 @@ let format_function_definition (body_label, body_param) name param body = Illustrate the difference between `Force_break and `Force_breaks_rec on labels. *) -let labelOneAtom = Atom ("reallyLongLabelOne", atom) -let labelTwoAtom = Atom ("reallyLongLabelTwo", atom) -let labelThreeAtom = Atom ("reallyLongLabelABC", atom) +let label_one_atom = Atom ("reallyLongLabelOne", atom) +let label_two_atom = Atom ("reallyLongLabelTwo", atom) +let label_three_atom = Atom ("reallyLongLabelABC", atom) let make_list_in_labels (wrap) = Label ( - (labelOneAtom, label), + (label_one_atom, label), ( Label ( - (labelTwoAtom, label), + (label_two_atom, label), ( Label ( - (labelThreeAtom, label), + (label_three_atom, label), List ( ("[", ",", "]", { list with wrap_body = wrap }), [ @@ -152,6 +152,7 @@ let make_list_in_labels (wrap) = ) ) ) + (* Illustrate the difference between `Force_break and `Force_breaks_rec *)