new module comma and some updates (#704)

update:
- cwdhist: openeditor changed from alt+e to alt+o
- docker: pull, push add nerdctl insecure-registry support
- docker: registry show use curl instead http get (may cause dns
resolution problems)
- git: status `table -n` changed to `table -i`

new module: comma

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
- Generate completions based on the structure of `$env.comma`
- You can use closure to customize completion
- In `$env.commax.act` of default closure, you can receive parameters
after the current position
- In `$env.commax.cmp` , you can receive the parameter before the
current position

---------

Co-authored-by: nash <nash@iffy.me>
This commit is contained in:
fj0r 2023-12-20 20:03:20 +08:00 committed by GitHub
parent 6f1c0dfef2
commit fce44fbbfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 318 additions and 28 deletions

60
modules/comma/README.md Normal file
View File

@ -0,0 +1,60 @@
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
- Generate completions based on the structure of `$env.comma`
- You can use closure to customize completion
- In `$env.commax.act` of default closure, you can receive parameters after the current position
- In `$env.commax.cmp` , you can receive the parameter before the current position
example:
```
$env.commav = {
}
$env.comma = {
created: { '2023-12-20[3]16:02:56' }
hello: {
$env.commax.act: {|x| print $'hello ($x)' }
$env.commax.dsc: 'hello (x)'
$env.commax.cmp: {|args| $args}
}
open: {
$env.commax.sub: {
any: {
$env.commax.act: {|x| open $x.0}
$env.commax.cmp: {ls | get name}
$env.commax.dsc: 'open a file'
}
json: {
$env.commax.act: {|x| open $x.0}
$env.commax.cmp: {ls *.json | get name}
$env.commax.dsc: 'open a json file'
}
}
$env.commax.dsc: 'open a file'
}
# Nest as you like
a: {
b: {
c: {
$env.commax.act: {|x| print $x }
$env.commax.dsc: 'description'
$env.commax.cmp: {|| ls | get name }
}
d: { pwd }
}
x: {
$env.commax.sub: {
y: {
$env.commax.act: {|x| print y}
$env.commax.cmp: {|| [y1 y2 y3]}
$env.commax.dsc: 'description'
}
}
$env.commax.dsc: 'xxx'
}
}
}
```

234
modules/comma/comma.nu Normal file
View File

@ -0,0 +1,234 @@
def unindent [] {
let txt = $in | lines | range 1..
let indent = $txt.0 | parse --regex '^(?P<indent>\s*)' | get indent.0 | str length
$txt
| each {|s| $s | str substring $indent.. }
| str join (char newline)
}
def 'path parents' [] {
$in
| path expand
| path split
| reduce -f [ '' ] {|x, acc| [( $acc.0 | path join $x ), ...$acc] }
| range ..-2
}
def find [] {
$in
| path parents
| filter {|x| $x | path join ',.nu' | path exists }
| get 0?
}
def comma_file [] {
[
{
condition: {|_, after| not ($after | path join ',.nu' | path exists)}
code: "$env.comma = null"
}
{
condition: {|_, after| $after | path join ',.nu' | path exists}
code: "
print $'(ansi default_underline)(ansi default_bold),(ansi reset).nu (ansi green_italic)detected(ansi reset)...'
print $'(ansi yellow_italic)activating(ansi reset) (ansi default_underline)(ansi default_bold),(ansi reset) module with `(ansi default_dimmed)(ansi default_italic)source ,.nu(ansi reset)`'
source ,.nu
"
}
]
}
export-env {
$env.config = ( $env.config | upsert hooks.env_change.PWD { |config|
let o = ($config | get -i hooks.env_change.PWD)
let val = (comma_file)
if $o == null {
$val
} else {
$o | append $val
}
})
let k = (gensym)
$env.commax = {
sub: $k.0
dsc: $k.1
act: $k.2
cmp: $k.3
}
}
def gensym [] {
mut r = []
let rk = random chars
for i in 1..4 {
let b = ($i - 1) * 5
let e = $i * 5
$r ++= [($rk | str substring $b..$e)]
}
$r
# TODO: debug
# [sub dsc act cmp]
}
def log [tag? -c] {
let o = $in
if ($c) {
echo $'---(char newline)' | save -f ~/.cache/comma.log
} else {
echo $'---($tag)---($o | describe)(char newline)($o | to yaml)' | save -a ~/.cache/comma.log
}
$o
}
def 'as act' [] {
let o = $in
let ix = $env.commax
let t = ($o | describe -d).type
if $t == 'closure' {
{ $ix.act: $o }
} else if ($ix.sub in $o) {
null
} else if ($ix.act in $o) {
$o
} else {
null
}
}
def run [tbl] {
let loc = $in
let ix = $env.commax
mut act = $tbl
mut arg = []
for i in $loc {
let a = $act | as act
if ($a | is-empty) {
if ($ix.sub in $act) and ($i in ($act | get $ix.sub)) {
let n = $act | get $ix.sub | get $i
$act = $n
} else if $i in $act {
let n = $act | get $i
$act = $n
} else {
$act = {|| print $"not found `($i)`"}
break
}
} else {
$arg ++= [$i]
}
}
let a = $act | as act
if ($a | is-empty) {
let c = if $ix.sub in $act { $act | get $ix.sub | columns } else { $act | columns }
print $'require argument: ($c)'
} else {
do ($a | get $ix.act) $arg
}
}
def complete [tbl] {
let argv = $in
let ix = $env.commax
mut tbl = $env.comma
for i in $argv {
let c = if ($i | is-empty) {
$tbl
} else {
let tp = ($tbl | describe -d).type
if ($tp == 'record') and ($i in $tbl) {
let j = $tbl | get $i
if $ix.sub in $j {
$j | get $ix.sub
} else {
$j
}
} else {
$tbl
}
}
let a = $c | as act
if not ($a | is-empty) {
let r = do ($a | get $ix.cmp) $argv
$tbl = $r
} else {
$tbl = $c
}
}
match ($tbl | describe -d).type {
record => {
$tbl
| transpose k v
| each {|x|
if ($x.v | describe -d).type == 'closure' {
$x.k
} else if $ix.dsc in $x.v {
{ value: $x.k, description: ($x.v | get $ix.dsc) }
} else {
$x.k
}
}
}
list => { $tbl }
_ => { $tbl }
}
}
def 'parse argv' [] {
let context = $in
$context.0
| str substring 0..$context.1
| split row -r '\s+'
| range 1..
| where not ($it | str starts-with '-')
}
def compos [...context] {
$context
| parse argv
| complete $env.comma
}
export def , [...args:string@compos] {
if ($args | is-empty) {
if ([$env.PWD, ',.nu'] | path join | path exists) {
^$env.EDITOR ,.nu
} else {
let a = [yes no] | input list 'create ,.nu?'
if $a == 'yes' {
$"
$env.commav = {
}
$env.comma = {
created: { '(date now | format date '%Y-%m-%d[%w]%H:%M:%S')' }
hello: {
$env.commax.act: {|x| print $'hello \($x\)' }
$env.commax.dsc: 'hello \(x\)'
$env.commax.cmp: {|args| $args}
}
open: {
$env.commax.sub: {
any: {
$env.commax.act: {|x| open $x.0}
$env.commax.cmp: {ls | get name}
$env.commax.dsc: 'open a file'
}
json: {
$env.commax.act: {|x| open $x.0}
$env.commax.cmp: {ls *.json | get name}
$env.commax.dsc: 'open a json file'
}
}
$env.commax.dsc: 'open a file'
}
}
"
| unindent
| save $",.nu"
#source ',.nu'
}
}
} else {
$args | run $env.comma
}
}

View File

@ -53,7 +53,7 @@ def __cwdhist_editing [] {
{
name: open_command_editor
modifier: alt
keycode: char_e
keycode: char_o
mode: [emacs, vi_normal, vi_insert]
event: { send: openeditor }
}
@ -63,7 +63,7 @@ def __cwdhist_switching [] {
{
name: cwdhist_switching
modifier: shift_alt
keycode: char_e
keycode: char_o
mode: [emacs, vi_normal, vi_insert]
event: [
{ send: ExecuteHostCommand, cmd: '$env.cwd_history_full = (not $env.cwd_history_full)' }

View File

@ -7,10 +7,8 @@ export-env {
}
}
def --wrapped with-flag [...ns] {
if ($in | is-empty) { [] } else {
[$ns $in] | flatten
}
def --wrapped with-flag [...flag] {
if ($in | is-empty) { [] } else { [...$flag $in] }
}
def local_image [name] {
@ -209,13 +207,15 @@ export def image-tag [from: string@"nu-complete docker images" to: string -n: s
}
# push image
export def image-push [img: string@"nu-complete docker images" -n: string@"nu-complete docker ns"] {
^$env.docker-cli ($n | with-flag -n) push $img
export def image-push [img: string@"nu-complete docker images" -n: string@"nu-complete docker ns" -i] {
let $insecure = if $i {[--insecure-registry]} else {[]}
^$env.docker-cli ($n | with-flag -n) $insecure push $img
}
# pull image
export def image-pull [img -n: string@"nu-complete docker ns"] {
^$env.docker-cli ($n | with-flag -n) pull $img
export def image-pull [img -n: string@"nu-complete docker ns" -i] {
let $insecure = if $i {[--insecure-registry]} else {[]}
^$env.docker-cli ($n | with-flag -n) $insecure pull $img
}
### list volume
@ -349,16 +349,16 @@ def "nu-complete registry show" [cmd: string, offset: int] {
let reg = $cmd.3?
let tag = $cmd.4?
let auth = if ($env | has 'REGISTRY_TOKEN') {
[authorization $"Basic ($env.REGISTRY_TOKEN)"]
[-H $"Authorization: Basic ($env.REGISTRY_TOKEN)"]
} else {
[]
}
if ($tag | is-empty) and (not $new) or ($reg | is-empty) {
http get -H $auth $"($url)/v2/_catalog"
| get repositories
curl -sSL $auth $"($url)/v2/_catalog"
| from json | get repositories
} else {
http get -H $auth $"($url)/v2/($reg)/tags/list"
| get tags
curl -sSL $auth $"($url)/v2/($reg)/tags/list"
| from json | get tags
}
}
@ -369,16 +369,16 @@ export def "registry show" [
tag?: string@"nu-complete registry show"
] {
let auth = if ($env | has 'REGISTRY_TOKEN') {
[authorization $"Basic ($env.REGISTRY_TOKEN)"]
[-H $"Authorization: Basic ($env.REGISTRY_TOKEN)"]
} else {
[]
}
if ($reg | is-empty) {
http get -H $auth $"($url)/v2/_catalog" | get repositories
curl -sSL $auth $"($url)/v2/_catalog" | from json | get repositories
} else if ($tag | is-empty) {
http get -H $auth $"($url)/v2/($reg)/tags/list" | get tags
curl -sSL $auth $"($url)/v2/($reg)/tags/list" | from json | get tags
} else {
http get -e -H [accept 'application/vnd.oci.image.manifest.v1+json'] -H $auth $"($url)/v2/($reg)/manifests/($tag)" | from json
curl -sSL -H 'Accept: application/vnd.oci.image.manifest.v1+json' $auth $"($url)/v2/($reg)/manifests/($tag)" | from json
}
}

View File

@ -12,10 +12,8 @@ def agree [
( if $default_not { [no yes] } else { [yes no] } | input list $prompt) in [yes]
}
def --wrapped with-flag [...ns] {
if ($in | is-empty) { [] } else {
[$ns $in] | flatten
}
def --wrapped with-flag [...flag] {
if ($in | is-empty) { [] } else { [...$flag $in] }
}
# git status
@ -80,7 +78,7 @@ export def gb [
remote: (git branch --remote | lines)
no-merged: (git branch --no-merged | lines)
}
print ($d | table -n 1 -e)
print ($d | table -i 1 -e)
} else if $delete {
if $branch in $bs and (agree 'branch will be delete!') {
git branch -D $branch

View File

@ -24,10 +24,8 @@ export def normalize-column-names [ ] {
$t
}
def --wrapped with-flag [...ns] {
if ($in | is-empty) { [] } else {
[$ns $in] | flatten
}
def --wrapped with-flag [...flag] {
if ($in | is-empty) { [] } else { [...$flag $in] }
}
export def `kcache flush` [] {