Move filepath into the Buffer struct.
This commit is contained in:
parent
4544efb299
commit
e1d91ff43d
|
@ -4,13 +4,13 @@ use std::{
|
|||
cmp::{max, min},
|
||||
collections::HashMap,
|
||||
fs::File,
|
||||
io::{self, BufReader, BufWriter, Write},
|
||||
path::{Path, PathBuf},
|
||||
io::{self, BufWriter, Write},
|
||||
};
|
||||
|
||||
use ropey::Rope;
|
||||
|
||||
use backend::{buffer::Buffer, marks::Mark};
|
||||
use backend::{
|
||||
buffer::{Buffer, BufferPath},
|
||||
marks::Mark,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
formatter::LineFormatter,
|
||||
|
@ -24,7 +24,6 @@ use crate::{
|
|||
pub struct Editor {
|
||||
pub buffer: Buffer,
|
||||
pub formatter: LineFormatter,
|
||||
pub file_path: PathBuf,
|
||||
pub line_ending_type: LineEnding,
|
||||
pub soft_tabs: bool,
|
||||
pub soft_tab_width: u8,
|
||||
|
@ -43,48 +42,18 @@ pub struct Editor {
|
|||
|
||||
impl Editor {
|
||||
/// Create a new blank editor
|
||||
pub fn new(formatter: LineFormatter) -> Editor {
|
||||
let (buffer, v_msi, c_msi) = {
|
||||
let mut buffer = Buffer::new("".into());
|
||||
let view_idx = buffer.add_mark_set();
|
||||
let cursors_idx = buffer.add_mark_set();
|
||||
pub fn new(buffer: Buffer, formatter: LineFormatter) -> Editor {
|
||||
let mut buffer = buffer;
|
||||
|
||||
buffer.mark_sets[view_idx].add_mark(Mark::new(0, 0));
|
||||
buffer.mark_sets[cursors_idx].add_mark(Mark::new(0, 0));
|
||||
|
||||
(buffer, view_idx, cursors_idx)
|
||||
};
|
||||
|
||||
Editor {
|
||||
buffer: buffer,
|
||||
formatter: formatter,
|
||||
file_path: PathBuf::new(),
|
||||
line_ending_type: LineEnding::LF,
|
||||
soft_tabs: false,
|
||||
soft_tab_width: 4,
|
||||
editor_dim: (0, 0),
|
||||
view_dim: (0, 0),
|
||||
v_msi: v_msi,
|
||||
c_msi: c_msi,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_file(formatter: LineFormatter, path: &Path) -> io::Result<Editor> {
|
||||
let (buffer, v_msi, c_msi) = {
|
||||
let mut buffer = Buffer::new(Rope::from_reader(BufReader::new(File::open(path)?))?);
|
||||
let view_idx = buffer.add_mark_set();
|
||||
let cursors_idx = buffer.add_mark_set();
|
||||
|
||||
buffer.mark_sets[view_idx].add_mark(Mark::new(0, 0));
|
||||
buffer.mark_sets[cursors_idx].add_mark(Mark::new(0, 0));
|
||||
|
||||
(buffer, view_idx, cursors_idx)
|
||||
};
|
||||
// Create appropriate mark sets for view positions and cursors.
|
||||
let v_msi = buffer.add_mark_set();
|
||||
let c_msi = buffer.add_mark_set();
|
||||
buffer.mark_sets[v_msi].add_mark(Mark::new(0, 0));
|
||||
buffer.mark_sets[c_msi].add_mark(Mark::new(0, 0));
|
||||
|
||||
let mut ed = Editor {
|
||||
buffer: buffer,
|
||||
formatter: formatter,
|
||||
file_path: path.to_path_buf(),
|
||||
line_ending_type: LineEnding::LF,
|
||||
soft_tabs: false,
|
||||
soft_tab_width: 4,
|
||||
|
@ -97,18 +66,20 @@ impl Editor {
|
|||
ed.auto_detect_line_ending();
|
||||
ed.auto_detect_indentation_style();
|
||||
|
||||
Ok(ed)
|
||||
ed
|
||||
}
|
||||
|
||||
pub fn save_if_dirty(&mut self) -> io::Result<()> {
|
||||
if self.buffer.is_dirty && self.file_path != PathBuf::new() {
|
||||
let mut f = BufWriter::new(File::create(&self.file_path)?);
|
||||
if let BufferPath::File(ref file_path) = self.buffer.path {
|
||||
if self.buffer.is_dirty {
|
||||
let mut f = BufWriter::new(File::create(file_path)?);
|
||||
|
||||
for c in self.buffer.text.chunks() {
|
||||
f.write(c.as_bytes())?;
|
||||
for c in self.buffer.text.chunks() {
|
||||
f.write(c.as_bytes())?;
|
||||
}
|
||||
|
||||
self.buffer.is_dirty = false;
|
||||
}
|
||||
|
||||
self.buffer.is_dirty = false;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,8 +1,13 @@
|
|||
use std::{io::Write, path::Path};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufReader, Write},
|
||||
};
|
||||
|
||||
use backend::buffer::{Buffer, BufferPath};
|
||||
use clap::{App, Arg};
|
||||
use editor::Editor;
|
||||
use formatter::LineFormatter;
|
||||
use ropey::Rope;
|
||||
use term_ui::TermUI;
|
||||
|
||||
mod editor;
|
||||
|
@ -14,7 +19,7 @@ mod utils;
|
|||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
fn main() {
|
||||
fn main() -> std::io::Result<()> {
|
||||
// Parse command line arguments.
|
||||
let args = App::new("Led")
|
||||
.version(VERSION)
|
||||
|
@ -28,13 +33,17 @@ fn main() {
|
|||
.get_matches();
|
||||
|
||||
// Load file, if specified
|
||||
let editor = if let Some(filepath) = args.value_of("file") {
|
||||
Editor::new_from_file(LineFormatter::new(4), &Path::new(&filepath[..]))
|
||||
.expect(&format!("Couldn't open file '{}'.", filepath))
|
||||
let buffer = if let Some(filepath) = args.value_of("file") {
|
||||
Buffer::new(
|
||||
Rope::from_reader(BufReader::new(File::open(filepath)?))?,
|
||||
BufferPath::File(filepath.into()),
|
||||
)
|
||||
} else {
|
||||
Editor::new(LineFormatter::new(4))
|
||||
Buffer::new("".into(), BufferPath::Temp(0))
|
||||
};
|
||||
|
||||
let editor = Editor::new(buffer, LineFormatter::new(4));
|
||||
|
||||
// Holds stderr output in an internal buffer, and prints it when dropped.
|
||||
// This keeps stderr from being swallowed by the TUI.
|
||||
let stderr_hold = gag::Hold::stderr().unwrap();
|
||||
|
@ -58,4 +67,6 @@ fn main() {
|
|||
// Resume panic unwind.
|
||||
std::panic::resume_unwind(e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@ use crossterm::{
|
|||
style::Color,
|
||||
};
|
||||
|
||||
use backend::buffer::BufferPath;
|
||||
|
||||
use crate::{
|
||||
editor::Editor,
|
||||
formatter::LineFormatter,
|
||||
string_utils::{char_count, is_line_ending, line_ending_to_str, LineEnding},
|
||||
utils::{digit_count, Timer},
|
||||
};
|
||||
|
@ -187,10 +188,6 @@ enum LoopStatus {
|
|||
}
|
||||
|
||||
impl TermUI {
|
||||
pub fn new() -> TermUI {
|
||||
TermUI::new_from_editor(Editor::new(LineFormatter::new(4)))
|
||||
}
|
||||
|
||||
pub fn new_from_editor(ed: Editor) -> TermUI {
|
||||
let (w, h) = crossterm::terminal::size().unwrap();
|
||||
let mut editor = ed;
|
||||
|
@ -463,7 +460,10 @@ impl TermUI {
|
|||
}
|
||||
|
||||
// Filename and dirty marker
|
||||
let filename = editor.file_path.display();
|
||||
let filename = match editor.buffer.path {
|
||||
BufferPath::File(ref p) => format!("{}", p.display()),
|
||||
BufferPath::Temp(i) => format!("Scratch #{}", i + 1),
|
||||
};
|
||||
let dirty_char = if editor.buffer.is_dirty { "*" } else { "" };
|
||||
let name = format!("{}{}", filename, dirty_char);
|
||||
self.screen.draw(c1.1 + 1, c1.0, &name[..], STYLE_INFO);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use ropey::Rope;
|
||||
|
||||
use crate::{
|
||||
|
@ -5,9 +7,20 @@ use crate::{
|
|||
marks::MarkSet,
|
||||
};
|
||||
|
||||
/// A path for an open text buffer.
|
||||
///
|
||||
/// This indicates where the text data of the buffer came from, and
|
||||
/// where it should be saved to.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum BufferPath {
|
||||
File(PathBuf), // A buffer for a normal file on disk.
|
||||
Temp(usize), // A temporary buffer, with a number ID.
|
||||
}
|
||||
|
||||
/// An open text buffer, currently being edited.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Buffer {
|
||||
pub path: BufferPath,
|
||||
pub is_dirty: bool, // Is this buffer currently out of sync with disk.
|
||||
pub text: Rope, // The actual text content.
|
||||
pub mark_sets: Vec<MarkSet>, // MarkSets for cursors, view positions, etc.
|
||||
|
@ -15,8 +28,9 @@ pub struct Buffer {
|
|||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn new(text: Rope) -> Buffer {
|
||||
pub fn new(text: Rope, path: BufferPath) -> Buffer {
|
||||
Buffer {
|
||||
path: path,
|
||||
is_dirty: false,
|
||||
text: text,
|
||||
mark_sets: Vec::new(),
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::buffer::Buffer;
|
||||
|
||||
/// A struct holding the current editor state.
|
||||
|
@ -7,12 +5,5 @@ use crate::buffer::Buffer;
|
|||
/// The Editor represents all currently open buffers available for editing.
|
||||
#[derive(Debug)]
|
||||
pub struct Editor {
|
||||
open_buffers: Vec<(BufferID, Buffer)>,
|
||||
}
|
||||
|
||||
/// An ID for an open text buffer.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BufferID {
|
||||
File(PathBuf), // A buffer for a normal file on disk, using the full on-disk path as the ID
|
||||
Temp(usize), // A temporary buffer, with a number ID
|
||||
open_buffers: Vec<Buffer>,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user