dprint_core/formatting/
conditions.rs

1use std::rc::Rc;
2
3use super::print_items::*;
4use super::*;
5
6pub fn indent_if_start_of_line(items: PrintItems) -> Condition {
7  let rc_path = items.into_rc_path();
8  if_true_or(
9    "indentIfStartOfLine",
10    condition_resolvers::is_start_of_line(),
11    ir_helpers::with_indent(rc_path.into()),
12    rc_path.into(),
13  )
14}
15
16pub fn indent_if_start_of_line_or_start_of_line_indented(items: PrintItems) -> Condition {
17  let rc_path = items.into_rc_path();
18  conditions::if_true_or(
19    "withIndentIfStartOfLineOrStartOfLineIndented",
20    condition_resolvers::is_start_of_line_or_is_start_of_line_indented(),
21    ir_helpers::with_indent(rc_path.into()),
22    rc_path.into(),
23  )
24}
25
26pub fn with_indent_if_start_of_line_indented(items: PrintItems) -> Condition {
27  let rc_path = items.into_rc_path();
28  if_true_or(
29    "withIndentIfStartOfLineIndented",
30    condition_resolvers::is_start_of_line_indented(),
31    ir_helpers::with_indent(rc_path.into()),
32    rc_path.into(),
33  )
34}
35
36pub struct NewLineIfHangingSpaceOtherwiseOptions {
37  pub start_lsil: LineStartIndentLevel,
38  pub end_lsil: Option<LineStartIndentLevel>,
39  pub space_char: Option<PrintItems>,
40}
41
42pub fn new_line_if_hanging_space_otherwise(opts: NewLineIfHangingSpaceOtherwiseOptions) -> Condition {
43  let space_char = opts.space_char.unwrap_or_else(|| " ".into());
44  let start_lsil = opts.start_lsil;
45  let end_lsil = opts.end_lsil;
46
47  if_true_or(
48    "newLineIfHangingSpaceOtherwise",
49    Rc::new(move |context| condition_helpers::is_hanging(context, start_lsil, end_lsil)),
50    Signal::NewLine.into(),
51    space_char,
52  )
53}
54
55pub fn new_line_if_hanging(start_lsil: LineStartIndentLevel, end_lsil: Option<LineStartIndentLevel>) -> Condition {
56  if_true(
57    "newlineIfHanging",
58    Rc::new(move |context| condition_helpers::is_hanging(context, start_lsil, end_lsil)),
59    Signal::NewLine.into(),
60  )
61}
62
63pub fn new_line_if_multiple_lines_space_or_new_line_otherwise(start_ln: LineNumber, end_ln: Option<LineNumber>) -> Condition {
64  if_true_or(
65    "newLineIfMultipleLinesSpaceOrNewLineOtherwise",
66    Rc::new(move |context| {
67      let start_ln = context.resolved_line_number(start_ln)?;
68      let end_ln = {
69        if let Some(end_ln) = end_ln {
70          context.resolved_line_number(end_ln)?
71        } else {
72          context.writer_info.line_number
73        }
74      };
75
76      Some(end_ln > start_ln)
77    }),
78    Signal::NewLine.into(),
79    Signal::SpaceOrNewLine.into(),
80  )
81}
82
83pub fn single_indent_if_start_of_line() -> Condition {
84  if_true(
85    "singleIndentIfStartOfLine",
86    condition_resolvers::is_start_of_line(),
87    Signal::SingleIndent.into(),
88  )
89}
90
91/// Prints the provided items when the current relative column number is above
92/// the specified width.
93pub fn if_above_width(width: u8, items: PrintItems) -> Condition {
94  if_above_width_or(width, items, PrintItems::new())
95}
96
97/// Prints the provided true_items when the current relative column number is above
98/// the specified width or prints the false_items otherwise.
99pub fn if_above_width_or(width: u8, true_items: PrintItems, false_items: PrintItems) -> Condition {
100  Condition::new(
101    "ifAboveWidth",
102    ConditionProperties {
103      condition: Rc::new(move |context| {
104        let writer_info = &context.writer_info;
105        let first_indent_col = writer_info.line_start_column_number() + (width as u32);
106        Some(writer_info.column_number > first_indent_col)
107      }),
108      true_path: Some(true_items),
109      false_path: if false_items.is_empty() { None } else { Some(false_items) },
110    },
111  )
112}
113
114pub fn if_true(name: &'static str, resolver: ConditionResolver, true_path: PrintItems) -> Condition {
115  Condition::new(
116    name,
117    ConditionProperties {
118      true_path: Some(true_path),
119      false_path: None,
120      condition: resolver,
121    },
122  )
123}
124
125pub fn if_true_or(name: &'static str, resolver: ConditionResolver, true_path: PrintItems, false_path: PrintItems) -> Condition {
126  Condition::new(
127    name,
128    ConditionProperties {
129      true_path: Some(true_path),
130      false_path: Some(false_path),
131      condition: resolver,
132    },
133  )
134}
135
136pub fn if_false(name: &'static str, resolver: ConditionResolver, false_path: PrintItems) -> Condition {
137  Condition::new(
138    name,
139    ConditionProperties {
140      true_path: None,
141      false_path: Some(false_path),
142      condition: resolver,
143    },
144  )
145}