use crate::{
core::{MarkBank, ModeStack, RegisterBank, SpecialMark, YankType},
mm::{BufferId, Position},
};
use super::context::KernelContext;
#[derive(Debug, Clone)]
pub struct KernelStateSnapshot {
pub buffer_count: usize,
pub buffer_ids: Vec<BufferId>,
pub event_handlers: usize,
pub event_queue_len: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum YankTypeSnapshot {
Characterwise,
Linewise,
}
impl From<YankType> for YankTypeSnapshot {
fn from(yt: YankType) -> Self {
match yt {
YankType::Characterwise => Self::Characterwise,
YankType::Linewise => Self::Linewise,
}
}
}
#[derive(Debug, Clone)]
pub struct RegisterSnapshot {
pub name: char,
pub text: String,
pub yank_type: YankTypeSnapshot,
}
#[derive(Debug, Clone)]
pub struct RegistersSnapshot {
pub unnamed: RegisterSnapshot,
pub named: Vec<RegisterSnapshot>,
}
#[derive(Debug, Clone)]
pub struct MarkSnapshot {
pub name: String,
pub position: Position,
pub buffer_id: Option<BufferId>,
}
#[derive(Debug, Clone)]
pub struct MarksSnapshot {
pub local: Vec<MarkSnapshot>,
pub global: Vec<MarkSnapshot>,
pub special: Vec<MarkSnapshot>,
}
#[derive(Debug, Clone)]
pub struct ModeStackSnapshot {
pub current: String,
pub stack: Vec<String>,
pub depth: usize,
}
#[must_use]
pub fn snapshot_kernel_state(ctx: &KernelContext) -> KernelStateSnapshot {
let buffer_ids = ctx.buffers.list();
let buffer_count = buffer_ids.len();
KernelStateSnapshot {
buffer_count,
buffer_ids,
event_handlers: ctx.event_bus.total_handler_count(),
event_queue_len: ctx.event_bus.queue_len(),
}
}
#[must_use]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn snapshot_registers(bank: &RegisterBank) -> RegistersSnapshot {
let unnamed_content = bank.get();
let unnamed = RegisterSnapshot {
name: '"',
text: unnamed_content.text.clone(),
yank_type: unnamed_content.yank_type.into(),
};
let mut named = Vec::new();
for c in 'a'..='z' {
if let Some(content) = bank.get_named(c)
&& !content.text.is_empty()
{
named.push(RegisterSnapshot {
name: c,
text: content.text.clone(),
yank_type: content.yank_type.into(),
});
}
}
RegistersSnapshot { unnamed, named }
}
#[must_use]
pub fn snapshot_marks(bank: &MarkBank) -> MarksSnapshot {
let local: Vec<MarkSnapshot> = bank
.list_local()
.into_iter()
.map(|(name, pos)| MarkSnapshot {
name: name.to_string(),
position: pos,
buffer_id: None,
})
.collect();
let global: Vec<MarkSnapshot> = bank
.list_global()
.into_iter()
.map(|(name, mark)| MarkSnapshot {
name: name.to_string(),
position: mark.position,
buffer_id: Some(mark.buffer_id),
})
.collect();
let special_marks = [
(SpecialMark::LastJump, "'"),
(SpecialMark::LastEdit, "."),
(SpecialMark::LastInsert, "^"),
(SpecialMark::VisualStart, "<"),
(SpecialMark::VisualEnd, ">"),
(SpecialMark::LastExitInsert, "]"),
];
let special: Vec<MarkSnapshot> = special_marks
.iter()
.filter_map(|(mark_type, name)| {
bank.get_special(*mark_type).map(|mark| MarkSnapshot {
name: (*name).to_string(),
position: mark.position,
buffer_id: Some(mark.buffer_id),
})
})
.collect();
MarksSnapshot {
local,
global,
special,
}
}
#[must_use]
pub fn snapshot_mode_stack(stack: &ModeStack) -> ModeStackSnapshot {
let current = stack.current().to_string();
let depth = stack.depth();
let stack_vec: Vec<String> = stack.as_slice().iter().map(ToString::to_string).collect();
ModeStackSnapshot {
current,
stack: stack_vec,
depth,
}
}