Hello Worlds!¶
The following is a collection of hello worlds ranging from simple to contrived that demonstrate the core aspects of writing tackle files.
- Single line print
- Print with variables
- Interactive prompts
- Loops and conditionals
- Manipulating context
- Public vs private hooks
- Python hooks
- Declarative hooks
- Declarative hook methods
- Strongly typed declarative hooks
- Declarative hooks inheritance
- Calling other tackle files
Future hello worlds
- Inheriting from schemas like openapi
- Declarative CLI help screens
Running the Hello world!
demo¶
Locally + Copy / Paste
You can create a file hello.yaml
and paste in the following or you can run some of these examples in tackle.
tackle robcxyz/tackle-hello-world
Single line print¶
Simply use the print hook.
hw->: print Hello world!
Anytime a key is suffixed with an arrow going to the right, it means the key is calling a hook, in this case a print hook.
Print with variables¶
Using jinja templating, the print hook can be called in three different ways using a variable.
words: Hello world!
expanded:
->: print
objects: "{{words}}"
compact->: print {{words}}
jinja_extension->: "{{ print(words) }}"
# Or combinations of the above
Note that key with arrow without an explicit hook is simply rendered
Interactive prompts¶
There are several types of prompt hooks which can also be used.
name->: input
target:
->: select Say hi to who?
choices:
- world
- universe
hello->: print My name is {{name}}. Hello {{target}}!
Which looks like this before printing.
? name >>> Rob
? Say hi to who?
❯ world
universe
Loops and conditionals¶
Hooks can have loops, conditionals, and other base methods.
words:
- Hello
- cruel
- world!
expanded:
->: print {{item}}
for: words
if: item != 'cruel'
compact->: print {{item}} --for words --if "item != 'cruel'"
Manipulating context¶
Hooks can manipulate the context with the context provider so using the preceding example, instead of doing a list comprehension we can instead remove the second element using the pop hook.
words:
- Hello
- cruel
- world!
rm cruel->: pop words 1
expanded:
->: print {{item}}
for: words
compact->: print {{item}} --for words
Blocks of context¶
Sometimes it is convenient to declare a group of logic that contains the base methods like in this case for
.
words:
- Hello
- world!
a-block->:
for: words
h->: print {{item}} --if "index == 0"
w->: print {{item}} --if "index == 1"
Blocks are simply any key ending with an ->
with a map as the value. In this case we also see that within for
loops, the iterand is also tracked via the index
variable.
Public vs private hooks¶
Hooks can have both public and private access modifiers which inform whether the hooks value is exported outside of the tackle file / function.
For instance running with the --print
or -p
flags, (ie tackle hello.yaml -p
), only the public context would be exported.
Input
words_>:
- Hello
- world!
output->: var {{item}} --for words
output:
- Hello
- world!
You can still use the output of a private hook but only within the tackle file that it is being called. By default, the public context moves with the call between tackle files.
Python hooks¶
Hooks can be written in python. Simply add your code to a hooks
directory and the hook will be available to be called from a tackle file.
from tackle import BaseHook
class Greeter(BaseHook):
hook_type: str = "greeter"
target: str
args: list = ['target']
def exec(self):
print(f"Hello {self.target}")
Declarative hooks¶
Hooks can be declaratively created with tackle. Arrows going to the left are basically reusable functions / methods.
greeter<-:
target: str
args: ['target']
exec<-:
hi->: print Hello {{target}}
Both python and declarative hooks can be called in the same way.
hello: world!
compact->: greeter {{hello}}
expanded:
->: greeter
target: "{{hello}}"
jinja_extension->: "{{ greeter(hello) }}"
jinja_filter->: "{{ hello | greeter }}"
Strongly typed declarative hooks¶
Declarative hooks are strongly typed objects with many declarative fields.
words<-:
hi:
type: str
regex: ^(Bonjour|Hola|Hello)
target: str
p->: print {{item}} --for values(words(hi="Hello",target="world!"))
Here we are also using the values hook which can also be daisy-chained with the pre-declared words
hook.
Note an error would be thrown if the
hi
key did not satisfy the regex.
Declarative hook methods¶
Declarative hooks can have methods that extend the base.
words<-:
hi: Wadup
say<-:
target: str
exec:
p->: print {{hi}} {{target}}
p->: words.say --hi Hello --target world!
Declarative hooks inheritance¶
Declarative hooks also support inheritance.
base<-:
hi:
default: Hello
words<-:
extends: base
say<-:
target: str
exec:
p->: print {{hi}} {{target}}
p->: words.say --target world!
Which can also be called from the command line.
tackle hello-world.yaml
Calling other tackle files¶
Every hook can be imported / called remotely from github repos with the same options as you would from the command line.
import-hello_>: import robcxyz/tackle-hello-world
call->: greeter world!
# Or
local-call->: tackle hello-world.yaml
remote-call->: tackle robcxyz/tackle-hello-world --version v0.1.0
Self Documenting Declarative CLIs¶
Documentation can be embedded into the hooks.
tackle robcxyz/tackle-hello-world help
<-:
help: This is the default hook
target:
type: str
description: The thing to say hello to
exec<-:
greeting->: select Who to greet? --choices ['world','universe']
hi->: greeter --target {{greeting}}
greeting-method<-:
help: A method that greets
# ... Greeting options / logic
greeter<-:
help: A reusable greeter object
target: str
exec<-:
hi->: print Hello {{target}}
Which when running tackle hello.yaml help
produces its own help screen.
usage: tackle hello.yaml [--target]
This is the default hook
options:
--target [str] The thing to say hello to
methods:
greeting-method A method that greets
greeter A reusable greeter object
That [will] drive a
help
screen by runningtackle hello-world.yaml --help
-> Coming soon