generated from PlexSheep/baserepo
Compare commits
No commits in common. "6a7974a0a6a043c75f7b42d957d188aa318ec27f" and "216b89606747bcc224fac7464203afe08877a643" have entirely different histories.
6a7974a0a6
...
216b896067
5 changed files with 13 additions and 76 deletions
|
@ -12,9 +12,6 @@ repository.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["log"]
|
default = ["log"]
|
||||||
log = ["dep:libpt-log", "dep:log"]
|
log = ["dep:libpt-log", "dep:log"]
|
||||||
|
@ -25,7 +22,6 @@ clap = { version = "4.5.7", features = ["derive"] }
|
||||||
comfy-table = "7.1.1"
|
comfy-table = "7.1.1"
|
||||||
console = "0.15.8"
|
console = "0.15.8"
|
||||||
dialoguer = { version = "0.11.0", features = ["completion", "history"] }
|
dialoguer = { version = "0.11.0", features = ["completion", "history"] }
|
||||||
embed-doc-image = "0.1.4"
|
|
||||||
exitcode = "1.1.2"
|
exitcode = "1.1.2"
|
||||||
human-panic = "2.0.0"
|
human-panic = "2.0.0"
|
||||||
indicatif = "0.17.8"
|
indicatif = "0.17.8"
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 142 KiB |
|
@ -1,61 +1,13 @@
|
||||||
//! This module implements a default repl that fullfills the [Repl] trait
|
|
||||||
//!
|
|
||||||
//! You can implement your own [Repl] if you want.
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use super::Repl;
|
use super::Repl;
|
||||||
|
|
||||||
use embed_doc_image::embed_doc_image;
|
|
||||||
|
|
||||||
/// [clap] help template with only usage and commands/options
|
|
||||||
pub const REPL_HELP_TEMPLATE: &str = r#"{usage-heading} {usage}
|
|
||||||
|
|
||||||
{all-args}{tab}
|
|
||||||
"#;
|
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use dialoguer::{BasicHistory, Completion};
|
use dialoguer::{BasicHistory, Completion};
|
||||||
use libpt_log::trace;
|
use libpt_log::trace;
|
||||||
|
|
||||||
#[allow(clippy::needless_doctest_main)] // It makes the example look better
|
|
||||||
/// Default implementation for a REPL
|
|
||||||
///
|
|
||||||
/// Note that you need to define the commands by yourself with a Subcommands enum.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```no_run
|
|
||||||
/// use libpt_cli::repl::{DefaultRepl, Repl};
|
|
||||||
/// use libpt_cli::clap::Subcommand;
|
|
||||||
/// use libpt_cli::strum::EnumIter;
|
|
||||||
///
|
|
||||||
/// #[derive(Subcommand, Debug, EnumIter, Clone)]
|
|
||||||
/// enum ReplCommand {
|
|
||||||
/// /// hello world
|
|
||||||
/// Hello,
|
|
||||||
/// /// leave the repl
|
|
||||||
/// Exit,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// let mut repl = DefaultRepl::<ReplCommand>::default();
|
|
||||||
/// loop {
|
|
||||||
/// repl.step().unwrap();
|
|
||||||
/// match repl.command().to_owned().unwrap() {
|
|
||||||
/// ReplCommand::Hello => println!("Hello"),
|
|
||||||
/// ReplCommand::Exit => break,
|
|
||||||
/// _ => (),
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// **Screenshot**
|
|
||||||
///
|
|
||||||
/// ![Screenshot of an example program with a REPL][repl_screenshot]
|
|
||||||
#[embed_doc_image("repl_screenshot", "data/media/repl.png")]
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(multicall = true, help_template = REPL_HELP_TEMPLATE)]
|
#[command(multicall = true)]
|
||||||
pub struct DefaultRepl<C>
|
pub struct DefaultRepl<C>
|
||||||
where
|
where
|
||||||
C: Debug,
|
C: Debug,
|
||||||
|
@ -79,7 +31,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
struct DefaultReplCompletion<C>
|
pub struct DefaultReplCompletion<C>
|
||||||
where
|
where
|
||||||
C: Debug,
|
C: Debug,
|
||||||
C: Subcommand,
|
C: Subcommand,
|
||||||
|
@ -106,6 +58,12 @@ where
|
||||||
fn command(&self) -> &Option<C> {
|
fn command(&self) -> &Option<C> {
|
||||||
&self.command
|
&self.command
|
||||||
}
|
}
|
||||||
|
#[allow(refining_impl_trait)]
|
||||||
|
fn completion() -> DefaultReplCompletion<C> {
|
||||||
|
DefaultReplCompletion {
|
||||||
|
commands: std::marker::PhantomData::<C>,
|
||||||
|
}
|
||||||
|
}
|
||||||
fn step(&mut self) -> Result<(), super::error::ReplError> {
|
fn step(&mut self) -> Result<(), super::error::ReplError> {
|
||||||
self.buf.clear();
|
self.buf.clear();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
//! Errors for the Repl module
|
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
|
@ -1,16 +1,3 @@
|
||||||
//! Create easy and well defined REPLs
|
|
||||||
//!
|
|
||||||
//! A REPL is a [Read-Eval-Print-Loop](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop).
|
|
||||||
//! Well known examples for REPLs are shells (like bash).
|
|
||||||
//!
|
|
||||||
//! This module offers a convenient way to create a well-defined REPL without a lot of complicated
|
|
||||||
//! code and with a visually pleasing aesthetic. An example REPL implementation can be found in the
|
|
||||||
//! examples.
|
|
||||||
//!
|
|
||||||
//! The basic idea is that the user defines the commands with an enum and uses [claps](clap)
|
|
||||||
//! `#[derive(Subcommand)]`. A loop is then used to read from the stdin into a buffer, that buffer
|
|
||||||
//! is put to [clap] for parsing, similar to how [clap] would parse commandline arguments.
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -19,10 +6,8 @@ mod default;
|
||||||
pub use default::*;
|
pub use default::*;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use dialoguer::Completion;
|
||||||
|
|
||||||
/// Common Trait for repl objects
|
|
||||||
///
|
|
||||||
/// Unless you want to implement custom features (not just commands), just use [DefaultRepl].
|
|
||||||
pub trait Repl<C>: Parser + Debug
|
pub trait Repl<C>: Parser + Debug
|
||||||
where
|
where
|
||||||
C: Debug,
|
C: Debug,
|
||||||
|
@ -33,12 +18,12 @@ where
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
/// get the command that was parsed from user input
|
/// get the command that was parsed from user input
|
||||||
///
|
///
|
||||||
/// Will only be [None] if the repl has not had [step](Repl::step) executed yet.
|
/// Will only be [None] if the repl has not had [step] executed yet.
|
||||||
fn command(&self) -> &Option<C>;
|
fn command(&self) -> &Option<C>;
|
||||||
|
/// return all possible commands in this repl
|
||||||
|
fn completion() -> impl Completion;
|
||||||
/// advance the repl to the next iteration of the main loop
|
/// advance the repl to the next iteration of the main loop
|
||||||
///
|
///
|
||||||
/// This should be used at the start of your loop.
|
/// This should be used at the start of your loop
|
||||||
///
|
|
||||||
/// Note that the help menu is an Error: [clap::error::ErrorKind::DisplayHelp]
|
|
||||||
fn step(&mut self) -> Result<(), ReplError>;
|
fn step(&mut self) -> Result<(), ReplError>;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue