summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2022-10-16 01:04:26 +0200
committerqkzk <qu3nt1n@gmail.com>2022-10-16 01:04:26 +0200
commit4db7b345d8d1439ab61d6c75938315b39b47b4d3 (patch)
tree08886251239ac3e8bd3b3414122bae3c81d9b72d
parent6e5f19310f42f2ac88f0def2779f79e9dd160943 (diff)
basic step, can't open editor yet. Need a Mode
-rw-r--r--Cargo.lock37
-rw-r--r--Cargo.toml1
-rw-r--r--readme.md2
-rw-r--r--src/bulkrename.rs113
-rw-r--r--src/lib.rs3
-rw-r--r--src/opener.rs38
-rw-r--r--src/status.rs2
7 files changed, 178 insertions, 18 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bcf0da7e..fc1ba4c2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -542,6 +542,7 @@ dependencies = [
"clap 4.0.2",
"content_inspector",
"pdf-extract",
+ "rand",
"regex",
"serde_yaml",
"shellexpand",
@@ -896,6 +897,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac1825c05c4f9e2f781202d1a02fff5e5f722bbafca542d818364e1b1ea22575"
[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -944,6 +951,36 @@ dependencies = [
]
[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
name = "rayon"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index d994e0de..5b112981 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@ chrono = "*"
clap = { version = "4.0", features = ["derive"] }
content_inspector = "0.2.4"
pdf-extract = "0.6.4"
+rand = "^0"
regex = "1"
serde_yaml = "0.9.13"
shellexpand = "2.1.2"
diff --git a/readme.md b/readme.md
index 4ccb53e7..e0ef79ea 100644
--- a/readme.md
+++ b/readme.md
@@ -77,6 +77,7 @@
- [x] improve the top row
- [x] confirmation display shows a list of edited files
- [x] integrate fzf or another fuzzy finder
+- [x] custom a file opener
## TODO
@@ -90,7 +91,6 @@
- https://github.com/KillTheMule/nvim-rs/blob/master/examples/basic.rs
- https://neovim.io/doc/user/api.html
- [ ] display / event separation. use async and message passing between coroutines
-- [ ] create a file opener
## BUGS
diff --git a/src/bulkrename.rs b/src/bulkrename.rs
new file mode 100644
index 00000000..e65b0da3
--- /dev/null
+++ b/src/bulkrename.rs
@@ -0,0 +1,113 @@
+use rand::Rng;
+use std::io::{self, BufRead};
+use std::path::PathBuf;
+
+use crate::opener::{ExtensionKind, Opener};
+
+//TODO: comme pour skim, attach a Arc<Term> and use it to display the editor
+
+static TMP_FOLDER: &str = "/tmp";
+
+struct BulkRenamer {
+ original_filepath: Vec<PathBuf>,
+ temp_file: Option<PathBuf>,
+}
+
+impl BulkRenamer {
+ pub fn new(original_filepath: Vec<PathBuf>) -> Self {
+ Self {
+ original_filepath,
+ temp_file: None,
+ }
+ }
+
+ fn random_name() -> String {
+ let mut rand_str = String::with_capacity(10);
+ rand_str.push_str("fm-");
+ rand::thread_rng()
+ .sample_iter(&rand::distributions::Alphanumeric)
+ .take(7)
+ .for_each(|ch| rand_str.push(ch as char));
+ rand_str
+ }
+
+ fn create_random_file(&mut self, rand_name: String) -> Result<(), io::Error> {
+ let mut filepath = PathBuf::from(&TMP_FOLDER);
+ filepath.push(rand_name);
+ let _ = std::fs::File::create(&filepath)?;
+ self.temp_file = Some(filepath);
+ Ok(())
+ }
+
+ fn write_original_names(&self) -> Result<(), io::Error> {
+ if let Some(filepath) = &self.temp_file {
+ for path in self.original_filepath.iter() {
+ if let Some(os_filename) = path.file_name() {
+ if let Some(filename) = os_filename.to_str() {
+ std::fs::write(&filepath, filename)?
+ }
+ }
+ }
+ Ok(())
+ } else {
+ Err(io::Error::new(
+ io::ErrorKind::NotFound,
+ "Temp file hasn't been created",
+ ))
+ }
+ }
+
+ fn open_temp_file_with_editor(&self, opener: &Opener) -> Result<(), io::Error> {
+ if let Some(filepath) = &self.temp_file {
+ if let Some(editor_info) = opener.get(ExtensionKind::Text) {
+ opener.open_with(editor_info, filepath.to_owned())
+ };
+ Ok(())
+ } else {
+ Err(io::Error::new(
+ io::ErrorKind::NotFound,
+ "Couldn't open the temp file.",
+ ))
+ }
+ }
+
+ fn is_file_modified(
+ filepath: PathBuf,
+ original_modification: std::time::SystemTime,
+ ) -> Result<bool, io::Error> {
+ let last_modification = std::fs::metadata(&filepath)?.modified()?;
+ Ok(last_modification <= original_modification)
+ }
+
+ fn get_new_filenames(&self, filepath: PathBuf) -> Result<Vec<String>, io::Error> {
+ let file = std::fs::File::open(&filepath)?;
+
+ let reader = std::io::BufReader::new(file);
+ let mut new_names = vec![];
+ for line in reader.lines() {
+ let line2 = line?;
+ let line = line2.trim();
+ if line.is_empty() {
+ return Err(io::Error::new(io::ErrorKind::Other, "empty filename"));
+ }
+ new_names.push(line2);
+ }
+ if new_names.len() < self.original_filepath.len() {
+ return Err(io::Error::new(io::ErrorKind::Other, "not enough filenames"));
+ }
+ Ok(new_names)
+ }
+
+ fn delete_temp_file(&self, filepath: PathBuf) -> Result<(), io::Error> {
+ Ok(std::fs::remove_file(&filepath)?)
+ }
+
+ fn rename(&self, new_filenames: Vec<String>) -> Result<(), io::Error> {
+ for (path, filename) in self.original_filepath.iter().zip(new_filenames.iter()) {
+ let mut parent = path.clone();
+ parent.pop();
+ std::fs::rename(path, parent.join(&filename))?;
+ }
+ Ok(())
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 9a688037..dcd9c016 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,6 @@
pub mod actioner;
pub mod args;
+pub mod bulkrename;
pub mod completion;
pub mod config;
pub mod content_window;
@@ -10,10 +11,10 @@ pub mod help;
pub mod input;
pub mod last_edition;
pub mod mode;
+pub mod opener;
pub mod preview;
pub mod shortcut;
pub mod skim;
pub mod status;
pub mod tabs;
pub mod visited;
-pub mod opener;
diff --git a/src/opener.rs b/src/opener.rs
index ad661bb0..c5dcaf1a 100644
--- a/src/opener.rs
+++ b/src/opener.rs
@@ -5,7 +5,7 @@ use std::process::Command;
use serde_yaml;
#[derive(Clone, Hash, Eq, PartialEq)]
-enum ExtensionKind {
+pub enum ExtensionKind {
Audio,
Bitmap,
Office,
@@ -112,7 +112,7 @@ impl ExtensionKind {
}
#[derive(Clone)]
-struct OpenerAssociation {
+pub struct OpenerAssociation {
association: HashMap<ExtensionKind, OpenerInfo>,
}
@@ -180,7 +180,7 @@ impl OpenerAssociation {
}
#[derive(Clone)]
-struct OpenerInfo {
+pub struct OpenerInfo {
opener: String,
use_term: bool,
}
@@ -210,7 +210,7 @@ impl OpenerInfo {
#[derive(Clone)]
pub struct Opener {
terminal: String,
- opener_association: OpenerAssociation,
+ pub opener_association: OpenerAssociation,
}
impl Opener {
@@ -229,21 +229,25 @@ impl Opener {
if let Some(extension_os_str) = filepath.extension() {
let extension = extension_os_str.to_str().unwrap();
if let Some(open_info) = self.opener_association.opener_info(extension) {
- if open_info.use_term {
- self.open_terminal(
- open_info.opener.clone(),
- filepath.to_str().unwrap().to_owned(),
- )
- } else {
- self.open_directly(
- open_info.opener.clone(),
- filepath.to_str().unwrap().to_owned(),
- )
- }
+ self.open_with(open_info, filepath)
}
}
}
+ pub fn open_with(&self, open_info: &OpenerInfo, filepath: std::path::PathBuf) {
+ if open_info.use_term {
+ self.open_terminal(
+ open_info.opener.clone(),
+ filepath.to_str().unwrap().to_owned(),
+ )
+ } else {
+ self.open_directly(
+ open_info.opener.clone(),
+ filepath.to_str().unwrap().to_owned(),
+ )
+ }
+ }
+
pub fn update_from_file(&mut self, yaml: &serde_yaml::value::Value) {
self.opener_association.update_from_file(yaml)
}
@@ -256,6 +260,10 @@ impl Opener {
fn open_terminal(&self, executable: String, filepath: String) {
execute_in_child(&self.terminal, &vec!["-e", &executable, &filepath]);
}
+
+ pub fn get(&self, kind: ExtensionKind) -> Option<&OpenerInfo> {
+ self.opener_association.association.get(&kind)
+ }
}
/// Execute the command in a fork.
diff --git a/src/status.rs b/src/status.rs
index 6a58559a..7a541fb1 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -54,7 +54,7 @@ pub struct Status {
pub history: History,
/// Predefined shortcuts
pub shortcut: Shortcut,
- opener: Opener,
+ pub opener: Opener,
}
impl Status {