forge_fmt/pp/
convenience.rs1use super::{BeginToken, BreakToken, Breaks, IndentStyle, Printer, SIZE_INFINITY, Token};
2use std::borrow::Cow;
3
4impl Printer {
5 pub fn rbox(&mut self, indent: isize, breaks: Breaks) {
7 self.scan_begin(BeginToken { indent: IndentStyle::Block { offset: indent }, breaks });
8 }
9
10 pub fn ibox(&mut self, indent: isize) {
12 self.rbox(indent, Breaks::Inconsistent);
13 }
14
15 pub fn cbox(&mut self, indent: isize) {
17 self.rbox(indent, Breaks::Consistent);
18 }
19
20 pub fn visual_align(&mut self) {
21 self.scan_begin(BeginToken { indent: IndentStyle::Visual, breaks: Breaks::Consistent });
22 }
23
24 pub fn break_offset(&mut self, n: usize, off: isize) {
25 self.scan_break(BreakToken { offset: off, blank_space: n, ..BreakToken::default() });
26 }
27
28 pub fn end(&mut self) {
29 self.scan_end();
30 }
31
32 pub fn eof(mut self) -> String {
33 self.scan_eof();
34 self.out
35 }
36
37 pub fn word(&mut self, w: impl Into<Cow<'static, str>>) {
38 self.scan_string(w.into());
39 }
40
41 fn spaces(&mut self, n: usize) {
42 self.break_offset(n, 0);
43 }
44
45 pub fn zerobreak(&mut self) {
46 self.spaces(0);
47 }
48
49 pub fn space(&mut self) {
50 self.spaces(1);
51 }
52
53 pub fn hardbreak(&mut self) {
54 self.spaces(SIZE_INFINITY as usize);
55 }
56
57 pub fn last_token_is_neverbreak(&self) -> bool {
58 if let Some(token) = self.last_token() {
59 return token.is_neverbreak();
60 }
61
62 false
63 }
64
65 pub fn last_token_is_break(&self) -> bool {
66 if let Some(token) = self.last_token() {
67 return matches!(token, Token::Break(_));
68 }
69 false
70 }
71
72 pub fn last_token_is_space(&self) -> bool {
73 if let Some(token) = self.last_token()
74 && token.is_space()
75 {
76 return true;
77 }
78
79 self.out.ends_with(" ")
80 }
81
82 pub fn is_beginning_of_line(&self) -> bool {
83 match self.last_token() {
84 Some(last_token) => last_token.is_hardbreak(),
85 None => self.out.is_empty() || self.out.ends_with('\n'),
86 }
87 }
88
89 pub fn is_bol_or_only_ind(&self) -> bool {
95 for i in self.buf.index_range().rev() {
96 let token = &self.buf[i].token;
97 if token.is_hardbreak() {
98 return true;
99 }
100 if Self::token_has_non_whitespace_content(token) {
101 return false;
102 }
103 }
104
105 let last_line =
106 if let Some(pos) = self.out.rfind('\n') { &self.out[pos + 1..] } else { &self.out[..] };
107
108 last_line.trim().is_empty()
109 }
110
111 fn token_has_non_whitespace_content(token: &Token) -> bool {
112 match token {
113 Token::String(s) => !s.trim().is_empty(),
114 Token::Break(BreakToken { pre_break: Some(s), .. }) => !s.trim().is_empty(),
115 _ => false,
116 }
117 }
118
119 pub(crate) fn hardbreak_tok_offset(offset: isize) -> Token {
120 Token::Break(BreakToken {
121 offset,
122 blank_space: SIZE_INFINITY as usize,
123 ..BreakToken::default()
124 })
125 }
126
127 pub fn hardbreak_if_nonempty(&mut self) {
128 self.scan_break(BreakToken {
129 blank_space: SIZE_INFINITY as usize,
130 if_nonempty: true,
131 ..BreakToken::default()
132 });
133 }
134
135 pub fn neverbreak(&mut self) {
136 self.scan_break(BreakToken { never_break: true, ..BreakToken::default() });
137 }
138}
139
140impl Token {
141 pub(crate) fn is_neverbreak(&self) -> bool {
142 if let Self::Break(BreakToken { never_break, .. }) = *self {
143 return never_break;
144 }
145 false
146 }
147
148 pub(crate) fn is_hardbreak(&self) -> bool {
149 if let Self::Break(BreakToken { blank_space, never_break, .. }) = *self {
150 return blank_space == SIZE_INFINITY as usize && !never_break;
151 }
152 false
153 }
154
155 pub(crate) fn is_space(&self) -> bool {
156 match self {
157 Self::Break(BreakToken { offset, blank_space, .. }) => {
158 *offset == 0 && *blank_space == 1
159 }
160 Self::String(s) => s.ends_with(' '),
161 _ => false,
162 }
163 }
164}