parent
1698eaa37d
commit
e8d215a65f
@ -0,0 +1,124 @@
|
|||||||
|
//! Graph inspection REPL
|
||||||
|
use super::*;
|
||||||
|
use std::{fmt, error};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use rustyline::error::ReadlineError;
|
||||||
|
use rustyline::Editor;
|
||||||
|
|
||||||
|
/// Default history file name
|
||||||
|
///
|
||||||
|
/// # Path lookup
|
||||||
|
/// * To make this an absolute path, start it with `/`
|
||||||
|
/// * To make this path relative to the user's home directory, start it with `~/` (Note: If we are unable to find the user's home directory, it is considered a lookup **failure** (*not* a **disable**) and `calculate_history_path()` will return `Err`.)
|
||||||
|
/// * Otherwise, the path is taken relative to the current working directory
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// This is only used when the `save-history` feature is enabled.
|
||||||
|
const DEFAULT_HISTORY_FILE: &'static str = "~/.dirstat_history";
|
||||||
|
|
||||||
|
/// Get the path to the history file.
|
||||||
|
///
|
||||||
|
/// # Lookup
|
||||||
|
/// * If the `DIRSTAT_HISTORY` envvar is set and not empty, use this file path.
|
||||||
|
/// * If the `DIRSTAT_HISTORY` envvar is set and empty, saving history is considered **disabled**, we return `Ok(None)`.
|
||||||
|
/// * Otherwise, refer to lookup rules for `DEFAULT_HISTORY_FILE`.
|
||||||
|
pub fn calculate_history_path() -> io::Result<Option<PathBuf>>
|
||||||
|
{
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature="save-history")] {
|
||||||
|
todo!()
|
||||||
|
} else {
|
||||||
|
unreachable!("Tried to calculate repl history path when binary was compiled with history saving perma-disabled.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inspect the graph with commands
|
||||||
|
pub fn inspect(cfg: &Config, graph: &HierarchicalINodeGraph) -> Result<(), ReplExitError>
|
||||||
|
{
|
||||||
|
let mut repl = Editor::<()>::new(); //TODO: Change `()` to our completer, when we have a decent idea of how they'll work.
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature="save-history")] {
|
||||||
|
let history_path = match calculate_history_path() {
|
||||||
|
Ok(Some(path)) => {
|
||||||
|
if let Err(err) = repl.load_history(&path)
|
||||||
|
{
|
||||||
|
cfg_eprintln!(cfg, "Failed to load repl history from {:?}: {}", path, err);
|
||||||
|
}
|
||||||
|
Some(path)
|
||||||
|
},
|
||||||
|
Ok(None) => None,
|
||||||
|
Err(err)
|
||||||
|
{
|
||||||
|
cfg_eprintln!(cfg, "Failed to find repl history: {}", err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let res: Result<(), ReplExitError> = try {
|
||||||
|
loop {
|
||||||
|
let line = repl.readline("> ")?;
|
||||||
|
repl.add_history_entry(&line);
|
||||||
|
|
||||||
|
//TODO: How to interpret commands?
|
||||||
|
todo!("Interpret commands from `line`.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature="save-history")] {
|
||||||
|
if let Some(path) = history_path {
|
||||||
|
if let Err(err) = repl.save_history(&path)
|
||||||
|
{
|
||||||
|
cfg_eprintln!(cfg, "Failed to save repl history to {:?}: {}", path, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When the inspection repl exists abnormally.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ReplExitError
|
||||||
|
{
|
||||||
|
ReadLine(ReadlineError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ReadlineError> for ReplExitError
|
||||||
|
{
|
||||||
|
#[inline] fn from(from: ReadlineError) -> Self
|
||||||
|
{
|
||||||
|
Self::ReadLine(from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for ReplExitError
|
||||||
|
{
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
Some(match &self
|
||||||
|
{
|
||||||
|
Self::ReadLine(rl) => rl
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for ReplExitError
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
|
{
|
||||||
|
match self
|
||||||
|
{
|
||||||
|
Self::ReadLine(ReadlineError::Eof) |
|
||||||
|
Self::ReadLine(ReadlineError::Interrupted) => write!(f, "exit"),
|
||||||
|
Self::ReadLine(_) => write!(f, "readline error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue