Skip to content

Commit

Permalink
make Indentation::add_capture associative with always capture types
Browse files Browse the repository at this point in the history
  • Loading branch information
dead10ck committed Jun 19, 2023
1 parent 66104de commit f28077d
Showing 1 changed file with 130 additions and 8 deletions.
138 changes: 130 additions & 8 deletions helix-core/src/indent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,47 +240,60 @@ fn get_first_in_line(mut node: Node, new_line_byte_pos: Option<usize>) -> Vec<bo
/// This is usually constructed in one of 2 ways:
/// - Successively add indent captures to get the (added) indent from a single line
/// - Successively add the indent results for each line
#[derive(Default, Debug)]
#[derive(Default, Debug, PartialEq, Clone)]
pub struct Indentation {
/// The total indent (the number of indent levels) is defined as max(0, indent-outdent).
/// The string that this results in depends on the indent style (spaces or tabs, etc.)
indent: usize,
indent_always: usize,
outdent: usize,
outdent_always: usize,
}
impl Indentation {
/// Add some other [Indentation] to this.
/// The added indent should be the total added indent from one line
fn add_line(&mut self, added: &Indentation) {
self.indent += added.indent;
self.indent_always += added.indent_always;
self.outdent += added.outdent;
self.outdent_always += added.outdent_always;
}

/// Add an indent capture to this indent.
/// All the captures that are added in this way should be on the same line.
fn add_capture(&mut self, added: IndentCaptureType) {
fn add_capture(&mut self, added: IndentCaptureType) -> &mut Self {
match added {
IndentCaptureType::Indent => {
if self.indent == 0 {
if self.indent_always == 0 {
self.indent = 1;
}
}
IndentCaptureType::IndentAlways => {
self.indent += 1;
// any time we encounter an `indent.always` on the same line, we
// want to cancel out all regular indents
self.indent_always += 1;
self.indent = 0;
}
IndentCaptureType::Outdent => {
if self.outdent == 0 {
if self.outdent_always == 0 {
self.outdent = 1;
}
}
IndentCaptureType::OutdentAlways => {
self.outdent += 1;
self.outdent_always += 1;
self.outdent = 0;
}
}

self
}

fn as_string(&self, indent_style: &IndentStyle) -> String {
let indent_level = if self.indent >= self.outdent {
self.indent - self.outdent
let indent = self.indent_always + self.indent;
let outdent = self.outdent_always + self.outdent;

let indent_level = if indent >= outdent {
indent - outdent
} else {
log::warn!("Encountered more outdent than indent nodes while calculating indentation: {} outdent, {} indent", self.outdent, self.indent);
0
Expand Down Expand Up @@ -865,4 +878,113 @@ mod test {
3
);
}

#[test]
fn add_capture() {
let indent = || Indentation {
indent: 1,
..Default::default()
};
let indent_always = || Indentation {
indent_always: 1,
..Default::default()
};
let outdent = || Indentation {
outdent: 1,
..Default::default()
};
let outdent_always = || Indentation {
outdent_always: 1,
..Default::default()
};

// adding an indent to no indent makes an indent
assert_eq!(
indent(),
*Indentation::default().add_capture(IndentCaptureType::Indent)
);
assert_eq!(
indent_always(),
*Indentation::default().add_capture(IndentCaptureType::IndentAlways)
);
assert_eq!(
outdent(),
*Indentation::default().add_capture(IndentCaptureType::Outdent)
);
assert_eq!(
outdent_always(),
*Indentation::default().add_capture(IndentCaptureType::OutdentAlways)
);

// adding an indent to an already indented has no effect
assert_eq!(indent(), *indent().add_capture(IndentCaptureType::Indent));
assert_eq!(
outdent(),
*outdent().add_capture(IndentCaptureType::Outdent)
);

// adding an always to a regular makes it always
assert_eq!(
indent_always(),
*indent().add_capture(IndentCaptureType::IndentAlways)
);
assert_eq!(
outdent_always(),
*outdent().add_capture(IndentCaptureType::OutdentAlways)
);

// adding an always to an always is additive
assert_eq!(
Indentation {
indent_always: 2,
..Default::default()
},
*indent_always().add_capture(IndentCaptureType::IndentAlways)
);
assert_eq!(
Indentation {
outdent_always: 2,
..Default::default()
},
*outdent_always().add_capture(IndentCaptureType::OutdentAlways)
);

// adding regular to always should be associative
assert_eq!(
Indentation {
indent_always: 1,
..Default::default()
},
*indent()
.add_capture(IndentCaptureType::Indent)
.add_capture(IndentCaptureType::IndentAlways)
);
assert_eq!(
Indentation {
indent_always: 1,
..Default::default()
},
*indent()
.add_capture(IndentCaptureType::IndentAlways)
.add_capture(IndentCaptureType::Indent)
);
assert_eq!(
Indentation {
outdent_always: 1,
..Default::default()
},
*outdent()
.add_capture(IndentCaptureType::Outdent)
.add_capture(IndentCaptureType::OutdentAlways)
);
assert_eq!(
Indentation {
outdent_always: 1,
..Default::default()
},
*outdent()
.add_capture(IndentCaptureType::OutdentAlways)
.add_capture(IndentCaptureType::Outdent)
);
}
}

0 comments on commit f28077d

Please sign in to comment.