{"id":13665638,"url":"https://github.com/sagiegurari/duckscript","last_synced_at":"2025-05-14T04:09:25.114Z","repository":{"id":36913835,"uuid":"227542815","full_name":"sagiegurari/duckscript","owner":"sagiegurari","description":"Simple, extendable and embeddable scripting language.","archived":false,"fork":false,"pushed_at":"2025-05-01T03:15:56.000Z","size":3373,"stargazers_count":546,"open_issues_count":30,"forks_count":52,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-05-07T18:56:45.719Z","etag":null,"topics":["interpreter","rust","rust-library","script","script-engine","script-language","script-runner","scripting","scripting-language","shell","shell-script","shell-scripting"],"latest_commit_sha":null,"homepage":"https://sagiegurari.github.io/duckscript","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sagiegurari.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-12-12T07:08:14.000Z","updated_at":"2025-04-28T06:49:17.000Z","dependencies_parsed_at":"2023-09-27T11:19:38.971Z","dependency_job_id":"48c27a7f-1e6c-4670-a6e2-ed6c1db000ad","html_url":"https://github.com/sagiegurari/duckscript","commit_stats":{"total_commits":685,"total_committers":19,"mean_commits":36.05263157894737,"dds":0.3211678832116789,"last_synced_commit":"b8411d096449686ba6acd99456a36435fb5125b8"},"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sagiegurari%2Fduckscript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sagiegurari%2Fduckscript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sagiegurari%2Fduckscript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sagiegurari%2Fduckscript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sagiegurari","download_url":"https://codeload.github.com/sagiegurari/duckscript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254070107,"owners_count":22009559,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["interpreter","rust","rust-library","script","script-engine","script-language","script-runner","scripting","scripting-language","shell","shell-script","shell-scripting"],"created_at":"2024-08-02T06:00:45.327Z","updated_at":"2025-05-14T04:09:20.089Z","avatar_url":"https://github.com/sagiegurari.png","language":"Rust","readme":"# duckscript\n\n| duckscript  | SDK     | CLI         |\n| ----------- | ------- | ----------- |\n| [![crates.io](https://img.shields.io/crates/v/duckscript.svg)](https://crates.io/crates/duckscript) | [![crates.io](https://img.shields.io/crates/v/duckscriptsdk.svg)](https://crates.io/crates/duckscriptsdk) | [![crates.io](https://img.shields.io/crates/v/duckscript_cli.svg)](https://crates.io/crates/duckscript_cli) |\n\n[![downloads](https://img.shields.io/crates/d/duckscript.svg)](https://crates.io/crates/duckscript)\n[![CI](https://github.com/sagiegurari/duckscript/workflows/CI/badge.svg?branch=master)](https://github.com/sagiegurari/duckscript/actions)\n[![codecov](https://codecov.io/gh/sagiegurari/duckscript/branch/master/graph/badge.svg)](https://codecov.io/gh/sagiegurari/duckscript)\n[![license](https://img.shields.io/crates/l/duckscript.svg)](https://github.com/sagiegurari/duckscript/blob/master/LICENSE)\n[![Built with cargo-make](https://sagiegurari.github.io/cargo-make/assets/badges/cargo-make.svg)](https://sagiegurari.github.io/cargo-make)\n\n\u003e Simple, extendable and embeddable scripting language.\n\n* [Overview](#overview)\n    * [Language Goals](#lang-goals)\n* [Installation](#installation)\n    * [Homebrew](#installation-homebrew)\n    * [Binary Release](#installation-binary-release)\n* [Duckscript Tutorial](#tutorial)\n    * [Hello World Example](#tutorial-hello-world)\n    * [Commands](#tutorial-commands)\n        * [Passing Arguments](#tutorial-commands-passing-arguments)\n        * [Storing Output](#tutorial-commands-storing-output)\n        * [Using Variables - Binding](#tutorial-commands-using-variables-binding)\n        * [Using Variables - Spread Binding](#tutorial-commands-using-variables-spread-binding)\n    * [Labels](#tutorial-labels)\n    * [Comments](#tutorial-comments)\n    * [Pre Processing](#tutorial-pre-processing)\n        * [!include_files](#tutorial-pre-processing-including-files)\n        * [!print](#tutorial-pre-processing-printout)\n    * [Standard API](#tutorial-standard-api)\n        * [Commands Instead Of Language Features](#tutorial-standard-api-commands-lang-features)\n        * [Full SDK Docs](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md)\n    * [Final Notes](#tutorial-final-notes)\n* [Duckscript Command Implementation Tutorial](#sdk-tutorial)\n    * [Commands](#sdk-tutorial-commands)\n    * [Access The Context](#sdk-tutorial-commands-context)\n* [Duckscript Embedding Tutorial](#embed-tutorial)\n    * [Setting Up The Context](#embed-tutorial-setup-context)\n    * [Running The Script](#embed-tutorial-running)\n* [Editor Support](#editor-support)\n* [Contributing](#contributing)\n* [Release History](https://github.com/sagiegurari/duckscript/blob/master/CHANGELOG.md)\n* [License](#license)\n\n\u003ca name=\"overview\"\u003e\u003c/a\u003e\n## Overview\nDuckscript is a simple, extendable and embeddable scripting language.\u003cbr\u003e\nThe language itself has only few rules and most common language features are implemented as commands rather than part of the language itself.\n\n\u003ca name=\"lang-goals\"\u003e\u003c/a\u003e\n### Language Goals\nDuckscript scripting language goals are:\n\n* Simple - This is probably the simplest language you will ever see.\n* Extendable - Instead of having common features such as functions and conditional blocks be a part of the language, they are actually part of the API. So they can easily be replaced/modified or you can add more 'feature' like commands on your own.\n* Embeddable - One of the main purposes of this language is to allow other libraries/executables/apps have scripting capability by embedding duckscript. Embedding is easy (for [rust](https://www.rust-lang.org/)) and requires only few lines of code.\n\n\u003ca name=\"installation\"\u003e\u003c/a\u003e\n## Installation\nIf you have [rust](https://www.rust-lang.org/), just run the following command\n\n```sh\ncargo install --force duckscript_cli\n```\n\nThis will install duckscript script runner, the standard duckscript SDK and the duckscript CLI.\u003cbr\u003e\nYou should then have a **duck** executable in your ~/.cargo/bin directory.\u003cbr\u003e\nMake sure to add ~/.cargo/bin directory to your PATH variable.\n\n\u003ca name=\"installation-homebrew\"\u003e\u003c/a\u003e\n### Homebrew\n\n```sh\nbrew install duckscript\n```\n\nMore details in the [brew page](https://formulae.brew.sh/formula/duckscript)\n\n\u003ca name=\"installation-binary-release\"\u003e\u003c/a\u003e\n### Binary Release\nBinary releases are available in the [github releases page](https://github.com/sagiegurari/duckscript/releases).\u003cbr\u003e\nThe following binaries are available for each release:\n\n* x86_64-unknown-linux-musl\n* x86_64-apple-darwin\n* x86_64-pc-windows-msvc\n\n\u003ca name=\"tutorial\"\u003e\u003c/a\u003e\n## Duckscript Tutorial\nThe following sections will teach you how to write and run duck scripts.\n\n\u003ca name=\"tutorial-hello-world\"\u003e\u003c/a\u003e\n### Hello World Example\nLet's take a really simple example (all examples are located in the [examples](https://github.com/sagiegurari/duckscript/tree/master/examples) directory:\n\n```sh\n# print the text \"Hello World\"\necho Hello World\n```\n\nRunning this script is done using the **duck** executable as follows:\n\n```sh\nduck ./examples/hello_world.ds\n```\n\nWe will understand more and break this down in the following sections.\n\n*Running the duck command without any arguments will open up the repl mode.*\n\n\u003ca name=\"tutorial-commands\"\u003e\u003c/a\u003e\n### Commands\nCommands are the basis of everything in duckscript.\u003cbr\u003e\nCommands may execute some action (like printing \"Hello World\" to the console) or serve as flow control (such as functions or if/else conditions).\u003cbr\u003e\nIn order to invoke an action, simply write the action name:\n\n```sh\necho\n```\n\nThe basic syntax of a command line is:\n\n```\n[:label] [output variable =] [command [arguments]]\n```\n\n\u003ca name=\"tutorial-commands-passing-arguments\"\u003e\u003c/a\u003e\n#### Passing Arguments\nCommands may accept arguments, for example the command **echo** may accept any number of arguments and it will print all of them.\u003cbr\u003e\nArguments are separated with the space character.\u003cbr\u003e\nSo in the example:\n\n```sh\n# print the text \"Hello World\"\necho Hello World\n```\n\nThe **echo** command got 2 arguments: \"Hello\" and \"World\".\u003cbr\u003e\nIf your argument contains a space, you can wrap the entire argument with the ```\"``` character as follows:\n\n```sh\n# print the text \"Hello World\"\necho \"Hello World\"\n```\n\nIn which case the **echo** command got only one argument: \"Hello World\" and prints it.\u003cbr\u003e\nYou can escape the ```\"``` character using the ```\"\\\"``` character, for example:\n\n```sh\n# print the text 'hello \"world\"'\necho \"hello \\\"world\\\"\"\n```\n\nIn the above example, the **echo** command got one argument: 'hello \"world\"' and prints it.\u003cbr\u003e\nThe ```\"\\\"``` is also used to escape the following:\n\n* \\n - End of line\n* \\r - Carriage return\n* \\t - Tab character\n\n\u003ca name=\"tutorial-commands-storing-output\"\u003e\u003c/a\u003e\n#### Storing Output\nCommands may return an output which can be stored in a variable.\u003cbr\u003e\nVariables in duckscript have no strict type.\u003cbr\u003e\nIn the following example, the **set** command takes one argument and stores it in the **out** variable.\n\n```sh\nout = set \"Hello World\"\n```\n\nDuckscript has only global scope, so once you have stored a value in a variable, you may use it anywhere in your script.\n\n\u003ca name=\"tutorial-commands-using-variables-binding\"\u003e\u003c/a\u003e\n#### Using Variables - Binding\nStored variables can be later on used as arguments for other commands.\u003cbr\u003e\nIn order to use a variable, we need to wrap it as follows: ```${variable}```.\u003cbr\u003e\n\u003cbr\u003e\nThe following example uses the **set** command to store a value in the **out** variable and then prints it:\n\n```sh\nout = set \"Hello World\"\n\n# This will print: \"The out variable holds the value: Hello World\"\necho The out variable holds the value: ${out}\n\n# This will print: \"To use the out variable just write: ${out}\"\necho To use the out variable just write: \\${out}\n```\n\nIn this example, although **out** holds the value **Hello World** which contains a space, it is still considered as a single input argument to the **echo** command.\u003cbr\u003e\nIn the second echo command we prevented the variable name from being replaced by escaping it using the ```\\``` character.\n\n\u003ca name=\"tutorial-commands-using-variables-spread-binding\"\u003e\u003c/a\u003e\n#### Using Variables - Spread Binding\n\nSpread binding provides a way to convert a variable value into multiple command arguments.\u003cbr\u003e\nFor example:\n\n```sh\nout = set \"Hello World\"\n```\n\nThe **out** variable holds the value \"Hello World\".\u003cbr\u003e\nIf we were to create an array from it using the **array** command as follows:\n\n```sh\nlist = array ${out}\n```\n\nThe array would be of size 1 and its only entry value would be \"Hello World\".\u003cbr\u003e\nSo it is the same as if we wrote:\n\n```sh\nlist = array \"Hello World\"\n```\n\nBut what if we want to split the value to multiple parts separated by spaces?\u003cbr\u003e\nFor that we have the spread binding which is defined as follows: ```%{variable}```.\u003cbr\u003e\nFor example:\n\n```sh\nlist = array %{out}\n```\n\nWhich would act the same as:\n\n```sh\nlist = array Hello World\n```\n\nAnd now our array is of size 2 with first entry \"Hello\" and second entry \"World\".\n\n\u003ca name=\"tutorial-labels\"\u003e\u003c/a\u003e\n### Labels\nLabels are simple textual names you can give to a specific line.\u003cbr\u003e\nCommands like **goto** can then be used to make the script execution jump from its current position to the label position.\u003cbr\u003e\nFor example:\n\n```sh\ngoto :good\n\necho error!!!!\n\n:good echo yay!!!!\n```\n\n\u003ca name=\"tutorial-comments\"\u003e\u003c/a\u003e\n### Comments\nComments are not executed and are simply in the code for documentation purposes.\u003cbr\u003e\nA document line must start with the ```#``` character.\u003cbr\u003e\nYou can also have a comment after the command and the command will ignore it.\u003cbr\u003e\nFor example:\n\n```sh\n# This is just a comment\n\necho This will print # But this will not\n```\n\n\u003ca name=\"tutorial-pre-processing\"\u003e\u003c/a\u003e\n### Pre Processing\nPre processing is the phase that duckscript is parsing the script content.\u003cbr\u003e\nIt is possible to run specific commands at that phase to modify the script during the parsing phase.\u003cbr\u003e\n\nThe basic syntax of a pre processing command line is:\n\n```\n!command [arguments]\n```\n\n\u003ca name=\"tutorial-pre-processing-including-files\"\u003e\u003c/a\u003e\n#### !include_files\nThe include_files command enables you to load script files into the position of the pre processor command.\u003cbr\u003e\nBasically it enables you to include many scripts and generate one bigger script for runtime.\u003cbr\u003e\nThe include files command accepts any number of files and all will be loaded by the order they are defined.\u003cbr\u003e\nFor example:\n\n```sh\n# load the hello_world.ds script here\n!include_files ./hello_world.ds\n\n# load 2 scripts here. The hello_world.ds is loaded again.\n!include_files ./hello_world.ds ./use_variable.ds\n```\n\nImportant to note that the script paths included are relative to the script file including them and not to the current working directory.\n\n\u003ca name=\"tutorial-pre-processing-including-files\"\u003e\u003c/a\u003e\n#### !print\nThe print pre processing command allows to print any number of arguments, which could be useful for debugging.\u003cbr\u003e\nIn the following example, although the print command comes after the echo command, it will execute first as it is invoked in the parsing phase and not in the script execution phase which comes later:\n\n```sh\n# this will print \"Hello World during script execution\"\necho Hello World during script execution\n\n# this will print \"Hello World during parsing\"\n!print Hello World during parsing\n```\n\n\u003ca name=\"tutorial-standard-api\"\u003e\u003c/a\u003e\n### Standard API\nDuckscript is split to several modules and while the script runner does not require it, by default it will come with the standard duckscript API called the duckscript SDK.\u003cbr\u003e\nThis SDK holds the most common commands, some which execute actions (such as echo) and some which serve as flow control (such as function).\u003cbr\u003e\nThe SDK enables users to develop their scripts and have a good starting point without the need to develop the commands on their own (as that is a bit more complex).\n\n\u003ca name=\"tutorial-standard-api-commands-lang-features\"\u003e\u003c/a\u003e\n#### Commands Instead Of Language Features\nAs mentioned before, duckscript is really simple and only has few basic rules.\u003cbr\u003e\nIn order to provide a more richer development experience, common language features such as functions and conditional blocks have been implemented as commands.\u003cbr\u003e\nThis is an example of the [function command](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md#std__flowcontrol__Function):\n\n```sh\nfn print_first_and_second_argument\n    echo ${1} ${2}\n    return printed\nend\n\nfn run_flow\n    status = print_first_and_second_argument Hello World\n    echo The printout status is: ${status}\nend\n\nrun_flow\n```\n\nThis example demonstrates how functions as a concept do not need to be part of the language and can be implemented by anyone as a command.\u003cbr\u003e\nThis also means that other developers can replace the function command with their implementation to provide additional/different functionality.\u003cbr\u003e\n\nBelow an example of loops using the [for/in command](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md#std__flowcontrol__ForIn):\n\n```sh\nvalues = range 1 10\n\nfor i in ${values}\n    for j in ${values}\n        echo i: ${i} j: ${j}\n    end\nend\n\nrelease ${values}\n```\n\nBelow an example of [if/else command](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md#std__flowcontrol__If):\n\n```sh\necho Enter Full Name:\nname = read\n\nif is_empty ${name}\n    echo You did not enter any value\nelse\n    echo Your name is: ${name}\nend\n\nvalue = set false\nif ${value}\n    echo should not be here\nelseif true or false\n    echo in else if but not done yet\n\n    value = set true\n\n    if not true and false\n        echo nested if\n\n        value = set \"some text\"\n\n        if starts_with ${value} \"some\"\n            echo after command\n        else\n            echo should not be here\n        end\n    end\nelse\n    echo should not be here\nend\n```\n\n\u003ca name=\"tutorial-standard-api-full-sdk-docs\"\u003e\u003c/a\u003e\n#### Full SDK Docs\nThe full SDK docs can be found [here](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md)\n\nKeep in mind that the command names (such as **std::Echo**) can be used to invoke the commands, however for simplicity, the documentation\nexamples uses the alias form of the commands (for example: **echo**).\u003cbr\u003e\nEach command may have multiple aliases which can be used to invoke it.\n\n\u003ca name=\"tutorial-final-notes\"\u003e\u003c/a\u003e\n### Final Notes\nThat's It!!!!\u003cbr\u003e\nThat is all the language.\u003cbr\u003e\nShort, simple, only few rules to follow and you mastered duckscript.\u003cbr\u003e\n\nIf you want to know what more you can do with it, look at the [SDK docs](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md).\u003cbr\u003e\nIf you want to know how to write your own commands or embed the duckscript runtime in your application, continue reading.\n\n\u003ca name=\"sdk-tutorial\"\u003e\u003c/a\u003e\n## Duckscript Command Implementation Tutorial\nWant to write new custom commands so you can use them in your duckscripts? great!\u003cbr\u003e\nHopefully the following sections will help you gain the basic knowledge on how to write them.\u003cbr\u003e\n\n\u003ca name=\"sdk-tutorial-commands\"\u003e\u003c/a\u003e\n## Commands\nCommands are structs that must implement the Command trait.\u003cbr\u003e\n\n* They must have a name, which is used to invoke the command.\u003cbr\u003e\n* They optionally may have aliases which can also be used to invoke the command.\u003cbr\u003e\n* They should return help documentation in markdown format in order to generate SDK documentation (must for PRs to duckscript official SDK).\u003cbr\u003e\n* They must implement the **run** function which holds the command logic.\u003cbr\u003e\n\nThe run function accepts the command invocation context (args array contains actual values and not original variables) and returns the command result.\u003cbr\u003e\nThe command result can be one of the following:\n\n* Continue(Option\u003cString\u003e) - Tells the runner to continue to the next command and optionally set the output variable the given value.\n* GoTo(Option\u003cString\u003e, GoToValue) - Tells the runner to jump to the requested line or label and optionally set the output variable the given value.\n* Error(String) - Returns the value 'false' and invokes the 'on_error' command if exists with the error message and instruction information.\n* Crash(String) - Tells the runner to stop the execution and return the error message.\n* Exit(Option\u003cString\u003e) - Tells the runner to stop the execution and optionally set the output variable the given value.\n\nLet's implement a simple **set** command which accepts a single argument and sets the output variable to that value.\u003cbr\u003e\nAnd if no argument was provided, return a None which will tell the runner to delete the output variable.\u003cbr\u003e\nAfterwards the runner should continue to the next line.\u003cbr\u003e\nSo we need to use a Continue(Option\u003cString\u003e) result.\u003cbr\u003e\nFull example:\n\n```rust\nstruct SetCommand {}\n\nimpl Command for SetCommand {\n    fn name(\u0026self) -\u003e String {\n        \"set\".to_string()\n    }\n\n    fn clone_and_box(\u0026self) -\u003e Box\u003cdyn Command\u003e {\n        Box::new((*self).clone())\n    }\n\n    fn run(\u0026self, context: CommandInvocationContext) -\u003e CommandResult {\n        let output = if context.arguments.is_empty() {\n            None\n        } else {\n            Some(context.arguments[0].clone())\n        };\n\n        CommandResult::Continue(output)\n    }\n}\n```\n\nLet's implement a **get_env** command which pulls an environment variable value and sets the output variable with that value.\u003cbr\u003e\nIn case no input was provided we will throw an error, otherwise we will use the first input as the environment variable key.\u003cbr\u003e\nWe will return the value if exists or nothing if it does not.\u003cbr\u003e\nFull example:\n\n```rust\nstruct GetEnvCommand {\n    package: String,\n}\n\nimpl Command for GetEnvCommand {\n    fn name(\u0026self) -\u003e String {\n        \"get_env\".to_string()\n    }\n\n    fn clone_and_box(\u0026self) -\u003e Box\u003cdyn Command\u003e {\n        Box::new((*self).clone())\n    }\n\n    fn run(\u0026self, context: CommandInvocationContext) -\u003e CommandResult {\n        if context.arguments.is_empty() {\n            CommandResult::Error(\"Missing environment variable name.\".to_string())\n        } else {\n            match env::var(\u0026context.arguments[0]) {\n                Ok(value) =\u003e CommandResult::Continue(Some(value)),\n                Err(_) =\u003e CommandResult::Continue(None),\n            }\n        }\n    }\n}\n```\n\nYou can look at more examples in the duckscript_sdk folder.\n\n\u003ca name=\"sdk-tutorial-commands-context\"\u003e\u003c/a\u003e\n## Access The Context\nThe duckscript runtime context is available in the CommandInvocationContext struc.\u003cbr\u003e\n\n```rust\n/// Run the instruction with access to the runtime context.\n///\n/// The CommandInvocationContext has the following members:\n/// * `arguments` - The command arguments array\n/// * `state` - Internal state which is only used by commands to store/pull data\n/// * `variables` - All script variables\n/// * `output_variable` - The output variable name (if defined)\n/// * `instructions` - The entire list of instructions which make up the currently running script\n/// * `commands` - The currently known commands\n/// * `line` - The current instruction line number (global line number after including all scripts into one global script)\n/// * `env` - The current runtime env with access to out/err writers, etc...\nfn run(\u0026self, context: CommandInvocationContext) -\u003e CommandResult;\n```\n\nWith access to this context you can add/remove/switch commands in runtime, store/pull internal state, add/remove/change variables and so on...\n\n\u003ca name=\"embed-tutorial\"\u003e\u003c/a\u003e\n## Duckscript Embedding Tutorial\nEmbedding duckscript is really simple and this is one of the language main goals.\u003cbr\u003e\nThe duckscript cli basically embeds duckscript so you can look at it as a reference, but basically it boils down to really few lines of code:\n\n```rust\nlet mut context = Context::new();\nduckscriptsdk::load(\u0026mut context.commands)?;\nrunner::run_script_file(file, context, None)?;\n```\n\nThat's it!\u003cbr\u003e\nUnless you want to provide your own custom SDK, pre populate the runtime context with custom variables/state or\npull information out of the context after invocation than those 3 lines of code is all you need to do.\u003cbr\u003e\nLet's go over it line by line.\u003cbr\u003e\n\n\u003ca name=\"embed-tutorial-setup-context\"\u003e\u003c/a\u003e\n## Setting Up The Context\nThe context holds the initial known commands, variables and state (internal objects used by commands).\u003cbr\u003e\nRunning the ```Context::new()``` simply creates a new empty context.\u003cbr\u003e\nYou can add to it any command, variable or state object you want before running the scripts.\u003cbr\u003e\nIn our example we load all default standard API commands into the new context via: ```duckscriptsdk::load(\u0026mut context.commands)?;```\n\n\u003ca name=\"embed-tutorial-running\"\u003e\u003c/a\u003e\n## Running The Script\nAfter we have a context setup, we will run the script.\u003cbr\u003e\nThe **runner** enables to run a script text or a script file.\u003cbr\u003e\nThe following public functions are available:\n\n```rust\n/// Executes the provided script with the given context\npub fn run_script(text: \u0026str, context: Context, env: Option\u003cEnv\u003e) -\u003e Result\u003cContext, ScriptError\u003e;\n\n/// Executes the provided script file with the given context\npub fn run_script_file(file: \u0026str, context: Context, env: Option\u003cEnv\u003e) -\u003e Result\u003cContext, ScriptError\u003e;\n```\n\n\u003ca name=\"editor-support\"\u003e\u003c/a\u003e\n## Editor Support\n* Vim: [vim-duckscript](https://github.com/nastevens/vim-duckscript)\n\n\u003ca name=\"contributing\"\u003e\u003c/a\u003e\n## Contributing\nThere are many ways to contribute to duckscript, including:\n\n* Writing more commands and adding them to the standard SDK\n* Improving existing commands by adding more features\n* Improving the documentation\n* Opening issues with new feature requests or bugs found\n* Spreading the word :)\n\nAs for expanding the language, I personally prefer not to make it complex.\u003cbr\u003e\nLet's try to add more language feature using commands and not changing the language itself.\u003cbr\u003e\n\nSee [contributing guide](.github/CONTRIBUTING.md)\n\n\u003ca name=\"history\"\u003e\u003c/a\u003e\n## Release History\n\nSee [Changelog](https://github.com/sagiegurari/duckscript/blob/master/CHANGELOG.md)\n\n\u003ca name=\"license\"\u003e\u003c/a\u003e\n## License\nDeveloped by Sagie Gur-Ari and licensed under the Apache 2 open source license.\n","funding_links":[],"categories":["库 Libraries","Rust","Libraries"],"sub_categories":["脚本 Scripting","Scripting"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsagiegurari%2Fduckscript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsagiegurari%2Fduckscript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsagiegurari%2Fduckscript/lists"}