pub mod editor;
pub mod render;
use std::collections::HashMap;
use crossterm::event::KeyEvent;
use ratatui::style::Color;
use ratatui::text::Span;
pub use editor::VimEditor;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VimMode {
Normal,
Insert,
Replace,
Visual(VisualKind),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CursorShape {
Block,
Bar,
Underline,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VisualKind {
Char,
Line,
Block,
}
#[derive(Debug, Clone)]
pub struct VimModeConfig {
pub insert_allowed: bool,
pub visual_allowed: bool,
}
impl Default for VimModeConfig {
fn default() -> Self {
Self {
insert_allowed: true,
visual_allowed: true,
}
}
}
impl VimModeConfig {
pub fn read_only() -> Self {
Self {
insert_allowed: false,
visual_allowed: true,
}
}
}
pub enum EditorAction {
Handled,
Unhandled(KeyEvent),
Save,
Close,
ForceClose,
SaveAndClose,
ToggleComment,
ToggleBlockComment { start_row: usize, end_row: usize },
GoToDefinition,
Hover,
}
pub const LEADER_KEY: char = ' ';
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operator {
Delete,
Yank,
Change,
Indent,
Dedent,
Uppercase,
Lowercase,
ToggleCase,
}
#[derive(Debug, Clone)]
pub struct MotionRange {
pub start_row: usize,
pub start_col: usize,
pub end_row: usize,
pub end_col: usize,
pub linewise: bool,
}
#[derive(Debug, Clone)]
pub struct Snapshot {
pub lines: Vec<String>,
pub cursor_row: usize,
pub cursor_col: usize,
}
#[derive(Debug, Clone, Default)]
pub struct Register {
pub content: String,
pub linewise: bool,
}
#[derive(Debug, Clone)]
pub struct SearchState {
pub pattern: String,
pub forward: bool,
pub active: bool,
pub input_buffer: String,
}
impl Default for SearchState {
fn default() -> Self {
Self {
pattern: String::new(),
forward: true,
active: false,
input_buffer: String::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct EditRecord {
pub keys: Vec<KeyEvent>,
}
#[derive(Debug, Clone)]
pub struct BlockInsertState {
pub start_row: usize,
pub end_row: usize,
pub col: usize,
}
#[derive(Debug, Clone)]
pub struct YankHighlight {
pub start_row: usize,
pub start_col: usize,
pub end_row: usize,
pub end_col: usize,
pub linewise: bool,
pub created_at: std::time::Instant,
}
impl YankHighlight {
const DURATION_MS: u128 = 150;
pub fn is_expired(&self) -> bool {
self.created_at.elapsed().as_millis() > Self::DURATION_MS
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GutterSign {
Added,
Modified,
DeletedAbove,
DeletedBelow,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DiagnosticSeverity {
Error,
Warning,
}
#[derive(Debug, Clone)]
pub struct Diagnostic {
pub severity: DiagnosticSeverity,
pub message: Option<String>,
}
#[derive(Debug, Clone)]
pub struct GutterConfig {
pub signs: HashMap<usize, GutterSign>,
pub diagnostics: HashMap<usize, Diagnostic>,
pub sign_added: Color,
pub sign_modified: Color,
pub sign_deleted: Color,
pub sign_error: Color,
pub sign_warning: Color,
}
impl Default for GutterConfig {
fn default() -> Self {
Self {
signs: HashMap::new(),
diagnostics: HashMap::new(),
sign_added: Color::Green,
sign_modified: Color::Yellow,
sign_deleted: Color::Red,
sign_error: Color::Red,
sign_warning: Color::Yellow,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FindDirection {
Forward,
Backward,
}
#[derive(Debug, Clone)]
pub struct VimTheme {
pub border_focused: Color,
pub border_unfocused: Color,
pub border_insert: Color,
pub editor_bg: Color,
pub line_nr: Color,
pub line_nr_active: Color,
pub visual_bg: Color,
pub visual_fg: Color,
pub dim: Color,
pub accent: Color,
pub search_match_bg: Color,
pub search_current_bg: Color,
pub search_match_fg: Color,
pub yank_highlight_bg: Color,
pub substitute_preview_bg: Color,
pub match_bracket_bg: Color,
pub match_bracket_fg: Color,
}
pub trait SyntaxHighlighter {
fn highlight_line<'a>(&self, line: &'a str, spans: &mut Vec<Span<'a>>);
fn highlight_segment<'a>(&self, text: &'a str, spans: &mut Vec<Span<'a>>) {
self.highlight_line(text, spans);
}
}
pub struct PlainHighlighter;
impl SyntaxHighlighter for PlainHighlighter {
fn highlight_line<'a>(&self, line: &'a str, spans: &mut Vec<Span<'a>>) {
if !line.is_empty() {
spans.push(Span::raw(line));
}
}
}
pub const SCROLLOFF: usize = 3;