diff options
| author | Daniel <kingdread@gmx.de> | 2020-05-03 17:34:28 +0200 | 
|---|---|---|
| committer | Daniel <kingdread@gmx.de> | 2020-05-03 17:34:28 +0200 | 
| commit | 18544e32ecd1d3bc3535214f0c2edca38346e3a5 (patch) | |
| tree | 3334b84a9bb014dcf5ffc768148ecd295afb78b2 | |
| parent | 913bc8c547e97a785cf1cd9fc20f8377f898da2c (diff) | |
| download | raidgrep-18544e32ecd1d3bc3535214f0c2edca38346e3a5.tar.gz raidgrep-18544e32ecd1d3bc3535214f0c2edca38346e3a5.tar.bz2 raidgrep-18544e32ecd1d3bc3535214f0c2edca38346e3a5.zip | |
save REPL history to a file
This persists the REPL history across program restarts.
The code should probably be cleaned up a bit more, the error handling in
this one is a bit all over the place. This is because we don't want to
make it a hard error in case the history cannot be saved.
| -rw-r--r-- | src/guilds.rs | 13 | ||||
| -rw-r--r-- | src/main.rs | 39 | ||||
| -rw-r--r-- | src/paths.rs | 19 | 
3 files changed, 60 insertions, 11 deletions
| diff --git a/src/guilds.rs b/src/guilds.rs index 0eff6ad..24ec817 100644 --- a/src/guilds.rs +++ b/src/guilds.rs @@ -1,7 +1,8 @@  //! Guild name retrieval and caching functions. +use super::paths; +  use std::collections::HashMap;  use std::fs::File; -use std::path::PathBuf;  use std::sync::RwLock;  use once_cell::sync::Lazy; @@ -52,15 +53,9 @@ pub fn lookup(api_id: &str) -> Option<Guild> {      Some(guild)  } -fn cache_path() -> PathBuf { -    let mut cache_path = dirs::cache_dir().unwrap(); -    cache_path.push("raidgrep"); -    cache_path -} -  /// Loads the cache from the file system.  pub fn prepare_cache() { -    let path = cache_path(); +    let path = paths::cache_path();      if !path.is_file() {          return;      } @@ -73,7 +68,7 @@ pub fn prepare_cache() {  /// Saves the cache to the file system  pub fn save_cache() { -    let path = cache_path(); +    let path = paths::cache_path();      let file = File::create(path).expect("Cannot open cache for writing");      serde_json::to_writer(file, &*CACHE.read().unwrap()).unwrap();  } diff --git a/src/main.rs b/src/main.rs index fd3399b..5b6d57f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@  #![feature(trait_alias)]  use std::collections::HashMap;  use std::fmt; -use std::fs::File; +use std::fs::{self, File};  use std::io::{BufReader, Read, Seek}; -use std::path::PathBuf; +use std::path::{Path, PathBuf};  use std::str::FromStr;  use std::sync::atomic::{AtomicBool, Ordering}; @@ -25,6 +25,10 @@ use filters::{log::LogFilter, Inclusion};  mod guilds;  mod logger;  mod output; +mod paths; + +/// Application name, as it should be used in configuration directory paths. +const APP_NAME: &str = "raidgrep";  /// A program that allows you to search through all your evtc logs for specific people.  /// @@ -299,9 +303,18 @@ fn repl(opt: &Opt) -> Result<()> {          .expect("Could not set interrupt hanlder");      let mut rl = Editor::<()>::new(); +    let history_path = paths::history_path(); +    if history_path.is_none() { +        debug!("Could not determine the history path"); +    } + +    maybe_load_history(&mut rl, history_path.as_ref().map(|r| r as &Path)); +      loop {          let line = rl.readline("Query> ")?;          rl.add_history_entry(&line); +        maybe_save_history(&rl, history_path.as_ref().map(|r| r as &Path)); +          let parsed = build_filter(&line);          INTERRUPTED.store(false, Ordering::Relaxed);          match parsed { @@ -311,6 +324,28 @@ fn repl(opt: &Opt) -> Result<()> {      }  } +fn maybe_load_history(rl: &mut Editor<()>, path: Option<&Path>) { +    if let Some(path) = path { +        debug!("Loading history from {:?}", path); +        if let Err(e) = rl.load_history(path) { +            debug!("Loading the history failed: {}", e); +        } +    } +} + +fn maybe_save_history(rl: &Editor<()>, path: Option<&Path>) { +    if let Some(path) = path { +        debug!("Saving history to {:?}", path); +        let result: Result<(), Box<dyn std::error::Error>> = +            fs::create_dir_all(path.parent().unwrap()) +                .map_err(Into::into) +                .and_then(|_| rl.save_history(path).map_err(Into::into)); +        if let Err(e) = result { +            debug!("Saving the history failed: {}", e); +        } +    } +} +  /// Check if the given entry represents a log file, based on the file name.  fn is_log_file(entry: &DirEntry) -> bool {      entry diff --git a/src/paths.rs b/src/paths.rs new file mode 100644 index 0000000..f219dc4 --- /dev/null +++ b/src/paths.rs @@ -0,0 +1,19 @@ +//! Module to resolve application-specific paths. +use super::APP_NAME; + +use std::path::PathBuf; + +/// Returns the path that should be used for the cache. +pub fn cache_path() -> PathBuf { +    let mut cache_path = dirs::cache_dir().unwrap(); +    cache_path.push(APP_NAME); +    cache_path +} + +/// Returns the path that should be used for the REPL history. +pub fn history_path() -> Option<PathBuf> { +    let mut config_path = dirs::config_dir()?; +    config_path.push(APP_NAME); +    config_path.push("history"); +    Some(config_path) +} | 
