diff --git a/README.md b/README.md
index f4c46bb..dbbf7ca 100644
--- a/README.md
+++ b/README.md
@@ -165,23 +165,6 @@ These are the main parts of every task file script.
Now see [usage](/usage) on how to use the task file.
-## Naming
+## Development
-The naming of functions is important. There are basically two styles:
-
-1. Action + Object
-2. Object + Action
-
-The task file functions use the first style. The name of the function starts with an action followed by an object. The object name can be singular or plural.
-
-**Examples for actions**: activate, install, dev, develop, init, build, start, update, remove, delete, enable, disable, template, convert, create, edit, change, get, set, patch, fetch, generate, push, pull, import, export, list, publish, release, test, setup, prepare, restart, stop, store, restore, translate, upgrade, zip, visualize, sync, switch, run, reset, load, dump, checkout, commit, drop, deploy, handle, trigger, render, lint, uninstall, split, parse, fix, refactor, transform, cat, ls, rm, serve, help, show, filter, login, logout, encrypt, decrypt, upload, download, analyse, transpile, compile, minify, copy
-
-**Examples for objects**: env, venv, submodule, container, database, snippet, model, module, repo, mail, doc, dependency, view, user, vault, file, host, node, log, password, hash, script, requirement, part, component, system, workspace, image, process, state, platform, dir, folder, readme, overview, lang, level, request, response, result, worker, server, proxy, workflow, volume, network, package, field, value, secret, chart, node, edge, function, method, firewall, html, css, image, svg, style, query, native, group, notebook
-
-**Objects can be tools**: odoo, vupress, nodejs, zsh, bash, fish, podman, kind, minikube, helm, nvim, docker, podman, rust, python, tmux, vim, helix, system, git, pass, llm, sql, dotenv, javascript, vue, vite, astro, typescript, turbo, pnpm, eslint, jenkins, k8s, nextcloud, postgres, metabase, ansible, prometheus, grafana, hugo, deno, bun, babel, panda, gulp, grunt, electron, react, express, mongodb, angular, ionic, meteor, webpack, bower, jupyter
-
-Generate Function Names
-
-## Style
-
-The bash scripts follow the [Bash Style Guide | ysap.sh](https://style.ysap.sh/). Have a look at the [AGENTS.md](/AGENTS) for details on the applied styling.
+Checkout the [development](/development) page for details.
diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk
index a515010..9f25b56 100644
--- a/_includes/layouts/base.njk
+++ b/_includes/layouts/base.njk
@@ -28,11 +28,11 @@
taskfile.build
diff --git a/development.md b/development.md
new file mode 100644
index 0000000..e319f48
--- /dev/null
+++ b/development.md
@@ -0,0 +1,40 @@
+---
+layout: layouts/base.njk
+---
+
+# Development
+
+The devleopment environment requires these tools:
+
+- [shellcheck](https://www.shellcheck.net/)
+- [pnpm](https://pnpm.io/)
+
+Clone this repo and enter the folder.
+
+```bash
+git clone https://git.taskfile.build "$HOME/taskfile.build"
+cd "$HOME/taskfile.build"
+```
+
+Run `task help` to list the commands of this project.
+
+## Style
+
+The bash scripts follow the [Bash Style Guide | ysap.sh](https://style.ysap.sh/). Have a look at the [AGENTS.md](/AGENTS) for details on the applied styling.
+
+## Naming
+
+The naming of functions is important. There are basically two styles:
+
+1. Action + Object
+2. Object + Action
+
+The task file functions use the first style. The name of the function starts with an action followed by an object. The object name can be singular or plural.
+
+**Examples for actions**:
activate, install, dev, develop, init, build, start, update, remove, delete, enable, disable, template, convert, create, edit, change, get, set, patch, fetch, generate, push, pull, import, export, list, publish, release, test, setup, prepare, restart, stop, store, restore, translate, upgrade, zip, visualize, sync, switch, run, reset, load, dump, checkout, commit, drop, deploy, handle, trigger, render, lint, uninstall, split, parse, fix, refactor, transform, cat, ls, rm, serve, help, show, filter, login, logout, encrypt, decrypt, upload, download, analyse, transpile, compile, minify, copy
+
+**Examples for objects**:
env, venv, submodule, container, database, snippet, model, module, repo, mail, doc, dependency, view, user, vault, file, host, node, log, password, hash, script, requirement, part, component, system, workspace, image, process, state, platform, dir, folder, readme, overview, lang, level, request, response, result, worker, server, proxy, workflow, volume, network, package, field, value, secret, chart, node, edge, function, method, firewall, html, css, image, svg, style, query, native, group, notebook
+
+**Objects can be tools**:
odoo, vupress, nodejs, zsh, bash, fish, podman, kind, minikube, helm, nvim, docker, podman, rust, python, tmux, vim, helix, system, git, pass, llm, sql, dotenv, javascript, vue, vite, astro, typescript, turbo, pnpm, eslint, jenkins, k8s, nextcloud, postgres, metabase, ansible, prometheus, grafana, hugo, deno, bun, babel, panda, gulp, grunt, electron, react, express, mongodb, angular, ionic, meteor, webpack, bower, jupyter
+
+
Generate Function Names
diff --git a/library.md b/library.md
index ef9cfb1..87782b5 100644
--- a/library.md
+++ b/library.md
@@ -219,6 +219,12 @@ The last parameter can be either a direct prompt string or a path to a text file
rows+=("update-changelog-with-llm||Update CHANGELOG.md with changes from staged git diff using LLM.")
```
+### setup-completion
+
+```bash
+rows+=("setup-completion|[shell]|Show shell completion instructions.")
+```
+
## Logging
Colorful logging in task commands.
diff --git a/prompts/04_add-command-update-changelog-from-git-diff.md b/prompts/04_add-command-update-changelog-from-git-diff.md
index 29ef581..67d70e2 100644
--- a/prompts/04_add-command-update-changelog-from-git-diff.md
+++ b/prompts/04_add-command-update-changelog-from-git-diff.md
@@ -4,4 +4,4 @@ Add a new command `update-changelog-with-llm`.
This command reads the `CHANGELOG.md` and the staged git diff. Then it updates the `CHANGELOG.md` with the changes made and adds the file to the staged changes.
-Add the new commands to the `library.md` in the LLM section. Then run `task update-template`.
\ No newline at end of file
+Add the new commands to the `library.md` in the LLM section. Then run `task update-template`.
diff --git a/prompts/05_add-emojies-to-navigation.md b/prompts/05_add-emojies-to-navigation.md
new file mode 100644
index 0000000..2524e9d
--- /dev/null
+++ b/prompts/05_add-emojies-to-navigation.md
@@ -0,0 +1,3 @@
+Read the AGENTS.md and README.md to get understanding of the project.
+
+Add a matching emoji to the navigation entries of the 11ty template `_includes/layouts/base.njk`.
diff --git a/prompts/06_completion_script.md b/prompts/06_completion_script.md
new file mode 100644
index 0000000..4013ee1
--- /dev/null
+++ b/prompts/06_completion_script.md
@@ -0,0 +1,43 @@
+Read the AGENTS.md and README.md to get understanding of the project.
+
+In the `usage.md` file, I have completion section. Instead of showing the completion scripts I want you to add a new command: `setup-completion`.
+
+The command shows the completion instructions. Here is an example of `opencode`:
+
+```bash
+
+[main][~/dotfiles]$ opencode completion
+#compdef opencode
+###-begin-opencode-completions-###
+#
+# yargs command completion script
+#
+# Installation: opencode completion >> ~/.zshrc
+# or opencode completion >> ~/.zprofile on OSX.
+#
+_opencode_yargs_completions()
+{
+ local reply
+ local si=$IFS
+ IFS=$'
+' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" opencode --get-yargs-completions "${words[@]}"))
+ IFS=$si
+ if [[ ${#reply} -gt 0 ]]; then
+ _describe 'values' reply
+ else
+ _default
+ fi
+}
+if [[ "'${zsh_eval_context[-1]}" == "loadautofunc" ]]; then
+ _opencode_yargs_completions "$@"
+else
+ compdef _opencode_yargs_completions opencode
+fi
+###-end-opencode-completions-###
+```
+
+The command detects if bash or zsh is active.
+
+If should be possible to `task setup-completion >> ~/.zshrc`
+
+Add the new commands to the `library.md` in the LLM section.
diff --git a/task b/task
index 77cf2d8..6f42ad5 100755
--- a/task
+++ b/task
@@ -9,7 +9,6 @@ help-table() {
rows+=("all||Run all tasks.")
rows+=("build-11ty||Build the 11ty website.")
rows+=("build-image|[output]|Build Docker image with buildx.")
- rows+=("commit-with-llm||Commit with llm generated commit message.")
rows+=("dev-11ty||Run 11ty server.")
rows+=("help|[grep]|Show help for commands.")
rows+=("install||Install Node packages.")
@@ -17,6 +16,7 @@ help-table() {
rows+=("run||Run Docker image.")
rows+=("run-tests||Test with shellcheck.")
rows+=("serve-11ty||Serve the 11ty output folder.")
+ rows+=("setup-completion|[shell]|Show shell completion instructions.")
rows+=("update-template||Update task.template from library.md.")
rows+=("version||Show version of required tools.")
@@ -118,7 +118,134 @@ serve-11ty() {
}
version() {
+ echo "pnpm: $(pnpm --version)"
echo "eleventy: $(pnpm dlx @11ty/eleventy --version)"
+ echo "shellcheck: $(shellcheck --version)"
+}
+
+setup-completion() {
+ local shell_type="$1"
+
+ # Set default shell type if not provided
+ if [[ -z "$shell_type" ]]; then
+ shell_type="bash" # Default to bash
+ fi
+
+ # Validate shell type
+ case "$shell_type" in
+ bash|zsh|fish)
+ # Valid shell type
+ ;;
+ *)
+ echo "Error: Unsupported shell type '$shell_type'. Use 'bash', 'zsh', or 'fish'."
+ echo "Usage: task setup-completion [bash|zsh|fish]"
+ return 1
+ ;;
+ esac
+
+ # Output the actual completion script
+ output_completion_script "$shell_type"
+
+ # Add instructions as comments at the end
+ echo ""
+ echo "# ============================================"
+ echo "# Taskfile completion setup instructions"
+ echo "# ============================================"
+ echo "# To enable completion, add this script to your shell configuration:"
+
+ if [[ "$shell_type" == "fish" ]]; then
+ echo "# task setup-completion fish >> ~/.config/fish/config.fish"
+ echo "# source ~/.config/fish/config.fish"
+ elif [[ "$shell_type" == "zsh" ]]; then
+ echo "# task setup-completion zsh >> ~/.zshrc"
+ echo "# source ~/.zshrc"
+ else
+ echo "# task setup-completion bash >> ~/.bashrc"
+ echo "# source ~/.bashrc"
+ fi
+ echo "# ============================================"
+}
+
+output_completion_script() {
+ local shell_type="$1"
+
+ # Default to bash if no shell type provided
+ if [[ -z "$shell_type" ]]; then
+ shell_type="bash"
+ fi
+
+ if [[ "$shell_type" == "fish" ]]; then
+ # Fish completion script
+ cat << 'EOF'
+# Taskfile completion for fish
+function _task_completions
+ # Get the current word being typed
+ set cur (commandline -p)
+
+ # Get the previous word
+ set prev (commandline -oprev)
+
+ # Get the available commands from `task help`
+ set commands (./task help | grep -A100 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '\n' ' ')
+
+ if test (count (commandline -opc)) -eq 1
+ # Provide completions for the command part (second word)
+ complete -c task -f -n "__fish_seen_subcommand_from $prev" -a "$commands"
+ else if test (count (commandline -opc)) -eq 2
+ # Provide file path completions for the third parameter
+ complete -c task -f -n "__fish_seen_subcommand_from $prev" -a (ls)
+ end
+end
+EOF
+ elif [[ "$shell_type" == "zsh" ]]; then
+ # ZSH completion script
+ cat << 'EOF'
+# Taskfile completion for zsh
+_task_completions() {
+ local reply
+ local si=$IFS
+ IFS=$'
+' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" ./task help | grep -A999 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '
+' ' '))
+ IFS=$si
+ if [[ ${#reply} -gt 0 ]]; then
+ _describe 'values' reply
+ else
+ _default
+ fi
+}
+
+if [[ "${zsh_eval_context[-1]}" == "loadautofunc" ]]; then
+ _task_completions "$@"
+else
+ compdef _task_completions task
+ compdef _task_completions t
+fi
+EOF
+ else
+ # Bash completion script
+ cat << 'EOF'
+# Taskfile completion for bash
+_task_completions() {
+ local cur prev commands
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+ commands=$(./task help | grep -A999 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '\n' ' ')
+
+ if [[ ${COMP_CWORD} == 1 ]]; then
+ COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") )
+ elif [[ ${COMP_CWORD} == 2 ]]; then
+ COMPREPLY=( $(compgen -f -- "${cur}") )
+ else
+ COMPREPLY=()
+ fi
+}
+
+complete -F _task_completions task
+complete -F _task_completions t
+EOF
+ fi
}
update-template() {
diff --git a/task.template b/task.template
index 0e78082..9905048 100755
--- a/task.template
+++ b/task.template
@@ -55,6 +55,7 @@ help-table() {
rows+=("login-docker|[user][token]|Run Docker login and create docker config.")
rows+=("build-image|[output]|Build Docker image with buildx.")
rows+=("install-ansible-build-scripts|[role]|Install scripts of the specified Ansbile role.")
+ rows+=("setup-completion||Show shell completion instructions.")
for row in "${rows[@]}"; do
IFS='|' read -r cmd opt desc <<< "$row"
diff --git a/usage.md b/usage.md
index 4ea6e22..cad1383 100644
--- a/usage.md
+++ b/usage.md
@@ -15,11 +15,11 @@ task
[options]
commands:
-| Command | Option | Description |
-|----------------------|--------|--------------------------------------|
-| all | | Run all tasks. |
-| install | | Install build dependencies. |
-| lint | | Lint code with prettier. |
+| Command | Option | Description |
+|-------------|--------|-----------------------------|
+| all | | Run all tasks. |
+| install | | Install build dependencies. |
+| lint | | Lint code with prettier. |
...
```
@@ -33,45 +33,35 @@ And if there is a command group run it with `task all`.
With the output of `task help` the task commands can be completed.
-Completion for bash: `/etc/bash_completion.d/task_completions`
+To set up shell completion, specify your shell type:
+
+For bash:
```bash
-#!/usr/bin/env bash
-
-_task_completions() {
- local cur prev commands
- cur="${COMP_WORDS[COMP_CWORD]}"
- prev="${COMP_WORDS[COMP_CWORD-1]}"
-
- commands=$(./task help | grep -A999 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '\n' ' ')
-
- if [[ ${COMP_CWORD} == 1 ]]; then
- COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") )
- elif [[ ${COMP_CWORD} == 2 ]]; then
- COMPREPLY=( $(compgen -f -- "${cur}") )
- else
- COMPREPLY=()
- fi
-}
-
-complete -F _task_completions task
-complete -F _task_completions t
+task setup-completion bash >> ~/.bashrc
+source ~/.bashrc
```
-Completion for zsh: `~/.oh-my-zsh/completions/_task`
+For zsh:
```bash
-#compdef task t
+task setup-completion zsh >> ~/.zshrc
+source ~/.zshrc
+```
-_arguments '1: :->tasks' '*: :_files'
+For fish:
-case "$state" in
- tasks)
- args=$(./task help | grep -A999 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '\n' ' ')
- args="$args help"
- _arguments "1:profiles:($args)"
- ;;
-esac
+```bash
+task setup-completion fish >> ~/.config/fish/config.fish
+source ~/.config/fish/config.fish
+```
+
+To see the completion script without applying it:
+
+```bash
+task setup-completion bash # Shows bash completion script
+task setup-completion zsh # Shows zsh completion script
+task setup-completion fish # Shows fish completion script
```
The completion also works for task alias `alias t='./task'`.