🦆

Navigation

🧑‍🦯

Yo - Define & Unify

Yo! Execution Workflow.

The Three Phase Execution Workflow

Phase 1: Special Flag Preprocessing
There are two special flags. "?" and "!".
These special flags control two enviorment variables: "$DRY_RUN" and "$VERBOSE".
They work before regular parsing, so they don't interfere with your script's actual parameters. It's like having meta-commands.

⮞ View Special Flags

? > VERBOSE++     # 🦆 says ⮞ increment $VERBOSE & set the scripts logLevel to "DEBUG" 
! > DRY_RUN=true  # 🦆 says ⮞ sets $DRY_RUN to true
Phase 2: Parameter Parsing
Yo supports both named and positional parameters.
⮞ View Example Parameter Usage

--help or -h   # 🦆 says ⮞ beautiful Glow rendered Markdown help
--param value  # 🦆 says ⮞ named parameters with type detection  
value          # 🦆 says ⮞ positional parameters
Boolean detection: --flag vs --flag true both work.
Unknown params: Instant "🦆 say ⮞ fuck ❌ Unknown parameter: .."
Help system: Generates documentation in markdown on-the-fly.


Phase 3: Validation & Execution
Yo has a strong validation system, ensuring your script's do not run with invalid parameters.
Which of course is a requirement, since we are going to execute them with our voice later on.
⮞ View Parameter Type Explaination

# 🦆 says ⮞ parameter type validation
int?      # 🦆 says ⮞ only numbers
path?     # 🦆 says ⮞ file exists
bool?     # 🦆 says ⮞ true/false
values?   # 🦆 says ⮞ allowed list check

optional? # 🦆 says ⮞ check if required parameters are supplied
# ELSE ⮞ if param has a default value configured - use that
# ELSE ⮞ "🦆 say ⮞ fuck ❌ Missing required parameter: ${param.name}"

The Full Execution Workflow

Here I will show the full workflow, please note that this is not the full module.
If you want it explained make sure you did not turn off the duck commentary.
It's a long code block, and I believe the duck handles the commentary for this block just fine.

