diff --git a/README.md b/README.md index 3af208d..27b5d32 100644 --- a/README.md +++ b/README.md @@ -80,4 +80,4 @@ ARGS: ## Language Reference -https://docs.rs/ucg/ \ No newline at end of file +https://ucg.marzhillstudios.com/reference/ \ No newline at end of file diff --git a/docsite/site/content/how-to/_index.md b/docsite/site/content/how-to/_index.md new file mode 100644 index 0000000..2b31913 --- /dev/null +++ b/docsite/site/content/how-to/_index.md @@ -0,0 +1,12 @@ ++++ +title = "HowTo Guides" +weight = 3 +sort_by = "weight" +in_search_index = true ++++ +A collection of useful HowTo Guides +---------- + +Some example use cases for ucg. + +* Creating a launch script for a docker container. \ No newline at end of file diff --git a/docsite/site/content/how-to/script.md b/docsite/site/content/how-to/script.md new file mode 100644 index 0000000..99a8f2e --- /dev/null +++ b/docsite/site/content/how-to/script.md @@ -0,0 +1,82 @@ ++++ +title = "Creating a launch script for a docker container" +weight = 1 +sort_by = "weight" +in_search_index = true ++++ +Let's say we wanted to use ucg generate a launch script for a local jupyter datascience +notebook container. This HowTo walks you through creating a ucg file that can generate +a script to launch the container. + +First lets define some docker configuration values that we'll use later. + +``` +let image_conf = { + port = 8888, + hostMount = "~/iJulia/notebooks", + mountPoint = "/var/iJulia/notebooks", +}; +``` + +Then we can define a helper macro for creating our host and port mappings + +``` +// A little helper macro for creating our host and port mappings. +let map_to_container = macro (host, container) => { + result = "@:@" % (host, container) +}; + +let publish = map_to_container(docker_conf.port, docker_conf.port); +let volumes = map_to_container(docker_conf.hostMount, docker_conf.mountPoint); +``` + +Now we set up our docker run flags. + +``` +let docker_flags = { + // d because we want this container to daemonize. + d = NULL, // no value for this one. + // We provide the container name from the environment. + name = env.CONTAINER_NAME, + // We use our generated publish and volume mappings from above. + publish = publish.result, + volume = volumes.result, +}; +``` + +Finally we are ready to define our jupyter specific flags. + +``` +let jupyter_flags = { + notebook-dir = docker_conf.mountPoint +}; +``` + +Finally we tie it all together into a script and output it as a bash script using +the exec converter. + +``` +let script = { + command = "docker", + args = [ + "run", "--rm", docker_flags, + "jupyter/datascience-notebook", + "jupyter", "notebook", jupyter_flags, + ], +}; + +out exec script; +``` + +The script tuple above will generate the following bash script: + +```sh +#!/usr/bin/env bash +# Turn on unofficial Bash-Strict-Mode +set -euo pipefail + +exec docker run --rm -d --name '' --publish '8888:8888' --volume '~/iJulia/notebooks:/var/iJulia/notebooks' jupyter/datascience-notebook jupyter notebook --notebook-dir '/var/iJulia/notebooks' +``` + +The items in the args should be either strings or tuples. The tuples are turned into +flags using the builtin flag converter. \ No newline at end of file diff --git a/docsite/site/content/reference/converters.md b/docsite/site/content/reference/converters.md new file mode 100644 index 0000000..2dde66c --- /dev/null +++ b/docsite/site/content/reference/converters.md @@ -0,0 +1,145 @@ ++++ +title = "UCG Converters" +weight = 5 +sort_by = "weight" +in_search_index = true ++++ +UCG has several formats it can convert a value into. Each one has various limits and +restrictions on the values that can be converted to that format. + +JSON and YAML +---- + +All UCG values can be converted into JSON or YAML. Integers and Floats are turned into +Their equivalent number types. Tuples are turned into dicts. Lists are turned into +arrays. Strings are turned into strings. + +The NULL or empty type is turned into null in JSON or YAML. + +TOML +---- + +TOML is very similar to the JSON and YAML formats. TOML has no notion of null though +so NULL types result in a compile error when converting to TOML. + +Command Line Flags +---- + +UCG is able to generate command line flags from ucg values following some translation +rules for each type. + +* Empty values are not emitted. +* Boolean values are translated to "true" and "false" repsectively. +* Integers and Floats are rendered as numbers. +* Tuples are rendered as `--field value` pairs for each field. + * Nested tuples concatenate the field names to create the field. + * Nested Lists generate a new `--field listitem` pair for each item in the list. + * For fields that are just one character in length use a single `-`. Use double + dashes for fields of longer than one character. + +### Example + +``` +let flags = { + port = 8080, + listen = "0.0.0.0", + verbose = NULL, + dir = [ + "some/dir", + "some/other/dir", + ], + log = { + debug = true, + format = "json", + }, +} +``` + +Generates the following flags in a file with the `.txt` extension. + +``` +-port 8080 --listen '0.0.0.0' --verbose --dir 'some/dir' --dir 'some/other/dir' --log.debug true --log.format 'json' +``` + +Environment Variables +-------- + +ucg is also able to generate environment variables from ucg values following a few +translation rules. + +* Booleans, Integers, Floats, and Strings are output as is. +* Lists are not output. +* Tuples are output as a `FIELD=value` for each field with strings surrounded by double + quotes. + * Nested Tuples are not output. + +``` +let vars = { + USER = "me", + HOSTNAME = "localhost", + TWO = 2, + VERBOSE = true, +}; +``` + +Generates the following in a file with a `.env` extension. + +```sh +USER='me' +HOSTNAME='localhost' +TWO=2 +VERBOSE=true +``` + +Exec Script +----- + +ucg has an exec converter that will generate a launch script in bash for applications +that are configured via command line flags or environment variables. The exec converter +uses a tuple with some required and optional fields to generate the script with. + +The `command` field is the path to the application the script will be launching. It is +expected to be a string. There must only be one `command` field in the tuple. + +The `args` field is a list of command line arguments. The elements of the list can be +strings or tuples. There must only be one `args` field in the tuple. + +The `env` field is a tuple representing the environment variables that will be set for +the application. there must only be one `env` field in the tuple. + +### Example + +``` +let common_flags = { + log-level = "debug", + maxMem = "2048M", +}; + +let script = { + env = { + apikey = "foo-key-and-stuff", + }, + command = "my-app", + args = [ + common_flags, + "serve", "--port", "8080", + ], +}; + +out exec script; +``` + +The script tuple above will generate the following bash script: + +```sh +#!/usr/bin/env bash +# Turn on unofficial Bash-Strict-Mode +set -euo pipefail + +VERBOSE_LOG="true" + +exec my-app --log-level debug --maxMem 2048M serve --port 8080 +``` + +The items in the args should be either strings or tuples. The tuples are turned into +flags using the builtin flag converter. \ No newline at end of file diff --git a/docsite/site/content/reference/statements.md b/docsite/site/content/reference/statements.md index 95550a3..78f0639 100644 --- a/docsite/site/content/reference/statements.md +++ b/docsite/site/content/reference/statements.md @@ -94,4 +94,6 @@ let myconf = { out json myconf; ``` -ucg will output the myconf tuple as json to a file called api_config.json \ No newline at end of file +ucg will output the myconf tuple as json to a file called api_config.json + +Next: Converters \ No newline at end of file diff --git a/examples/test_env.env b/examples/test_env.env new file mode 100644 index 0000000..e09d26e --- /dev/null +++ b/examples/test_env.env @@ -0,0 +1,4 @@ +USER='me' +HOSTNAME='localhost' +TWO=2 +VERBOSE=true diff --git a/examples/test_env.ucg b/examples/test_env.ucg new file mode 100644 index 0000000..f9be8b8 --- /dev/null +++ b/examples/test_env.ucg @@ -0,0 +1,8 @@ +let vars = { + USER = "me", + HOSTNAME = "localhost", + TWO = 2, + VERBOSE = true, +}; + +out env vars; \ No newline at end of file diff --git a/examples/test_flags.txt b/examples/test_flags.txt new file mode 100644 index 0000000..e52863d --- /dev/null +++ b/examples/test_flags.txt @@ -0,0 +1 @@ +--port 8080 --listen '0.0.0.0' --verbose --dir 'some/dir' --dir 'some/other/dir' --log.debug true--log.format 'json' \ No newline at end of file diff --git a/examples/test_flags.ucg b/examples/test_flags.ucg new file mode 100644 index 0000000..2b3d221 --- /dev/null +++ b/examples/test_flags.ucg @@ -0,0 +1,15 @@ +let args = { + port = 8080, + listen = "0.0.0.0", + verbose = NULL, + dir = [ + "some/dir", + "some/other/dir", + ], + log = { + debug = true, + format = "json", + }, +}; + +out flags args; \ No newline at end of file