now actually modifies the filesystem. renaming files tbd
parent
4f9b52151c
commit
15a2b700cd
|
@ -1,6 +1,10 @@
|
|||
mod display;
|
||||
mod item;
|
||||
|
||||
use std::fs::{remove_dir_all, remove_file, DirBuilder, File};
|
||||
use std::io::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use tui::widgets::{Block, Borders, List, ListItem};
|
||||
use tui::style::{Color, Style};
|
||||
use tui::layout::Rect;
|
||||
|
@ -17,12 +21,37 @@ pub struct Directory {
|
|||
editing: bool,
|
||||
}
|
||||
impl Directory {
|
||||
pub fn new(root: String) -> Self {
|
||||
Self {
|
||||
pub fn new(root: String) -> Result<Self, Error> {
|
||||
DirBuilder::new()
|
||||
.recursive(true)
|
||||
.create(&root)?;
|
||||
|
||||
Ok(Self {
|
||||
dirs: vec![Item::new(root, 0, false)],
|
||||
selection: 0,
|
||||
editing: false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn path(&self) -> PathBuf {
|
||||
let s = self.selected();
|
||||
let init = (PathBuf::from(s.name.as_str()), s.depth);
|
||||
let (result, _) = self.dirs[0..=self.selection()]
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(
|
||||
init,
|
||||
|(mut path, mut depth), d| {
|
||||
if d.depth < depth {
|
||||
path = PathBuf::from(&d.name).join(path);
|
||||
depth = d.depth;
|
||||
}
|
||||
|
||||
(path, depth)
|
||||
}
|
||||
);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn select_prev(&mut self) {
|
||||
|
@ -47,7 +76,28 @@ impl Directory {
|
|||
};
|
||||
|
||||
let new = Item::new(name, depth, is_file);
|
||||
self.dirs.insert(self.selection()+1, new);
|
||||
|
||||
self.selection += 1;
|
||||
self.dirs.insert(self.selection(), new);
|
||||
}
|
||||
|
||||
fn create(&self) -> Result<(), Error> {
|
||||
if self.selected().is_file {
|
||||
File::create(self.path())?;
|
||||
} else {
|
||||
DirBuilder::new()
|
||||
.recursive(true)
|
||||
.create(self.path())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete(&self) -> Result<(), Error> {
|
||||
if self.selected().is_file {
|
||||
remove_file(self.path())
|
||||
} else {
|
||||
remove_dir_all(self.path())
|
||||
}
|
||||
}
|
||||
|
||||
fn selected(&self) -> &Item {
|
||||
|
@ -69,12 +119,10 @@ impl Directory {
|
|||
match c {
|
||||
'f' | 'F' => {
|
||||
self.insert(String::new(), true);
|
||||
self.select_next();
|
||||
self.editing = true;
|
||||
},
|
||||
'd' | 'D' => {
|
||||
self.insert(String::new(), false);
|
||||
self.select_next();
|
||||
self.editing = true;
|
||||
},
|
||||
'x' | 'X' => {
|
||||
|
@ -89,12 +137,22 @@ impl Directory {
|
|||
self.editing = true;
|
||||
},
|
||||
KeyCode::Esc => return Message::Exit,
|
||||
KeyCode::Backspace => {
|
||||
KeyCode::Backspace if self.selected().depth > 0 => {
|
||||
self.delete().unwrap();
|
||||
if self.selected().is_file {
|
||||
self.dirs.remove(self.selection());
|
||||
if self.selection() == self.dirs.len() {
|
||||
self.selection -= 1;
|
||||
}
|
||||
} else {
|
||||
let target_depth = self.selected().depth;
|
||||
|
||||
let end = (self.selection()+1 .. self.dirs.len())
|
||||
.find(|&i| self.dirs[i].depth <= target_depth)
|
||||
.unwrap_or(self.dirs.len());
|
||||
|
||||
self.dirs.drain(self.selection()..end);
|
||||
|
||||
}
|
||||
if self.selection() >= self.dirs.len() {
|
||||
self.selection -= 1;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
@ -107,9 +165,12 @@ impl Directory {
|
|||
match key {
|
||||
KeyCode::Char(c) => self.selected_mut().name.push(c),
|
||||
KeyCode::Enter | KeyCode::Esc if !self.selected().name.is_empty() => {
|
||||
self.create().unwrap();
|
||||
self.editing = false;
|
||||
},
|
||||
KeyCode::Backspace => { self.selected_mut().name.pop(); },
|
||||
KeyCode::Backspace => {
|
||||
self.selected_mut().name.pop();
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ fn main() -> Result<(), Error> {
|
|||
let mut terminal = Terminal::new()?;
|
||||
let area = terminal.size()?;
|
||||
|
||||
let mut state = State::new(area);
|
||||
let mut state = State::new(area)?;
|
||||
|
||||
loop {
|
||||
state.render(&mut terminal)?;
|
||||
|
|
12
src/state.rs
12
src/state.rs
|
@ -22,13 +22,13 @@ pub struct State {
|
|||
command: Option<Either<Command, CommandOutput>>
|
||||
}
|
||||
impl State {
|
||||
pub fn new(area: Rect) -> Self {
|
||||
let dir = Directory::new("root".into());
|
||||
Self {
|
||||
pub fn new(area: Rect) -> Result<Self, Error> {
|
||||
let dir = Directory::new("root".into())?;
|
||||
Ok(Self {
|
||||
dir,
|
||||
size: area,
|
||||
command: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render(&self, terminal: &mut Terminal) -> Result<(), Error> {
|
||||
|
@ -112,11 +112,13 @@ impl State {
|
|||
else { unsafe { unreachable_unchecked() } };
|
||||
|
||||
let mut iter = cmd.buf()
|
||||
.split(' ');
|
||||
.split(' ')
|
||||
.filter(|s| !s.is_empty());
|
||||
|
||||
let prog_name = iter.next().unwrap();
|
||||
let output = Executable::new(prog_name)
|
||||
.args(iter)
|
||||
.arg(self.dir.path())
|
||||
.output();
|
||||
|
||||
let command_output = CommandOutput::new(output.map(|o| o.stdout));
|
||||
|
|
Loading…
Reference in New Issue