⮞ View yo Execution Workflow

  # 🦆 duck say ⮞ letz create da yo scripts pkgs - we symlinkz all yo scripts togetha .. quack quack 
  yoScriptsPackage = pkgs.symlinkJoin {
    name = "yo-scripts"; # 🦆 duck say ⮞ map over yo scripts and gen dem shell scriptz wrapperz!!
    paths = mapAttrsToList (name: script:
      let # 🦆 duck say ⮞ compile help sentences at build time      
        # 🦆 duck say ⮞ compile help sentences at build time
        voiceSentencesHelp = if script.voice != null && script.voice.sentences != [] then
          let
            patterns = countGeneratedPatterns script;
            phrases = countUnderstoodPhrases script;
            # 🦆 duck say ⮞ copy the parameter replacement logic from voiceSentencesHelpFile
            replaceParamsWithValues = sentence: voiceData:
              let
                processToken = token:
                  if lib.hasPrefix "{" token && lib.hasSuffix "}" token then
                    let
                      paramName = lib.removePrefix "{" (lib.removeSuffix "}" token);
                      listData = voiceData.lists.${paramName} or null;
                    in
                      if listData != null then
                        if listData.wildcard or false then
                          "ANYTHING"
                        else
                          let
                            # 🦆 duck say ⮞ get all possible input values
                            values = map (v: v."in") listData.values;
                            # 🦆 duck say ⮞ expand any optional patterns like [foo|bar]
                            expandedValues = lib.concatMap expandListInputVariants values;
                            # 🦆 duck say ⮞ take first few examples for display
                            examples = lib.take 3 (lib.unique expandedValues);
                          in
                            if examples == [] then "ANYTHING"
                            else "(" + lib.concatStringsSep "|" examples + 
                                 (if lib.length examples < lib.length expandedValues then "|...)" else ")")
                      else
                        "ANYTHING" # 🦆 duck say ⮞ fallback if param not found
                  else
                    token;
                
                # 🦆 duck say ⮞ split sentence and process each token
                tokens = lib.splitString " " sentence;
                processedTokens = map processToken tokens;
              in
                lib.concatStringsSep " " processedTokens;
            
            # 🦆 duck say ⮞ replace params in each sentence for the help display
            processedSentences = map (sentence: 
              replaceParamsWithValues sentence script.voice
            ) script.voice.sentences;
            
            sentencesMarkdown = lib.concatMapStrings (sentence: 
              "- \"${escapeMD sentence}\"\n"
            ) processedSentences;
          in
            "## Voice Commands\n\nPatterns: ${toString patterns}  \nPhrases: ${toString phrases}  \n\n${sentencesMarkdown}"
        else "";
       
      
        # 🦆 duck say ⮞ generate a string for da CLI usage optional parameters [--like] diz yo
        param_usage = lib.concatMapStringsSep " " (param:
          if param.optional
          then "[--${param.name}]" # 🦆 duck say ⮞ iptional params baked inoto brackets
          else "--${param.name}" # 🦆 duck say ⮞ otherz paramz shown az iz yo
        # 🦆 duck say ⮞ filter out da special flagz from standard usage 
        ) (lib.filter (p: !builtins.elem p.name ["!" "?"]) script.parameters);
        
        # 🦆 duck say ⮞ diz iz where da magic'z at yo! trust da duck yo 
        scriptContent = ''
          #!${pkgs.runtimeShell}
          set -euo pipefail # 🦆 duck say ⮞ strict error handlin' yo - will exit on errorz
          set -o noglob  # 🦆 duck say ⮞ disable wildcard expansion for ? and ! flags
          ${yoEnvGenVar script} # 🦆 duck say ⮞ inject da env quack quack.... quack
          export LC_NUMERIC=C
          start=$(date +%s.%N)
          
          # 🦆 duck say ⮞ duckTrace log setup
          export DT_LOG_PATH="$HOME/.config/duckTrace/"
          mkdir -p "$DT_LOG_PATH"   
          export DT_LOG_FILE="${name}.log" # 🦆 duck say ⮞ duck tracin' be namin' da log file for da ran script
          touch "$DT_LOG_PATH/$DT_LOG_FILE"
          export DT_LOG_LEVEL="${script.logLevel}" # 🦆 duck say ⮞ da tracin' duck back to fetch da log level yo
          DT_MONITOR_HOSTS="${sysHostsComma}";
          DT_MONITOR_PORT="9999";
      
          # 🦆 duck say ⮞ PHASE 1: preprocess special flagz woop woop
          VERBOSE=0
          DRY_RUN=false
          FILTERED_ARGS=()
          # 🦆 duck say ⮞ LOOP through da ARGz til' duckie duck all  dizzy duck
          while [[ $# -gt 0 ]]; do
            case "$1" in
              \?) ((VERBOSE++)); shift ;;        # 🦆 duck say ⮞ if da arg iz '?' == increment verbose counter
              '!') DRY_RUN=true; shift ;;        # 🦆 duck say ⮞ if da arg iz '!' == enablez da dry run mode yo
              *) FILTERED_ARGS+=("$1"); shift ;; # 🦆 duck say ⮞ else we collect dem arguments for script processin'
            esac
          done  
          VERBOSE=$VERBOSE
          export VERBOSE DRY_RUN
          
          # 🦆 duck say ⮞ reset arguments without special flags
          set -- "''${FILTERED_ARGS[@]}"

          # 🦆 duck say ⮞ PHASE 2: regular parameter parsin' flappin' flappin' quack quack yo
          declare -A PARAMS=()
          POSITIONAL=()
          VERBOSE=$VERBOSE
          DRY_RUN=$DRY_RUN
          # 🦆 duck say ⮞ if ? flag used - sets scripts logLevel to DEBUG
          if [ "$VERBOSE" -ge 1 ]; then
            DT_LOG_LEVEL="DEBUG"
          fi
          
          # 🦆 duck say ⮞ parse all parameters
          while [[ $# -gt 0 ]]; do
            case "$1" in
              --help|-h) # 🦆 duck say ⮞ if  u needz help call `--help` or `-h`
                width=$(tput cols 2>/dev/null || echo 100) # 🦆 duck say ⮞ get terminal width for formatin' - fallin' back to 100
                help_footer=$(${script.helpFooter}) # 🦆 duck say ⮞ dynamically generatez da helpFooter if ya defined it yo   
                # 🦆 duck say ⮞ script haz paramz?
                usage_suffix=""
                if [[ -n "${toString (script.parameters != [])}" ]]; then
                  usage_suffix=" [OPTIONS]"
                fi
                
                cat <&2
              exit 1
            fi
          ''}

          # 🦆 duck say ⮞ param type validation quuackidly quack yo
          ${concatStringsSep "\n" (map (param: 
            optionalString (param.type != "string") ''
              if [ -n "''${${param.name}:-}" ]; then
                case "${param.type}" in
                  int)
                    if ! [[ "''${${param.name}}" =~ ^[0-9]+$ ]]; then
                      echo -e "\033[1;31m 🦆 duck say ⮞ fuck ❌ ${name} --${param.name} must be integer\033[0m" >&2
                      exit 1
                    fi
                    ;;
                  path)
                    if ! [ -e "''${${param.name}}" ]; then
                      echo -e "\033[1;31m 🦆 duck say ⮞ fuck ❌ ${name} Path not found: ''${${param.name}}\033[0m" >&2
                      exit 1
                    fi
                    ;;
                  bool)
                    if ! [[ "''${${param.name}}" =~ ^(true|false)$ ]]; then
                      echo -e "\033[1;31m 🦆 duck say ⮞ fuck ❌ ${name} Parameter ${param.name} must be true or false\033[0m" >&2
                      exit 1
                    fi
                    ;;
                esac
              fi
            ''
          ) script.parameters)}


          # 🦆 duck say ⮞ values validation - explicit allowed list yo
          ${concatStringsSep "\n" (map (param: 
            optionalString (param.values != null && param.type == "string") ''
              if [ -n "''${${param.name}:-}" ]; then
                # 🦆 duck say ⮞ check if value is in allowed list
                allowed_values=(${lib.concatMapStringsSep " " (v: "'${lib.escapeShellArg v}'") param.values})
                value_found=false
                for allowed in "''${allowed_values[@]}"; do
                  if [[ "''${${param.name}}" == "$allowed" ]]; then
                    value_found=true
                    break
                  fi
                done
                if [[ "$value_found" == "false" ]]; then
                  echo -e "\033[1;31m 🦆 duck say ⮞ fuck ❌ ${name} --${param.name} must be one of: ${lib.concatStringsSep ", " param.values}\033[0m" >&2
                  exit 1
                fi
              fi
            ''
          ) script.parameters)}


          # 🦆 duck say ⮞ boolean defaults - false if not provided
          ${concatStringsSep "\n" (map (param: 
            optionalString (param.type == "bool" && param.default != null) ''
              if [[ -z "''${${param.name}:-}" ]]; then
                ${param.name}=${if param.default then "true" else "false"}
              fi
            '') script.parameters)}


          ${concatStringsSep "\n" (map (param: 
            optionalString (param.default != null) ''
              if [[ -z "''${${param.name}:-}" ]]; then
                ${param.name}=${
                  if param.type == "string" then 
                    "'${lib.escapeShellArg (toString param.default)}'" 
                  else if param.type == "int" then
                    "${toString param.default}"
                  else if param.type == "bool" then
                    (if param.default then "true" else "false")
                  else if param.type == "path" then
                    "'${lib.escapeShellArg (toString param.default)}'"
                  else
                    "'${lib.escapeShellArg (toString param.default)}'"
                }
              fi
            '') script.parameters)}
            
          # 🦆 duck say ⮞ checkz required param yo - missing? errorz out 
          ${concatStringsSep "\n" (map (param: ''
            ${optionalString (!param.optional && param.default == null) ''
              if [[ -z "''${${param.name}:-}" ]]; then
                echo -e "\033[1;31m 🦆 duck say ⮞ fuck ❌ ${name} Missing required parameter: ${param.name}\033[0m" >&2
                exit 1
              fi
            ''}
          '') script.parameters)}

          # 🦆 duck say ⮞ EXECUTEEEEEAAAOO 🦆quack🦆quack🦆quack🦆quack🦆quack🦆quack🦆quack🦆quack🦆quack🦆quack🦆quack🦆yo
          ${script.code}
        '';
        # 🦆 duck say ⮞ generate da entrypoint
        mainScript = pkgs.writeShellScriptBin "yo-${script.name}" scriptContent;
      in # 🦆 duck say ⮞ letz wrap diz up already  
        pkgs.runCommand "yo-script-${script.name}" {} ''
          mkdir -p $out/bin  # 🦆 duck say ⮞ symlinkz da main script
          ln -s ${mainScript}/bin/yo-${script.name} $out/bin/yo-${script.name} 
          ${concatMapStrings (alias: '' # 🦆 duck say ⮞ dont forget to symlinkz da aliases too yo!
            ln -s ${mainScript}/bin/yo-${script.name} $out/bin/yo-${alias}
          '') script.aliases}
        ''
    ) cfg.scripts; # 🦆 duck say ⮞ apply da logic to da yo scriptz
  };
SUMMARY:
⮞ View Worlflow Summary
             
scriptContent = ''
  #!${pkgs.runtimeShell}
  ${yoEnvGenVar script}  # 🦆 says ⮞ inject environment
  ${parameter_parsing}   # 🦆 says ⮞ generated parsing logic
  ${validation}          # 🦆 says ⮞ generated validation
  ${script.code}         # 🦆 says ⮞ user's actual script code
'';

The symlinkJoin Architecture

Every script becomes a separate binary in your PATH: yo-scriptname, yo-alias1, yo-alias2.
In my opinion this is much cleaner than a single monolithic binary with subcommands.
⮞ View symlinkJoinsymlinkJoin Example
             
yoScriptsPackage = pkgs.symlinkJoin {
  name = "yo-scripts";
  paths = mapAttrsToList (name: script: ...) cfg.scripts;
};   
Think of yo as a Bash compiler - it takes declarative Nix configurations and generates optimized, type-safe shell scripts with beautiful documentation.

That's It For Now!


View the entire source code on GitHub

⮞ hope dis was a enjoyable read and dat u learned sumthing