AI prompts
base on A small, interactive command runner Dotree is a small interactive command runner. It wants to be a better home for your
aliases and bash functions, especially those that you don't use that often, and an
alternative to [just](https://github.com/casey/just).
![](./demo.gif)
Given a config file like this:
```
menu root {
g: git
m: misc
}
menu git {
am: "amend" - "git commit --amend --no-edit"
aam: "all amend" - "git commit -a --amend --no-edit"
ca: "git commit -a"
b: "git switch $(git branch | fzf)"
w: cmd {
vars output_dir, branch
"add worktree" - "git worktree add -b $branch $output_dir"
}
}
menu misc {
mn: "mount-netdrives"
un: "unmount-netdrives"
cv: "connect-vpn"
}
```
It presents you with the options to execute the commands configured in the file
by typing the configured key. For Example: with the given config file above, I could
start dotree by typing `dt` (after it was installed), and then type `gb` while dotree is
running to execute `git switch $(git branch | fzf)` in bash.
Alternatively you can also do that by entering `dt gb`. If you provide an argument, its
characters will be processed as if you typed them when the program is running.
A command can either be declared as quick command, i.e. a string that contains bash code,
optionally with another string and a `-` in front of it, to have a name displayed in place
of the bash code, or as command via the `cmd` keyword, which allows for the additional
definition of variables that will be queried and then passed as env vars to the bash invocation.
To query the input, [rustyline](https://github.com/kkawakam/rustyline) is used, and you have
path completion and a history.
An alternate form of strings are protected strings: `!"<content>"!`, in which case you can use
`"` freely within the string. And in case you even need `!"` in a string, you can add any
characters between the `!` and the `"`. The characters are not mirrored on the closing
delimiter. So `!ab"<content>"ab!` is valid, but ~`!ab"<content>"ba!`~ is not.
For an example of a real world config, [click here](./example.dt)
### Command Arguments
Commands can have arguments, which will be queried interactively, like this:
```
...
menu git {
...
w: cmd {
vars output_dir, branch
"add worktree" - "git worktree add -b $branch $output_dir"
}
}
...
```
The values are exposed via environment variables to the callee.
If you invoke dt with additional arguments, the additional arguments will be used as values
for the vars. For example: `dt gw fknorr/some-feature /tmp/worktree_dir`.
You can also assign default values for variables like this:
```
menu root {
f: cmd {
vars a, b, c="foo"
"echo $a $b $c"
}
}
```
Vars with default values will be queried, but if you just press enter,
the default value will be used. They will not be used if you pass the values
via arguments. I.e., if you call the above example with `dtl f alpha beta`, it will still ask
for a value for c interactively.
### Repeating Commands
You can configure dotree to continue after a command was executed, so that you can trigger
the command again with a single key press. This is useful for example, if you want to
change screen brightness when you don't have a keyboard with appropriate keys:
```
menu root {
m: brightnessctl
}
menu brightnessctl {
+: cmd {
set repeat
"brightnessctl set +10%"
}
-: cmd {
set repeat
"brightnessctl set -10%"
}
}
```
You can also add `ignore_result` as a config option, in which case dotree won't escape
when the command has a non-zero exit code, like this:
```
menu brightnessctl {
...
+: cmd {
set repeat, ignore_result
"brightnessctl set +10%"
}
...
```
### Echoing Commands
By default, dotree will echo the command it executes to stderr (this behavior change was introduced in 0.8.0).
If you don't like that, you can add `echo off` to the top of the file, like this:
```
echo off
menu root {
n: "echo don\'t show me"
y: "echo 'show me' without echoing the command" - @"echo show me"
}
```
This will switch the default behavior to not echoing the executed command. Before a command, you can
add an `@`, which will toggle the default behavior, i.e. if you have an `echo off` at the top of
your file, then commands with `@` will be echoed. If you do not have `echo off` at the top of the file
`@` will supress echoing.
### Naming Menus
You can also assign a different display name to a menu, like this:
```
menu "Worktree" git_worktree {
...
}
```
### Local mode
If you start dotree with -l, it will search for a dotree.dt file between the cwd and the file
system root. If it finds one, it uses it instead of the normal config file, and changes the
working directory before executing commands, to the containing directory. This way, you can
use dotree as a more interactive version of [just](https://github.com/casey/just). I aliased
`dt -l` to `dtl`
### Default Shell
By default, dotree uses "bash -euo pipefail -c" as shell invocation on linux, or "cmd /c" on
Windows. The shell string is always appended as last argument. You can change the default shell
by setting the environment variable `DT_DEFAULT_SHELL` or on a per-file basis, by placing
a shell directive as first element in the config file like this:
```
shell sh -c
menu root {
g: git
m: misc
}
...
```
It is also possible to change the shell for a command, by putting a shell directive into a
command like this:
```
menu root {
p: cmd {
shell python -c
"python hi" - !"print("hello from python")"!
}
}
```
### Alternative Config Path
By default, dotree looks at a file named `dotree.dt` in the XDG config dir, you can make
it look somewhere else with the `-c` command line argument
### Snippets
To share code between multiple commands, you can define snippets:
```
snippet shared_vars = !"
a_var=a_value
b_var=b_value
"!
menu root {
e: $shared_vars + "echo $a_var"
}
```
A snippet can be referenced by its name prefixed with a `$`. You use them in the definition
of commands or in the definition of snippets. The can occur in any order like this:
```
snippet vars = !"
FOO="foo"
"!
snippet a_fn = " # we want a newline here
append_foo() {
echo $1 foo
}
" # and here, since strings are simpli concatenated, and bash needs those newlines
# alternatively, we could use a ; in the command
menu root {
e: $vars + "echo foo=$FOO" + $a_fn + "append_foo $FOO"
}
```
## Installation
Download the appropriate binary for your platform (windows is untested) from the release page,
or install via cargo: `cargo install --git https://github.com/knorrfg/dotree`.
### Arch Linux
- [dotree](https://aur.archlinux.org/packages/dotree)
- [dotree-bin](https://aur.archlinux.org/packages/dotree-bin)
- [dotree-git](https://aur.archlinux.org/packages/dotree-git)
", Assign "at most 3 tags" to the expected json: {"id":"4666","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"