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