Yo - Define & Unify
This section is about the Heart and Soul of this project.
Why?!
Yo is a Command-Line tool and scripting framework I wrote because of two main reasons:
1. Define
I needed somewhere to define my sentences for the voice assistant, and a stable solution for defining the language processor's 'tools' (scripts) for execution.
2. Unify
Reduced scatter. Ever since I was a kid I have had a golden talent for scattering scripts around me, like a crazy mad man on speed, which sadly in the end of course lead to me loosing a lot of value.
Key Features
Centralized Script Management
Define all your scripts in one place with consistent structure, eliminating scattered scripts across your system.
Built entirely in Nix for declarative, reproducible script management across your entire system.
Unified --help command, Markdown rendered beautifully in the terminal that have extensive parameter documentation.
Parameter System
Type validation, optional parameters, default values, allowed values, and both positional & named parameter support.
Automated Execution
Schedule scripts to run at boot, periodically, or specific times with systemd integration.
Smart Validation
Comprehensive error checking with friendly duck error messages and parameter validation.
YO Script Structure
I chose to define my scripts like this:
⮞ Hide Scriot Structure
{ # 🦆says⮞yo! letz do a script yo!
config,
lib,
pkgs,
cmdHelpers, # 🦆says⮞shared functionz (/bin/helpers.nix)
...
} : let
in { # 🦆says⮞qwack
yo = {
scripts = {
bed = { # 🦆says⮞plx pick da script name
description = "Bed controller";
# 🦆says⮞for da --help cmd in da terminal md table & README markdown table
category = "🛖 Home Automation";
autoStart = false; # 🦆says⮞run bed@boot?
runEvery = []; # 🦆says⮞periodic start (minutes)
runAt = []; # 🦆says⮞scheduled start (list of strings - "HH:MM" 24h format)
logLevel = "INFO"; # 🦆says⮞duckTrace loggin'
parameters = [
{ # 🦆says⮞paramz haz extensive validation
name = "part";
description = "Which part of the bed (head/feet)";
type = "string";
values = [ # 🦆says⮞doez not run if $part is something else than
"feet"
"head"
];
default = "head"; # 🦆says⮞if --part iz omitted default value iz uzed for --part
}
{
name = "state";
description = "Move up or down";
type = "string";
values = [ "down" "up" ];
default = "up";
}
];
helpFooter = ''
echo "🦆says⮞extra code to be ran and displayed in da scripts --help cmd"
'';
code = ''
${cmdHelpers} # 🦆says⮞load da shared functionz yo
dt_debug "Sending bed $part $down" # 🦆says⮞ duckTrace logging
# 🦆says⮞ rezt of da script code
'';
voice = { # 🦆says⮞enabled by default if sentences are defined
priority = 2; # 🦆says⮞1-5 (5 lowest)
fuzzy = {
enable = true; # 🦆says⮞ enabled by default if sentences are defined
threashhold = 15; # 🦆says⮞set a script specific fuzzy threashhold
};
sentences = [
# 🦆says⮞ [these|words] are optiional & can be omitted
# 🦆says⮞ (these|words) are alternatives - u have to say one of them
# 🦆says⮞ {this} word is a parameter (must match BOTH scripts parameter AND entity list
"[send|control] bed[s] {part} {state}"
"(take|send|control) {state] [the] bed[s] {part}"
];
lists = { # 🦆says⮞ entity lists
part.wildcard = false; # 🦆says⮞ entities can be wildcards (anything)
part.values = [
{ # 🦆says⮞ if u say one of these words
"in" = "[head|heads|bedhead|top]";
out = "head"; # 🦆says⮞ it becomes this word
}
{ "in" = "[foot|foots|feet|feets]"; out = "feet"; }
];
state.values = [
{ "in" = "[up|upp]"; out = "up"; }
{ "in" = "[down|downs]"; out = "down"; }
];
};
};
};
};
};}
⮞ Hide Scriot Structure
{ # 🦆says⮞yo! letz do a script yo! config, lib, pkgs, cmdHelpers, # 🦆says⮞shared functionz (/bin/helpers.nix) ... } : let in { # 🦆says⮞qwack yo = { scripts = { bed = { # 🦆says⮞plx pick da script name description = "Bed controller"; # 🦆says⮞for da --help cmd in da terminal md table & README markdown table category = "🛖 Home Automation"; autoStart = false; # 🦆says⮞run bed@boot? runEvery = []; # 🦆says⮞periodic start (minutes) runAt = []; # 🦆says⮞scheduled start (list of strings - "HH:MM" 24h format) logLevel = "INFO"; # 🦆says⮞duckTrace loggin' parameters = [ { # 🦆says⮞paramz haz extensive validation name = "part"; description = "Which part of the bed (head/feet)"; type = "string"; values = [ # 🦆says⮞doez not run if $part is something else than "feet" "head" ]; default = "head"; # 🦆says⮞if --part iz omitted default value iz uzed for --part } { name = "state"; description = "Move up or down"; type = "string"; values = [ "down" "up" ]; default = "up"; } ]; helpFooter = '' echo "🦆says⮞extra code to be ran and displayed in da scripts --help cmd" ''; code = '' ${cmdHelpers} # 🦆says⮞load da shared functionz yo dt_debug "Sending bed $part $down" # 🦆says⮞ duckTrace logging # 🦆says⮞ rezt of da script code ''; voice = { # 🦆says⮞enabled by default if sentences are defined priority = 2; # 🦆says⮞1-5 (5 lowest) fuzzy = { enable = true; # 🦆says⮞ enabled by default if sentences are defined threashhold = 15; # 🦆says⮞set a script specific fuzzy threashhold }; sentences = [ # 🦆says⮞ [these|words] are optiional & can be omitted # 🦆says⮞ (these|words) are alternatives - u have to say one of them # 🦆says⮞ {this} word is a parameter (must match BOTH scripts parameter AND entity list "[send|control] bed[s] {part} {state}" "(take|send|control) {state] [the] bed[s] {part}" ]; lists = { # 🦆says⮞ entity lists part.wildcard = false; # 🦆says⮞ entities can be wildcards (anything) part.values = [ { # 🦆says⮞ if u say one of these words "in" = "[head|heads|bedhead|top]"; out = "head"; # 🦆says⮞ it becomes this word } { "in" = "[foot|foots|feet|feets]"; out = "feet"; } ]; state.values = [ { "in" = "[up|upp]"; out = "up"; } { "in" = "[down|downs]"; out = "down"; } ]; }; }; }; }; };}


⮞ dis is rly helpful if you forget a scripts name or sumeting! quack quack