Better opening and editing
This commit is contained in:
parent
32589dab6d
commit
ac1232164e
5 changed files with 51 additions and 28 deletions
|
|
@ -24,6 +24,8 @@ struct Args {
|
|||
pub enum Error {
|
||||
#[error("io: {0}")]
|
||||
Io(#[from] io::Error),
|
||||
#[error("no such buffer")]
|
||||
NoSuchBuffer,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
|
|
|
|||
69
src/state.rs
69
src/state.rs
|
|
@ -179,28 +179,31 @@ impl Change {
|
|||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn from_file(path: PathBuf) -> Result<Self, Error> {
|
||||
let (unsaved, chars, s) = match std::fs::read_to_string(&path) {
|
||||
Ok(s) => (false, s.chars().collect(), s),
|
||||
// If the file doesn't exist, create a new file
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => (true, Vec::new(), String::new()),
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
pub fn new(unsaved: bool, chars: Vec<char>, path: PathBuf) -> Self {
|
||||
let lang = LangPack::from_file_name(&path);
|
||||
Ok(Self {
|
||||
Self {
|
||||
unsaved,
|
||||
diverged: false,
|
||||
highlights: lang.highlighter.highlight(&chars),
|
||||
lang,
|
||||
text: Text { chars },
|
||||
cursors: HopSlotMap::default(),
|
||||
path: Some(path.canonicalize()?),
|
||||
path: Some(path),
|
||||
undo: Vec::new(),
|
||||
redo: Vec::new(),
|
||||
opened_at: Some(SystemTime::now()),
|
||||
action_counter: 0,
|
||||
most_recent_rank: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(path: PathBuf) -> Result<Self, Error> {
|
||||
let path = path.canonicalize()?;
|
||||
let (unsaved, chars) = match std::fs::read_to_string(&path) {
|
||||
Ok(s) => (false, s.chars().collect()),
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
Ok(Self::new(unsaved, chars, path))
|
||||
}
|
||||
|
||||
pub fn save(&mut self) -> Result<(), Error> {
|
||||
|
|
@ -871,13 +874,12 @@ impl Buffer {
|
|||
if let Some(path) = &self.path {
|
||||
let stale = std::fs::metadata(path)
|
||||
.and_then(|m| m.modified())
|
||||
.ok()
|
||||
.and_then(|lm| Some(lm > self.opened_at?));
|
||||
.map(|lm| lm > self.opened_at.expect("state buffer must have open time"));
|
||||
match (stale, self.unsaved) {
|
||||
(Some(false), _) => {}
|
||||
(Some(true), true) => self.diverged = true,
|
||||
(Some(true), false) => self.reload(),
|
||||
(None, _) => self.diverged = true,
|
||||
(Ok(false), _) => {}
|
||||
(Ok(true), true) => self.diverged = true,
|
||||
(Ok(true), false) => self.reload(),
|
||||
(Err(_), _) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -914,7 +916,7 @@ impl TryFrom<Args> for State {
|
|||
this.buffers.insert(Buffer::default());
|
||||
} else {
|
||||
for path in args.paths {
|
||||
this.buffers.insert(Buffer::from_file(path)?);
|
||||
this.create(path)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -923,16 +925,35 @@ impl TryFrom<Args> for State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
pub fn create_file(&mut self, path: PathBuf) -> Result<BufferId, Error> {
|
||||
self.open_or_get(path.clone())
|
||||
.or_else(|_| Ok(self.buffers.insert(Buffer::from_file(path)?)))
|
||||
}
|
||||
|
||||
pub fn open_or_get(&mut self, path: PathBuf) -> Result<BufferId, Error> {
|
||||
pub fn get(&self, path: PathBuf) -> Result<BufferId, Error> {
|
||||
if let Some((buffer_id, _)) = self.buffers.iter().find(|(_, b)| b.is_same_path(&path)) {
|
||||
Ok(buffer_id)
|
||||
} else {
|
||||
Ok(self.buffers.insert(Buffer::from_file(path)?))
|
||||
Err(Error::NoSuchBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&mut self, path: PathBuf) -> Result<BufferId, Error> {
|
||||
match self.get(path.clone()) {
|
||||
Ok(id) => Ok(id),
|
||||
Err(Error::NoSuchBuffer) => Ok(self.buffers.insert(Buffer::open(path)?)),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(&mut self, path: PathBuf) -> Result<BufferId, Error> {
|
||||
match self.open(path.clone()) {
|
||||
Ok(id) => Ok(id),
|
||||
// If the file was not found, create a new file
|
||||
Err(Error::Io(err)) if err.kind() == io::ErrorKind::NotFound => {
|
||||
let path = if path.has_root() {
|
||||
path
|
||||
} else {
|
||||
std::env::current_dir()?.join(path)
|
||||
};
|
||||
Ok(self.buffers.insert(Buffer::new(true, Vec::new(), path)))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ impl Element for Doc {
|
|||
self.switch_buffer(state, new_buffer);
|
||||
Ok(Resp::handled(None))
|
||||
}
|
||||
Some(Action::OpenFile(path, line_idx)) => match state.open_or_get(path) {
|
||||
Some(Action::OpenFile(path, line_idx)) => match state.open(path) {
|
||||
Ok(buffer_id) => {
|
||||
self.switch_buffer(state, buffer_id);
|
||||
if let Some(buffer) = state.buffers.get_mut(self.buffer) {
|
||||
|
|
@ -120,7 +120,7 @@ impl Element for Doc {
|
|||
Action::Show(Some(format!("Could not open file")), format!("{err}")).into(),
|
||||
))),
|
||||
},
|
||||
Some(Action::CreateFile(path)) => match state.create_file(path) {
|
||||
Some(Action::CreateFile(path)) => match state.create(path) {
|
||||
Ok(buffer_id) => {
|
||||
self.switch_buffer(state, buffer_id);
|
||||
Ok(Resp::handled(None))
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ impl Visual for Opener {
|
|||
.take()
|
||||
.filter(|(b, _, _)| b.is_same_path(&f.path))
|
||||
.or_else(|| {
|
||||
let mut buffer = Buffer::from_file(f.path.clone()).ok()?;
|
||||
let mut buffer = Buffer::open(f.path.clone()).ok()?;
|
||||
let cursor_id = buffer.start_session();
|
||||
Some((buffer, cursor_id, Input::default()))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ impl Visual for Searcher {
|
|||
.take()
|
||||
.filter(|(_, _, _, r)| r == result)
|
||||
.or_else(|| {
|
||||
let mut buffer = Buffer::from_file(result.path.clone()).ok()?;
|
||||
let mut buffer = Buffer::open(result.path.clone()).ok()?;
|
||||
let cursor_id = buffer.start_session();
|
||||
let mut input = Input::default();
|
||||
buffer.goto_cursor(cursor_id, [0, result.line_idx as isize], true);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue