3434 * [ Full SDK Docs] ( https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md )
3535 * [ Final Notes] ( #tutorial-final-notes )
3636* [ Duckscript Command Implementation Tutorial] ( #sdk-tutorial )
37- * [ Standard Commands] ( #sdk-tutorial-standard -commands )
38- * [ Context Commands ] ( #sdk-tutorial-context- commands )
37+ * [ Commands] ( #sdk-tutorial-commands )
38+ * [ Access The Context ] ( #sdk-tutorial-commands-context )
3939* [ Duckscript Embedding Tutorial] ( #embed-tutorial )
4040 * [ Setting Up The Context] ( #embed-tutorial-setup-context )
4141 * [ Running The Script] ( #embed-tutorial-running )
@@ -401,21 +401,16 @@ If you want to know how to write your own commands or embed the duckscript runti
401401Want to write new custom commands so you can use them in your duckscripts? great!<br>
402402Hopefully the following sections will help you gain the basic knowledge on how to write them.<br>
403403
404- First of all it is important to understand that there are two types of commands:
405-
406- * Commands which execute some action like copying files, printing some text to the console or returning an environment variable.
407- * Commands which provide flow control or some more complex action and require modifying the internal context in runtime.
408-
409- <a name="sdk-tutorial-standard-commands"></a>
410- ## Standard Commands
404+ <a name="sdk-tutorial-commands"></a>
405+ ## Commands
411406Commands are structs that must implement the Command trait.<br>
412407
413408* They must have a name, which is used to invoke the command.<br>
414409* They optionally may have aliases which can also be used to invoke the command.<br>
415410* They should return help documentation in markdown format in order to generate SDK documentation (must for PRs to duckscript official SDK).<br>
416411* They must implement the **run** function which holds the command logic.<br>
417412
418- The run function accepts the command arguments (variables already replaced to actual values) and returns the command result.<br>
413+ The run function accepts the command arguments (args array contains actual values and not original variables ) and returns the command result.<br>
419414The command result can be one of the following:
420415
421416* Continue(Option<String>) - Tells the runner to continue to the next command and optionally set the output variable the given value.
@@ -438,11 +433,15 @@ impl Command for SetCommand {
438433 " set" .to_string()
439434 }
440435
441- fn run(& self, arguments: Vec< String> ) -> CommandResult {
442- let output = if arguments.is_empty () {
436+ fn clone_and_box(& self) -> Box< dyn Command> {
437+ Box::new((*self).clone ())
438+ }
439+
440+ fn run(& self, arguments: CommandArgs) -> CommandResult {
441+ let output = if arguments.args.is_empty () {
443442 None
444443 } else {
445- Some(arguments[0].clone ())
444+ Some(arguments.args [0].clone ())
446445 };
447446
448447 CommandResult::Continue(output)
@@ -465,11 +464,15 @@ impl Command for GetEnvCommand {
465464 "get_env".to_string()
466465 }
467466
468- fn run(&self, arguments: Vec<String>) -> CommandResult {
469- if arguments.is_empty() {
467+ fn clone_and_box(&self) -> Box<dyn Command> {
468+ Box::new((*self).clone())
469+ }
470+
471+ fn run(&self, arguments: CommandArgs) -> CommandResult {
472+ if arguments.args.is_empty() {
470473 CommandResult::Error("Missing environment variable name.".to_string())
471474 } else {
472- match env::var(&arguments[0]) {
475+ match env::var(&arguments.args [0]) {
473476 Ok(value) => CommandResult::Continue(Some(value)),
474477 Err(_) => CommandResult::Continue(None),
475478 }
@@ -480,38 +483,23 @@ impl Command for GetEnvCommand {
480483
481484You can look at more examples in the duckscript_sdk folder.
482485
483- <a name="sdk-tutorial-context-commands"></a>
484- ## Context Commands
485- Context commands are exactly the same as standard commands except that they have access to the runtime context.<br>
486- Therefore they implement the same Command trait but this time instead of implementing the run function, they need to implement the following:
487-
488- * requires_context - Must return true
489- * run_with_context - The same logic you would put in the run function but now you have access to a lot more of the runtime context.
490-
491- The run_with_context signature is as follows:
486+ <a name="sdk-tutorial-commands-context"></a>
487+ ## Access The Context
488+ The duckscript runtime context is available in the CommandArgs struc.<br>
492489
493490```rust
494491/// Run the instruction with access to the runtime context.
495492///
496- /// # Arguments
497- ///
498- /// * `arguments` - The command arguments array
493+ /// The CommandArgs has the following members:
494+ /// * `args` - The command arguments array
499495/// * `state` - Internal state which is only used by commands to store/pull data
500496/// * `variables` - All script variables
501497/// * `output_variable` - The output variable name (if defined)
502498/// * `instructions` - The entire list of instructions which make up the currently running script
503499/// * `commands` - The currently known commands
504500/// * `line` - The current instruction line number (global line number after including all scripts into one global script)
505- fn run_with_context(
506- &self,
507- arguments: Vec<String>,
508- state: &mut HashMap<String, StateValue>,
509- variables: &mut HashMap<String, String>,
510- output_variable: Option<String>,
511- instructions: &Vec<Instruction>,
512- commands: &mut Commands,
513- line: usize,
514- ) -> CommandResult;
501+ /// * `env` - The current runtime env with access to out/err writers, etc...
502+ fn run(&self, arguments: CommandArgs) -> CommandResult;
515503```
516504
517505With access to this context you can add/remove/switch commands in runtime, store/pull internal state, add/remove/change variables and so on...
@@ -524,7 +512,7 @@ The duckscript cli basically embeds duckscript so you can look at it as a refere
524512```rust
525513let mut context = Context::new();
526514duckscriptsdk::load(&mut context.commands)?;
527- runner::run_script_file(file, context)?;
515+ runner::run_script_file(file, context, None )?;
528516```
529517
530518That' s it! < br>
@@ -547,10 +535,10 @@ The following public functions are available:
547535
548536```rust
549537/// Executes the provided script with the given context
550- pub fn run_script(text: &str, context: Context) -> Result<Context, ScriptError>;
538+ pub fn run_script(text: &str, context: Context, env: Option<Env> ) -> Result<Context, ScriptError>;
551539
552540/// Executes the provided script file with the given context
553- pub fn run_script_file(file: &str, context: Context) -> Result<Context, ScriptError>;
541+ pub fn run_script_file(file: &str, context: Context, env: Option<Env> ) -> Result<Context, ScriptError>;
554542```
555543
556544<a name="editor-support"></a>
0 commit comments