summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2023-02-14 23:08:16 +0100
committerqkzk <qu3nt1n@gmail.com>2023-02-14 23:08:16 +0100
commitba395f2f69efaf4ae314ef54703cf3c530d8b2e2 (patch)
tree5fd3a004338f0d4c6b039c21e67bb1610878d161 /src
parent8dc54f0463fe9ad860a6b08e190b84b915ebb046 (diff)
compression almost done
Diffstat (limited to 'src')
-rw-r--r--src/action_map.rs4
-rw-r--r--src/compress.rs52
-rw-r--r--src/event_exec.rs52
-rw-r--r--src/fm_error.rs7
-rw-r--r--src/keybindings.rs1
-rw-r--r--src/main.rs15
-rw-r--r--src/mode.rs3
-rw-r--r--src/status.rs6
-rw-r--r--src/term_manager.rs24
9 files changed, 147 insertions, 17 deletions
diff --git a/src/action_map.rs b/src/action_map.rs
index c3a85c9..5800f3a 100644
--- a/src/action_map.rs
+++ b/src/action_map.rs
@@ -17,6 +17,7 @@ pub enum ActionMap {
Bulkrename,
Chmod,
ClearFlags,
+ Compress,
CopyFilename,
CopyFilepath,
CopyPaste,
@@ -50,6 +51,7 @@ pub enum ActionMap {
NewFile,
Nothing,
NvimFilepicker,
+ OpenConfig,
OpenFile,
PageDown,
PageUp,
@@ -78,7 +80,6 @@ pub enum ActionMap {
TreeFold,
TreeUnFoldAll,
TreeFoldAll,
- OpenConfig,
}
impl ActionMap {
@@ -93,6 +94,7 @@ impl ActionMap {
ActionMap::Bulkrename => EventExec::event_bulkrename(status),
ActionMap::Chmod => EventExec::event_chmod(status),
ActionMap::ClearFlags => EventExec::event_clear_flags(status),
+ ActionMap::Compress => EventExec::event_compress(status),
ActionMap::CopyFilename => EventExec::event_copy_filename(status),
ActionMap::CopyFilepath => EventExec::event_copy_filepath(status),
ActionMap::CopyPaste => EventExec::event_copy_paste(status),
diff --git a/src/compress.rs b/src/compress.rs
index aa8ab13..af7792f 100644
--- a/src/compress.rs
+++ b/src/compress.rs
@@ -1,10 +1,44 @@
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::Write;
+
use flate2::write::{DeflateEncoder, GzEncoder, ZlibEncoder};
use flate2::Compression;
-use std::fs::File;
use tar::Builder;
+use zip::write::FileOptions;
-// use crate::fileinfo::FileInfo;
use crate::fm_error::FmResult;
+use crate::impl_selectable_content;
+
+#[derive(Debug)]
+pub enum CompressionMethod {
+ DEFLATE,
+ GZ,
+ ZLIB,
+ ZIP,
+}
+
+#[derive(Debug)]
+pub struct CompressionPicker {
+ content: Vec<CompressionMethod>,
+ pub index: usize,
+}
+
+impl CompressionPicker {
+ pub fn new() -> Self {
+ Self {
+ content: vec![
+ CompressionMethod::DEFLATE,
+ CompressionMethod::GZ,
+ CompressionMethod::ZLIB,
+ CompressionMethod::ZIP,
+ ],
+ index: 0,
+ }
+ }
+}
+
+impl_selectable_content!(CompressionMethod, CompressionPicker);
pub fn compressed_gzip(archive_name: String, files: Vec<std::path::PathBuf>) -> FmResult<()> {
let compressed_file = File::create(archive_name)?;
@@ -71,3 +105,17 @@ pub fn compressed_zlib(archive_name: String, files: Vec<std::path::PathBuf>) ->
Ok(())
}
+
+pub fn compressed_zip(archive_name: String, files: Vec<std::path::PathBuf>) -> FmResult<()> {
+ let archive = std::fs::File::create(&archive_name).unwrap();
+ let mut zip = zip::ZipWriter::new(archive);
+ for file in files.iter() {
+ let mut buffer = Vec::new();
+ zip.start_file(file.to_str().unwrap(), FileOptions::default())?;
+ let mut content = File::open(file)?;
+ content.read_to_end(&mut buffer)?;
+ zip.write_all(&buffer)?;
+ }
+ zip.finish()?;
+ Ok(())
+}
diff --git a/src/event_exec.rs b/src/event_exec.rs
index 061291a..428b973 100644
--- a/src/event_exec.rs
+++ b/src/event_exec.rs
@@ -9,6 +9,9 @@ use sysinfo::SystemExt;
use crate::bulkrename::Bulkrename;
use crate::completion::InputCompleted;
+use crate::compress::{
+ compressed_deflate, compressed_gzip, compressed_zip, compressed_zlib, CompressionMethod,
+};
use crate::config::Colors;
use crate::constant_strings_paths::CONFIG_PATH;
use crate::constant_strings_paths::DEFAULT_DRAGNDROP;
@@ -1170,6 +1173,7 @@ impl EventExec {
Mode::Navigate(Navigate::Trash) => EventExec::event_trash_prev(status),
Mode::Navigate(Navigate::Shortcut) => EventExec::event_shortcut_prev(status.selected()),
Mode::Navigate(Navigate::Marks(_)) => EventExec::event_marks_prev(status),
+ Mode::Navigate(Navigate::Compress) => EventExec::event_compression_prev(status),
Mode::Navigate(Navigate::EncryptedDrive) => {
EventExec::event_encrypted_drive_prev(status)
}
@@ -1192,6 +1196,7 @@ impl EventExec {
Mode::Navigate(Navigate::Trash) => EventExec::event_trash_next(status),
Mode::Navigate(Navigate::Shortcut) => EventExec::event_shortcut_next(status.selected()),
Mode::Navigate(Navigate::Marks(_)) => EventExec::event_marks_next(status),
+ Mode::Navigate(Navigate::Compress) => EventExec::event_compression_next(status),
Mode::Navigate(Navigate::EncryptedDrive) => {
EventExec::event_encrypted_drive_next(status)
}
@@ -1347,6 +1352,7 @@ impl EventExec {
Mode::Navigate(Navigate::Marks(MarkAction::Jump)) => {
EventExec::exec_marks_jump_selected(status)?
}
+ Mode::Navigate(Navigate::Compress) => EventExec::exec_compress(status)?,
};
status.selected().input.reset();
@@ -1724,6 +1730,52 @@ impl EventExec {
}
Ok(())
}
+
+ pub fn event_compress(status: &mut Status) -> FmResult<()> {
+ status
+ .selected()
+ .set_mode(Mode::Navigate(Navigate::Compress));
+ Ok(())
+ }
+
+ pub fn exec_compress(status: &mut Status) -> FmResult<()> {
+ let cwd = std::env::current_dir()?;
+ let files = status
+ .flagged
+ .content
+ .iter()
+ .map(|abs_path| pathdiff::diff_paths(abs_path, &cwd))
+ .filter(|p| p.is_some())
+ .map(|p| p.unwrap())
+ .collect();
+ match status.compression.selected() {
+ Some(CompressionMethod::DEFLATE) => {
+ let archive_name = "archive.tar.gz".to_owned();
+ compressed_gzip(archive_name, files)
+ }
+ Some(CompressionMethod::GZ) => {
+ let archive_name = "archive.tar.gz".to_owned();
+ compressed_deflate(archive_name, files)
+ }
+ Some(CompressionMethod::ZLIB) => {
+ let archive_name = "archive.tar.xz".to_owned();
+ compressed_zlib(archive_name, files)
+ }
+ Some(CompressionMethod::ZIP) => {
+ let archive_name = "archive.zip".to_owned();
+ compressed_zip(archive_name, files)
+ }
+ None => Ok(()),
+ }
+ }
+
+ pub fn event_compression_prev(status: &mut Status) {
+ status.compression.prev()
+ }
+
+ pub fn event_compression_next(status: &mut Status) {
+ status.compression.next()
+ }
}
fn string_to_path(path_string: &str) -> FmResult<path::PathBuf> {
diff --git a/src/fm_error.rs b/src/fm_error.rs
index bc7352f..f811822 100644
--- a/src/fm_error.rs
+++ b/src/fm_error.rs
@@ -30,6 +30,7 @@ pub enum ErrorVariant {
SERDEYAML,
CHRONO,
UTF8ERROR,
+ ZIPERROR,
CUSTOM(String),
}
@@ -187,5 +188,11 @@ impl From<std::string::FromUtf8Error> for FmError {
}
}
+impl From<zip::result::ZipError> for FmError {
+ fn from(error: zip::result::ZipError) -> Self {
+ Self::new(ErrorVariant::ZIPERROR, &error.to_string())
+ }
+}
+
/// A Result with type `T` and `FmError`.
pub type FmResult<T> = Result<T, FmError>;
diff --git a/src/keybindings.rs b/src/keybindings.rs
index 1cac624..c2cbc4a 100644
--- a/src/keybindings.rs
+++ b/src/keybindings.rs
@@ -45,6 +45,7 @@ impl Bindings {
(Key::Char('-'), ActionMap::Back),
(Key::Char('~'), ActionMap::Home),
(Key::Char('B'), ActionMap::Bulkrename),
+ (Key::Char('C'), ActionMap::Compress),
(Key::Char('D'), ActionMap::ToggleDualPane),
(Key::Char('F'), ActionMap::Filter),
(Key::Char('G'), ActionMap::Shortcut),
diff --git a/src/main.rs b/src/main.rs
index a22b8ef..5807e28 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -18,7 +18,7 @@ use fm::utils::{drop_everything, init_term, print_on_quit};
/// Init the status and display and listen to events (keyboard, mouse, resize, custom...).
/// The application is redrawn after every event.
/// When the user issues a quit event, the main loop is broken and we reset the cursor.
-fn main2() -> FmResult<()> {
+fn main() -> FmResult<()> {
set_logger()?;
info!("fm is starting");
@@ -56,16 +56,3 @@ fn main2() -> FmResult<()> {
info!("fm is shutting down");
Ok(())
}
-
-fn main() -> FmResult<()> {
- use fm::compress::compressed_gzip;
- use std::path::PathBuf;
-
- compressed_gzip(
- "archive.tar.gz".to_owned(),
- vec![
- PathBuf::from("compress_example/2022_nsi_metropole_j1_reseau_1.png"),
- PathBuf::from("compress_example/2022_nsi_metropole_j1_correction.pdf"),
- ],
- )
-}
diff --git a/src/mode.rs b/src/mode.rs
index 26b2b38..10e2e84 100644
--- a/src/mode.rs
+++ b/src/mode.rs
@@ -94,6 +94,8 @@ pub enum Navigate {
EncryptedDrive,
/// Jump to a saved mark
Marks(MarkAction),
+ /// Pick a compression method
+ Compress,
}
/// Different mode in which the application can be.
@@ -144,6 +146,7 @@ impl fmt::Display for Mode {
Mode::Navigate(Navigate::History) => write!(f, "History :"),
Mode::Navigate(Navigate::Shortcut) => write!(f, "Shortcut :"),
Mode::Navigate(Navigate::Trash) => write!(f, "Trash :"),
+ Mode::Navigate(Navigate::Compress) => write!(f, "Compress :"),
Mode::Navigate(Navigate::EncryptedDrive) => {
write!(f, "Encrypted devices :")
}
diff --git a/src/status.rs b/src/status.rs
index 05ef219..3702635 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -10,6 +10,7 @@ use tuikit::term::Term;
use users::UsersCache;
use crate::args::Args;
+use crate::compress::CompressionPicker;
use crate::constant_strings_paths::OPENER_PATH;
use crate::copy_move::{copy_move, CopyMove};
use crate::cryptsetup::DeviceOpener;
@@ -57,7 +58,10 @@ pub struct Status {
pub help: String,
/// The trash
pub trash: Trash,
+ /// Encrypted devices opener
pub encrypted_devices: DeviceOpener,
+ /// Compression methods
+ pub compression: CompressionPicker,
}
impl Status {
@@ -88,6 +92,7 @@ impl Status {
tab2.shortcut
.extend_with_mount_points(&Self::disks_mounts(sys.disks()));
let trash = Trash::new()?;
+ let compression = CompressionPicker::new();
Ok(Self {
tabs: [tab2, tab],
@@ -103,6 +108,7 @@ impl Status {
help,
trash,
encrypted_devices,
+ compression,
})
}
diff --git a/src/term_manager.rs b/src/term_manager.rs
index 2238e8f..d870d66 100644
--- a/src/term_manager.rs
+++ b/src/term_manager.rs
@@ -9,6 +9,7 @@ use tuikit::event::Event;
use tuikit::prelude::*;
use tuikit::term::Term;
+use crate::compress::CompressionMethod;
use crate::config::Colors;
use crate::constant_strings_paths::{
FILTER_PRESENTATION, HELP_FIRST_SENTENCE, HELP_SECOND_SENTENCE,
@@ -376,6 +377,7 @@ impl<'a> Draw for WinSecondary<'a> {
Mode::Navigate(Navigate::History) => self.destination(canvas, &self.tab.history),
Mode::Navigate(Navigate::Shortcut) => self.destination(canvas, &self.tab.shortcut),
Mode::Navigate(Navigate::Trash) => self.trash(canvas, &self.status.trash),
+ Mode::Navigate(Navigate::Compress) => self.compress(canvas, &self.status.compression),
Mode::Navigate(Navigate::EncryptedDrive) => {
self.encrypted_devices(self.status, self.tab, canvas)
}
@@ -521,6 +523,28 @@ impl<'a> WinSecondary<'a> {
Ok(())
}
+ fn compress(
+ &self,
+ canvas: &mut dyn Canvas,
+ selectable: &impl SelectableContent<CompressionMethod>,
+ ) -> FmResult<()> {
+ canvas.print(1, 0, "Pick a compression method")?;
+ for (row, compression_method) in selectable.content().iter().enumerate() {
+ let mut attr = Attr::default();
+ if row == selectable.index() {
+ attr.effect |= Effect::REVERSE;
+ }
+
+ let _ = canvas.print_with_attr(
+ row + ContentWindow::WINDOW_MARGIN_TOP,
+ 4,
+ &format!("{compression_method:?}"),
+ attr,
+ );
+ }
+ Ok(())
+ }
+
fn marks(&self, status: &Status, tab: &Tab, canvas: &mut dyn Canvas) -> FmResult<()> {
canvas.print_with_attr(2, 1, "mark path", Self::ATTR_YELLOW)?;