~cdv/cedv

89954bea7d909d4f30362198624bc8de7265ddd5 — Chris Vittal 5 months ago 42d5892
Add tracking of buffer modification
1 files changed, 61 insertions(+), 23 deletions(-)

M src/main.rs
M src/main.rs => src/main.rs +61 -23
@@ 67,6 67,9 @@ struct Editor {

    #[allow(unused)]
    suppress: bool,
    modified: bool,
    quitting: bool,
    new_edit: bool,
}

impl Editor {


@@ 74,7 77,12 @@ impl Editor {
    fn run(&mut self) {
        let mut line = String::new();
        match self.read_line(&mut line) {
            Ok(0) => throw!(Error::Quit),
            Ok(0) => if !self.modified || self.quitting {
                throw!(Error::Quit)
            } else {
                self.quitting = true;
                throw!(Error::ModifiedWarning)
            },
            Ok(_) => {}
            Err(e) => throw!(Error::Io(e.into())),
        }


@@ 101,25 109,37 @@ impl Editor {
        self.addrs(addr)?;

        match kind {
            Delete(cmd::Delete { start, delim, end }) => {
                let start = self.resolve(start, delim)?;
                let end = self.resolve(end, Delim::End)?;
                if start == 0 || end == 0 {
                    throw!(Error::InvalidAddress);
            Edit { path, force } => {
                self.quitting = false;
                if have_addrs {
                    throw!(Error::UnexpectedAddress)
                } else if !self.modified || force || self.new_edit {
                    return self.edit(path)?;
                } else {
                    self.new_edit = true;
                    throw!(Error::ModifiedWarning);
                }

                let start_idx = self.text.line_to_char(start - 1);
                let end_idx = self.text.line_to_char(end);
                self.text.remove(start_idx..end_idx);
                self.line = self.text.char_to_line(start_idx) + 1;
            }
            Edit { path, .. } => {
            Quit { force } => {
                self.new_edit = false;
                if have_addrs {
                    throw!(Error::UnexpectedAddress)
                    throw!(Error::UnexpectedAddress);
                } else if !self.modified || force || self.quitting {
                    throw!(Error::Quit);
                } else {
                    self.quitting = true;
                    throw!(Error::ModifiedWarning);
                }

                self.edit(path)?;
            }
            _ => {
                self.new_edit = false;
                self.quitting = false;
            },
        }

        match kind {
            Quit { .. } | Edit { .. } => unreachable!(),

            File { path } => {
                if have_addrs {
                    throw!(Error::UnexpectedAddress)


@@ 135,13 155,6 @@ impl Editor {
                    throw!(Error::NoFilename);
                }
            }
            Quit { .. } => {
                if have_addrs {
                    throw!(Error::UnexpectedAddress)
                } else {
                    throw!(Error::Quit)
                }
            }

            SimpleInput { addr, append } => {
                self.resolve(addr, Delim::Semi)?;


@@ 151,6 164,19 @@ impl Editor {
                    self.insert()?;
                }
            }
            Delete(cmd::Delete { start, delim, end }) => {
                let start = self.resolve(start, delim)?;
                let end = self.resolve(end, Delim::End)?;
                if start == 0 || end == 0 {
                    throw!(Error::InvalidAddress);
                }

                let start_idx = self.text.line_to_char(start - 1);
                let end_idx = self.text.line_to_char(end);
                self.text.remove(start_idx..end_idx);
                self.line = self.text.char_to_line(start_idx) + 1;
            }

            Null { addr } => {
                let line = self.resolve(addr, Delim::End)?;
                if line == 0 {


@@ 163,7 189,6 @@ impl Editor {
                let line = self.resolve(addr, Delim::End)?;
                println!("{}", line);
            }

            Print(cmd::Print { start, delim, end }) => {
                let start = self.resolve(start, delim)?;
                let end = self.resolve(end, Delim::Semi)?;


@@ 267,6 292,7 @@ impl Editor {
        let mut input = String::new();

        while read_input_line(&mut stdin, &mut input)? {
            self.modified = true;
            let start = self.text.line_to_char(self.line);
            self.text.insert(start, &input);
            self.line += 1;


@@ 279,6 305,7 @@ impl Editor {
        if !read_input_line(&mut io::stdin().lock(), &mut input)? {
            return;
        }
        self.modified = true;
        self.line = self.line.saturating_sub(1);
        let start = self.text.line_to_char(self.line);
        self.text.insert(start, &input);


@@ 322,6 349,8 @@ impl Editor {
            self.text = text;
            self.line = self.text.len_lines() - 1;
            self.prev_line = self.line;
            self.modified = false;
            self.new_edit = false;
            println!("{}", self.text.len_bytes());
        } else {
            throw!(Error::NoFilename);


@@ 376,6 405,9 @@ impl Editor {
        }
        wtr.flush()?;
        println!("{}", text.len_bytes());
        if text.len_bytes() == self.text.len_bytes() {
            self.modified = false;
        }
    }

    #[throws(Box<dyn std::error::Error>)]


@@ 438,7 470,11 @@ impl EditorBuilder {
            text: Rope::new(),
            line: 0,
            prev_line: 0,

            suppress: self.suppress,
            modified: false,
            quitting: false,
            new_edit: false,
        }
    }



@@ 483,6 519,7 @@ enum Error {
    InvalidAddress,
    NoFilename,
    Quit,
    ModifiedWarning,
    UnexpectedAddress,
    Unimplemented(char),
    Unknown(char),


@@ 502,6 539,7 @@ impl fmt::Display for Error {
        match self {
            Self::InvalidAddress => f.pad("invalid address"),
            Self::NoFilename => f.pad("no current filename"),
            Self::ModifiedWarning => f.pad("warning - buffer modified"),
            Self::Quit => f.pad("quit"), // should never be called
            Self::UnexpectedAddress => f.pad("unexpected address"),
            Self::Unimplemented(c) => write!(f, "'{}' command not implemented yet", c),