aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/example-dispatch-tree/src/main.rs7
-rw-r--r--examples/example-exit-code/src/main.rs6
-rw-r--r--examples/example-repl/Cargo.lock92
-rw-r--r--examples/example-repl/Cargo.toml8
-rw-r--r--examples/example-repl/src/main.rs142
5 files changed, 248 insertions, 7 deletions
diff --git a/examples/example-dispatch-tree/src/main.rs b/examples/example-dispatch-tree/src/main.rs
index 90879e5..d8be32a 100644
--- a/examples/example-dispatch-tree/src/main.rs
+++ b/examples/example-dispatch-tree/src/main.rs
@@ -13,7 +13,7 @@
//!
//! ```bash
//! cargo expand --manifest-path examples/example-dispatch-tree/Cargo.toml > expanded.rs
-//! cat expanded.rs | grep dispatch_args_trie -A 264
+//! cat expanded.rs
//! ```
#![allow(unused_mut)]
@@ -23,11 +23,10 @@ use mingling::prelude::*;
fn main() {
let mut program = ThisProgram::new();
- // After enabling `dispatch_tree`, this method will no longer exist
+ // // After enabling `dispatch_tree`, this method will no longer exist
// program.with_dispatcher(CommandGreet);
//
- // The `CompletionDispatcher` automatically generated by `comp` will also be imported
- // automatically
+ // // The `CompletionDispatcher` automatically generated by `comp` will also be imported automatically
// program.with_dispatcher(CompletionDispatcher);
program.exec();
diff --git a/examples/example-exit-code/src/main.rs b/examples/example-exit-code/src/main.rs
index 028692e..39428e9 100644
--- a/examples/example-exit-code/src/main.rs
+++ b/examples/example-exit-code/src/main.rs
@@ -13,7 +13,7 @@
use mingling::prelude::*;
use mingling::{
- res::{exit_code, update_exit_code},
+ res::{ExitCode, exit_code},
setup::ExitCodeSetup,
};
@@ -28,8 +28,8 @@ dispatcher!("error", ErrorCommand => ErrorEntry);
pack!(ResultError = ());
#[chain]
-fn handle_error_entry(_prev: ErrorEntry) -> Next {
- update_exit_code::<ThisProgram>(1);
+fn handle_error_entry(_prev: ErrorEntry, ec: &mut ExitCode) -> Next {
+ ec.exit_code = 1;
return ResultError::default();
}
diff --git a/examples/example-repl/Cargo.lock b/examples/example-repl/Cargo.lock
new file mode 100644
index 0000000..cabbe98
--- /dev/null
+++ b/examples/example-repl/Cargo.lock
@@ -0,0 +1,92 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "example-repl"
+version = "0.0.1"
+dependencies = [
+ "just_fmt",
+ "mingling",
+]
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "mingling"
+version = "0.1.9"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+ "size",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.1.9"
+dependencies = [
+ "just_fmt",
+ "once_cell",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.1.9"
+dependencies = [
+ "just_fmt",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "size"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b6709c7b6754dca1311b3c73e79fcce40dd414c782c66d88e8823030093b02b"
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/examples/example-repl/Cargo.toml b/examples/example-repl/Cargo.toml
new file mode 100644
index 0000000..34b85e3
--- /dev/null
+++ b/examples/example-repl/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "example-repl"
+version = "0.0.1"
+edition = "2024"
+
+[dependencies]
+mingling = { path = "../../mingling", features = ["repl", "parser"] }
+just_fmt = "0.1.2"
diff --git a/examples/example-repl/src/main.rs b/examples/example-repl/src/main.rs
new file mode 100644
index 0000000..2eb92e1
--- /dev/null
+++ b/examples/example-repl/src/main.rs
@@ -0,0 +1,142 @@
+use mingling::{REPL, hook::ProgramHook, prelude::*, this};
+use std::{env::current_dir, path::PathBuf};
+
+// Resource to store the current directory
+#[derive(Clone)]
+struct CurrentDir {
+ dir: PathBuf,
+}
+
+impl Default for CurrentDir {
+ fn default() -> Self {
+ Self {
+ dir: current_dir().unwrap(),
+ }
+ }
+}
+
+fn main() {
+ let mut program = ThisProgram::new();
+
+ // Add resource
+ program.with_resource(CurrentDir::default());
+
+ // Add dispatchers
+ program.with_dispatcher(ChangeDirectoryCommand);
+ program.with_dispatcher(ListCommand);
+ program.with_dispatcher(ExitCommand);
+
+ // Add hooks to handle REPL-related events
+ program.with_hook(
+ ProgramHook::empty()
+ .on_repl_begin(|| {
+ // Print welcome message
+ println!("Welcome!")
+ })
+ .on_repl_pre_readline(|| {
+ // Print prompt
+ let res = this::<ThisProgram>().res::<CurrentDir>().unwrap();
+ let dir_str: String = res.dir.to_string_lossy().into();
+ let prompt = format!(
+ "{}> ",
+ dir_str
+ .replace(&['/', '\\'][..], ">")
+ .trim_start_matches('>')
+ .trim_end_matches('>')
+ );
+ print!("{}", prompt)
+ })
+ .on_repl_receive_result(|r| {
+ // Print output
+ if !r.is_empty() {
+ println!("{}", r.trim())
+ }
+ }),
+ );
+
+ // Start the REPL loop
+ program.exec_repl();
+}
+
+// Create error route
+pack!(ErrorDirectoryNotExist = PathBuf);
+
+// Create commands: cd ls exit
+dispatcher!("cd", ChangeDirectoryCommand => ChangeDirectoryEntry);
+dispatcher!("ls", ListCommand => ListEntry);
+dispatcher!("exit", ExitCommand => ExitEntry);
+
+// Define data needed for the cd command's execution phase
+pack!(StateChangeDirectory = String);
+
+// Define data needed for the ls command's rendering phase
+pack!(ResultList = Vec<String>);
+
+// Parse cd command arguments
+#[chain]
+fn parse_cd_args(prev: ChangeDirectoryEntry) -> Next {
+ let join = prev.pick(()).unpack();
+ StateChangeDirectory::new(join)
+}
+
+// Execute directory change
+#[chain]
+fn handle_cd(prev: StateChangeDirectory, current_dir: &mut CurrentDir) -> Next {
+ let join = prev.inner;
+ let new_dir = just_fmt::fmt_path::fmt_path(current_dir.dir.join(join)).unwrap_or_default();
+
+ // If the path is not found, route to error handling
+ if !new_dir.exists() {
+ return ErrorDirectoryNotExist::new(new_dir).to_render();
+ }
+
+ current_dir.dir = new_dir;
+ empty_result!()
+}
+
+// Get directory contents via the CurrentDir resource
+#[chain]
+fn handle_ls(_prev: ListEntry, current_dir: &CurrentDir) -> Next {
+ let dir = &current_dir.dir;
+ let entries: Vec<String> = std::fs::read_dir(dir)
+ .into_iter()
+ .flat_map(|rd| rd.filter_map(|e| e.ok()))
+ .map(|e| {
+ let name = e.file_name().to_string_lossy().to_string();
+ if e.file_type().map(|t| t.is_dir()).unwrap_or(false) {
+ format!("{}/", name)
+ } else {
+ name
+ }
+ })
+ .collect();
+
+ // Render ResultList
+ ResultList::new(entries).to_render()
+}
+
+// Render ResultList data
+#[renderer]
+fn render_list(list: ResultList) {
+ for item in list.inner {
+ r_println!("{}", item)
+ }
+}
+
+// Handle exit command event
+#[chain]
+fn handle_exit(
+ _prev: ExitEntry,
+ repl: &mut REPL, // Import REPL resource, registered in `exec_repl`, usable directly
+) {
+ // Set the REPL exit flag; REPL will exit after this loop iteration
+ repl.exit = true;
+}
+
+// Handle path not found event
+#[renderer]
+fn render_error_directory_not_exist(err: ErrorDirectoryNotExist) {
+ r_println!("Directory not found: {}", err.inner.display())
+}
+
+gen_program!();