1#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2pub enum IndentType {
3 Spaces,
4 Tabs,
5}
6
7#[derive(Debug, Clone)]
8pub struct IndentOptions {
9 width: usize,
10 indent_string: String,
11 split_line_attributes: bool,
12}
13
14impl IndentOptions {
15 pub fn new(typ: IndentType, width: usize, split_line_attributes: bool) -> Self {
16 assert_ne!(width, 0, "Cannot have an indent width of 0");
17 Self {
18 width,
19 indent_string: match typ {
20 IndentType::Tabs => "\t".into(),
21 IndentType::Spaces => " ".repeat(width),
22 },
23 split_line_attributes,
24 }
25 }
26
27 pub fn indent_str(&self) -> &str {
29 &self.indent_string
30 }
31
32 pub fn line_length(&self, line: &str) -> usize {
34 line.chars()
35 .map(|ch| if ch == '\t' { self.width } else { 1 })
36 .sum()
37 }
38
39 pub fn count_indents(&self, mut line: &str) -> usize {
41 let mut indent = 0;
42 while !line.is_empty() {
43 let num_tabs = line.chars().take_while(|ch| *ch == '\t').count();
45 if num_tabs > 0 {
46 indent += num_tabs;
47 line = &line[num_tabs..];
48 continue;
49 }
50
51 let num_spaces = line.chars().take_while(|ch| *ch == ' ').count();
53 if num_spaces >= self.width {
54 let num_space_indents = num_spaces / self.width;
56 indent += num_space_indents;
57 line = &line[num_space_indents * self.width..];
58 continue;
59 }
60
61 break;
64 }
65 indent
66 }
67
68 pub fn split_line_attributes(&self) -> bool {
69 self.split_line_attributes
70 }
71}
72
73impl Default for IndentOptions {
74 fn default() -> Self {
75 Self::new(IndentType::Spaces, 4, false)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn count_indents() {
85 assert_eq!(
86 IndentOptions::new(IndentType::Spaces, 4, false).count_indents("no indentation here!"),
87 0
88 );
89 assert_eq!(
90 IndentOptions::new(IndentType::Spaces, 4, false).count_indents(" v += 2"),
91 1
92 );
93 assert_eq!(
94 IndentOptions::new(IndentType::Spaces, 4, false).count_indents(" v += 2"),
95 2
96 );
97 assert_eq!(
98 IndentOptions::new(IndentType::Spaces, 4, false).count_indents(" v += 2"),
99 2
100 );
101 assert_eq!(
102 IndentOptions::new(IndentType::Spaces, 4, false).count_indents("\t\tv += 2"),
103 2
104 );
105 assert_eq!(
106 IndentOptions::new(IndentType::Spaces, 4, false).count_indents("\t\t v += 2"),
107 2
108 );
109 assert_eq!(
110 IndentOptions::new(IndentType::Spaces, 2, false).count_indents(" v += 2"),
111 2
112 );
113 }
114}