diff --git a/Cargo.lock b/Cargo.lock index 1cb85ef..9afb743 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,9 +108,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.0" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bitflags" @@ -123,6 +123,9 @@ name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -223,11 +226,12 @@ dependencies = [ [[package]] name = "config" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f1667b8320afa80d69d8bbe40830df2c8a06003d86f73d8e003b2c48df416d" +checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" dependencies = [ "async-trait", + "convert_case", "json5", "lazy_static", "nom", @@ -284,6 +288,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -327,9 +337,18 @@ dependencies = [ [[package]] name = "dlv-list" -version = "0.3.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" @@ -403,7 +422,7 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" @@ -679,9 +698,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "ordered-multimap" -version = "0.4.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" dependencies = [ "dlv-list", "hashbrown 0.13.2", @@ -796,12 +815,11 @@ checksum = "e33e4fb37ba46888052c763e4ec2acfedd8f00f62897b630cadb6298b833675e" [[package]] name = "ron" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64", - "bitflags 1.3.2", "bitflags 2.4.2", "serde", "serde_derive", @@ -823,9 +841,9 @@ dependencies = [ [[package]] name = "rust-ini" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" dependencies = [ "cfg-if", "ordered-multimap", @@ -988,11 +1006,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -1013,6 +1056,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 3f07155..4967fcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ colored = "2" fs_extra = "1.3" anyhow = "1.0" size_format = "1.0.2" -config = "0.13" +config = "0.14" xz2 = "0.1" tar = "0.4" clap = { version = "4.3.23", features = ["derive"] } diff --git a/src/bin/drop.rs b/src/bin/drop.rs index 4dbe856..ffb823c 100644 --- a/src/bin/drop.rs +++ b/src/bin/drop.rs @@ -44,7 +44,8 @@ fn main() -> Result<()> { let slot = unwrapped_slot.as_str(); let out = cli.output.unwrap_or(get_current_dir()?); - item::drop(&cli.file, slot, out, true, cli.slot.is_some())?; + item::drop(&cli.file, slot, out, true, cli.slot.is_some(), true)?; + Ok(()) } diff --git a/src/bin/take.rs b/src/bin/take.rs index ec58ca3..2cc0671 100644 --- a/src/bin/take.rs +++ b/src/bin/take.rs @@ -40,6 +40,6 @@ fn main() -> Result<()> { let cli = Cli::parse(); let slot = cli.slot.clone().unwrap_or(String::from("active")); - item::take(&cli.file, &slot, true, cli.slot.is_some())?; + item::take(&cli.file, &slot, true, cli.slot.is_some(), true)?; Ok(()) } diff --git a/src/bin/vento.rs b/src/bin/vento.rs index 41bc8c9..cb0935b 100644 --- a/src/bin/vento.rs +++ b/src/bin/vento.rs @@ -39,9 +39,13 @@ struct Cli { #[arg(short = 'c', long)] switch: bool, - /// Undo the last action - #[arg(short, long)] - undo: bool, + /// Undo actions by a certain amount of steps + #[arg(short, long, value_name="STEPS", default_missing_value = "1", num_args = ..=1)] + undo: Option, + + /// Redo actions by a certain amount of steps + #[arg(short, long, value_name="STEPS", default_missing_value = "1", num_args = ..=1)] + redo: Option, /// Export an inventory #[arg(short, long, value_names = &["SLOT", "ARCHIVE"], num_args = ..=2)] @@ -73,11 +77,19 @@ fn main() -> Result<()> { let dir = unwrapped_dir.as_str(); if cli.switch { - inv::switch(true)? - } else if cli.undo { - history::undo()? + inv::switch(true, true)? } else if cli.init { inv::init()? + } else if cli.undo.is_some() { + history::undo(match cli.undo { + Some(x) => x, + None => 1, + })? + } else if cli.redo.is_some() { + history::redo(match cli.redo { + Some(x) => x, + None => 1, + })? } else if cli.export_inv.is_some() { let unwrapped_export_inv = cli.export_inv.unwrap(); let export_inv_values = match unwrapped_export_inv.len() { diff --git a/src/common.rs b/src/common.rs index 4e99a3a..4274ecc 100644 --- a/src/common.rs +++ b/src/common.rs @@ -21,11 +21,11 @@ use crate::message::{throw_error, ErrorType}; use anyhow::Result; use colored::control::set_override; use config::Config; +use rusqlite::Connection; use serde::Deserialize; use std::env::current_dir; -use std::fs::File; -use std::io::Write; use std::path::{Path, PathBuf}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub struct Settings { pub vento_dir: PathBuf, @@ -33,11 +33,15 @@ pub struct Settings { pub inactive_dir: PathBuf, } +#[derive(Debug)] pub struct HistoryData { - pub path: PathBuf, - pub file: String, - pub slot: String, + pub id: i32, + pub path: Option, + pub file: Option, + pub slot: Option, pub action: Action, + pub time: i64, + pub current: i32, } pub struct DeserializedConfig { @@ -60,6 +64,7 @@ struct History { display_dir: bool, } +#[derive(Debug)] pub enum Action { Take, Drop, @@ -139,26 +144,48 @@ pub fn parse_config() -> Result { }) } -/// Writes an action into the history file +/// Writes an action into the history database pub fn history(data: HistoryData) -> Result<()> { - let mut last_path = env_config()?.vento_dir; - last_path.push("last"); - let mut last_file = File::create(last_path)?; + let mut path = env_config()?.vento_dir; + path.push("history.db3"); + let db = Connection::open(path)?; - write!( - &mut last_file, - "{} -{} -{} -{}", - data.path.to_str().unwrap(), - data.file, - data.slot, - match data.action { - Action::Take => "take", - Action::Drop => "drop", - Action::Switch => "switch", - } + // Create table if it doesn't exist. + db.execute( + "CREATE TABLE IF NOT EXISTS history ( + id INTEGER PRIMARY KEY, + path TEXT, + file TEXT, + slot TEXT, + action TEXT NOT NULL, + time INTEGER NOT NULL, + current INTEGER NOT NULL)", + (), + )?; + + // Remove future actions + let mut current = db.prepare("SELECT id FROM history WHERE current = 1")?; + let actions = current.query_map([], |row| Ok(row.get(0)?))?; + let lastaction: i64 = actions.last().unwrap_or(Ok(0))?; + db.execute("DELETE FROM history WHERE id > ?1", [lastaction])?; + + // Unset current actions + db.execute("UPDATE history SET current = 0 WHERE current = 1", ())?; + + // Insert action into table + db.execute( + "INSERT INTO history (path, file, slot, action, time, current) VALUES (?1, ?2, ?3, ?4, ?5, 1)", + ( + data.path.unwrap_or(PathBuf::new()).to_str(), + data.file, + data.slot, + match data.action { + Action::Take => "take", + Action::Drop => "drop", + Action::Switch => "switch", + }, + SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::new(0, 0)).as_secs(), + ), )?; Ok(()) diff --git a/src/history.rs b/src/history.rs index a2ca195..39127be 100644 --- a/src/history.rs +++ b/src/history.rs @@ -18,98 +18,171 @@ */ use crate::{ - common::{env_config, parse_config}, + common::{env_config, parse_config, Action, HistoryData}, inv, item, message::{append_emoji, throw_error, EmojiType, ErrorType}, }; use anyhow::Result; +use chrono::prelude::*; use colored::Colorize; -use std::fs; +use rusqlite::Connection; use std::path::{Path, PathBuf}; -/// Undoes the last action made by Vento using the history file located on the Vento directory -pub fn undo() -> Result<()> { - let lastpath: PathBuf = [env_config()?.vento_dir, Path::new("last").to_path_buf()] - .iter() - .collect(); +/// Undoes actions made by Vento using the history database located on the Vento directory +pub fn undo(steps: usize) -> Result<()> { + let path: PathBuf = [ + env_config()?.vento_dir, + Path::new("history.db3").to_path_buf(), + ] + .iter() + .collect(); + let db = Connection::open(path)?; - let lastfile = fs::read_to_string(lastpath)?; + // Determine if step amount is greater than the position of the action + let mut current = db.prepare("SELECT id FROM history WHERE current = 1")?; + let actions = current.query_map([], |row| Ok(row.get(0)?))?; + let last_action: usize = actions.last().unwrap_or(Ok(0))?; - let mut contents = vec![]; - - for line in lastfile.lines() { - contents.push(line); + if last_action <= steps { + throw_error(ErrorType::InvalidStepsLength)?; } - if contents.len() != 4 { - throw_error(ErrorType::InvalidHistoryLength)?; + let final_dest = last_action - steps; + + // Calculates how many actions need to be undone + let mut undo_queue_transaction = db.prepare( + "SELECT id, path, file, slot, action FROM history WHERE id > ?2 AND id <= ?1 ORDER BY id DESC", + )?; + let undo_queue = undo_queue_transaction.query_map([last_action, final_dest], |row| { + Ok(HistoryData { + id: row.get(0)?, + path: Some(PathBuf::from(row.get::<_, String>(1)?)), + file: row.get(2)?, + slot: row.get(3)?, + action: match row.get::<_, String>(4)?.as_str() { + "take" => Action::Take, + "drop" => Action::Drop, + "switch" => Action::Switch, + _ => unreachable!(), + }, + time: 0, + current: 0, + }) + })?; + + // Undoes actions for each step + for raw_step in undo_queue { + let step = raw_step?; + + match step.action { + Action::Take => { + item::drop( + &step.file.unwrap(), + &step.slot.unwrap(), + step.path.unwrap(), + false, + false, + false, + )?; + } + Action::Drop => { + let path: String = vec![ + String::from(step.path.unwrap().to_str().unwrap()), + step.file.unwrap(), + ] + .join("/"); + item::take(&path, step.slot.unwrap().as_str(), false, false, false)?; + } + Action::Switch => inv::switch(false, false)?, + } + + db.execute("UPDATE history SET current = 0 WHERE current = 1", ())?; + db.execute( + "UPDATE history SET current = 1 WHERE id = ?1", + [step.id - 1], + )?; } - match contents[3] { - "take" => { - let destpath = Path::new(contents[0]).to_path_buf(); - item::drop( - &String::from(contents[1]), - contents[2], - destpath, - false, - false, - )?; - } - "drop" => { - let path = vec![contents[0], contents[1]].join("/"); - item::take(&path, contents[2], false, false)?; - } - "switch" => { - inv::switch(false)?; - } - _ => throw_error(ErrorType::IllegalAction)?, - } + // Prepares to display details of the final position + let mut final_transaction = db.prepare("SELECT * FROM history WHERE current = 1")?; + let final_action_iter = final_transaction.query_map([], |row| { + Ok(HistoryData { + id: row.get(0)?, + path: Some(PathBuf::from(row.get::<_, String>(1)?)), + file: row.get(2)?, + slot: row.get(3)?, + action: match row.get::<_, String>(4)?.as_str() { + "take" => Action::Take, + "drop" => Action::Drop, + "switch" => Action::Switch, + _ => unreachable!(), + }, + time: row.get(5)?, + current: row.get::<_, i32>(5)?, + }) + })?; + + let final_action = final_action_iter.last().unwrap()?; + + // Formats the current action's timestamp to readable, local time + let timestamp = final_action.time; + let naive = NaiveDateTime::from_timestamp_opt(timestamp, 0); + let datetime = TimeZone::from_utc_datetime(&Local, &naive.unwrap()); + let newdate = datetime.format("%Y-%m-%d, %H:%M:%S"); println!( - "{}{}{}{}", + "{}{}{}{}{}{}", append_emoji(EmojiType::Success)?, - match contents[3] { - "take" => "Take", - "drop" => "Drop", - "switch" => "Switch", - _ => "Unknown", + "Rolled back to ".green(), + match final_action.action { + Action::Take => "Take", + Action::Drop => "Drop", + Action::Switch => "Switch", } .bold(), - " action undone".green(), - match contents[3] { - "take" => format!( + " action, on ".green(), + newdate, + match final_action.action { + Action::Take => format!( "{}{}{}{}{}{}{}", " (".green(), - contents[1].bold(), + final_action.file.unwrap().bold(), ", ".green(), match parse_config()?.history_display_dir { - true => format!("{} {} ", "from".green(), contents[0],), + true => format!( + "{} {} ", + "from".green(), + final_action.path.unwrap().to_str().unwrap(), + ), _ => String::new(), }, "to ".green(), - match contents[2] { - "active" => contents[2].green(), - "inactive" => contents[2].blue(), - _ => contents[2].red(), + match final_action.slot.clone().unwrap().as_str() { + "active" => final_action.slot.unwrap().green(), + "inactive" => final_action.slot.unwrap().blue(), + _ => final_action.slot.unwrap().red(), } .bold(), " slot)".green(), ), - "drop" => format!( + Action::Drop => format!( "{}{}{}{}{}{}{}", " (".green(), - contents[1].bold(), + final_action.file.unwrap().bold(), ", from ".green(), - match contents[2] { - "active" => contents[2].green(), - "inactive" => contents[2].blue(), - _ => contents[2].red(), + match final_action.slot.clone().unwrap().as_str() { + "active" => final_action.slot.unwrap().green(), + "inactive" => final_action.slot.unwrap().blue(), + _ => final_action.slot.unwrap().red(), } .bold(), " slot".green(), match parse_config()?.history_display_dir { - true => format!(" {} {}", "to".green(), contents[0],), + true => format!( + " {} {}", + "to".green(), + final_action.path.unwrap().to_str().unwrap(), + ), false => String::new(), }, ")".green(), @@ -120,3 +193,172 @@ pub fn undo() -> Result<()> { Ok(()) } + +/// Redoes actions made by Vento using the history database located on the Vento directory +pub fn redo(steps: usize) -> Result<()> { + let path: PathBuf = [ + env_config()?.vento_dir, + Path::new("history.db3").to_path_buf(), + ] + .iter() + .collect(); + let db = Connection::open(path)?; + + // Determine if step amount is greater than the position of the action + let mut current = db.prepare("SELECT id FROM history WHERE current = 1")?; + let actions = current.query_map([], |row| Ok(row.get(0)?))?; + let last_action: usize = actions.last().unwrap_or(Ok(0))?; + + // Determine table size + let mut size_transaction = db.prepare("SELECT id FROM history")?; + let size_actions = size_transaction.query_map([], |row| Ok(row.get(0)?))?; + let size: usize = size_actions.last().unwrap_or(Ok(0))?; + + if size - last_action < steps { + throw_error(ErrorType::InvalidStepsLength)?; + } + + let final_dest = last_action + steps; + + // Calculates how many actions need to be redone + let mut redo_queue_transaction = db.prepare( + "SELECT id, path, file, slot, action FROM history WHERE id > ?1 AND id <= ?2 ORDER BY id ASC", + )?; + let redo_queue = redo_queue_transaction.query_map([last_action, final_dest], |row| { + Ok(HistoryData { + id: row.get(0)?, + path: Some(PathBuf::from(row.get::<_, String>(1)?)), + file: row.get(2)?, + slot: row.get(3)?, + action: match row.get::<_, String>(4)?.as_str() { + "take" => Action::Take, + "drop" => Action::Drop, + "switch" => Action::Switch, + _ => unreachable!(), + }, + time: 0, + current: 0, + }) + })?; + + // Redoes actions for each step + for raw_step in redo_queue { + let step = raw_step?; + + match step.action { + Action::Take => { + let path: String = vec![ + String::from(step.path.unwrap().to_str().unwrap()), + step.file.unwrap(), + ] + .join("/"); + item::take(&path, step.slot.unwrap().as_str(), false, false, false)?; + } + Action::Drop => { + item::drop( + &step.file.unwrap(), + &step.slot.unwrap(), + step.path.unwrap(), + false, + false, + false, + )?; + } + Action::Switch => inv::switch(false, false)?, + } + + db.execute("UPDATE history SET current = 0 WHERE current = 1", ())?; + db.execute("UPDATE history SET current = 1 WHERE id = ?1", [step.id])?; + } + + // Prepares to display details of the final position + let mut final_transaction = db.prepare("SELECT * FROM history WHERE current = 1")?; + let final_action_iter = final_transaction.query_map([], |row| { + Ok(HistoryData { + id: row.get(0)?, + path: Some(PathBuf::from(row.get::<_, String>(1)?)), + file: row.get(2)?, + slot: row.get(3)?, + action: match row.get::<_, String>(4)?.as_str() { + "take" => Action::Take, + "drop" => Action::Drop, + "switch" => Action::Switch, + _ => unreachable!(), + }, + time: row.get(5)?, + current: row.get::<_, i32>(5)?, + }) + })?; + + let final_action = final_action_iter.last().unwrap()?; + + // Formats the current action's timestamp to readable, local time + let timestamp = final_action.time; + let naive = NaiveDateTime::from_timestamp_opt(timestamp, 0); + let datetime = TimeZone::from_utc_datetime(&Local, &naive.unwrap()); + let newdate = datetime.format("%Y-%m-%d, %H:%M:%S"); + + // Prints transaction result + println!( + "{}{}{}{}{}{}", + append_emoji(EmojiType::Success)?, + "Returned to ".green(), + match final_action.action { + Action::Take => "Take", + Action::Drop => "Drop", + Action::Switch => "Switch", + } + .bold(), + " action, on ".green(), + newdate, + match final_action.action { + Action::Take => format!( + "{}{}{}{}{}{}{}", + " (".green(), + final_action.file.unwrap().bold(), + ", ".green(), + match parse_config()?.history_display_dir { + true => format!( + "{} {} ", + "from".green(), + final_action.path.unwrap().to_str().unwrap(), + ), + _ => String::new(), + }, + "to ".green(), + match final_action.slot.clone().unwrap().as_str() { + "active" => final_action.slot.unwrap().green(), + "inactive" => final_action.slot.unwrap().blue(), + _ => final_action.slot.unwrap().red(), + } + .bold(), + " slot)".green(), + ), + Action::Drop => format!( + "{}{}{}{}{}{}{}", + " (".green(), + final_action.file.unwrap().bold(), + ", from ".green(), + match final_action.slot.clone().unwrap().as_str() { + "active" => final_action.slot.unwrap().green(), + "inactive" => final_action.slot.unwrap().blue(), + _ => final_action.slot.unwrap().red(), + } + .bold(), + " slot".green(), + match parse_config()?.history_display_dir { + true => format!( + " {} {}", + "to".green(), + final_action.path.unwrap().to_str().unwrap(), + ), + false => String::new(), + }, + ")".green(), + ), + _ => String::from(""), + } + ); + + Ok(()) + } diff --git a/src/inv.rs b/src/inv.rs index 2f1faa3..011d4a1 100644 --- a/src/inv.rs +++ b/src/inv.rs @@ -178,7 +178,7 @@ pub fn list(slot: &str, dir: &str, display_slot: bool) -> Result<()> { } /// Switches inevntory slots between each other, making the currently active inventory inactive and viceversa -pub fn switch(message: bool) -> Result<()> { +pub fn switch(message: bool, save_history: bool) -> Result<()> { let ventodir = &common::env_config()?.vento_dir; let active = &common::env_config()?.active_dir; let inactive = &common::env_config()?.inactive_dir; @@ -192,12 +192,17 @@ pub fn switch(message: bool) -> Result<()> { fs::rename(inactive, active).context(rename_error)?; fs::rename(&temp, inactive).context(rename_error)?; - common::history(common::HistoryData { - path: PathBuf::new(), - file: String::new(), - slot: String::new(), - action: common::Action::Switch, - })?; + if save_history { + common::history(common::HistoryData { + id: 0, + path: None, + file: None, + slot: None, + action: common::Action::Switch, + current: 1, + time: 0, + })?; + } if message { println!( diff --git a/src/item.rs b/src/item.rs index ffdafc2..68c3676 100644 --- a/src/item.rs +++ b/src/item.rs @@ -28,7 +28,7 @@ use std::fs; use std::path::{Path, PathBuf}; /// Takes a file or directory and stores it in an inventory slot -pub fn take(file: &String, slot: &str, message: bool, display_slot: bool) -> Result<()> { +pub fn take(file: &String, slot: &str, message: bool, display_slot: bool, save_history: bool) -> Result<()> { let ventodir = &env_config()?.vento_dir; if !ventodir.is_dir() { @@ -78,12 +78,17 @@ pub fn take(file: &String, slot: &str, message: bool, display_slot: bool) -> Res throw_error(ErrorType::NoFileOrDir)?; } - history(HistoryData { - path: sourcelocation.clone(), - file: String::from(filename), - slot: String::from(slot), - action: Action::Take, - })?; + if save_history { + history(HistoryData { + id: 0, + path: Some(sourcelocation.clone()), + file: Some(String::from(filename)), + slot: Some(String::from(slot)), + action: Action::Take, + current: 1, + time: 0, + })?; + } if message { println!( @@ -125,6 +130,7 @@ pub fn drop( dest: PathBuf, message: bool, display_slot: bool, + save_history: bool ) -> Result<()> { // Drops a file or directory let ventodir = &env_config()?.vento_dir; @@ -180,12 +186,17 @@ pub fn drop( destpath.pop(); - history(HistoryData { - path: destpath.clone(), - file: String::from(file), - slot: String::from(slot), - action: Action::Drop, - })?; + if save_history { + history(HistoryData { + id: 0, + path: Some(destpath.clone()), + file: Some(String::from(file)), + slot: Some(String::from(slot)), + action: Action::Drop, + current: 1, + time: 0, + })?; + } if message { println!( diff --git a/src/message.rs b/src/message.rs index 61a9f7b..0afa2fe 100644 --- a/src/message.rs +++ b/src/message.rs @@ -28,6 +28,7 @@ pub enum ErrorType { NoCurrentDirectory, NoHomeDirectory, InvalidHistoryLength, + InvalidStepsLength, IllegalAction, NotInitialized, NoAccessParent, @@ -68,7 +69,8 @@ pub fn throw_error(error: ErrorType) -> Result<()> { ErrorType::SpecifySlot => "You need to specify a slot", ErrorType::NoCurrentDirectory => "Vento was unable to detect your current directory. Have you configured your environment correctly?", ErrorType::NoHomeDirectory => "Vento was unable to detect your home directory. Have you configured your environment correctly?", - ErrorType::InvalidHistoryLength => "Invalid history length", + ErrorType::InvalidHistoryLength => "Invalid history length", + ErrorType::InvalidStepsLength => "Invalid steps length", ErrorType::IllegalAction => "Illegal action", ErrorType::NotInitialized => "Vento not initialized. Run \"vento -i\" to initialize Vento", ErrorType::NoAccessParent => "Cannot access parent",