mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-08-01 06:37: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
|
||||
- `,` 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:
|
||||
```
|
||||
$env.comma_scope = {|_|{
|
||||
created: '2023-12-24{0}01:46:27'
|
||||
computed: {$_.computed:{|a, s| $'($s.created)($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)>'
|
||||
}}
|
||||
}}
|
||||
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 = {|_|{
|
||||
created: {|a, s| $s.computed }
|
||||
inspect: {|a, s| {index: $_, scope: $s, args: $a} | table -e }
|
||||
test: {
|
||||
$_.sub: {
|
||||
batch: { 'created; inspect' | do $_.batch }
|
||||
watch: {
|
||||
$_.action: {|a, s| $s | get $_.watch }
|
||||
$_.completion: {ls *.json | get name}
|
||||
$_.desc: 'inspect watch context'
|
||||
$_.watch: {
|
||||
glob: '*'
|
||||
op: ['Write', 'Create']
|
||||
postpone: true
|
||||
}
|
||||
}
|
||||
open_file: {
|
||||
$_.action: {|a, s| open $a.0 }
|
||||
$_.completion: {ls | get name}
|
||||
$_.desc: 'open a file'
|
||||
$_.filter: ['slow']
|
||||
}
|
||||
ping: {
|
||||
$_.action: {|a, s| ping -c 2 localhost }
|
||||
$_.watch: {
|
||||
interval: 2sec
|
||||
clear: true
|
||||
}
|
||||
}
|
||||
dev: {
|
||||
run: {
|
||||
$_.action: {|a,s| nu $a.0 }
|
||||
$_.watch: { glob: '*.nu', clear: true }
|
||||
$_.completion: { ls *.nu | get name }
|
||||
$_.desc: "develop a nu script"
|
||||
}
|
||||
$_.desc: 'run test'
|
||||
$_.filter: ['quick']
|
||||
}
|
||||
}}
|
||||
```
|
||||
|
||||
### todo
|
||||
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 = {|_|{
|
||||
hello: 'hello'
|
||||
greet: {$_.computed:{|a, s| $'($s.hello): ($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 = {|_|{
|
||||
foo: {
|
||||
$_.sub: {
|
||||
bar: {
|
||||
$_.action: { echo 'hello' }
|
||||
$_.filter: ['log']
|
||||
}
|
||||
}
|
||||
$_.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: {
|
||||
glob: '*'
|
||||
op: ['Write', 'Create']
|
||||
postpone: true
|
||||
}
|
||||
}
|
||||
}}
|
||||
```
|
||||
- `glob` defaults to `*`, `op` defaults to `['Write']`, `postpone` defaults to `false`
|
||||
- In watch mode (not Polling) inject `$_.watch`(op, path, new_path) into parameter `$s`
|
||||
- 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
|
||||
}
|
||||
$_.d: "generate .vscode/tasks.json"
|
||||
$_.w: { glob: ',.nu' }
|
||||
}
|
||||
}}
|
||||
```
|
||||
> requires `augustocdias.tasks-shell-input` to run `$_.completion` closure.
|
||||
|
||||
## todo
|
||||
- [x] run
|
||||
- [ ] dry
|
||||
- [ ] dry wrap lines
|
||||
- [ ] accept list<string>
|
||||
- [x] dry
|
||||
- [x] dry wrap lines
|
||||
- [x] accept list<string>
|
||||
- [x] formatter: outdent
|
||||
- [x] complete
|
||||
- [x] with args
|
||||
- [x] scoped test
|
||||
- [x] pass scoped
|
||||
- [x] tree map
|
||||
- [x] test
|
||||
- [ ] tag
|
||||
|
@ -116,7 +188,6 @@ $env.comma = {|_|{
|
|||
- [ ] pickString
|
||||
- [x] augustocdias.tasks-shell-input
|
||||
- [x] allow rest args as `promptString`
|
||||
- https://code.visualstudio.com/docs/editor/variables-reference
|
||||
- [x] clean filter output
|
||||
- [x] add gen vscode-tasks to template
|
||||
- [ ] test and watch
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
export def lg [tag?] {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -190,7 +196,9 @@ module resolve {
|
|||
}
|
||||
for i in ($flts | default []) {
|
||||
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 {
|
||||
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)"
|
||||
}
|
||||
}
|
||||
T: { true }
|
||||
F: { false }
|
||||
T: {|f| {|r,a,s| do $f $r $a $s; true } }
|
||||
F: {|f| {|r,a,s| do $f $r $a $s; false } }
|
||||
I: {|x| $x }
|
||||
diff: {|x|
|
||||
use test
|
||||
|
|
|
@ -65,8 +65,8 @@ $env.comma = {|_|{
|
|||
'example a b c e': {
|
||||
$_.act: {, -c example a b c e }
|
||||
$_.x: [
|
||||
{|r,a| $r | where value == 'f' | not ($in | is-empty) }
|
||||
$_.T
|
||||
{|r,a,s| $r | where value == 'f' | not ($in | is-empty) }
|
||||
(do $_.T {|r,a,s| $s | lg 'expect'})
|
||||
{|r,a| 'q1|q2|q3|q4| open a file' == ($r | get 1.description) }
|
||||
]
|
||||
}
|
||||
|
@ -105,8 +105,8 @@ $env.comma = {|_|{
|
|||
b: {
|
||||
$_.sub: {
|
||||
t1: {
|
||||
$_.act: $_.T
|
||||
$_.exp: $_.T
|
||||
$_.act: { true }
|
||||
$_.exp: { true }
|
||||
}
|
||||
open_file: {
|
||||
$_.act: {|a, s| open $a.0 }
|
||||
|
@ -119,7 +119,7 @@ $env.comma = {|_|{
|
|||
e: {
|
||||
$_.sub: {
|
||||
f: {
|
||||
$_.act: $_.T
|
||||
$_.act: { true }
|
||||
}
|
||||
open_file: {
|
||||
$_.act: {|a, s| open $a.0 }
|
||||
|
@ -131,8 +131,8 @@ $env.comma = {|_|{
|
|||
$_.report: $_.diff
|
||||
}
|
||||
t3: {
|
||||
$_.act: $_.T
|
||||
$_.exp: $_.T
|
||||
$_.act: { true }
|
||||
$_.exp: { true }
|
||||
}
|
||||
}
|
||||
$_.dsc: 'ok'
|
||||
|
@ -141,8 +141,8 @@ $env.comma = {|_|{
|
|||
}
|
||||
}
|
||||
t2: {
|
||||
$_.act: $_.T
|
||||
$_.exp: $_.T
|
||||
$_.act: { true }
|
||||
$_.exp: { true }
|
||||
}
|
||||
}
|
||||
$_.dsc: 'this way'
|
||||
|
@ -198,15 +198,15 @@ $env.comma = {|_|{
|
|||
args: [example a b c e]
|
||||
}
|
||||
do $_.test 'run test' {
|
||||
expect: $_.T
|
||||
expect: { true }
|
||||
spec: {, -e test example }
|
||||
}
|
||||
do $_.test 'run leaf test' {
|
||||
expect: $_.T
|
||||
expect: { true }
|
||||
spec: { , -t example a b t1 }
|
||||
}
|
||||
do $_.test 'suit' {
|
||||
expect: $_.T
|
||||
expect: { true }
|
||||
spec: { , -t suit }
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ $env.comma = {|_|{
|
|||
$_.wth: { glob: '*.nu' }
|
||||
}
|
||||
complete: {
|
||||
$_.act: $_.T
|
||||
$_.act: { true }
|
||||
$_.wth: { glob: '*.nu' }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
$env.comma_scope = {|_|{
|
||||
created: '{{time}}'
|
||||
computed: {$_.computed:{|a, s| $'($s.created)($a)' }}
|
||||
quick: {$_.filter:{|a, s| do $_.tips 'run filter' `quick` }}
|
||||
slow: {$_.filter:{|a, s|
|
||||
do $_.tips 'run filter' `slow`
|
||||
sleep 1sec
|
||||
do $_.tips 'filter need to be declared'
|
||||
sleep 1sec
|
||||
$'($s.computed)<($a)>'
|
||||
}}
|
||||
log_args: {$_.filter:{|a, s| do $_.tips 'received arguments' $a }}
|
||||
}}
|
||||
|
||||
$env.comma = {|_|{
|
||||
|
@ -29,36 +22,42 @@ $env.comma = {|_|{
|
|||
$_.completion: { ls *.nu | get name }
|
||||
$_.desc: "develop a nu script"
|
||||
}
|
||||
watch: {
|
||||
$_.a: {|a,s| $', dev run ($a.0)' | do $_.batch ',.nu' }
|
||||
$_.x: {|r,a| false }
|
||||
$_.m: [,.nu]
|
||||
$_.c: { ls *.nu | get name }
|
||||
}
|
||||
}
|
||||
test: {
|
||||
$_.sub: {
|
||||
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
|
||||
build: {
|
||||
image: {
|
||||
$_.a: {|a,s|
|
||||
^$env.docker-cli pull $a.0
|
||||
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
|
||||
}
|
||||
}
|
||||
ping: {
|
||||
$_.action: {|a, s| ping -c 2 localhost }
|
||||
$_.watch: {
|
||||
interval: 2sec
|
||||
clear: true
|
||||
$_.c: {|a,s|
|
||||
let l = $a | length
|
||||
if $l < 1 {
|
||||
['ubuntu', 'alpine', 'nginx']
|
||||
} else if $l < 2 {
|
||||
['target']
|
||||
} else {
|
||||
['vendor']
|
||||
}
|
||||
}
|
||||
$_.filter: ['slow']
|
||||
$_.d: 'build docker image'
|
||||
$_.f: ['log_args']
|
||||
}
|
||||
}
|
||||
$_.desc: 'run test'
|
||||
$_.filter: ['quick']
|
||||
}
|
||||
}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue