rename and clippy
This commit is contained in:
+34
-22
@@ -1,24 +1,23 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Error;
|
use std::path::{Path, PathBuf};
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use crate::fleen_app::FleenError::{RootDirNonexistenceError, RootDirPopulatedError};
|
use crate::fleen_app::FleenError::{RootDirNonexistence, RootDirPopulated};
|
||||||
use crate::fleen_app::TreeEntry::{CloseDir, Dir};
|
use crate::fleen_app::TreeEntry::{CloseDir, Dir};
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum FleenError {
|
pub enum FleenError {
|
||||||
#[error("Can't reach root dir {0}")]
|
#[error("Can't reach root dir {0}")]
|
||||||
RootDirNonexistenceError(PathBuf),
|
RootDirNonexistence(PathBuf),
|
||||||
#[error("Root dir is nonempty, you probably don't want to create an app here: {0}")]
|
#[error("Root dir is nonempty, you probably don't want to create an app here: {0}")]
|
||||||
RootDirPopulatedError(PathBuf),
|
RootDirPopulated(PathBuf),
|
||||||
#[error("Failed to open {0}: {1}")]
|
#[error("IO error on {0}: {1}")]
|
||||||
FileIoError(String, String),
|
FileIo(String, String),
|
||||||
#[error("Can't create {0} because it already exists")]
|
#[error("Can't create {0} because it already exists")]
|
||||||
FileExistsError(PathBuf),
|
FileExists(PathBuf),
|
||||||
#[error("Can't create {0}: {1}")]
|
#[error("Can't create {0}: {1}")]
|
||||||
FileCreateError(PathBuf, String)
|
FileCreate(PathBuf, String)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -42,7 +41,7 @@ impl FleenApp {
|
|||||||
pub fn open(root: PathBuf) -> Result<Self, FleenError> {
|
pub fn open(root: PathBuf) -> Result<Self, FleenError> {
|
||||||
match root.try_exists() {
|
match root.try_exists() {
|
||||||
Ok(true) => Ok(Self { root, files_cache: RefCell::new(None) }),
|
Ok(true) => Ok(Self { root, files_cache: RefCell::new(None) }),
|
||||||
_ => Err(RootDirNonexistenceError(root))
|
_ => Err(RootDirNonexistence(root))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,13 +49,13 @@ impl FleenApp {
|
|||||||
match root.read_dir() {
|
match root.read_dir() {
|
||||||
Ok(mut iter) => {
|
Ok(mut iter) => {
|
||||||
if iter.next().is_some() {
|
if iter.next().is_some() {
|
||||||
Err(RootDirPopulatedError(root))
|
Err(RootDirPopulated(root))
|
||||||
} else {
|
} else {
|
||||||
Ok(Self { root, files_cache: RefCell::new(None) })
|
Ok(Self { root, files_cache: RefCell::new(None) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
Err(RootDirNonexistenceError(root))
|
Err(RootDirNonexistence(root))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +65,7 @@ impl FleenApp {
|
|||||||
if self.files_cache.borrow().is_none() || force {
|
if self.files_cache.borrow().is_none() || force {
|
||||||
let mut entries = vec![];
|
let mut entries = vec![];
|
||||||
|
|
||||||
fn visit_dir(dir: &PathBuf, entries: &mut Vec<TreeEntry>) {
|
fn visit_dir(dir: &Path, entries: &mut Vec<TreeEntry>) {
|
||||||
for entry in dir.read_dir().unwrap() {
|
for entry in dir.read_dir().unwrap() {
|
||||||
let path = entry.unwrap().path();
|
let path = entry.unwrap().path();
|
||||||
if path.is_file() && !path.file_name().unwrap().to_str().unwrap().starts_with('.') {
|
if path.is_file() && !path.file_name().unwrap().to_str().unwrap().starts_with('.') {
|
||||||
@@ -92,31 +91,31 @@ impl FleenApp {
|
|||||||
self.files_cache.borrow().clone().expect("Can't happen because we just refreshed the cache")
|
self.files_cache.borrow().clone().expect("Can't happen because we just refreshed the cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_filename(&self, filename: &String) -> Result<(), FleenError> {
|
pub fn open_filename(&self, filename: &str) -> Result<(), FleenError> {
|
||||||
Command::new("open").arg(filename.clone()).spawn().map_err(|err| {
|
Command::new("open").arg(filename).spawn().map_err(|err| {
|
||||||
FleenError::FileIoError(filename.clone(), err.to_string())
|
FleenError::FileIo(filename.to_owned(), err.to_string())
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_page(&self, file_type: FileType, name: &String, parent: Option<&String>) -> Result<(), FleenError> {
|
pub fn create_page(&self, file_type: FileType, name: &str, parent: Option<&String>) -> Result<(), FleenError> {
|
||||||
let mut target = match parent {
|
let mut target = match parent {
|
||||||
Some(s) => PathBuf::from(s),
|
Some(s) => PathBuf::from(s),
|
||||||
None => self.root.clone()
|
None => self.root.clone()
|
||||||
};
|
};
|
||||||
target.push(name.clone());
|
target.push(name);
|
||||||
if target.exists() {
|
if target.exists() {
|
||||||
return Err(FleenError::FileExistsError(target))
|
return Err(FleenError::FileExists(target))
|
||||||
}
|
}
|
||||||
|
|
||||||
match file_type {
|
match file_type {
|
||||||
FileType::File => std::fs::write(target.clone(), []),
|
FileType::File => std::fs::write(target.clone(), []),
|
||||||
FileType::Dir => std::fs::create_dir(target.clone())
|
FileType::Dir => std::fs::create_dir(target.clone())
|
||||||
}.map_err(|err| FleenError::FileCreateError(target.clone(), err.to_string()))?;
|
}.map_err(|err| FleenError::FileCreate(target.clone(), err.to_string()))?;
|
||||||
|
|
||||||
self.refresh_file_cache(true);
|
self.refresh_file_cache(true);
|
||||||
if file_type == FileType::File {
|
if file_type == FileType::File {
|
||||||
self.open_filename(&target.to_string_lossy().to_string())?
|
self.open_filename(target.to_string_lossy().as_ref())?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -127,8 +126,21 @@ impl FleenApp {
|
|||||||
fs::remove_dir_all(target)
|
fs::remove_dir_all(target)
|
||||||
} else {
|
} else {
|
||||||
fs::remove_file(target)
|
fs::remove_file(target)
|
||||||
}.map_err(|err| FleenError::FileIoError(path.clone(), err.to_string()))?;
|
}.map_err(|err| FleenError::FileIo(path.clone(), err.to_string()))?;
|
||||||
self.refresh_file_cache(true);
|
self.refresh_file_cache(true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rename_page(&self, target: &String, new_name: &str) -> Result<(), FleenError> {
|
||||||
|
let path = PathBuf::from(target);
|
||||||
|
let mut new_path = path.clone();
|
||||||
|
new_path.set_file_name(new_name);
|
||||||
|
fs::rename(path, new_path).map_err(|err| FleenError::FileIo(target.clone(), err.to_string()))?;
|
||||||
|
self.refresh_file_cache(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root_path(&self) -> String {
|
||||||
|
self.root.to_string_lossy().to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-40
@@ -1,7 +1,7 @@
|
|||||||
mod fleen_app;
|
mod fleen_app;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use eframe::egui::{Color32, Context, Id, Stroke};
|
use eframe::egui::{Color32, Context, Id, RichText};
|
||||||
use eframe::{egui, Frame};
|
use eframe::{egui, Frame};
|
||||||
use egui_ltreeview::Action;
|
use egui_ltreeview::Action;
|
||||||
use crate::fleen_app::{FileType, FleenApp, FleenError, TreeEntry};
|
use crate::fleen_app::{FileType, FleenApp, FleenError, TreeEntry};
|
||||||
@@ -19,6 +19,7 @@ enum DialogMode {
|
|||||||
RenameFile(String)
|
RenameFile(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct FleenUi {
|
struct FleenUi {
|
||||||
app: Option<FleenApp>,
|
app: Option<FleenApp>,
|
||||||
error: Option<FleenError>,
|
error: Option<FleenError>,
|
||||||
@@ -26,77 +27,67 @@ struct FleenUi {
|
|||||||
dialog_mode: Option<DialogMode>
|
dialog_mode: Option<DialogMode>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FleenUi {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
app: None,
|
|
||||||
error: None,
|
|
||||||
selected_file: None,
|
|
||||||
dialog_mode: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FleenUi {
|
impl FleenUi {
|
||||||
fn site_chooser(&mut self, ctx: &Context) {
|
fn site_chooser(&mut self, ctx: &Context) {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.label("No site selected!");
|
ui.label("No site selected!");
|
||||||
|
|
||||||
if ui.button("Open site...").clicked() {
|
if ui.button("Open site...").clicked() && let Some(path) = rfd::FileDialog::new().pick_folder() {
|
||||||
if let Some(path) = rfd::FileDialog::new().pick_folder() {
|
match FleenApp::open(path) {
|
||||||
match FleenApp::open(path) {
|
Ok(app) => { self.app = Some(app) }
|
||||||
Ok(app) => { self.app = Some(app) }
|
Err(err) => { self.error = Some(err) }
|
||||||
Err(err) => { self.error = Some(err) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("New site...").clicked() {
|
if ui.button("New site...").clicked() && let Some(path) = rfd::FileDialog::new().pick_folder() {
|
||||||
if let Some(path) = rfd::FileDialog::new().pick_folder() {
|
match FleenApp::create(path) {
|
||||||
match FleenApp::create(path) {
|
Ok(app) => { self.app = Some(app) }
|
||||||
Ok(app) => { self.app = Some(app) }
|
Err(err) => { self.error = Some(err) }
|
||||||
Err(err) => { self.error = Some(err) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display(&mut self, ctx: &Context) {
|
fn display(&mut self, ctx: &Context) {
|
||||||
let mut new_clicked = false;
|
let mut just_clicked = false;
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
self.tree_view(ui);
|
self.tree_view(ui);
|
||||||
if ui.add(egui::Button::new("Open")).clicked() {
|
if ui.add(egui::Button::new("Open")).clicked() &&
|
||||||
if let Some(fname) = &self.selected_file {
|
let Some(fname) = &self.selected_file {
|
||||||
self.handle_error(self.app.as_ref().unwrap().open_filename(fname))
|
self.handle_error(self.app.as_ref().unwrap().open_filename(fname))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.add(egui::Button::new("New page")).clicked() {
|
let new_btn = egui::Button::new(RichText::new("New page").color(Color32::WHITE)).fill(Color32::DARK_GREEN);
|
||||||
new_clicked = true;
|
if ui.add(new_btn).clicked() {
|
||||||
|
just_clicked = true;
|
||||||
self.dialog_mode = Some(DialogMode::NewFile(String::new()));
|
self.dialog_mode = Some(DialogMode::NewFile(String::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rename_btn = egui::Button::new("Rename");
|
||||||
let delete_btn = egui::Button::new("Delete").fill(Color32::DARK_RED);
|
let delete_btn = egui::Button::new("Delete").fill(Color32::DARK_RED);
|
||||||
if let Some(selected) = &self.selected_file {
|
if self.root_selected() || self.selected_file.is_none() {
|
||||||
|
ui.add_enabled(false, rename_btn);
|
||||||
|
ui.add_enabled(false, delete_btn);
|
||||||
|
} else if let Some(selected) = &self.selected_file {
|
||||||
|
if ui.add(rename_btn).clicked() {
|
||||||
|
self.dialog_mode = Some(DialogMode::RenameFile(label_for_path(&PathBuf::from(&selected))));
|
||||||
|
just_clicked = true;
|
||||||
|
}
|
||||||
if ui.add(delete_btn).clicked() {
|
if ui.add(delete_btn).clicked() {
|
||||||
self.dialog_mode = Some(DialogMode::ConfirmDelete(selected.clone()));
|
self.dialog_mode = Some(DialogMode::ConfirmDelete(selected.clone()));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ui.add_enabled(false, delete_btn);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
match self.dialog_mode {
|
match self.dialog_mode {
|
||||||
Some(DialogMode::NewFile(_)) => self.new_file_dialog(ctx, new_clicked),
|
Some(DialogMode::NewFile(_)) => self.new_file_dialog(ctx, just_clicked),
|
||||||
Some(DialogMode::ConfirmDelete(_)) => self.confirm_delete_dialog(ctx),
|
Some(DialogMode::ConfirmDelete(_)) => self.confirm_delete_dialog(ctx),
|
||||||
Some(DialogMode::RenameFile(_)) => todo!(),
|
Some(DialogMode::RenameFile(_)) => self.rename_dialog(ctx, just_clicked),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +109,7 @@ impl FleenUi {
|
|||||||
for action in actions {
|
for action in actions {
|
||||||
match action {
|
match action {
|
||||||
Action::SetSelected(files) => {
|
Action::SetSelected(files) => {
|
||||||
self.selected_file = files.first().map(String::clone)
|
self.selected_file = files.first().cloned()
|
||||||
}
|
}
|
||||||
Action::Activate(activate) => {
|
Action::Activate(activate) => {
|
||||||
for fname in activate.selected {
|
for fname in activate.selected {
|
||||||
@@ -173,6 +164,35 @@ impl FleenUi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rename_dialog(&mut self, ctx: &Context, just_clicked: bool) {
|
||||||
|
egui::Window::new("Rename").collapsible(false).resizable(false).show(ctx, |ui| {
|
||||||
|
ui.label("New name");
|
||||||
|
let Some(DialogMode::RenameFile(fname)) = &mut self.dialog_mode else { unreachable!() };
|
||||||
|
let name_field = egui::TextEdit::singleline(fname);
|
||||||
|
let resp = ui.add(name_field);
|
||||||
|
let enter_key = resp.lost_focus();
|
||||||
|
if just_clicked { resp.request_focus() } // See new_file_dialog
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let btn = ui.button("Rename");
|
||||||
|
if enter_key { btn.request_focus() }
|
||||||
|
if btn.clicked() {
|
||||||
|
let Some(DialogMode::RenameFile(fname)) = &self.dialog_mode else { unreachable!() };
|
||||||
|
let app = self.app.as_ref().unwrap();
|
||||||
|
let r = app.rename_page(self.selected_file.as_ref().unwrap(), fname);
|
||||||
|
if r.is_err() {
|
||||||
|
self.handle_error(r);
|
||||||
|
} else {
|
||||||
|
self.dialog_mode = None; // Close the dialog, we're done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ui.button("Cancel").clicked() {
|
||||||
|
self.dialog_mode = None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn confirm_delete_dialog(&mut self, ctx: &Context) {
|
fn confirm_delete_dialog(&mut self, ctx: &Context) {
|
||||||
let (mut del, mut cancel) = (false, false);
|
let (mut del, mut cancel) = (false, false);
|
||||||
let Some(DialogMode::ConfirmDelete(fname)) = &self.dialog_mode else { unreachable!() };
|
let Some(DialogMode::ConfirmDelete(fname)) = &self.dialog_mode else { unreachable!() };
|
||||||
@@ -201,6 +221,14 @@ impl FleenUi {
|
|||||||
self.error = Some(e)
|
self.error = Some(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn root_selected(&self) -> bool {
|
||||||
|
if let Some(path) = &self.selected_file {
|
||||||
|
path == &self.app.as_ref().unwrap().root_path()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for FleenUi {
|
impl eframe::App for FleenUi {
|
||||||
@@ -222,10 +250,10 @@ impl eframe::App for FleenUi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label_for_path(path: &PathBuf) -> String {
|
fn label_for_path(path: &Path) -> String {
|
||||||
path.file_name().unwrap().to_string_lossy().to_string()
|
path.file_name().unwrap().to_string_lossy().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id_for_path(path: &PathBuf) -> String {
|
fn id_for_path(path: &Path) -> String {
|
||||||
path.to_string_lossy().to_string()
|
path.to_string_lossy().to_string()
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user