mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-08-02 07:07:46 +00:00
comma: upgrade template (#725)
- README.md: delete the content of template and replace it with a link - comma_test: T/F execute a closure and return a true or false - comma_tmpl: add example of building image --------- Co-authored-by: nash <nash@iffy.me>
This commit is contained in:
parent
0d55be71ea
commit
0632778754
4 changed files with 205 additions and 127 deletions
|
@ -1,93 +1,165 @@
|
||||||
|
# Comma, task and test runner of nu script
|
||||||
|
|
||||||
Working dir task runner, similar to `pwd-module`, but supports completion and description through custom data formats
|
Working dir task runner, similar to `pwd-module`, but supports completion and description through custom data formats
|
||||||
- `,` or `*` need to be exported in order to use `,` directly
|
|
||||||
- Directly execute `,` to create a new template file or edit an existing file
|
|
||||||
- Custom tasks are written in `$env.comma` and can be nested
|
|
||||||
- no spaces allowed in name (except testing)
|
|
||||||
- Generate completions based on the structure of `$env.comma`
|
|
||||||
- You can use closure to customize completion
|
|
||||||
- In `$_.act` of default closure, you can receive parameters after the current position
|
|
||||||
- In `$_.cmp` , you can receive the parameter before the current position
|
|
||||||
- Supports `computed`, the definition method refers to `$env.comma_scope.computed`, accepts two parameters, runtime parameters and `$env.comma_scope`
|
|
||||||
- Supports `filter`, similar to `computed`, but only runs when declared, specified through `$_.flt`
|
|
||||||
- Supports `watch` (and polling), specified through `$_.wth`.
|
|
||||||
- `glob` defaults to `*`, `op` defaults to `['Write']`, `postpone` defaults to `false`
|
|
||||||
- In watch mode (not Polling) inject `$_.wth`(op, path, new_path) into parameter `$s`
|
|
||||||
- when the `interval` field is included, it is polling mode(`clear` defaults to 'false')
|
|
||||||
- Identity supports alias
|
|
||||||
- children sub s
|
|
||||||
- description desc dsc d
|
|
||||||
- action act a
|
|
||||||
- completion cmp c
|
|
||||||
- filter flt f
|
|
||||||
- computed cpu u
|
|
||||||
- watch wth w
|
|
||||||
- tag
|
|
||||||
- expect exp e x
|
|
||||||
- mock test_args m
|
|
||||||
- report rpt r
|
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
`,` or `*` need to be exported in order to use `,` Directly
|
||||||
|
|
||||||
example:
|
```
|
||||||
|
use comma.nu *
|
||||||
|
```
|
||||||
|
|
||||||
|
When you enter a directory, if a `,.nu` file exists, it will be loaded. (Currently you need to press the Enter key again to take effect)
|
||||||
|
|
||||||
|
Or `source` any file that defines `$env.comma_scope` and `$env.comma` variables
|
||||||
|
|
||||||
|
If there is no `,.nu` file in the current directory, executing `,` without arguments will create a new one from the template. If the file exists, edit it
|
||||||
|
|
||||||
|
### Task Definition
|
||||||
|
Tasks are written in `$env.comma` and can be nested, and no spaces allowed in name (except testing).
|
||||||
|
|
||||||
|
The nodes of the tree can be ordinary records, and the tasks are defined in the closure of the leaf nodes.
|
||||||
|
|
||||||
|
This tree will be traversed during completion. For tasks, you can customize the completion behavior.
|
||||||
|
|
||||||
|
Customize completion behavior, as well as descriptions, filters, watches, tests, etc. Need to add some special attributes to the record, such as `$_.children`, `$_.action`, `$_.completion` (so `$env.comma` and `$env.comma_scope` accepts a closure to avoid potential naming conflicts).
|
||||||
|
|
||||||
|
```
|
||||||
|
$env.comma = {|_|{
|
||||||
|
dev: {
|
||||||
|
run: {
|
||||||
|
$_.action: {|a,s| nu $a.0 }
|
||||||
|
$_.watch: { glob: '*.nu', clear: true }
|
||||||
|
$_.completion: { ls *.nu | get name }
|
||||||
|
$_.desc: "develop a nu script"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
These attributes support aliases like:
|
||||||
|
|
||||||
|
| attribute | alias |
|
||||||
|
|-------------|----------------|
|
||||||
|
| children | sub, s |
|
||||||
|
| description | desc, dsc, d |
|
||||||
|
| action | act, a |
|
||||||
|
| completion | cmp, c |
|
||||||
|
| filter | flt, f |
|
||||||
|
| computed | cpu, u |
|
||||||
|
| watch | wth, w |
|
||||||
|
| tag | |
|
||||||
|
| expect | exp, e, x |
|
||||||
|
| mock | test_args, m |
|
||||||
|
| report | rpt, r |
|
||||||
|
|
||||||
|
The closure of the task's `action`, `completion` accepts two parameters, the rest arguments after the breadcrumbs and `$env.comma_scope`.
|
||||||
|
|
||||||
|
`computed` and `filter` are defined in `$env.comma_scope` which is used to share data, alse accept these two parameters.
|
||||||
|
|
||||||
|
`computed` is calculated in the defined order and replaced with the result.
|
||||||
```
|
```
|
||||||
$env.comma_scope = {|_|{
|
$env.comma_scope = {|_|{
|
||||||
created: '2023-12-24{0}01:46:27'
|
hello: 'hello'
|
||||||
computed: {$_.computed:{|a, s| $'($s.created)($a)' }}
|
greet: {$_.computed:{|a, s| $'($s.hello): ($a)' }}
|
||||||
say: {|s| print $'(ansi $_.settings.theme.info)($s)(ansi reset)' }
|
|
||||||
quick: {$_.filter:{|a, s| do $s.say 'run a `quick` filter' }}
|
|
||||||
slow: {$_.filter:{|a, s|
|
|
||||||
do $s.say 'run a `slow` filter'
|
|
||||||
sleep 1sec
|
|
||||||
do $s.say 'filter need to be declared'
|
|
||||||
sleep 1sec
|
|
||||||
$'($s.computed)<($a)>'
|
|
||||||
}}
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
`filter` is called when it is declared. If a record is returned, it will be merged back to the $env.comma_scope.
|
||||||
|
```
|
||||||
|
$env.comma_scope = {|_|{
|
||||||
|
log: {$_.filter:{|a, s| do $_.tips 'run filter' `foo` }}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
$env.comma = {|_|{
|
$env.comma = {|_|{
|
||||||
created: {|a, s| $s.computed }
|
foo: {
|
||||||
inspect: {|a, s| {index: $_, scope: $s, args: $a} | table -e }
|
|
||||||
test: {
|
|
||||||
$_.sub: {
|
$_.sub: {
|
||||||
batch: { 'created; inspect' | do $_.batch }
|
bar: {
|
||||||
watch: {
|
$_.action: { echo 'hello' }
|
||||||
$_.action: {|a, s| $s | get $_.watch }
|
$_.filter: ['log']
|
||||||
$_.completion: {ls *.json | get name}
|
}
|
||||||
$_.desc: 'inspect watch context'
|
}
|
||||||
|
$_.filter: ['log']
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Dry run
|
||||||
|
If execute the command in `$_.action` with `pp`, and pass `--print` flag with `,`, only prints the arguments received by `pp` without actually executing it.
|
||||||
|
|
||||||
|
`pp` can be run alone with flag `--print`.
|
||||||
|
```
|
||||||
|
pp --print aaa bbbb ccccc dddddd eeeeee [
|
||||||
|
ffffff gggggggggg [
|
||||||
|
hhhhhhhhh iiiiiiiiii lllllllll
|
||||||
|
] mmmmmmmmmmmmm nnnnnnnnnnnn
|
||||||
|
aaaaaaaaaaaaaaa
|
||||||
|
xxxxxxxxxxxxxxxx
|
||||||
|
yyyyyyyyyyyyyyyy
|
||||||
|
zzzzzzzzzzzzzzz
|
||||||
|
jjjjjjjjjjjjj
|
||||||
|
] oooooooo ppppppppp [qqqqqq [rrrrrr ssssss tttttt] uuuuuu]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Watch and polling
|
||||||
|
If `$_.watch` is defined and run with `--watch` flag, it will be run in watch mode.
|
||||||
|
```
|
||||||
|
$env.comma = {|_|{
|
||||||
|
foo: {
|
||||||
$_.watch: {
|
$_.watch: {
|
||||||
glob: '*'
|
glob: '*'
|
||||||
op: ['Write', 'Create']
|
op: ['Write', 'Create']
|
||||||
postpone: true
|
postpone: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open_file: {
|
}}
|
||||||
$_.action: {|a, s| open $a.0 }
|
```
|
||||||
$_.completion: {ls | get name}
|
- `glob` defaults to `*`, `op` defaults to `['Write']`, `postpone` defaults to `false`
|
||||||
$_.desc: 'open a file'
|
- In watch mode (not Polling) inject `$_.watch`(op, path, new_path) into parameter `$s`
|
||||||
$_.filter: ['slow']
|
- when the `interval` field is included, it is polling mode(`clear` defaults to 'false')
|
||||||
|
|
||||||
|
### Test
|
||||||
|
If run with the `--test` flag, it will detect that all nodes with `$_.expect` under the current and run their actions.
|
||||||
|
|
||||||
|
If there is also the --watch flag, it will run in watch mode without defining `$_.watch`.
|
||||||
|
|
||||||
|
If `$_.mock` exists, it will be passed as arguments to the `$_.action` and `$_.expect`.
|
||||||
|
|
||||||
|
If `$_.expect` is closure, pass it the result of `$_.action`, rest arguments and `$_.comma_scope`, if return True and the test passes.
|
||||||
|
|
||||||
|
If `$_.expect` is list, will use the closures in it as a set of tests.
|
||||||
|
|
||||||
|
If `$_.expect` is a scalar, it is compared directly with the result of actions.
|
||||||
|
|
||||||
|
If `$_.report` exists and the test fails, execute `$_.report` (has a predefined report `$_.diff`)
|
||||||
|
|
||||||
|
### vscode-tasks
|
||||||
|
The default template contains `vscode-tasks` and outputs a `.vscode/tasks.json`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$env.comma = {|_|{
|
||||||
|
vscode-tasks: {
|
||||||
|
$_.a: {
|
||||||
|
mkdir .vscode
|
||||||
|
', --vscode -j' | do $_.batch ',.nu' | save -f .vscode/tasks.json
|
||||||
}
|
}
|
||||||
ping: {
|
$_.d: "generate .vscode/tasks.json"
|
||||||
$_.action: {|a, s| ping -c 2 localhost }
|
$_.w: { glob: ',.nu' }
|
||||||
$_.watch: {
|
|
||||||
interval: 2sec
|
|
||||||
clear: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$_.desc: 'run test'
|
|
||||||
$_.filter: ['quick']
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
```
|
```
|
||||||
|
> requires `augustocdias.tasks-shell-input` to run `$_.completion` closure.
|
||||||
|
|
||||||
### todo
|
## todo
|
||||||
- [x] run
|
- [x] run
|
||||||
- [ ] dry
|
- [x] dry
|
||||||
- [ ] dry wrap lines
|
- [x] dry wrap lines
|
||||||
- [ ] accept list<string>
|
- [x] accept list<string>
|
||||||
- [x] formatter: outdent
|
- [x] formatter: outdent
|
||||||
- [x] complete
|
- [x] complete
|
||||||
- [x] with args
|
- [x] with args
|
||||||
- [x] scoped test
|
- [x] scoped test
|
||||||
|
- [x] pass scoped
|
||||||
- [x] tree map
|
- [x] tree map
|
||||||
- [x] test
|
- [x] test
|
||||||
- [ ] tag
|
- [ ] tag
|
||||||
|
@ -116,7 +188,6 @@ $env.comma = {|_|{
|
||||||
- [ ] pickString
|
- [ ] pickString
|
||||||
- [x] augustocdias.tasks-shell-input
|
- [x] augustocdias.tasks-shell-input
|
||||||
- [x] allow rest args as `promptString`
|
- [x] allow rest args as `promptString`
|
||||||
- https://code.visualstudio.com/docs/editor/variables-reference
|
|
||||||
- [x] clean filter output
|
- [x] clean filter output
|
||||||
- [x] add gen vscode-tasks to template
|
- [x] add gen vscode-tasks to template
|
||||||
- [ ] test and watch
|
- [ ] test and watch
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
export def lg [tag?] {
|
export def lg [tag?] {
|
||||||
let o = $in
|
let o = $in
|
||||||
print -e $'---($tag)---($o | describe)(char newline)($o | to yaml)'
|
let t = [
|
||||||
|
$'(ansi xterm_grey)--------(ansi xterm_olive)($tag)(ansi xterm_grey)--------'
|
||||||
|
$'(ansi xterm_grey39)($o | describe)'
|
||||||
|
$'(ansi xterm_grey66)($o | to yaml)'
|
||||||
|
(ansi reset)
|
||||||
|
]
|
||||||
|
print -e ($t | str join (char newline))
|
||||||
$o
|
$o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +196,9 @@ module resolve {
|
||||||
}
|
}
|
||||||
for i in ($flts | default []) {
|
for i in ($flts | default []) {
|
||||||
if $i in $flt {
|
if $i in $flt {
|
||||||
$vs = ($vs | merge {$i: (do ($flt | get $i) $args $vs)} )
|
let fr = do ($flt | get $i) $args $vs
|
||||||
|
let fr = if ($fr | describe -d).type == 'record' { $fr } else { {} }
|
||||||
|
$vs = ($vs | merge $fr)
|
||||||
} else {
|
} else {
|
||||||
error make -u {msg: $"filter `($i)` not found" }
|
error make -u {msg: $"filter `($i)` not found" }
|
||||||
}
|
}
|
||||||
|
@ -770,8 +778,8 @@ export-env {
|
||||||
print -e $"(ansi light_gray_italic)($m.0)(ansi reset) (ansi yellow_bold)($m.1?)(ansi reset)"
|
print -e $"(ansi light_gray_italic)($m.0)(ansi reset) (ansi yellow_bold)($m.1?)(ansi reset)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
T: { true }
|
T: {|f| {|r,a,s| do $f $r $a $s; true } }
|
||||||
F: { false }
|
F: {|f| {|r,a,s| do $f $r $a $s; false } }
|
||||||
I: {|x| $x }
|
I: {|x| $x }
|
||||||
diff: {|x|
|
diff: {|x|
|
||||||
use test
|
use test
|
||||||
|
|
|
@ -65,8 +65,8 @@ $env.comma = {|_|{
|
||||||
'example a b c e': {
|
'example a b c e': {
|
||||||
$_.act: {, -c example a b c e }
|
$_.act: {, -c example a b c e }
|
||||||
$_.x: [
|
$_.x: [
|
||||||
{|r,a| $r | where value == 'f' | not ($in | is-empty) }
|
{|r,a,s| $r | where value == 'f' | not ($in | is-empty) }
|
||||||
$_.T
|
(do $_.T {|r,a,s| $s | lg 'expect'})
|
||||||
{|r,a| 'q1|q2|q3|q4| open a file' == ($r | get 1.description) }
|
{|r,a| 'q1|q2|q3|q4| open a file' == ($r | get 1.description) }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -105,8 +105,8 @@ $env.comma = {|_|{
|
||||||
b: {
|
b: {
|
||||||
$_.sub: {
|
$_.sub: {
|
||||||
t1: {
|
t1: {
|
||||||
$_.act: $_.T
|
$_.act: { true }
|
||||||
$_.exp: $_.T
|
$_.exp: { true }
|
||||||
}
|
}
|
||||||
open_file: {
|
open_file: {
|
||||||
$_.act: {|a, s| open $a.0 }
|
$_.act: {|a, s| open $a.0 }
|
||||||
|
@ -119,7 +119,7 @@ $env.comma = {|_|{
|
||||||
e: {
|
e: {
|
||||||
$_.sub: {
|
$_.sub: {
|
||||||
f: {
|
f: {
|
||||||
$_.act: $_.T
|
$_.act: { true }
|
||||||
}
|
}
|
||||||
open_file: {
|
open_file: {
|
||||||
$_.act: {|a, s| open $a.0 }
|
$_.act: {|a, s| open $a.0 }
|
||||||
|
@ -131,8 +131,8 @@ $env.comma = {|_|{
|
||||||
$_.report: $_.diff
|
$_.report: $_.diff
|
||||||
}
|
}
|
||||||
t3: {
|
t3: {
|
||||||
$_.act: $_.T
|
$_.act: { true }
|
||||||
$_.exp: $_.T
|
$_.exp: { true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$_.dsc: 'ok'
|
$_.dsc: 'ok'
|
||||||
|
@ -141,8 +141,8 @@ $env.comma = {|_|{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t2: {
|
t2: {
|
||||||
$_.act: $_.T
|
$_.act: { true }
|
||||||
$_.exp: $_.T
|
$_.exp: { true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$_.dsc: 'this way'
|
$_.dsc: 'this way'
|
||||||
|
@ -198,15 +198,15 @@ $env.comma = {|_|{
|
||||||
args: [example a b c e]
|
args: [example a b c e]
|
||||||
}
|
}
|
||||||
do $_.test 'run test' {
|
do $_.test 'run test' {
|
||||||
expect: $_.T
|
expect: { true }
|
||||||
spec: {, -e test example }
|
spec: {, -e test example }
|
||||||
}
|
}
|
||||||
do $_.test 'run leaf test' {
|
do $_.test 'run leaf test' {
|
||||||
expect: $_.T
|
expect: { true }
|
||||||
spec: { , -t example a b t1 }
|
spec: { , -t example a b t1 }
|
||||||
}
|
}
|
||||||
do $_.test 'suit' {
|
do $_.test 'suit' {
|
||||||
expect: $_.T
|
expect: { true }
|
||||||
spec: { , -t suit }
|
spec: { , -t suit }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ $env.comma = {|_|{
|
||||||
$_.wth: { glob: '*.nu' }
|
$_.wth: { glob: '*.nu' }
|
||||||
}
|
}
|
||||||
complete: {
|
complete: {
|
||||||
$_.act: $_.T
|
$_.act: { true }
|
||||||
$_.wth: { glob: '*.nu' }
|
$_.wth: { glob: '*.nu' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
$env.comma_scope = {|_|{
|
$env.comma_scope = {|_|{
|
||||||
created: '{{time}}'
|
created: '{{time}}'
|
||||||
computed: {$_.computed:{|a, s| $'($s.created)($a)' }}
|
computed: {$_.computed:{|a, s| $'($s.created)($a)' }}
|
||||||
quick: {$_.filter:{|a, s| do $_.tips 'run filter' `quick` }}
|
log_args: {$_.filter:{|a, s| do $_.tips 'received arguments' $a }}
|
||||||
slow: {$_.filter:{|a, s|
|
|
||||||
do $_.tips 'run filter' `slow`
|
|
||||||
sleep 1sec
|
|
||||||
do $_.tips 'filter need to be declared'
|
|
||||||
sleep 1sec
|
|
||||||
$'($s.computed)<($a)>'
|
|
||||||
}}
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
$env.comma = {|_|{
|
$env.comma = {|_|{
|
||||||
|
@ -29,36 +22,42 @@ $env.comma = {|_|{
|
||||||
$_.completion: { ls *.nu | get name }
|
$_.completion: { ls *.nu | get name }
|
||||||
$_.desc: "develop a nu script"
|
$_.desc: "develop a nu script"
|
||||||
}
|
}
|
||||||
watch: {
|
build: {
|
||||||
$_.a: {|a,s| $', dev run ($a.0)' | do $_.batch ',.nu' }
|
image: {
|
||||||
$_.x: {|r,a| false }
|
$_.a: {|a,s|
|
||||||
$_.m: [,.nu]
|
^$env.docker-cli pull $a.0
|
||||||
$_.c: { ls *.nu | get name }
|
let tmp = mktemp
|
||||||
|
$"
|
||||||
|
FROM ($a.0)
|
||||||
|
|
||||||
|
RUN apt update \\
|
||||||
|
&& apt-get upgrade -y \\
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive \\
|
||||||
|
apt-get install -y --no-install-recommends \\
|
||||||
|
curl ca-certificates \\
|
||||||
|
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* \\
|
||||||
|
&& curl -sSL ($a.2) | tar zxf - -C /opt/vendor \\
|
||||||
|
&& chown -R 33:33 /opt/vendor"
|
||||||
|
| do $_.outdent
|
||||||
|
| save -f $tmp
|
||||||
|
|
||||||
|
^$env.docker-cli build -f $tmp -t $a.1 .
|
||||||
|
rm -f $tmp
|
||||||
|
^$env.docker-cli push $a.1
|
||||||
|
}
|
||||||
|
$_.c: {|a,s|
|
||||||
|
let l = $a | length
|
||||||
|
if $l < 1 {
|
||||||
|
['ubuntu', 'alpine', 'nginx']
|
||||||
|
} else if $l < 2 {
|
||||||
|
['target']
|
||||||
|
} else {
|
||||||
|
['vendor']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
test: {
|
$_.d: 'build docker image'
|
||||||
$_.sub: {
|
$_.f: ['log_args']
|
||||||
batch: { ', created; , inspect' | do $_.batch ',.nu' }
|
|
||||||
watch: {
|
|
||||||
$_.act: {|a, s| $s | get $_.watch }
|
|
||||||
$_.cmp: {ls *.json | get name}
|
|
||||||
$_.dsc: 'inspect watch context'
|
|
||||||
$_.wth: {
|
|
||||||
glob: '*'
|
|
||||||
op: ['Write', 'Create']
|
|
||||||
postpone: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ping: {
|
|
||||||
$_.action: {|a, s| ping -c 2 localhost }
|
|
||||||
$_.watch: {
|
|
||||||
interval: 2sec
|
|
||||||
clear: true
|
|
||||||
}
|
|
||||||
$_.filter: ['slow']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$_.desc: 'run test'
|
|
||||||
$_.filter: ['quick']
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue