use ropey::Rope;
use super::{highlighter::DiagnosticSet, indent::TabSize, text_wrapper::TextWrapper};
#[derive(Clone)]
pub(crate) enum InputMode {
PlainText { tab: TabSize, rows: usize },
AutoGrow {
rows: usize,
min_rows: usize,
max_rows: usize,
},
CodeEditor {
tab: TabSize,
rows: usize,
line_number: bool,
indent_guides: bool,
diagnostics: DiagnosticSet,
},
}
impl Default for InputMode {
fn default() -> Self {
InputMode::plain_text()
}
}
#[allow(unused)]
impl InputMode {
pub(super) fn plain_text() -> Self {
InputMode::PlainText {
tab: TabSize::default(),
rows: 1,
}
}
pub(super) fn code_editor() -> Self {
InputMode::CodeEditor {
rows: 2,
tab: TabSize::default(),
line_number: true,
indent_guides: true,
diagnostics: DiagnosticSet::new(&Rope::new()),
}
}
pub(super) fn auto_grow(min_rows: usize, max_rows: usize) -> Self {
InputMode::AutoGrow {
rows: min_rows,
min_rows,
max_rows,
}
}
#[inline]
pub(super) fn is_code_editor(&self) -> bool {
matches!(self, InputMode::CodeEditor { .. })
}
#[inline]
pub(super) fn is_auto_grow(&self) -> bool {
matches!(self, InputMode::AutoGrow { .. })
}
#[inline]
pub(super) fn is_multi_line(&self) -> bool {
true
}
pub(super) fn set_rows(&mut self, new_rows: usize) {
match self {
InputMode::PlainText { rows, .. } => {
*rows = new_rows;
}
InputMode::CodeEditor { rows, .. } => {
*rows = new_rows;
}
InputMode::AutoGrow {
rows,
min_rows,
max_rows,
} => {
*rows = new_rows.clamp(*min_rows, *max_rows);
}
}
}
pub(super) fn update_auto_grow(&mut self, text_wrapper: &TextWrapper) {
let wrapped_lines = text_wrapper.len();
self.set_rows(wrapped_lines);
}
pub(super) fn rows(&self) -> usize {
match self {
InputMode::PlainText { rows, .. } => *rows,
InputMode::CodeEditor { rows, .. } => *rows,
InputMode::AutoGrow { rows, .. } => *rows,
}
.max(1)
}
#[allow(unused)]
pub(super) fn min_rows(&self) -> usize {
match self {
InputMode::AutoGrow { min_rows, .. } => *min_rows,
_ => 1,
}
.max(1)
}
#[allow(unused)]
pub(super) fn max_rows(&self) -> usize {
match self {
InputMode::AutoGrow { max_rows, .. } => *max_rows,
_ => usize::MAX,
}
}
#[allow(unused)]
#[inline]
pub(super) fn line_number(&self) -> bool {
match self {
InputMode::CodeEditor { line_number, .. } => *line_number,
_ => false,
}
}
#[allow(unused)]
pub(super) fn diagnostics(&self) -> Option<&DiagnosticSet> {
match self {
InputMode::CodeEditor { diagnostics, .. } => Some(diagnostics),
_ => None,
}
}
pub(super) fn diagnostics_mut(&mut self) -> Option<&mut DiagnosticSet> {
match self {
InputMode::CodeEditor { diagnostics, .. } => Some(diagnostics),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use crate::widgets::editor::{TabSize, mode::InputMode};
#[test]
fn test_code_editor() {
let mode = InputMode::code_editor();
assert!(mode.is_code_editor());
assert!(mode.is_multi_line());
assert!(mode.line_number());
assert!(mode.has_indent_guides());
assert_eq!(mode.max_rows(), usize::MAX);
assert_eq!(mode.min_rows(), 1);
}
#[test]
fn test_plain() {
let mode = InputMode::PlainText {
tab: TabSize::default(),
rows: 5,
};
assert!(!mode.is_code_editor());
assert!(mode.is_multi_line());
assert!(!mode.line_number());
assert_eq!(mode.rows(), 5);
assert_eq!(mode.max_rows(), usize::MAX);
assert_eq!(mode.min_rows(), 1);
let mode = InputMode::plain_text();
assert!(!mode.is_code_editor());
assert!(mode.is_multi_line());
assert!(!mode.line_number());
assert_eq!(mode.max_rows(), usize::MAX);
assert_eq!(mode.min_rows(), 1);
}
#[test]
fn test_auto_grow() {
let mut mode = InputMode::auto_grow(2, 5);
assert!(!mode.is_code_editor());
assert!(mode.is_multi_line());
assert!(!mode.line_number());
assert_eq!(mode.rows(), 2);
assert_eq!(mode.max_rows(), 5);
assert_eq!(mode.min_rows(), 2);
mode.set_rows(4);
assert_eq!(mode.rows(), 4);
mode.set_rows(1);
assert_eq!(mode.rows(), 2);
mode.set_rows(10);
assert_eq!(mode.rows(), 5);
}
}