Skip to content

Commit

Permalink
add dirty flag check, quit confirmation
Browse files Browse the repository at this point in the history
  • Loading branch information
artem-streltsov committed Feb 16, 2024
1 parent cc79e8b commit 79facfe
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
22 changes: 15 additions & 7 deletions src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use std::io::{Error, Write};
#[derive(Default)]
pub struct Document {
rows: Vec<Row>,
pub file_name: Option<String>
pub file_name: Option<String>,
dirty: bool
}

impl Document {
Expand All @@ -18,7 +19,8 @@ impl Document {
}
Ok(Self {
rows,
file_name: Some(filename.to_string())
file_name: Some(filename.to_string()),
dirty: false
})
}
pub fn row(&self, index: usize) -> Option<&Row> {
Expand All @@ -31,6 +33,10 @@ impl Document {
self.rows.len()
}
pub fn insert(&mut self, at: &Position, c: char) {
if at.y > self.len() {
return;
}
self.dirty = true;
if c == '\n' {
self.insert_newline(at);
return;
Expand All @@ -39,7 +45,7 @@ impl Document {
let mut row = Row::default();
row.insert(0, c);
self.rows.push(row);
} else if at.y < self.len() {
} else {
let row = self.rows.get_mut(at.y).unwrap();
row.insert(at.x, c);
}
Expand All @@ -49,6 +55,7 @@ impl Document {
if at.y >= len {
return;
}
self.dirty = true;

if at.x == self.rows.get_mut(at.y).unwrap().len() && at.y < len - 1 {
let next_row = self.rows.remove(at.y + 1);
Expand All @@ -60,24 +67,25 @@ impl Document {
}
}
fn insert_newline(&mut self, at: &Position) {
if at.y > self.len() {
return;
}
if at.y == self.len() {
self.rows.push(Row::default());
return;
}
let new_row = self.rows.get_mut(at.y).unwrap().split(at.x);
self.rows.insert(at.y + 1, new_row);
}
pub fn save(&self) -> Result<(), Error> {
pub fn save(&mut self) -> Result<(), Error> {
if let Some(file_name) = &self.file_name {
let mut file = fs::File::create(file_name)?;
for row in &self.rows {
file.write_all(row.as_bytes())?;
file.write_all(b"\n")?;
}
self.dirty = false;
}
Ok(())
}
pub fn is_dirty(&self) -> bool {
self.dirty
}
}
37 changes: 33 additions & 4 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::Document;
use crate::Row;
use crate::Terminal;
use std::env;
use std::u8;
use std::usize;
use termion::event::Key;
use termion::color;
Expand All @@ -11,6 +12,7 @@ use std::time::Instant;
const STATUS_FG_COLOR: color::Rgb = color::Rgb(63, 63, 63);
const STATUS_BG_COLOR: color::Rgb = color::Rgb(239, 239, 239);
const VERSION: &str = env!("CARGO_PKG_VERSION");
const QUIT_TIMES: u8 = 3;

#[derive(Default)]
pub struct Position {
Expand Down Expand Up @@ -38,7 +40,8 @@ pub struct Editor {
cursor_position: Position,
document: Document,
offset: Position,
status_message: StatusMessage
status_message: StatusMessage,
quit_times: u8
}

impl Editor {
Expand Down Expand Up @@ -77,7 +80,8 @@ impl Editor {
document,
cursor_position: Position::default(),
offset: Position::default(),
status_message: StatusMessage::from(initial_status)
status_message: StatusMessage::from(initial_status),
quit_times: QUIT_TIMES
}
}

Expand All @@ -102,8 +106,18 @@ impl Editor {
fn process_keypress(&mut self) -> Result<(), std::io::Error> {
let pressed_key = Terminal::read_key()?;
match pressed_key {
Key::Ctrl('q') => self.should_quit = true,
Key::Ctrl('s') => self.save(),
Key::Ctrl('q') => {
if self.quit_times > 0 && self.document.is_dirty() {
self.status_message = StatusMessage::from(format!(
"Warning! File has unsaved changes. Press Ctrl-Q {} more times to quit",
self.quit_times
));
self.quit_times -= 1;
return Ok(());
}
self.should_quit = true
}
Key::Char(c) => {
self.document.insert(&self.cursor_position, c);
self.move_cursor(Key::Right);
Expand All @@ -126,6 +140,10 @@ impl Editor {
_ => ()
}
self.scroll();
if self.quit_times < QUIT_TIMES {
self.quit_times = QUIT_TIMES;
self.status_message = StatusMessage::from(String::new());
}
Ok(())
}
pub fn draw_row(&self, row: &Row) {
Expand Down Expand Up @@ -246,12 +264,23 @@ impl Editor {
fn draw_status_bar(&self) {
let mut status;
let width = self.terminal.size().width as usize;
let modified_indicator = if self.document.is_dirty() {
" (modified)"
} else {
""
};

let mut file_name = "[No Name]".to_string();
if let Some(name) = &self.document.file_name {
file_name = name.clone();
file_name.truncate(20);
}
status = format!("{} - {} lines", file_name, self.document.len());
status = format!(
"{} - {} lines{}",
file_name,
self.document.len(),
modified_indicator
);
status.truncate(width);
let line_indicator = format!(
"{}/{}",
Expand Down

0 comments on commit 79facfe

Please sign in to comment.