use std::cell::{Cell, RefCell};
use std::rc::Rc;
use std::fmt::Debug;
use crate::{Result, EdError};
use crate::history::Snapshot;
pub mod iters;
use iters::*;
#[derive(Debug, PartialEq, Eq)]
pub struct Line {
pub(crate) matched: Rc<RefCell<Vec<bool>>>,
pub tag: Rc<Cell<char>>,
pub text: Rc<String>,
}
impl Line {
pub (crate) fn new<T: Into<String>>(text: T, tag: char) -> Self {
Self{
matched: Rc::new(RefCell::new(Vec::new())),
tag: Rc::new(Cell::new(tag)),
text: Rc::new(text.into()),
}
}
}
impl Snapshot for Line {
fn create_snapshot(&self) -> Self {
Line{
tag: self.tag.clone(),
matched: self.matched.clone(),
text: self.text.clone(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PubLine {
pub tag: char,
pub text: Rc<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Clipboard {
inner: Vec<PubLine>,
}
impl Clipboard {
pub fn new() -> Self {
Self{ inner: Vec::new() }
}
}
impl std::ops::Deref for Clipboard {
type Target = Vec<PubLine>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl std::ops::DerefMut for Clipboard {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl From<&str> for PubLine {
fn from(l: &str) -> Self {
Self{tag: '\0', text: Rc::new(l.to_owned())}
}
}
impl From<(char, &str)> for PubLine {
fn from(l: (char, &str)) -> Self {
Self{tag: l.0, text: Rc::new(l.1.to_owned())}
}
}
impl From<&Line> for PubLine {
fn from(l: &Line) -> Self {
Self{tag: l.tag.get(), text: l.text.clone()}
}
}
impl<'a, T> From<&'a [T]> for Clipboard
where
&'a T: Into<PubLine>,
{
fn from(l: &'a [T]) -> Self {
let mut tmp = Vec::new();
for line in l {
tmp.push(line.into());
}
Self{
inner: tmp,
}
}
}
impl From<&PubLine> for Line {
fn from(l: &PubLine) -> Self {
Self{
tag: Rc::new(Cell::new(l.tag)),
text: l.text.clone(),
matched: Rc::new(RefCell::new(Vec::new())),
}
}
}
impl From<&str> for Line {
fn from(l: &str) -> Self {
Self{
tag: Rc::new(Cell::new('\0')),
text: Rc::new(l.to_owned()),
matched: Rc::new(RefCell::new(Vec::new())),
}
}
}
impl Into<Vec<Line>> for &Clipboard {
fn into(self) -> Vec<Line> {
let mut tmp = Vec::new();
for line in &self.inner {
tmp.push(line.into());
}
tmp
}
}
#[derive(Debug, PartialEq)]
pub struct Buffer {
pub inner: Vec<Line>,
}
impl std::ops::Deref for Buffer {
type Target = Vec<Line>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl std::ops::DerefMut for Buffer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl Snapshot for Buffer {
fn create_snapshot(&self) -> Self {
let mut new_inner = Vec::new();
for line in self.inner.iter() {
new_inner.push(line.create_snapshot());
}
Self{ inner: new_inner }
}
}
impl Default for Buffer {
fn default() -> Self{ Self{ inner: Vec::new() } }
}
impl Buffer {
pub fn verify_index(
&self,
index: usize,
) -> Result<()> {
let buffer_len = self.len();
if index > buffer_len {
Err(EdError::IndexTooBig{index, buffer_len})
} else {
Ok(())
}
}
pub fn verify_line(
&self,
index: usize,
) -> Result<()> {
if index == 0 { Err(EdError::Line0Invalid) }
else { self.verify_index(index) }
}
pub fn verify_selection(
&self,
selection: (usize, usize),
) -> Result<()> {
self.verify_line(selection.0)?;
self.verify_line(selection.1)?;
if selection.0 > selection.1 {
Err(EdError::SelectionEmpty(selection))
} else {
Ok(())
}
}
pub fn get_lines(
&self,
selection: (usize, usize),
) -> Result<LinesIter> {
self.verify_selection(selection)?;
Ok(self[selection.0 - 1 .. selection.1]
.iter()
.map(get_lines_helper as fn(&Line) -> &str)
.into()
)
}
pub fn get_tagged_lines(
&self,
selection: (usize, usize),
) -> Result<TaggedLinesIter> {
self.verify_selection(selection)?;
Ok(self[selection.0 - 1 .. selection.1]
.iter()
.map(get_tagged_lines_helper as fn(&Line) -> (char, &str))
.into()
)
}
}
fn get_lines_helper(line: &Line) -> &str {
&line.text[..]
}
fn get_tagged_lines_helper(line: &Line) -> (char, &str) {
(line.tag.get(), &line.text[..])
}