mirror of
https://github.com/Cian-H/dotfiles.git
synced 2026-01-08 10:01:58 +00:00
Changed . token to _dot
This change allows the dotfiles to work with chezmoi (e.g: on windows) and improves grepability with neovim/telescope
This commit is contained in:
230
dot_config/nushell/nu_scripts/modules/README.md
Normal file
230
dot_config/nushell/nu_scripts/modules/README.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# Modules
|
||||
|
||||
- [Modules](#modules)
|
||||
- [after](#after)
|
||||
- [api\_wrappers](#api_wrappers)
|
||||
- [background\_task](#background_task)
|
||||
- [base16](#base16)
|
||||
- [coloring](#coloring)
|
||||
- [data\_extraction](#data_extraction)
|
||||
- [docker](#docker)
|
||||
- [filesystem](#filesystem)
|
||||
- [formats](#formats)
|
||||
- [fun](#fun)
|
||||
- [github](#github)
|
||||
- [gitlab](#gitlab)
|
||||
- [jc](#jc)
|
||||
- [kubernetes](#kubernetes)
|
||||
- [make\_release](#make_release)
|
||||
- [maths](#maths)
|
||||
- [network](#network)
|
||||
- [nvim](#nvim)
|
||||
- [progress\_bar](#progress_bar)
|
||||
- [rbenv](#rbenv)
|
||||
- [record](#record)
|
||||
- [system](#system)
|
||||
- [virtual\_environments](#virtual_environments)
|
||||
- [weather](#weather)
|
||||
- [webscraping](#webscraping)
|
||||
|
||||
|
||||
## [after](./after)
|
||||
|
||||
Run a function after the given program (by PID)
|
||||
|
||||
## api_wrappers
|
||||
|
||||
Demo of various API wrappers:
|
||||
- [Wolfram Alpha](../sourced/api_wrappers/wolframalpha.nu)
|
||||
- [AWS]()
|
||||
|
||||
## background_task
|
||||
|
||||
make nushell "support" background task feature.
|
||||
see [README](./background_task/)
|
||||
|
||||
|
||||
## base16
|
||||
|
||||
Base16 theme generator (for Linux, might work for other OS)
|
||||
see [README](./base16/)
|
||||
|
||||
## coloring
|
||||
|
||||
These scripts are used to demonstrate the `ansi` command using `ansi` coloring. This is mainly a demo area where we have taken typical `bash` scripts and ported them to nushell scripts. It would be nice if all scripts here showed the "other" version of script and the ported nushell version. We can show "other" flavors of scripts by including them as comments in the nushell scripts or by naming the nushell script and the other script the same basename.
|
||||
|
||||
|
||||
## data_extraction
|
||||
|
||||
- [Ultimate Extractor](./data_extraction/ultimate_extractor.nu) - Extract any compressed archive, UE will call the proper program under the hood 😎
|
||||
|
||||
## [docker](./docker/)
|
||||
|
||||
An extensive example of a wrapper for docker operations, with nushell completions.
|
||||
|
||||
## filesystem
|
||||
|
||||
- [bm](./filesystem/bm.nu) - A Simple bookmarking module. It uses `XGD_DATA_HOME` to save bookmarks.
|
||||
- [expand](./filesystem/expand.nu) - expansion module that implements bashes brace expansion.
|
||||
The expansion uses a list inside of braces separated by `,` to expand into a list of multiple string variations like:
|
||||
```
|
||||
expand a/{b,c}/d{e,f,g}.nu{,on}
|
||||
```
|
||||
parses into:
|
||||
|
||||
```
|
||||
╭────┬─────────────╮
|
||||
│ 0 │ a/b/de.nu │
|
||||
│ 1 │ a/c/de.nu │
|
||||
│ 2 │ a/b/df.nu │
|
||||
│ 3 │ a/c/df.nu │
|
||||
│ 4 │ a/b/dg.nu │
|
||||
│ 5 │ a/c/dg.nu │
|
||||
│ 6 │ a/b/de.nuon │
|
||||
│ 7 │ a/c/de.nuon │
|
||||
│ 8 │ a/b/df.nuon │
|
||||
│ 9 │ a/c/df.nuon │
|
||||
│ 10 │ a/b/dg.nuon │
|
||||
│ 11 │ a/c/dg.nuon │
|
||||
╰────┴─────────────╯
|
||||
```
|
||||
|
||||
## formats
|
||||
Examples of input/output formatters:
|
||||
- [from-cpuinfo](./formats/from-cpuinfo.nu)
|
||||
- [from-dmidecode](./formats/from-dmidecode.nu)
|
||||
- [to-ini](./formats/to-ini.nu)
|
||||
- [remove-diacritics](./formats/remove-diacritics.nu) - Turns `Zażółć gęślą jaźń` into `Zazolc gesla jazn`
|
||||
|
||||
|
||||
## fun
|
||||
|
||||
- [spark](../sourced/fun/spark.nu) - send an array into spark and get a sparkline out:
|
||||
```console
|
||||
> let v = [2, 250, 670, 890, 2, 430, 11, 908, 123, 57]
|
||||
> spark $v
|
||||
▁▂▆▇▁▄▁█▁▁
|
||||
```
|
||||
- [website-builder](../sourced/fun/website_builder.nu) - converts markdown into their equivalent html pages
|
||||
- [wordle](./fun/wordle.nu) - A Terminal Wordle game. The code is based on this [gist](https://gist.github.com/huytd/6a1a6a7b34a0d0abcac00b47e3d01513), but slightly personalized.
|
||||
|
||||
|
||||
## github
|
||||
|
||||
- [branch-protections](../sourced/github/branch-protections/) - Do you have hundreds or thousands of GitHub repositories in your organization? Are you tired of manually managing their branch protection rules? Don't! Let nushell do it for you! see [README](../sourced/github/branch-protections/README.md)
|
||||
- [merged-branches](../sourced/github/merged-branches/) - Do your developers often forget to delete their branches after merging PRs? Are you tired of manually going into every repository and deleting them? Don't! Let nushell do it for you! see [README](../sourced/github/merged-branches/README.md)
|
||||
|
||||
## [gitlab](../sourced/gitlab/)
|
||||
Search files on your GitLab server
|
||||
|
||||
## [jc](./jc/)
|
||||
|
||||
Converts the output of many common external commands into nushell data structures.
|
||||
|
||||
Example:
|
||||
```nushell
|
||||
: jc ping -4 -c 2 google.com
|
||||
╭──────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ destination_ip │ 216.58.209.46 │
|
||||
│ data_bytes │ 56 │
|
||||
│ pattern │ │
|
||||
│ destination │ google.com │
|
||||
│ duplicates │ 0 │
|
||||
│ packets_transmitted │ 2 │
|
||||
│ packets_received │ 2 │
|
||||
│ packet_loss_percent │ 0.00 │
|
||||
│ time_ms │ 1001.00 │
|
||||
│ round_trip_ms_min │ 3.87 │
|
||||
│ round_trip_ms_avg │ 4.04 │
|
||||
│ round_trip_ms_max │ 4.21 │
|
||||
│ round_trip_ms_stddev │ 0.17 │
|
||||
│ │ ╭───┬───────┬───────────┬───────┬───────────────┬──────────┬─────┬─────────┬───────────╮ │
|
||||
│ responses │ │ # │ type │ timestamp │ bytes │ response_ip │ icmp_seq │ ttl │ time_ms │ duplicate │ │
|
||||
│ │ ├───┼───────┼───────────┼───────┼───────────────┼──────────┼─────┼─────────┼───────────┤ │
|
||||
│ │ │ 0 │ reply │ │ 64 │ 216.58.209.46 │ 1 │ 120 │ 4.21 │ false │ │
|
||||
│ │ │ 1 │ reply │ │ 64 │ 216.58.209.46 │ 2 │ 120 │ 3.87 │ false │ │
|
||||
│ │ ╰───┴───────┴───────────┴───────┴───────────────┴──────────┴─────┴─────────┴───────────╯ │
|
||||
╰──────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
```nushell
|
||||
: (jc ping -4 -c 2 google.com).round_trip_ms_avg
|
||||
6.054
|
||||
```
|
||||
For supported commands see [JC parsers documentation](https://kellyjonbrazil.github.io/jc/#parsers)
|
||||
|
||||
Installation:
|
||||
|
||||
1. Install the `jc` command line: https://kellyjonbrazil.github.io/jc/#installation
|
||||
2. Import this module in your `config.nu`: `import ~/.local/share/nu_scripts/modules/jc/`
|
||||
|
||||
## [kubernetes](./kubernetes/)
|
||||
???
|
||||
|
||||
## [make_release](../make_release/)
|
||||
???
|
||||
|
||||
## [maths](./maths/)
|
||||
|
||||
- [math_functions] - module with the following commands:
|
||||
- `root` - root with a custom denominator
|
||||
- `croot` - cube root
|
||||
- `aroot` - root with a custom scaler and denominator
|
||||
- `delta` - calculate the delta of the quadratic function
|
||||
- `fact` - factorial of the given number
|
||||
- `q_roots` - calculare roots of the quadratic function: ax^2+bx+x
|
||||
- `isprime` - check if integer is prime
|
||||
- `primelist` - list primes until given number
|
||||
- `mtable` - multiplication table of n till max
|
||||
- `isleap` - check if year is leap
|
||||
- `gcd` - greatest common divisor between 2 integers
|
||||
- `lcm` - least commoin multiple between 2 integers
|
||||
- `dec2base` - decimal number to custom base representation
|
||||
- `scale-minmax` - scale list to `[a,b]` interval
|
||||
- `scale-minmax-table` - Scale every column of a table (separately) to `[a,b]` interval
|
||||
- `math exp` - exp function
|
||||
|
||||
## network
|
||||
- [remoting](./network/remoting/) - This module provide convenient way to manage multiple remote clients. see [README](./network/remoting)
|
||||
|
||||
- [sockets](./network/sockets/) - The `sockets` command returns a table containing information on network sockets and the processes they belong to.
|
||||
It is basically a join of the tables produced by the `lsof` command, and the nushell `ps` command.
|
||||
|
||||
<img width="1486" alt="image" src="https://user-images.githubusercontent.com/52205/196287615-00e46f8e-06ed-45ce-8fe7-a5c5f38afaaa.png">
|
||||
|
||||
|
||||
- [ssh](./network/ssh.nu) wrapper that provides the following commands:
|
||||
- `ssh`
|
||||
- `scp`
|
||||
- `ssh-list`
|
||||
- `parse-ssh-file`
|
||||
- `str max-length`
|
||||
- `ensure-index`
|
||||
|
||||
|
||||
## [nvim](./nvim/)
|
||||
??? (not sure how universal this is) Mix of hooks, defs and alias wrapper around neovim.
|
||||
|
||||
## [progress_bar](../sourced/progress_bar/)
|
||||
??? (make a module out of these scripts?) - Collection of progress bars
|
||||
|
||||
## [rbenv](./rbenv/)
|
||||
??? (not sure how universal this is) This script provides minimal working rbenv setup.
|
||||
|
||||
## [record](../stdlib-candidate/record/)
|
||||
A module to manipulate nu's record
|
||||
|
||||
## [system](./system/)
|
||||
Currently holds the `clip` command which was previously incorrectly in the standard library of Nushell.
|
||||
```nushell
|
||||
use modules/system * # will bring `clip` into scope
|
||||
```
|
||||
|
||||
## [virtual_environments](./virtual_environments/)
|
||||
The scripts in this directory activate virtual environments for Conda environments.
|
||||
|
||||
## [weather](./weather/)
|
||||
These scripts should be used to demonstrate how get your local weather and/or weather forecasts.
|
||||
|
||||
|
||||
## [webscraping](../sourced/webscraping/)
|
||||
Simple scripts to demonstrate how to scrape websites in nushell. Requires `query web` plugin
|
||||
21
dot_config/nushell/nu_scripts/modules/after/after.nu
Normal file
21
dot_config/nushell/nu_scripts/modules/after/after.nu
Normal file
@@ -0,0 +1,21 @@
|
||||
def "nu-complete ps" [] {
|
||||
ps -l | each {|x| { value: $"($x.pid)", description: $x.command } }
|
||||
}
|
||||
|
||||
# after <pid> {|| do something ... }
|
||||
export def main [
|
||||
pid: string@"nu-complete ps"
|
||||
action
|
||||
] {
|
||||
do -i { tail --pid $pid -f /dev/null }
|
||||
do $action
|
||||
}
|
||||
|
||||
# before {|| do something ... } <pid>
|
||||
export def before [
|
||||
action
|
||||
pid: string@"nu-complete ps"
|
||||
] {
|
||||
do -i { tail --pid $pid -f /dev/null }
|
||||
do $action
|
||||
}
|
||||
127
dot_config/nushell/nu_scripts/modules/argx/mod.nu
Normal file
127
dot_config/nushell/nu_scripts/modules/argx/mod.nu
Normal file
@@ -0,0 +1,127 @@
|
||||
export def get-sign [cmd] {
|
||||
let x = (scope commands | where name == $cmd).signatures?.0?.any?
|
||||
mut s = []
|
||||
mut n = {}
|
||||
mut p = []
|
||||
mut pr = []
|
||||
mut r = []
|
||||
for it in $x {
|
||||
if $it.parameter_type == 'switch' {
|
||||
if ($it.short_flag | is-not-empty) {
|
||||
$s ++= $it.short_flag
|
||||
}
|
||||
if ($it.parameter_name | is-not-empty) {
|
||||
$s ++= $it.parameter_name
|
||||
}
|
||||
} else if $it.parameter_type == 'named' {
|
||||
if ($it.parameter_name | is-empty) {
|
||||
$n = ($n | upsert $it.short_flag $it.short_flag)
|
||||
} else if ($it.short_flag | is-empty) {
|
||||
$n = ($n | upsert $it.parameter_name $it.parameter_name)
|
||||
} else {
|
||||
$n = ($n | upsert $it.short_flag $it.parameter_name)
|
||||
}
|
||||
} else if $it.parameter_type == 'positional' {
|
||||
if $it.is_optional == false {
|
||||
$p ++= $it.parameter_name
|
||||
} else {
|
||||
$pr ++= $it.parameter_name
|
||||
}
|
||||
} else if $it.parameter_type == 'rest' {
|
||||
$r ++= $it.parameter_name
|
||||
}
|
||||
}
|
||||
{ switch: $s, name: $n, positional: ($p ++ $pr), rest: $r }
|
||||
}
|
||||
|
||||
# "test -h [123 (3213 3)] 123 `a sdf` --cd --ef sadf -g" | token
|
||||
export def token [] {
|
||||
let s = ($in | split row '' | range 1..-2)
|
||||
let s = if ($s | last) == ' ' { $s } else { $s | append ' ' }
|
||||
mut par = []
|
||||
mut res = []
|
||||
mut cur = ''
|
||||
mut esc = false
|
||||
for c in $s {
|
||||
if $c == '\' {
|
||||
$esc = true
|
||||
} else {
|
||||
if $esc {
|
||||
$cur ++= $c
|
||||
$esc = false
|
||||
} else {
|
||||
if $c == ' ' and ($par | length) == 0 {
|
||||
$res ++= [$cur]
|
||||
$cur = ''
|
||||
} else {
|
||||
if $c in ['{' '[' '('] {
|
||||
$par ++= $c
|
||||
}
|
||||
if $c in ['}' ']' ')'] {
|
||||
$par = ($par | range ..-2)
|
||||
}
|
||||
if $c in ['"' "'" '`'] {
|
||||
if ($par | length) > 0 and ($par | last) == $c {
|
||||
$par = ($par | range ..-2)
|
||||
} else {
|
||||
$par ++= $c
|
||||
}
|
||||
}
|
||||
$cur ++= $c
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return $res
|
||||
}
|
||||
|
||||
export def parse [] {
|
||||
let token = ($in | token)
|
||||
let sign = (get-sign $token.0)
|
||||
mut sw = ''
|
||||
mut pos = []
|
||||
mut opt = {}
|
||||
for c in $token {
|
||||
if ($sw | is-empty) {
|
||||
if ($c | str starts-with '-') {
|
||||
let c = if ($c | str substring 1..<2) != '-' {
|
||||
let k = ($c | str substring 1..)
|
||||
if $k in $sign.name {
|
||||
$'($sign.name | get $k)'
|
||||
} else {
|
||||
$k
|
||||
}
|
||||
} else {
|
||||
$c | str substring 2..
|
||||
}
|
||||
if $c in $sign.switch {
|
||||
$opt = ($opt | upsert $c true)
|
||||
} else {
|
||||
$sw = $c
|
||||
}
|
||||
} else {
|
||||
$pos ++= [$c]
|
||||
}
|
||||
} else {
|
||||
$opt = ($opt | upsert $sw $c)
|
||||
$sw = ''
|
||||
}
|
||||
}
|
||||
$opt._args = $pos
|
||||
let p = $pos | range 1..($sign.positional | length)
|
||||
let rest = $pos | range (($sign.positional | length) + 1)..-1
|
||||
$opt._pos = ( $p | enumerate
|
||||
| reduce -f {} {|it, acc|
|
||||
$acc | upsert ($sign.positional | get $it.index) $it.item
|
||||
} )
|
||||
if ($sign.rest | length) > 0 {
|
||||
$opt._pos = ($opt._pos | upsert $sign.rest.0 $rest)
|
||||
}
|
||||
$opt
|
||||
}
|
||||
|
||||
# def test [a b x? ...y --cd(-c) --ef(-e):string -g -h:int --ij --lm:bool] {}
|
||||
# (scope commands | where name == test).signatures?.0?.any?
|
||||
# get-sign test | to yaml
|
||||
# "test -h 111 123 'asdf' --cd --ef sadf -g -h 222" | cmd parse | to yaml
|
||||
@@ -0,0 +1,45 @@
|
||||
# This alias lets you choose your aws environment variables with ease.
|
||||
#
|
||||
# Dependencies:
|
||||
# * fzf
|
||||
#
|
||||
# Installation:
|
||||
# 1. store in ~/.config/nushell/select-aws-profile.nu
|
||||
# 2. add to your config.nu: `use ~/.config/nushell/select-aws-profile.nu *`
|
||||
#
|
||||
# Usage:
|
||||
# select-aws-profile
|
||||
export def --env main [] {
|
||||
hide AWS_REGION
|
||||
|
||||
do {
|
||||
let creds = open ($env.HOME + "/.aws/credentials") | from toml
|
||||
let selected_profile = $creds
|
||||
| transpose name creds
|
||||
| get name
|
||||
| str join "\n"
|
||||
| fzf
|
||||
|
||||
if $selected_profile != "" {
|
||||
let out = {
|
||||
AWS_PROFILE: $selected_profile,
|
||||
AWS_ACCESS_KEY_ID: ($creds | get $selected_profile | get "aws_access_key_id"),
|
||||
AWS_SECRET_ACCESS_KEY: ($creds | get $selected_profile | get "aws_secret_access_key"),
|
||||
}
|
||||
|
||||
let region = ($creds | get $selected_profile | get -i "region")
|
||||
if $region != null {
|
||||
$out | insert AWS_REGION $region
|
||||
} else {
|
||||
$out
|
||||
}
|
||||
}
|
||||
} | load-env
|
||||
|
||||
{
|
||||
AWS_PROFILE: $env.AWS_PROFILE,
|
||||
AWS_ACCESS_KEY_ID: $env.AWS_ACCESS_KEY_ID,
|
||||
AWS_SECRET_ACCESS_KEY: $env.AWS_SECRET_ACCESS_KEY,
|
||||
AWS_REGION: $env.AWS_REGION
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
# Background tasks with pueue
|
||||
|
||||
Makes Nushell "support" background tasks.
|
||||
|
||||
## Prerequisite
|
||||
|
||||
Install [pueue](https://github.com/Nukesor/pueue) and make sure `pueued` is running and that `pueue` is in `PATH`.
|
||||
|
||||
## Usage
|
||||
|
||||
You will get tab completions and suggestions when you install the module.
|
||||
Please check those.
|
||||
|
||||
To install the module, copy the `task.nu` to the `$env.NU_LIB_DIRS` directory, then do:
|
||||
|
||||
```nu
|
||||
use task.nu
|
||||
```
|
||||
|
||||
In your Nushell config under `~/.config/nushell`.
|
||||
|
||||
## Q&A
|
||||
|
||||
### How can I pass data to a background task?
|
||||
|
||||
You can use environment variables, since they
|
||||
are inherited from the parent when spawning a process.
|
||||
|
||||
```nu
|
||||
$env.FOO = 123
|
||||
|
||||
task spawn {
|
||||
echo $env.FOO
|
||||
}
|
||||
```
|
||||
|
||||
If you want to pass serialized data, you can do this:
|
||||
|
||||
```nu
|
||||
let foo = { a: 1 b: 2 c: 3 }
|
||||
|
||||
with-env { FOO: ($foo | to json) } {
|
||||
task spawn {
|
||||
let foo = ($env.FOO | from json)
|
||||
|
||||
echo $foo
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### How can I reuse custom commands in a background task?
|
||||
|
||||
You can define these commands in a separate module, like so:
|
||||
|
||||
```nu
|
||||
# --- in foo.nu ---
|
||||
export def bar [] { echo bar }
|
||||
|
||||
# --- in main.nu ---
|
||||
task spawn {
|
||||
use foo.nu
|
||||
|
||||
foo bar
|
||||
}
|
||||
```
|
||||
## Troubleshooting
|
||||
|
||||
- On some setups (e.g. NixOS with `nu` installed as a binary in user's `$HOME`), `sh` (which `pueue` delegates tasks to run) might fail to find `nu` in the `$PATH`. In this case hard-coding the location of your nu binary in the `task spawn` function definition in `task.nu` can solve the issue.
|
||||
434
dot_config/nushell/nu_scripts/modules/background_task/task.nu
Normal file
434
dot_config/nushell/nu_scripts/modules/background_task/task.nu
Normal file
@@ -0,0 +1,434 @@
|
||||
# Spawn a task to run in the background, even when the shell is closed.
|
||||
#
|
||||
# Note that a fresh Nushell interpreter is spawned to execute the
|
||||
# given task, so it won't inherit the current scope's variables,
|
||||
# custom commands and alias definitions.
|
||||
#
|
||||
# It will only inherit environment variables which can be converted to a string.
|
||||
#
|
||||
# Note that the closure can't take arguments.
|
||||
#
|
||||
# Example usage: task spawn { echo "Hello, World!" }
|
||||
export def spawn [
|
||||
command: closure # The closure to run.
|
||||
--working-directory (-w): directory # Specify the working directory the task will be run in.
|
||||
--immediate (-i) # Immediately start the task.
|
||||
--stashed (-s) # Create the task in Stashed state. Useful to avoid immediate execution if the queue is empty
|
||||
--delay (-d): duration # Queue the task for execution only after the duration.
|
||||
--group (-g): string # The group to spawn the task under.
|
||||
--after (-a): int # Start the task once all specified tasks have successfully finished. As soon as one of the dependencies fails, this task will fail as well.
|
||||
--priority (-o): string # Start this task with a higher priority. The higher the number, the faster it will be processed.
|
||||
--label (-l): string # Label the task. This string will be shown in the `status` column of `task status`.
|
||||
] -> int {
|
||||
mut args = []
|
||||
|
||||
if $working_directory != null {
|
||||
$args = ($args | prepend ["--working-directory", $working_directory])
|
||||
}
|
||||
if $immediate {
|
||||
$args = ($args | prepend "--immediate")
|
||||
}
|
||||
if $stashed {
|
||||
$args = ($args | prepend "--stashed")
|
||||
}
|
||||
if $delay != null {
|
||||
$args = ($args | prepend ["--delay" ($delay | format duration sec | parse "{secs} {_}" | get 0.secs)])
|
||||
}
|
||||
if $group != null {
|
||||
$args = ($args | prepend ["--group" $group])
|
||||
}
|
||||
if $after != null {
|
||||
$args = ($args | prepend ["--after" $after])
|
||||
}
|
||||
if $priority != null {
|
||||
$args = ($args | prepend ["--priority" $priority])
|
||||
}
|
||||
if $label != null {
|
||||
$args = ($args | prepend ["--label" $label])
|
||||
}
|
||||
|
||||
let source_path = mktemp --tmpdir --suffix "-nu-task"
|
||||
|
||||
(
|
||||
view source $command
|
||||
| str trim --left --char "{"
|
||||
| str trim --right --char "}"
|
||||
)
|
||||
| save --force $source_path
|
||||
|
||||
(pueue add --print-task-id ...$args $"nu --config '($nu.config-path)' --env-config '($nu.env-path)' ($source_path)")
|
||||
}
|
||||
|
||||
# Remove tasks from the queue.
|
||||
# Running or paused tasks need to be killed first.
|
||||
export def remove [
|
||||
...ids: int # IDs of the tasks to remove from the status list.
|
||||
] {
|
||||
pueue remove ...$ids
|
||||
}
|
||||
|
||||
# Switches the queue position of two tasks.
|
||||
# Only works for queued or stashed tasks.
|
||||
export def switch [
|
||||
task_id_1: int # The first task ID.
|
||||
task_id_2: int # The second task ID.
|
||||
] {
|
||||
pueue switch $task_id_1 $task_id_2
|
||||
}
|
||||
|
||||
# Stash a task that is not currently running.
|
||||
#
|
||||
# Stashed tasks won't be automatically started.
|
||||
# You will have to queue them or start them by hand.
|
||||
export def stash [
|
||||
...ids: int # IDs of the tasks to stash.
|
||||
] {
|
||||
pueue stash ...$ids
|
||||
}
|
||||
|
||||
# Queue stashed tasks for execution.
|
||||
export def queue [
|
||||
...ids: int # IDs of the tasks to queue.
|
||||
--delay (-d): duration # Queue only after the specified delay.
|
||||
] {
|
||||
let args = if $delay != null {
|
||||
["--delay" ($delay | format duration sec | parse '{secs} {_}' | get 0.secs)]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
|
||||
pueue enqueue ...$args ...$ids
|
||||
}
|
||||
|
||||
# Resume operation of specific tasks or groups of tasks.
|
||||
#
|
||||
# By default, this resumes the default group and all its tasks.
|
||||
# It can also be used force-start specific tasks or start whole groups.
|
||||
export def start [
|
||||
...ids: int # IDs of the tasks to start. By default all the tasks in the default group will be started.
|
||||
--group (-g): string # Resume a specific group and all paused tasks in it. The group will be set to running and its paused tasks will be resumed.
|
||||
--all (-a) # Resume all groups. All groups will be set to running and paused tasks will be resumed.
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $group != null {
|
||||
$args = ($args | prepend ["--group" $group])
|
||||
}
|
||||
if $all {
|
||||
$args = ($args | prepend "--all")
|
||||
}
|
||||
|
||||
pueue start ...$args
|
||||
}
|
||||
|
||||
# Restart failed or successful task(s).
|
||||
#
|
||||
# By default, identical tasks will be created and
|
||||
# enqueued, but it's possible to restart in-place.
|
||||
#
|
||||
# You can also edit a few properties, such as
|
||||
# the path and the command of the task, before restarting.
|
||||
export def restart [
|
||||
...ids: int # IDs of the tasks to restart.
|
||||
--all-failed (-a) # Restart all failed tasks across all groups. Nice to use in combination with `--in-place/i`.
|
||||
--failed-in-group (-g): string # Like `--all-failed`, but only restart tasks failed tasks of a specific group. The group will be set to running and its paused tasks will be resumed.
|
||||
--start-immediately (-k) # Immediately start the tasks, no matter how many open slots there are. This will ignore any dependencies tasks may have.
|
||||
--stashed (-s) # Set the restarted task to a "Stashed" state. Useful to avoid immediate execution.
|
||||
--in-place (-i) # Restart the tasks by reusing the already existing tasks.
|
||||
--not-in-place (-n) # Opposite of `--in-place`. This is already the default unless you have `restart_in_place` set to true.
|
||||
--edit (-e) # Edit the tasks' commands before restarting
|
||||
--edit-path (-p) # Edit the tasks' paths before restarting
|
||||
--edit-label (-l) # Edit the tasks' labels before restarting
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $all_failed {
|
||||
$args = ($args | prepend "--all-failed")
|
||||
}
|
||||
if $failed_in_group != null {
|
||||
$args = ($args | prepend "--failed-in-group")
|
||||
}
|
||||
if $start_immediately {
|
||||
$args = ($args | prepend "--start-immediately")
|
||||
}
|
||||
if $stashed {
|
||||
$args = ($args | prepend "--stashed")
|
||||
}
|
||||
if $in_place {
|
||||
$args = ($args | prepend "--in-place")
|
||||
}
|
||||
if $not_in_place {
|
||||
$args = ($args | prepend "--not-in-place")
|
||||
}
|
||||
if $edit {
|
||||
$args = ($args | prepend "--edit")
|
||||
}
|
||||
if $edit_path {
|
||||
$args = ($args | prepend "--edit-path")
|
||||
}
|
||||
if $edit_label {
|
||||
$args = ($args | prepend "--edit-label")
|
||||
}
|
||||
|
||||
pueue restart ...$args ...$ids
|
||||
}
|
||||
|
||||
# Either pause a running tasks or a specific groups of tasks.
|
||||
#
|
||||
# By default, pauses the default group and all its tasks.
|
||||
#
|
||||
# A paused group won't start any new tasks automatically.
|
||||
export def pause [
|
||||
...ids: int # IDs of the tasks to pause.
|
||||
--group (-g) # Pause a specific group
|
||||
--all (-a) # Pause all groups.
|
||||
--wait (-w) # Only pause the specified group and let already running tasks finish by themselves
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $group != null {
|
||||
$args = ($args | prepend "--group")
|
||||
}
|
||||
if $all != null {
|
||||
$args = ($args | prepend "--all")
|
||||
}
|
||||
if $wait != null {
|
||||
$args = ($args | prepend "--wait")
|
||||
}
|
||||
|
||||
pueue pause ...$args ...$ids
|
||||
}
|
||||
|
||||
# Kill specific running tasks or whole task groups.
|
||||
#
|
||||
# Kills all tasks of the default group when no ids or a specific group are provided.
|
||||
export def kill [
|
||||
...ids: int # IDs of the tasks to kill.
|
||||
--group (-g): string # Kill all running tasks in a group. This also pauses the group.
|
||||
--all (-a) # Kill all running tasks across ALL groups. This also pauses all groups.
|
||||
--signal (-s): string # Send a UNIX signal instead of simply killing the process. DISCLAIMER: This bypasses Pueue's process handling logic! You might enter weird invalid states, use at your own descretion.
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $group != null {
|
||||
$args = ($args | prepend ["--group" $group])
|
||||
}
|
||||
if $all {
|
||||
$args = ($args | prepend "--all")
|
||||
}
|
||||
if $signal != null {
|
||||
$args = ($args | prepend ["--signal" $signal])
|
||||
}
|
||||
|
||||
pueue kill ...$args ...$ids
|
||||
}
|
||||
|
||||
# Send something to a task. Useful for sending confirmations such as "y\n".
|
||||
export def send [
|
||||
id: int # ID of the task to send something to.
|
||||
input: string # The input that should be sent to the process.
|
||||
] {
|
||||
pueue send $id $input
|
||||
}
|
||||
|
||||
# Edit the command, path or label of a stashed or queued task.
|
||||
#
|
||||
# By default only the command is edited.
|
||||
#
|
||||
# Multiple properties can be added in one go.
|
||||
export def edit [
|
||||
id: int # ID of the task to edit.
|
||||
--command (-c) # Edit the task's command
|
||||
--path (-p) # Edit the task's path
|
||||
--label (-l) # Edit the task's label
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $command {
|
||||
$args = ($args | prepend "--command")
|
||||
}
|
||||
if $path {
|
||||
$args = ($args | prepend "--path")
|
||||
}
|
||||
if $label {
|
||||
$args = ($args | prepend "--label")
|
||||
}
|
||||
|
||||
pueue edit ...$args $id
|
||||
}
|
||||
|
||||
# Use this to add or remove groups.
|
||||
#
|
||||
# By default, this will simply display all known groups.
|
||||
export def group [] {
|
||||
pueue group --json | from json
|
||||
}
|
||||
|
||||
# Create a new group with a name.
|
||||
export def "group add" [
|
||||
name: string # The name of the new group.
|
||||
--parallel (-p): int # The amount of parallel tasks the group can run at one time.
|
||||
] {
|
||||
let args = if $parallel != null {
|
||||
["--parallel" $parallel]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
|
||||
pueue group add ...$args $name
|
||||
}
|
||||
|
||||
# Remove a group with a name.
|
||||
export def "group remove" [
|
||||
name: string # The name of the group to be removed.
|
||||
] {
|
||||
pueue group remove $name
|
||||
}
|
||||
|
||||
# Display the current status of all tasks.
|
||||
export def status [
|
||||
--detailed (-d) # Return a table with more detailed information.
|
||||
] {
|
||||
let output = (
|
||||
pueue status --json
|
||||
| from json
|
||||
| get tasks
|
||||
| transpose --ignore-titles status
|
||||
| flatten
|
||||
)
|
||||
|
||||
# TODO: Rename the Done column to done.
|
||||
if not $detailed {
|
||||
$output | select id label group Done? status? start? end?
|
||||
} else {
|
||||
$output
|
||||
}
|
||||
}
|
||||
|
||||
# Display the output of tasks.
|
||||
#
|
||||
# Only the last few lines will be shown by default for multiple tasks.
|
||||
# If you want to follow the output, use `--tail/-t`.
|
||||
export def log [
|
||||
...ids: int # The tasks to check the outputs of.
|
||||
--last (-l): int # Only print the last N lines of each task's output. This is done by default if you're looking at multiple tasks.
|
||||
--tail (-t) # Follow the output as it is printing. Only works with 1 task. When used in conjunction with `--last`, the last N lines will be printed before starting to wait for output.
|
||||
--detailed (-d) # Include all fields, don't simplify output.
|
||||
] {
|
||||
def process_raw [raw: string] {
|
||||
let full = (
|
||||
$raw
|
||||
| from json
|
||||
| transpose -i info
|
||||
| flatten --all
|
||||
| flatten --all
|
||||
)
|
||||
|
||||
if $detailed {
|
||||
$full
|
||||
} else {
|
||||
$full | select id label group Done? status? start? end?
|
||||
}
|
||||
}
|
||||
|
||||
if (($ids | length) == 1) {
|
||||
if $tail {
|
||||
let args = if $last != null {
|
||||
["--lines" $last]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
|
||||
pueue follow ...$ids
|
||||
} else {
|
||||
let args = if $last != null {
|
||||
["--lines" $last]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
|
||||
process_raw (pueue log --full --json ...$args ...$ids)
|
||||
| first
|
||||
}
|
||||
} else {
|
||||
if $tail {
|
||||
echo $"(ansi red)--tail can only be used with one task.(ansi reset)"
|
||||
return
|
||||
}
|
||||
|
||||
let args = if $last != null {
|
||||
["--lines" $last]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
|
||||
process_raw (pueue log --full --json ...$args ...$ids)
|
||||
}
|
||||
}
|
||||
|
||||
# Wait until the provided tasks are finished.
|
||||
#
|
||||
# This is like join() or await in many languages.
|
||||
export def wait [
|
||||
...ids: int # IDs of the tasks to wait for.
|
||||
--group (-g): string # Wait for all tasks in a specific group.
|
||||
--all (-a) # Wait for all tasks across all groups and the default group.
|
||||
--quiet (-q) # Don't show any log output while waiting.
|
||||
--status (-s): string # Wait for tasks to reach a specific task status.
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $group != null {
|
||||
$args = ($args | prepend ["--group" $group])
|
||||
}
|
||||
if $all {
|
||||
$args = ($args | prepend $all)
|
||||
}
|
||||
if $quiet {
|
||||
$args = ($args | prepend $quiet)
|
||||
}
|
||||
if $status != null {
|
||||
$args = ($args | prepend ["--status" $status])
|
||||
}
|
||||
|
||||
pueue wait ...$args ...$ids
|
||||
}
|
||||
|
||||
# Remove tasks from the status list.
|
||||
export def clean [
|
||||
--successful-only (-s) # Only clean tasks that finished successfully
|
||||
--group (-g): string # Only clean tasks of a specific group
|
||||
] {
|
||||
mut args = []
|
||||
|
||||
if $successful_only {
|
||||
$args = ($args | prepend "--successful-only")
|
||||
}
|
||||
if $group != null {
|
||||
$args = ($args | prepend ["--group" $group])
|
||||
}
|
||||
|
||||
pueue clean ...$args
|
||||
}
|
||||
|
||||
# Shutdown pueue and thus this module.
|
||||
export def shutdown [] {
|
||||
pueue shutdown
|
||||
}
|
||||
|
||||
# Set the maximum parallel tasks for a group.
|
||||
#
|
||||
# Note that no tasks will be stopped if the number is lowered.
|
||||
# The limit only applies when schelduing.
|
||||
export def set-parallel-limit [
|
||||
max: int # The maximum parallel tasks allowed for a group when schelduing.
|
||||
--group (-g): string # The group to set the limit for. By default this is `default`.
|
||||
] {
|
||||
let args = if $group != null {
|
||||
["--group" $group]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
|
||||
pueue parallel ...$args $max
|
||||
}
|
||||
48
dot_config/nushell/nu_scripts/modules/base16/README.md
Normal file
48
dot_config/nushell/nu_scripts/modules/base16/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Base16 themes integration
|
||||
|
||||
This folder contains a couple of files that let you configure Nushell and other terminal tools to use base16 themes.
|
||||
|
||||
## Requirements
|
||||
|
||||
Assumes a Linux system with an X-based window manager.
|
||||
Specific packages and environment variable requirements are listed in each file.
|
||||
|
||||
## Files explanation
|
||||
* **base16.nu** - Main module -- see comments inside
|
||||
* **auto_base16.nu** - Generates a base16 theme from a wallpaper
|
||||
* **alacritty_colors.template** - Template for Alacritty terminal colors
|
||||
|
||||
## Example integration
|
||||
|
||||
Fist, set up base16 theme generation from a wallpaper:
|
||||
```
|
||||
# ~/.xinitrc
|
||||
|
||||
...
|
||||
|
||||
[ -f ~/.auto_base16.nu ] && ~/.auto_base16.nu &
|
||||
```
|
||||
This will generate a base16 theme to a file from a current wallpaper.
|
||||
You can combine this with a random wallpaper generation using the fehbg.nu
|
||||
script for more chaos fun.
|
||||
|
||||
Next, set up Nushell config, assuming the base16 colors are generated
|
||||
```
|
||||
# config.nu
|
||||
|
||||
use ~/.config/nushell/base16.nu
|
||||
|
||||
# File containing base16 colors
|
||||
$env.BASE16_TXT = "/tmp/base16.txt"
|
||||
|
||||
let config = {
|
||||
color_config: (base16 build-nu-config $env.BASE16_TXT)
|
||||
}
|
||||
```
|
||||
|
||||
To select a new wallpaper and regenerate the base16 config:
|
||||
```
|
||||
> base16 new-wallpaper
|
||||
|
||||
> source ~/.config/nushell/config.nu
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
# Base16 template for Alacritty, 256 colors
|
||||
#
|
||||
# Adapted from :
|
||||
# github.com/aarowill/base16-alacritty/blob/master/templates/default-256.mustache
|
||||
#
|
||||
# The "{{baseXX-hex}}" strings will be replaced with a Nushell script and saved
|
||||
# as ~/.config/alacritty/alacritty_colors.yml. The main config (alacritty.yml)
|
||||
# should be configured to load the generated file.
|
||||
#
|
||||
# I'm setting only the background and the foreground but in the comments is the
|
||||
# full config for reference.
|
||||
|
||||
colors:
|
||||
# Default colors
|
||||
primary:
|
||||
background: '{{base00-hex}}'
|
||||
foreground: '{{base05-hex}}'
|
||||
|
||||
# Colors the cursor will use if `custom_cursor_colors` is true
|
||||
# cursor:
|
||||
# text: '{{base00-hex}}'
|
||||
# cursor: '{{base05-hex}}'
|
||||
|
||||
# Normal colors
|
||||
# normal:
|
||||
# black: '{{base00-hex}}'
|
||||
# red: '{{base08-hex}}'
|
||||
# green: '{{base0b-hex}}'
|
||||
# yellow: '{{base0a-hex}}'
|
||||
# blue: '{{base0d-hex}}'
|
||||
# magenta: '{{base0e-hex}}'
|
||||
# cyan: '{{base0c-hex}}'
|
||||
# white: '{{base05-hex}}'
|
||||
|
||||
# Bright colors
|
||||
# bright:
|
||||
# black: '{{base03-hex}}'
|
||||
# red: '{{base08-hex}}'
|
||||
# green: '{{base0b-hex}}'
|
||||
# yellow: '{{base0a-hex}}'
|
||||
# blue: '{{base0d-hex}}'
|
||||
# magenta: '{{base0e-hex}}'
|
||||
# cyan: '{{base0c-hex}}'
|
||||
# white: '{{base07-hex}}'
|
||||
|
||||
# indexed_colors:
|
||||
# - { index: 16, color: '{{base09-hex}}' }
|
||||
# - { index: 17, color: '{{base0f-hex}}' }
|
||||
# - { index: 18, color: '{{base01-hex}}' }
|
||||
# - { index: 19, color: '{{base02-hex}}' }
|
||||
# - { index: 20, color: '{{base04-hex}}' }
|
||||
# - { index: 21, color: '{{base06-hex}}' }
|
||||
21
dot_config/nushell/nu_scripts/modules/base16/auto_base16.nu
Normal file
21
dot_config/nushell/nu_scripts/modules/base16/auto_base16.nu
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env engine-q
|
||||
#
|
||||
# ~/.auto_base16.nu
|
||||
#
|
||||
# This is a wrapper around fehbg.nu that on top of setting a random wallpaper
|
||||
# also generates a base16 theme from it.
|
||||
#
|
||||
# This script is intended to run on desktop startup, e.g., by calling it in
|
||||
# ~/.xinitrc.
|
||||
#
|
||||
# Requirements:
|
||||
# 1. go, Python 3, fehbg.nu
|
||||
# 2. Install schemer2 from https://github.com/makuto/auto-base16-theme and put
|
||||
# it into your PATH
|
||||
# 3. Expected environment variables:
|
||||
# * WALLPAPER_IMG - The wallpaper used for generating the base16 scheme
|
||||
# * BASE16_TXT - Target file to store the generated base16 scheme
|
||||
# 4. Both this script and fehbg.nu are expected to be in the home directory as
|
||||
# '~/.auto_base16.nu' and '~/.fehbg.nu'.
|
||||
|
||||
schemer2 -format img::colors -in $env.WALLPAPER_IMG -out $env.BASE16_TXT
|
||||
150
dot_config/nushell/nu_scripts/modules/base16/base16.nu
Normal file
150
dot_config/nushell/nu_scripts/modules/base16/base16.nu
Normal file
@@ -0,0 +1,150 @@
|
||||
# Build a color config for engine-q based on generated base16 file
|
||||
#
|
||||
# The input file is supposed to have 16 lines, each base16 colors on a separate
|
||||
# line like this:
|
||||
#
|
||||
# ```
|
||||
# #base00-hex
|
||||
# #base01-hex
|
||||
# ...etc.
|
||||
# #base0f-hex
|
||||
# ```
|
||||
export def build-nu-config [base_txt: path] {
|
||||
let b16 = (from-file $base_txt)
|
||||
|
||||
{
|
||||
separator: $b16.base03
|
||||
leading_trailing_space_bg: $b16.base04
|
||||
header: $b16.base0b
|
||||
date: $b16.base0e
|
||||
filesize: $b16.base0d
|
||||
row_index: $b16.base0c
|
||||
bool: $b16.base08
|
||||
int: $b16.base0b
|
||||
duration: $b16.base08
|
||||
range: $b16.base08
|
||||
float: $b16.base08
|
||||
string: $b16.base04
|
||||
nothing: $b16.base08
|
||||
binary: $b16.base08
|
||||
cellpath: $b16.base08
|
||||
hints: dark_gray
|
||||
|
||||
# base16 white on red
|
||||
flatshape_garbage: { fg: $b16.base07 bg: $b16.base08 attr: b}
|
||||
# if you like the regular white on red for parse errors:
|
||||
# flatshape_garbage: { fg: "#FFFFFF" bg: "#FF0000" attr: b}
|
||||
flatshape_bool: $b16.base0d
|
||||
flatshape_int: { fg: $b16.base0e attr: b}
|
||||
flatshape_float: { fg: $b16.base0e attr: b}
|
||||
flatshape_range: { fg: $b16.base0a attr: b}
|
||||
flatshape_internalcall: { fg: $b16.base0c attr: b}
|
||||
flatshape_external: $b16.base0c
|
||||
flatshape_externalarg: { fg: $b16.base0b attr: b}
|
||||
flatshape_literal: $b16.base0d
|
||||
flatshape_operator: $b16.base0a
|
||||
flatshape_signature: { fg: $b16.base0b attr: b}
|
||||
flatshape_string: $b16.base0b
|
||||
flatshape_filepath: $b16.base0d
|
||||
flatshape_globpattern: { fg: $b16.base0d attr: b}
|
||||
flatshape_variable: $b16.base0e
|
||||
flatshape_flag: { fg: $b16.base0d attr: b}
|
||||
flatshape_custom: {attr: b}
|
||||
}
|
||||
}
|
||||
|
||||
# Generate Alacritty color config to be included in the main Alacritty config
|
||||
#
|
||||
# It injects the base16 colors into the Alacritty config template
|
||||
export def build-alacritty-config [base_txt: path] {
|
||||
let base16 = (from-file-table $base_txt)
|
||||
let template = (
|
||||
open "~/.config/nushell/alacritty_colors.mustache" |
|
||||
decode utf-8
|
||||
)
|
||||
|
||||
# TODO: need a save command:
|
||||
# | save --raw "~/.config/alacritty/alacritty_colors.yml"
|
||||
let conf = ($base16 | apply-base16-mustache $template)
|
||||
|
||||
$env.ALACRITTY_CONFIG = $conf
|
||||
|
||||
nu -c "$nu.env.ALACRITTY_CONFIG | save --raw '~/.config/alacritty/alacritty_colors.yml'"
|
||||
}
|
||||
|
||||
# Generate LS_COLORS value
|
||||
export def build-lscolors [base_txt: path] {
|
||||
# TODO
|
||||
}
|
||||
|
||||
# Show the current base16 colors
|
||||
export def show [base_txt: path] {
|
||||
from-file $base_txt | each { |it|
|
||||
{ $it.column: $"(ansi -e { fg: ($it.value) bg: ($it.value) })($it.value)(ansi reset)" }
|
||||
}
|
||||
}
|
||||
|
||||
# Regenerate the wallpaper, its base16 theme, and apply it to external tools
|
||||
export def new-wallpaper [] {
|
||||
~/.fehbg.nu
|
||||
~/.auto_base16.nu
|
||||
build-alacritty-config $env.BASE16_TXT
|
||||
}
|
||||
|
||||
# Get base16 as a record from an input file
|
||||
export def from-file [base_txt: path] {
|
||||
let base16_lines = (open $base_txt | lines | where ($it | str length) > 0)
|
||||
|
||||
{
|
||||
base00 : $base16_lines.0 # Default Background
|
||||
base01 : $base16_lines.1 # Lighter Background (Used for status bars, line number and folding marks)
|
||||
base02 : $base16_lines.2 # Selection Background
|
||||
base03 : $base16_lines.3 # Comments, Invisibles, Line Highlighting
|
||||
base04 : $base16_lines.4 # Dark Foreground (Used for status bars)
|
||||
base05 : $base16_lines.5 # Default Foreground, Caret, Delimiters, Operators
|
||||
base06 : $base16_lines.6 # Light Foreground (Not often used)
|
||||
base07 : $base16_lines.7 # Light Background (Not often used)
|
||||
base08 : $base16_lines.8 # Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted
|
||||
base09 : $base16_lines.9 # Integers, Boolean, Constants, XML Attributes, Markup Link Url
|
||||
base0a : $base16_lines.10 # Classes, Markup Bold, Search Text Background
|
||||
base0b : $base16_lines.11 # Strings, Inherited Class, Markup Code, Diff Inserted
|
||||
base0c : $base16_lines.12 # Support, Regular Expressions, Escape Characters, Markup Quotes
|
||||
base0d : $base16_lines.13 # Functions, Methods, Attribute IDs, Headings
|
||||
base0e : $base16_lines.14 # Keywords, Storage, Selector, Markup Italic, Diff Changed
|
||||
base0f : $base16_lines.15 # Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?>
|
||||
}
|
||||
}
|
||||
|
||||
# Get base16 as a table from an input file
|
||||
export def from-file-table [base_txt: path] {
|
||||
let base16_lines = (open $base_txt | lines | where ($it | str length) > 0)
|
||||
|
||||
[
|
||||
[ name color ];
|
||||
[ base00 $base16_lines.0 ] # Default Background
|
||||
[ base01 $base16_lines.1 ] # Lighter Background (Used for status bars, line number and folding marks)
|
||||
[ base02 $base16_lines.2 ] # Selection Background
|
||||
[ base03 $base16_lines.3 ] # Comments, Invisibles, Line Highlighting
|
||||
[ base04 $base16_lines.4 ] # Dark Foreground (Used for status bars)
|
||||
[ base05 $base16_lines.5 ] # Default Foreground, Caret, Delimiters, Operators
|
||||
[ base06 $base16_lines.6 ] # Light Foreground (Not often used)
|
||||
[ base07 $base16_lines.7 ] # Light Background (Not often used)
|
||||
[ base08 $base16_lines.8 ] # Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted
|
||||
[ base09 $base16_lines.9 ] # Integers, Boolean, Constants, XML Attributes, Markup Link Url
|
||||
[ base0a $base16_lines.10 ] # Classes, Markup Bold, Search Text Background
|
||||
[ base0b $base16_lines.11 ] # Strings, Inherited Class, Markup Code, Diff Inserted
|
||||
[ base0c $base16_lines.12 ] # Support, Regular Expressions, Escape Characters, Markup Quotes
|
||||
[ base0d $base16_lines.13 ] # Functions, Methods, Attribute IDs, Headings
|
||||
[ base0e $base16_lines.14 ] # Keywords, Storage, Selector, Markup Italic, Diff Changed
|
||||
[ base0f $base16_lines.15 ] # Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?>
|
||||
]
|
||||
}
|
||||
|
||||
# Replace {{baseXX-hex}} with proper colors, such as #ffeedd
|
||||
def apply-base16-mustache [template: string] {
|
||||
reduce -f $template { |it|
|
||||
let subs = $"\{\{($it.item.name)-hex\}\}" # regex
|
||||
let color = $it.item.color
|
||||
$it.acc | str replace -a $subs $color
|
||||
}
|
||||
}
|
||||
64
dot_config/nushell/nu_scripts/modules/clone-all/README.md
Normal file
64
dot_config/nushell/nu_scripts/modules/clone-all/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Clone all
|
||||
|
||||
Do you want to automate cloning a list repos into a folder? This script is for you!
|
||||
|
||||
## Requirements:
|
||||
- [`gh` cli](https://github.com/cli/cli)
|
||||
|
||||
## How to use it
|
||||
|
||||
Load the script:
|
||||
|
||||
- if you have cloned the repo before:
|
||||
|
||||
```nushell env.nu
|
||||
source ~/your/directory/to/nu_scripts/modules/clone-all/clone-all.nu
|
||||
```
|
||||
|
||||
or if you have the file, and you want it to use in a nushell session:
|
||||
|
||||
```nushell
|
||||
use clone-all.nu *
|
||||
# and it's ready to use in the current prompt!
|
||||
```
|
||||
|
||||
Then, create a list of github routes to repositories `ORGANIZATION_NAME/REPO`
|
||||
like this:
|
||||
|
||||
```nu
|
||||
let list_of_repos = [
|
||||
"nushell/nushell"
|
||||
"nushell/nu_scripts"
|
||||
"nushell/vscode-nushell-lang"
|
||||
]
|
||||
```
|
||||
|
||||
And then you need to pass that variable and a destination folder
|
||||
|
||||
```nu
|
||||
clone all $list_of_repos $"($env.home)/other-repos/nu_repos"
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
I (@AucaCoyan) use it for cloning both org repos and my forks
|
||||
|
||||
```nushell
|
||||
let nushell_repos = [
|
||||
"nushell/nushell"
|
||||
"nushell/nu_scripts"
|
||||
"nushell/vscode-nushell-lang"
|
||||
]
|
||||
|
||||
clone all $nushell_repos $"($env.home)/other-repos/nu"
|
||||
|
||||
let nushell_forks = [
|
||||
"AucaCoyan/nushell"
|
||||
"AucaCoyan/nu_scripts"
|
||||
"AucaCoyan/vscode-nushell-lang"
|
||||
]
|
||||
|
||||
clone all $nushell_forks $"($env.home)/repos"
|
||||
```
|
||||
|
||||
and do that with every gh org (work or open source!)
|
||||
47
dot_config/nushell/nu_scripts/modules/clone-all/clone-all.nu
Normal file
47
dot_config/nushell/nu_scripts/modules/clone-all/clone-all.nu
Normal file
@@ -0,0 +1,47 @@
|
||||
# grabs the repo name of a github (ORG/repo) string
|
||||
#
|
||||
# for example
|
||||
# grab repo name "organization/my_special_repo"
|
||||
# returns "myspecial_repo"
|
||||
|
||||
# Grabs the repo name of a github (ORG/repo) string
|
||||
def "grab repo name" [ghrepo: string]: [string -> string] {
|
||||
$ghrepo | split column "/" | get column2 | last
|
||||
}
|
||||
|
||||
# Generic fn to clone all repos of one organization into a specific folder
|
||||
#
|
||||
# # Parameters
|
||||
# `list_of_repos` is a list of <ORG/REPO> from github
|
||||
# for example:
|
||||
# ```nu
|
||||
# let list_of_repos = [
|
||||
# "nushell/nushell"
|
||||
# "nushell/nu_scripts"
|
||||
# "nushell/vscode-nushell-lang"
|
||||
# ]
|
||||
#
|
||||
# and destination is the location where those repos are cloned
|
||||
# $ use clone-all.nu *
|
||||
# $ clone all ['nushell/nu_scripts'] /home/my-dir/
|
||||
# equals
|
||||
# gh repo clone nushell/nu_scripts /home/my-dir/nu_scripts
|
||||
# (note that it doesn't create the organization folder)
|
||||
|
||||
# Clones all the `list_of_repos` into `destination` folder
|
||||
export def "clone all" [list_of_repos: list<string>, destination: path] {
|
||||
print $" creating ($destination) folder"
|
||||
mkdir $destination
|
||||
|
||||
for $repo in $list_of_repos {
|
||||
let repo_name = grab repo name $repo
|
||||
let single_repo_dir = $"($destination)/($repo_name)"
|
||||
if ($single_repo_dir | path exists) {
|
||||
print $"\n repo ($single_repo_dir) exists, skipping"
|
||||
continue
|
||||
} else {
|
||||
print $"\n cloning ($repo)"
|
||||
gh repo clone $repo $single_repo_dir
|
||||
}
|
||||
}
|
||||
}
|
||||
37
dot_config/nushell/nu_scripts/modules/coloring/24bit-1.nu
Normal file
37
dot_config/nushell/nu_scripts/modules/coloring/24bit-1.nu
Normal file
@@ -0,0 +1,37 @@
|
||||
export def draw [] {
|
||||
let term_cols = ((term size).columns - 1)
|
||||
|
||||
# let's itertate through each of the columns of our terminal
|
||||
0..$term_cols | each { |col|
|
||||
let r = (255 - ($col * 255 / $term_cols) | math round)
|
||||
let g = ($col * 510 / $term_cols | math round)
|
||||
let b = ($col * 255 / $term_cols | math round)
|
||||
if $g > 255 {
|
||||
let g = (510 - $g)
|
||||
build-colorstr $r $g $b $col
|
||||
} else {
|
||||
build-colorstr $r $g $b $col
|
||||
}
|
||||
} | str join
|
||||
}
|
||||
|
||||
def build-colorstr [
|
||||
r:int # Red
|
||||
g:int # Green
|
||||
b:int # Blue
|
||||
c:int # Column
|
||||
] {
|
||||
# Heavy use of string interpolation below
|
||||
let bg = $"(ansi rgb_bg)($r);($g);($b)m"
|
||||
let fg = $"(ansi rgb_fg)(255 - $r);(255 - $g);(255 - $b)m"
|
||||
let idx = ($c mod 2)
|
||||
let slash_str = (if $idx == 0 {
|
||||
$'/(ansi reset)'
|
||||
} else {
|
||||
$'\(ansi reset)'
|
||||
})
|
||||
$"($bg)($fg)($slash_str)"
|
||||
# sleep 10ms | ignore
|
||||
}
|
||||
|
||||
draw
|
||||
@@ -0,0 +1,169 @@
|
||||
def contrast_colour [ colour:int ] {
|
||||
# The first 16 colors
|
||||
if $colour < 16 {
|
||||
if $colour == 0 {
|
||||
15
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else {
|
||||
# The gray colors
|
||||
if $colour > 231 {
|
||||
if $colour < 244 {
|
||||
15
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else {
|
||||
# The rest
|
||||
let r = ($colour - 16) / 36
|
||||
let g = (($colour - 16) mod 36) / 6
|
||||
let b = ($colour - 16) mod 6
|
||||
|
||||
let luminance = ($r * 299) + ($g * 587) + ($b * 114)
|
||||
if $luminance > 2500 {
|
||||
0
|
||||
} else {
|
||||
15
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def print_colour [ colour:int ] {
|
||||
let contrast = (contrast_colour $colour)
|
||||
let bg_color = $"(ansi idx_bg)($colour)m" # Start block of colour
|
||||
let fg_color = $"(ansi idx_fg)($contrast)m" # In contrast, print number
|
||||
let text = $"($colour | into string | fill -c ' ' -w 3 -a r)(ansi reset)"
|
||||
$bg_color + $fg_color + $text + " "
|
||||
}
|
||||
|
||||
let printable_colours = 256
|
||||
|
||||
def print_run [start:int, amount:int] {
|
||||
$start..<($start + $amount) | each { |i|
|
||||
if $i < $printable_colours {
|
||||
print_colour $i
|
||||
} else {
|
||||
""
|
||||
}
|
||||
} | append " " | str join
|
||||
}
|
||||
|
||||
def print_blocks [start:int, end:int, block_cols:int, block_rows:int, blocks_per_line:int] {
|
||||
let block_length = ($block_cols * $block_rows)
|
||||
let end = (($end - $start) / (($blocks_per_line) * $block_length)) | math round
|
||||
0..<$end | each { |i|
|
||||
0..<$block_rows | each { |row|
|
||||
0..<$blocks_per_line | each { |block|
|
||||
print_run ($start + $block * $block_length + $row * $block_cols + $i * $block_length * $blocks_per_line) $block_cols
|
||||
} | append (char nl) | str join
|
||||
} | str join
|
||||
} | str join
|
||||
}
|
||||
|
||||
print (print_run 0 16) # The first 16 colours are spread over the whole spectrum
|
||||
print "" # Single line
|
||||
print (print_blocks 16 123 6 6 3) # 6x6x6 colour cube between 16 and 123 inclusive
|
||||
print (print_blocks 124 231 6 6 3) # 6x6x6 colour cube between 124 and 231 inclusive
|
||||
print (print_blocks 232 255 12 2 1) # Not 50, but 24 Shades of Grey
|
||||
|
||||
|
||||
# bash:
|
||||
|
||||
# #!/bin/bash
|
||||
#
|
||||
# # Tom Hale, 2016. MIT Licence.
|
||||
# # Print out 256 colours, with each number printed in its corresponding colour
|
||||
# # See http://askubuntu.com/questions/821157/print-a-256-color-test-pattern-in-the-terminal/821163#821163
|
||||
#
|
||||
# set -eu # Fail on errors or undeclared variables
|
||||
#
|
||||
# printable_colours=256
|
||||
#
|
||||
# # Return a colour that contrasts with the given colour
|
||||
# # Bash only does integer division, so keep it integral
|
||||
# function contrast_colour {
|
||||
# local r g b luminance
|
||||
# colour="$1"
|
||||
#
|
||||
# if (( colour < 16 )); then # Initial 16 ANSI colours
|
||||
# (( colour == 0 )) && printf "15" || printf "0"
|
||||
# return
|
||||
# fi
|
||||
#
|
||||
# # Greyscale # rgb_R = rgb_G = rgb_B = (number - 232) * 10 + 8
|
||||
# if (( colour > 231 )); then # Greyscale ramp
|
||||
# (( colour < 244 )) && printf "15" || printf "0"
|
||||
# return
|
||||
# fi
|
||||
#
|
||||
# # All other colours:
|
||||
# # 6x6x6 colour cube = 16 + 36*R + 6*G + B # Where RGB are [0..5]
|
||||
# # See http://stackoverflow.com/a/27165165/5353461
|
||||
#
|
||||
# # r=$(( (colour-16) / 36 ))
|
||||
# g=$(( ((colour-16) % 36) / 6 ))
|
||||
# # b=$(( (colour-16) % 6 ))
|
||||
#
|
||||
# # If luminance is bright, print number in black, white otherwise.
|
||||
# # Green contributes 587/1000 to human perceived luminance - ITU R-REC-BT.601
|
||||
# (( g > 2)) && printf "0" || printf "15"
|
||||
# return
|
||||
#
|
||||
# # Uncomment the below for more precise luminance calculations
|
||||
#
|
||||
# # # Calculate percieved brightness
|
||||
# # # See https://www.w3.org/TR/AERT#color-contrast
|
||||
# # # and http://www.itu.int/rec/R-REC-BT.601
|
||||
# # # Luminance is in range 0..5000 as each value is 0..5
|
||||
# # luminance=$(( (r * 299) + (g * 587) + (b * 114) ))
|
||||
# # (( $luminance > 2500 )) && printf "0" || printf "15"
|
||||
# }
|
||||
#
|
||||
# # Print a coloured block with the number of that colour
|
||||
# function print_colour {
|
||||
# local colour="$1" contrast
|
||||
# contrast=$(contrast_colour "$1")
|
||||
# printf "\e[48;5;%sm" "$colour" # Start block of colour
|
||||
# printf "\e[38;5;%sm%3d" "$contrast" "$colour" # In contrast, print number
|
||||
# printf "\e[0m " # Reset colour
|
||||
# }
|
||||
#
|
||||
# # Starting at $1, print a run of $2 colours
|
||||
# function print_run {
|
||||
# local i
|
||||
# for (( i = "$1"; i < "$1" + "$2" && i < printable_colours; i++ )) do
|
||||
# print_colour "$i"
|
||||
# done
|
||||
# printf " "
|
||||
# }
|
||||
#
|
||||
# # Print blocks of colours
|
||||
# function print_blocks {
|
||||
# local start="$1" i
|
||||
# local end="$2" # inclusive
|
||||
# local block_cols="$3"
|
||||
# local block_rows="$4"
|
||||
# local blocks_per_line="$5"
|
||||
# local block_length=$((block_cols * block_rows))
|
||||
#
|
||||
# # Print sets of blocks
|
||||
# for (( i = start; i <= end; i += (blocks_per_line-1) * block_length )) do
|
||||
# printf "\n" # Space before each set of blocks
|
||||
# # For each block row
|
||||
# for (( row = 0; row < block_rows; row++ )) do
|
||||
# # Print block columns for all blocks on the line
|
||||
# for (( block = 0; block < blocks_per_line; block++ )) do
|
||||
# print_run $(( i + (block * block_length) )) "$block_cols"
|
||||
# done
|
||||
# (( i += block_cols )) # Prepare to print the next row
|
||||
# printf "\n"
|
||||
# done
|
||||
# done
|
||||
# }
|
||||
#
|
||||
# print_run 0 16 # The first 16 colours are spread over the whole spectrum
|
||||
# printf "\n"
|
||||
# print_blocks 16 231 6 6 3 # 6x6x6 colour cube between 16 and 231 inclusive
|
||||
# print_blocks 232 255 12 2 1 # Not 50, but 24 Shades of Grey
|
||||
5
dot_config/nushell/nu_scripts/modules/coloring/README.md
Normal file
5
dot_config/nushell/nu_scripts/modules/coloring/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Coloring Scripts
|
||||
|
||||
### Definition
|
||||
|
||||
These scripts are used to demonstrate the `ansi` command using `ansi` coloring. This is mainly a demo area where we have taken typical `bash` scripts and ported them to nushell scripts. It would be nice if all scripts here showed the "other" version of script and the ported nushell version. We can show "other" flavors of scripts by including them as comments in the nushell scripts or by naming the nushell script and the other script the same basename.
|
||||
@@ -0,0 +1,94 @@
|
||||
def make_header [hi] {
|
||||
if $hi == true {
|
||||
let ansi100m = ('100m' | fill -a l -w 11 -c ' ')
|
||||
let ansi101m = ('101m' | fill -a l -w 9 -c ' ')
|
||||
let ansi102m = ('102m' | fill -a l -w 9 -c ' ')
|
||||
let ansi103m = ('103m' | fill -a l -w 9 -c ' ')
|
||||
let ansi104m = ('104m' | fill -a l -w 9 -c ' ')
|
||||
let ansi105m = ('105m' | fill -a l -w 9 -c ' ')
|
||||
let ansi106m = ('106m' | fill -a l -w 9 -c ' ')
|
||||
let ansi107m = ('107m' | fill -a l -w 9 -c ' ')
|
||||
$"(char newline)($ansi100m)($ansi101m)($ansi102m)($ansi103m)($ansi104m)($ansi105m)($ansi106m)($ansi107m)(char newline)"
|
||||
|
||||
} else {
|
||||
let ansi40m = ('40m' | fill -a l -w 10 -c ' ')
|
||||
let ansi41m = ('41m' | fill -a l -w 8 -c ' ')
|
||||
let ansi42m = ('42m' | fill -a l -w 8 -c ' ')
|
||||
let ansi43m = ('43m' | fill -a l -w 8 -c ' ')
|
||||
let ansi44m = ('44m' | fill -a l -w 8 -c ' ')
|
||||
let ansi45m = ('45m' | fill -a l -w 8 -c ' ')
|
||||
let ansi46m = ('46m' | fill -a l -w 8 -c ' ')
|
||||
let ansi47m = ('47m' | fill -a l -w 8 -c ' ')
|
||||
$"(char newline)($ansi40m)($ansi41m)($ansi42m)($ansi43m)($ansi44m)($ansi45m)($ansi46m)($ansi47m)(char newline)"
|
||||
}
|
||||
}
|
||||
|
||||
# mk_header and make_header do the same thing in different ways
|
||||
# make_header is far easier to read and understand
|
||||
# mk_header is more convoluted but less repetitive
|
||||
|
||||
def mk_header [color_range:range] {
|
||||
let min_rng = (echo $color_range | math min)
|
||||
let hi_start_pad = 11
|
||||
let hi_regular_pad = 9
|
||||
let lo_start_pad = 10
|
||||
let lo_regular_pad = 8
|
||||
echo $color_range | each { |color|
|
||||
let ansi_color = $"($color)m"
|
||||
if $color == $min_rng {
|
||||
if $min_rng == 100 {
|
||||
($ansi_color | fill -a l -w $hi_start_pad -c ' ')
|
||||
|
||||
} else {
|
||||
($ansi_color | fill -a l -w $lo_start_pad -c ' ')
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
if $min_rng >= 100 {
|
||||
($ansi_color | fill -a l -w $hi_regular_pad -c ' ')
|
||||
|
||||
} else {
|
||||
($ansi_color | fill -a l -w $lo_regular_pad -c ' ')
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} | str join
|
||||
echo (char newline)
|
||||
}
|
||||
|
||||
def color_row_range [num:int bg_rg:range] {
|
||||
let reset = (ansi reset)
|
||||
let row_header = $"($num)m ($reset)"
|
||||
let row_data = (echo $bg_rg | each { |back|
|
||||
let row_name = $"($num);($back)m"
|
||||
let ansi_color = (ansi -e $row_name)
|
||||
$"($ansi_color) ($row_name) ($reset)"
|
||||
} | append (char newline) | str join)
|
||||
$"($row_header)($row_data)"
|
||||
}
|
||||
|
||||
def create_color_tables [fg_range:range bg_range:range] {
|
||||
echo $fg_range | each { |fg|
|
||||
color_row_range $fg $bg_range
|
||||
} | str join
|
||||
}
|
||||
|
||||
def color_table [] {
|
||||
[
|
||||
# make_header $false
|
||||
(mk_header 40..47)
|
||||
(create_color_tables 30..37 40..47)
|
||||
|
||||
# put a line between tables
|
||||
(char newline)
|
||||
|
||||
#make_header $true
|
||||
(mk_header 100..107)
|
||||
(create_color_tables 90..97 100..107)
|
||||
] | str join
|
||||
}
|
||||
|
||||
color_table
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Bash script
|
||||
# for x in {0..8}; do
|
||||
# for i in {30..37}; do
|
||||
# for a in {40..47}; do
|
||||
# echo -ne "\e[$x;$i;$a""m\\\e[$x;$i;$a""m\e[0;37;40m "
|
||||
# done
|
||||
# echo
|
||||
# done
|
||||
# echo
|
||||
# done
|
||||
# echo ""
|
||||
|
||||
0..8 | each {|x|
|
||||
let row = (30..37 | each {|i|
|
||||
let row = (40..47 | each {|a|
|
||||
let color = $"($x);($i);($a)"
|
||||
$"(ansi -e $color)m\\e[($color)(ansi -e '0;37;40')m "
|
||||
} | str join)
|
||||
$"($row)(char newline)"
|
||||
} | str join)
|
||||
$"($row)(char newline)"
|
||||
} | str join
|
||||
|
||||
82
dot_config/nushell/nu_scripts/modules/coloring/gradient.nu
Normal file
82
dot_config/nushell/nu_scripts/modules/coloring/gradient.nu
Normal file
@@ -0,0 +1,82 @@
|
||||
# this script will print a blue gradient on the screen
|
||||
|
||||
# We can get the terminal width and height now with term size
|
||||
# but we like to use the script as a benchmark, so let's keep
|
||||
# it a constant size for now
|
||||
let height = 40 # really need to get the terminal height here
|
||||
let width = 160 # really need to get the terminal width here
|
||||
let stamp = 'Nu'
|
||||
|
||||
def iter_inc [incr mult iter] {
|
||||
$incr + $mult * $iter
|
||||
}
|
||||
|
||||
seq 0 $height | each {
|
||||
let row_data = (seq 0 $width | each { |col|
|
||||
let fgcolor = (iter_inc 2 2 $col)
|
||||
if $fgcolor > 200 and $fgcolor < 210 {
|
||||
$"(ansi -e '48;2;0;0;')($fgcolor)m($stamp)(ansi -e '0m')"
|
||||
} else {
|
||||
$"(ansi -e '48;2;0;0;')($fgcolor)m(char sp)(ansi -e '0m')"
|
||||
}
|
||||
} | str join)
|
||||
$"($row_data)(char newline)"
|
||||
} | str join
|
||||
|
||||
|
||||
# python:
|
||||
#
|
||||
# #!/usr/bin/env python
|
||||
# from colors import *
|
||||
#
|
||||
# def iter_inc(incr, mult, it):
|
||||
# return incr + mult * it
|
||||
#
|
||||
# height = 40
|
||||
# width = 160
|
||||
# stamp = "py"
|
||||
#
|
||||
# for line in range(0, height):
|
||||
# row_data = ""
|
||||
#
|
||||
# for col in range(0, width):
|
||||
# fgcolor = iter_inc(2, 2, col)
|
||||
# if fgcolor > 200 and fgcolor < 210:
|
||||
# row_data = row_data + color(stamp, bg='rgb(0, 0, %d)' % fgcolor)
|
||||
# else:
|
||||
# fg = fgcolor % 256
|
||||
# row_data = row_data + color(' ', bg='rgb(0, 0, %d)' % fg)
|
||||
#
|
||||
# print(row_data)
|
||||
|
||||
|
||||
# powershell:
|
||||
|
||||
# function Set-Cursor {
|
||||
# [CmdletBinding()]
|
||||
# param ([int] $x, [int] $y)
|
||||
# $Host.UI.RawUI.CursorPosition = @{x = $x; y = $y }
|
||||
# }
|
||||
#
|
||||
# function Get-Character {
|
||||
# [CmdletBinding()]
|
||||
# param ([int]$index)
|
||||
# $mystring = ' Trevor Sullivan'
|
||||
# return $index -ge ($mystring.Length) ? ' ' : $mystring[$index]
|
||||
# }
|
||||
#
|
||||
# function main {
|
||||
#
|
||||
# for ($y = 0; $y -le ($host.ui.RawUI.BufferSize.Height - 1); $y++) {
|
||||
# $Color = 25
|
||||
# Set-Cursor -x $PSItem -y $y
|
||||
# 0..($Host.UI.RawUI.BufferSize.Width - 1) | ForEach-Object {
|
||||
# Write-Host -Object ("`e[48;2;0;0;$Color`m{0}" -f (Get-Character -Index $PSItem)) -NoNewline
|
||||
# $Color += 2
|
||||
# }
|
||||
# }
|
||||
# Start-Sleep -Seconds 5
|
||||
# }
|
||||
#
|
||||
# main
|
||||
|
||||
56
dot_config/nushell/nu_scripts/modules/coloring/hl.nu
Normal file
56
dot_config/nushell/nu_scripts/modules/coloring/hl.nu
Normal file
@@ -0,0 +1,56 @@
|
||||
export def combine [txt: string, fg: record, bg: record] {
|
||||
{
|
||||
txt: $txt,
|
||||
fg: $fg.fg,
|
||||
bg: $bg.fg,
|
||||
bli: ($fg.bli or $bg.bli),
|
||||
bol: ($fg.bol or $bg.bol),
|
||||
dim: ($fg.dim or $bg.dim),
|
||||
hid: ($fg.hid or $bg.hid),
|
||||
ita: ($fg.ita or $bg.ita),
|
||||
rev: ($fg.rev or $bg.rev),
|
||||
stk: ($fg.stk or $bg.stk),
|
||||
und: ($fg.und or $bg.und)
|
||||
}
|
||||
}
|
||||
|
||||
export def create [txt: string,
|
||||
fg = "default", bg = "default",
|
||||
bli = false, bol = false, dim = false, hid = false,
|
||||
ita = false, rev = false, stk = false, und = false] {
|
||||
{
|
||||
txt: $txt,
|
||||
fg: $fg,
|
||||
bg: $bg,
|
||||
bli: $bli,
|
||||
bol: $bol,
|
||||
dim: $dim,
|
||||
hid: $hid,
|
||||
ita: $ita,
|
||||
rev: $rev,
|
||||
stk: $stk,
|
||||
und: $und
|
||||
}
|
||||
}
|
||||
|
||||
export def render [obj: record] {
|
||||
let attr = ""
|
||||
let attr = $"($attr)(if $obj.bli {'l'})"
|
||||
let attr = $"($attr)(if $obj.bol {'b'})"
|
||||
let attr = $"($attr)(if $obj.dim {'d'})"
|
||||
let attr = $"($attr)(if $obj.hid {'h'})"
|
||||
let attr = $"($attr)(if $obj.ita {'i'})"
|
||||
let attr = $"($attr)(if $obj.rev {'r'})"
|
||||
let attr = $"($attr)(if $obj.stk {'s'})"
|
||||
let attr = $"($attr)(if $obj.und {'u'})"
|
||||
|
||||
let color = {fg: $obj.fg, bg: $obj.bg, attr: $attr}
|
||||
|
||||
$"(ansi $color)($obj.txt)(ansi reset)"
|
||||
}
|
||||
|
||||
export def reverse [obj: record] {
|
||||
let r = ($obj | update fg $obj.bg)
|
||||
let r = ($r | update bg $obj.fg)
|
||||
$r
|
||||
}
|
||||
149
dot_config/nushell/nu_scripts/modules/coloring/html_colors.nu
Normal file
149
dot_config/nushell/nu_scripts/modules/coloring/html_colors.nu
Normal file
@@ -0,0 +1,149 @@
|
||||
# these are common colors from https://en.wikipedia.org/wiki/web_colors
|
||||
let aliceblue = "#f0f8ff"
|
||||
let antiquewhite = "#faebd7"
|
||||
let aqua = "#00ffff"
|
||||
let aquamarine = "#7fffd4"
|
||||
let azure = "#f0ffff"
|
||||
let beige = "#f5f5dc"
|
||||
let bisque = "#ffe4c4"
|
||||
let black = "#000000"
|
||||
let blanchedalmond = "#ffebcd"
|
||||
let blue = "#0000ff"
|
||||
let blueviolet = "#8a2be2"
|
||||
let brown = "#a52a2a"
|
||||
let burlywood = "#deb887"
|
||||
let cadetblue = "#5f9ea0"
|
||||
let chartreuse = "#7fff00"
|
||||
let chocolate = "#d2691e"
|
||||
let coral = "#ff7f50"
|
||||
let cornflowerblue = "#6495ed"
|
||||
let cornsilk = "#fff8dc"
|
||||
let crimson = "#dc143c"
|
||||
let cyan = "#00ffff"
|
||||
let darkblue = "#00008b"
|
||||
let darkcyan = "#008b8b"
|
||||
let darkgoldenrod = "#b8860b"
|
||||
let darkgray = "#a9a9a9"
|
||||
let darkgrey = "#a9a9a9"
|
||||
let darkgreen = "#006400"
|
||||
let darkkhaki = "#bdb76b"
|
||||
let darkmagenta = "#8b008b"
|
||||
let darkolivegreen = "#556b2f"
|
||||
let darkorange = "#ff8c00"
|
||||
let darkorchid = "#9932cc"
|
||||
let darkred = "#8b0000"
|
||||
let darksalmon = "#e9967a"
|
||||
let darkseagreen = "#8fbc8f"
|
||||
let darkslateblue = "#483d8b"
|
||||
let darkslategray = "#2f4f4f"
|
||||
let darkslategrey = "#2f4f4f"
|
||||
let darkturquoise = "#00ced1"
|
||||
let darkviolet = "#9400d3"
|
||||
let deeppink = "#ff1493"
|
||||
let deepskyblue = "#00bfff"
|
||||
let dimgray = "#696969"
|
||||
let dimgrey = "#696969"
|
||||
let dodgerblue = "#1e90ff"
|
||||
let firebrick = "#b22222"
|
||||
let floralwhite = "#fffaf0"
|
||||
let forestgreen = "#228b22"
|
||||
let fuchsia = "#ff00ff"
|
||||
let gainsboro = "#dcdcdc"
|
||||
let ghostwhite = "#f8f8ff"
|
||||
let gold = "#ffd700"
|
||||
let goldenrod = "#daa520"
|
||||
let gray = "#808080"
|
||||
let grey = "#808080"
|
||||
let green = "#008000"
|
||||
let greenyellow = "#adff2f"
|
||||
let honeydew = "#f0fff0"
|
||||
let hotpink = "#ff69b4"
|
||||
let indianred = "#cd5c5c"
|
||||
let indigo = "#4b0082"
|
||||
let ivory = "#fffff0"
|
||||
let khaki = "#f0e68c"
|
||||
let lavender = "#e6e6fa"
|
||||
let lavenderblush = "#fff0f5"
|
||||
let lawngreen = "#7cfc00"
|
||||
let lemonchiffon = "#fffacd"
|
||||
let lightblue = "#add8e6"
|
||||
let lightcoral = "#f08080"
|
||||
let lightcyan = "#e0ffff"
|
||||
let lightgoldenrodyellow = "#fafad2"
|
||||
let lightgray = "#d3d3d3"
|
||||
let lightgrey = "#d3d3d3"
|
||||
let lightgreen = "#90ee90"
|
||||
let lightpink = "#ffb6c1"
|
||||
let lightsalmon = "#ffa07a"
|
||||
let lightseagreen = "#20b2aa"
|
||||
let lightskyblue = "#87cefa"
|
||||
let lightslategray = "#778899"
|
||||
let lightslategrey = "#778899"
|
||||
let lightsteelblue = "#b0c4de"
|
||||
let lightyellow = "#ffffe0"
|
||||
let lime = "#00ff00"
|
||||
let limegreen = "#32cd32"
|
||||
let linen = "#faf0e6"
|
||||
let magenta = "#ff00ff"
|
||||
let maroon = "#800000"
|
||||
let mediumaquamarine = "#66cdaa"
|
||||
let mediumblue = "#0000cd"
|
||||
let mediumorchid = "#ba55d3"
|
||||
let mediumpurple = "#9370d8"
|
||||
let mediumseagreen = "#3cb371"
|
||||
let mediumslateblue = "#7b68ee"
|
||||
let mediumspringgreen = "#00fa9a"
|
||||
let mediumturquoise = "#48d1cc"
|
||||
let mediumvioletred = "#c71585"
|
||||
let midnightblue = "#191970"
|
||||
let mintcream = "#f5fffa"
|
||||
let mistyrose = "#ffe4e1"
|
||||
let moccasin = "#ffe4b5"
|
||||
let navajowhite = "#ffdead"
|
||||
let navy = "#000080"
|
||||
let oldlace = "#fdf5e6"
|
||||
let olive = "#808000"
|
||||
let olivedrab = "#6b8e23"
|
||||
let orange = "#ffa500"
|
||||
let orangered = "#ff4500"
|
||||
let orchid = "#da70d6"
|
||||
let palegoldenrod = "#eee8aa"
|
||||
let palegreen = "#98fb98"
|
||||
let paleturquoise = "#afeeee"
|
||||
let palevioletred = "#d87093"
|
||||
let papayawhip = "#ffefd5"
|
||||
let peachpuff = "#ffdab9"
|
||||
let peru = "#cd853f"
|
||||
let pink = "#ffc0cb"
|
||||
let plum = "#dda0dd"
|
||||
let powderblue = "#b0e0e6"
|
||||
let purple = "#800080"
|
||||
let rebeccapurple = "#663399"
|
||||
let red = "#ff0000"
|
||||
let rosybrown = "#bc8f8f"
|
||||
let royalblue = "#4169e1"
|
||||
let saddlebrown = "#8b4513"
|
||||
let salmon = "#fa8072"
|
||||
let sandybrown = "#f4a460"
|
||||
let seagreen = "#2e8b57"
|
||||
let seashell = "#fff5ee"
|
||||
let sienna = "#a0522d"
|
||||
let silver = "#c0c0c0"
|
||||
let skyblue = "#87ceeb"
|
||||
let slateblue = "#6a5acd"
|
||||
let slategray = "#708090"
|
||||
let slategrey = "#708090"
|
||||
let snow = "#fffafa"
|
||||
let springgreen = "#00ff7f"
|
||||
let steelblue = "#4682b4"
|
||||
let tan = "#d2b48c"
|
||||
let teal = "#008080"
|
||||
let thistle = "#d8bfd8"
|
||||
let tomato = "#ff6347"
|
||||
let turquoise = "#40e0d0"
|
||||
let violet = "#ee82ee"
|
||||
let wheat = "#f5deb3"
|
||||
let white = "#ffffff"
|
||||
let whitesmoke = "#f5f5f5"
|
||||
let yellow = "#ffff00"
|
||||
let yellowgreen = "#9acd32"
|
||||
@@ -0,0 +1,15 @@
|
||||
def show_index_colors [] {
|
||||
let prefix = "48;5;"
|
||||
1..256 | each { |idx|
|
||||
let color = $"(ansi -e $prefix)($idx)m"
|
||||
let padded_number = ($"($idx)" | fill -a l -w 3 -c '0')
|
||||
let cr = ($idx mod 16)
|
||||
if $cr == 0 {
|
||||
$"($color)($padded_number) (ansi -e 0m)(char newline)"
|
||||
} else {
|
||||
$"($color)($padded_number) (ansi -e 0m)"
|
||||
}
|
||||
} | str join
|
||||
}
|
||||
|
||||
show_index_colors
|
||||
@@ -0,0 +1,27 @@
|
||||
# this script uses foreground ansi index colors to print
|
||||
# a table of 16 rows by 16 colums where each item is a
|
||||
# different color
|
||||
def show_index_colors [] {
|
||||
let prefix = "38;5;"
|
||||
echo 1..256 | each { |idx|
|
||||
let cr = (($idx) mod 16)
|
||||
let color = ($"(ansi -e $prefix)($idx)m")
|
||||
let padded_number = ($"($idx)" | fill -a l -w 3 -c '0')
|
||||
|
||||
if $cr == 0 {
|
||||
$"($color)($padded_number) (char newline)"
|
||||
} else {
|
||||
$"($color)($padded_number) "
|
||||
}
|
||||
} | str join
|
||||
}
|
||||
|
||||
# one-liner version that just prints
|
||||
# it all on one line which wraps in
|
||||
# your terminal
|
||||
def one_liner [] {
|
||||
0..255 | each {|fg| [(ansi -e '38;5;') ($fg | into string) 'm' ($fg | into string) ' ']} | flatten | str join
|
||||
}
|
||||
|
||||
|
||||
show_index_colors
|
||||
@@ -0,0 +1,29 @@
|
||||
# This is the python script
|
||||
# import sys
|
||||
# for i in range(0, 16):
|
||||
# for j in range(0, 16):
|
||||
# code = str(i * 16 + j)
|
||||
# sys.stdout.write(u"\u001b[38;5;" + code + "m " + code.ljust(4))
|
||||
# print u"\u001b[0m"
|
||||
|
||||
# Foreground Colors
|
||||
print (0..16 | each { |col|
|
||||
let row = (echo 0..16 | each { |row|
|
||||
let code = ($col * 16 + $row)
|
||||
if $code < 256 {
|
||||
$"(ansi -e '38;5;')($code | into string)m($code | into string | fill -a l -w 4 -c ' ')(ansi reset)"
|
||||
}
|
||||
} | str join)
|
||||
$"($row)(char newline)"
|
||||
} | str join)
|
||||
|
||||
# Background Colors
|
||||
print (0..16 | each { |col|
|
||||
let row = (echo 0..16 | each { |row|
|
||||
let code = ($col * 16 + $row)
|
||||
if $code < 256 {
|
||||
$"(ansi -e '48;5;')($code | into string)m($code | into string | fill -a l -w 4 -c ' ')(ansi reset)"
|
||||
}
|
||||
} | str join)
|
||||
$"($row)(char newline)"
|
||||
} | str join)
|
||||
51
dot_config/nushell/nu_scripts/modules/coloring/ref_table.nu
Normal file
51
dot_config/nushell/nu_scripts/modules/coloring/ref_table.nu
Normal file
@@ -0,0 +1,51 @@
|
||||
# This script will print a table 8 rows by 36 columns
|
||||
# of background colors using ansi index coloring
|
||||
|
||||
# #!/bin/bash
|
||||
# echo -en "\n + "
|
||||
# for i in {0..35}; do
|
||||
# printf "%2b " $i
|
||||
# done
|
||||
# printf "\n\n %3b " 0
|
||||
# for i in {0..15}; do
|
||||
# echo -en "\033[48;5;${i}m \033[m "
|
||||
# done
|
||||
# #for i in 16 52 88 124 160 196 232; do
|
||||
# for i in {0..6}; do
|
||||
# let "i = i*36 +16"
|
||||
# printf "\n\n %3b " $i
|
||||
# for j in {0..35}; do
|
||||
# let "val = i+j"
|
||||
# echo -en "\033[48;5;${val}m \033[m "
|
||||
# done
|
||||
# done
|
||||
# echo -e "\n"
|
||||
|
||||
|
||||
# This prints the column headers
|
||||
let nl = (char newline)
|
||||
let plus = $"($nl) + "
|
||||
let cols = (seq 0 35 | each { |col| $"($col)" | fill -a l -c ' ' -w 3 } | str join)
|
||||
print $"($plus)($cols)"
|
||||
|
||||
let ansi_bg = (ansi -e '48;5;')
|
||||
let ansi_reset = (ansi reset)
|
||||
print $"($nl)($nl)"
|
||||
|
||||
# This prints the row headers
|
||||
let row_header = ' 0 '
|
||||
let row_data = (seq 0 15 | each { |row|
|
||||
$"($ansi_bg)($row)m ($ansi_reset)"
|
||||
} | str join)
|
||||
print $"($row_header)($row_data)($nl)($nl)"
|
||||
|
||||
# This is the meat of the script that prints the little squares of color
|
||||
seq 0 6 | each { |row_idx|
|
||||
let r = ($row_idx * 36 + 16)
|
||||
let row_header = (echo $r | into string -d 0 | fill -a l -c ' ' -w 4)
|
||||
let row_data = (seq 0 35 | each { |row|
|
||||
let val = (($r + $row) | into string -d 0)
|
||||
$"($ansi_bg)($val)m (ansi -e 'm') "
|
||||
} | str join)
|
||||
$"($row_header) ($row_data)($nl)($nl)"
|
||||
} | str join
|
||||
46
dot_config/nushell/nu_scripts/modules/coloring/sample.nu
Normal file
46
dot_config/nushell/nu_scripts/modules/coloring/sample.nu
Normal file
@@ -0,0 +1,46 @@
|
||||
# Background Colors
|
||||
[40..47 100..107 49] | each { flatten } | flatten | each { |clbg|
|
||||
# Foreground Colors
|
||||
[30..37 90..97 39] | each { flatten } | flatten | each { |clfg|
|
||||
# 0 Normal
|
||||
# 1 Bold or increased intensity
|
||||
# 2 Faint or decreased intensity
|
||||
# 3 Italic (not widely supported)
|
||||
# 4 Underline
|
||||
# 5 Slow Blink < 150 per minute
|
||||
# 6 Rapid Blink > 150 per minute
|
||||
# 7 Reverse Video
|
||||
# 8 Conceal (not widely supported)
|
||||
# 9 Strike-through
|
||||
let row = (0..9 | each { |attr|
|
||||
let ansi_str = $"($attr);($clbg);($clfg)m"
|
||||
$"(ansi -e $ansi_str) ($ansi_str) (ansi reset)"
|
||||
} | str join)
|
||||
$"($row)(char newline)"
|
||||
} | str join
|
||||
} | str join
|
||||
|
||||
# Bash Script
|
||||
|
||||
# #!/bin/bash
|
||||
#
|
||||
# # This program is free software. It comes without any warranty, to
|
||||
# # the extent permitted by applicable law. You can redistribute it
|
||||
# # and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# # To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# # http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
#
|
||||
# #Background
|
||||
# for clbg in {40..47} {100..107} 49 ; do
|
||||
# #Foreground
|
||||
# for clfg in {30..37} {90..97} 39 ; do
|
||||
# #Formatting
|
||||
# for attr in 0 1 2 4 5 7 ; do
|
||||
# #Print the result
|
||||
# echo -en "\033[${attr};${clbg};${clfg}m ^[${attr};${clbg};${clfg}m \033[0m"
|
||||
# done
|
||||
# echo #Newline
|
||||
# done
|
||||
# done
|
||||
#
|
||||
# exit 0
|
||||
189
dot_config/nushell/nu_scripts/modules/coloring/short_list.nu
Normal file
189
dot_config/nushell/nu_scripts/modules/coloring/short_list.nu
Normal file
@@ -0,0 +1,189 @@
|
||||
source ../stdlib_candidate/nu_style.nu
|
||||
|
||||
# # Regular Colors
|
||||
$" Regular Colors (char newline) (char newline)"
|
||||
# | Value | Color |
|
||||
# | -------- | ------ |
|
||||
# | \e[0;30m | Black |
|
||||
# | \e[0;31m | Red |
|
||||
# | \e[0;32m | Green |
|
||||
# | \e[0;33m | Yellow |
|
||||
# | \e[0;34m | Blue |
|
||||
# | \e[0;35m | Purple |
|
||||
# | \e[0;36m | Cyan |
|
||||
# | \e[0;37m | White |
|
||||
$"| Value | Color | Name | (char newline)"
|
||||
$"| ----- | ----- | --------- | (char newline)"
|
||||
$"| (fg_black)0;30m(relet) | Black | fg_black | (char newline)"
|
||||
$"| (fg_red)0;31m(relet) | Red | fg_red | (char newline)"
|
||||
$"| (fg_green)0;32m(relet) | Green | fg_green | (char newline)"
|
||||
$"| (fg_yellow)0;33m(relet) | Yellow | fg_yellow | (char newline)"
|
||||
$"| (fg_blue)0;34m(relet) | Blue | fg_blue | (char newline)"
|
||||
$"| (fg_purple)0;35m(relet) | Purple | fg_purple | (char newline)"
|
||||
$"| (fg_cyan)0;36m(relet) | Cyan | fg_cyan | (char newline)"
|
||||
$"| (fg_white)0;37m(relet) | White | fg_white | (char newline)"
|
||||
char newline
|
||||
|
||||
# # Bold
|
||||
$" Bold Colors (char newline) (char newline)"
|
||||
|
||||
# | Value | Color |
|
||||
# | -------- | -------- |
|
||||
# | \e[1;30m | Black |
|
||||
# | \e[1;31m | Red |
|
||||
# | \e[1;32m | Green |
|
||||
# | \e[1;33m | Yellow |
|
||||
# | \e[1;34m | Blue |
|
||||
# | \e[1;35m | Purple |
|
||||
# | \e[1;36m | Cyan |
|
||||
# | \e[1;37m | White |
|
||||
# | \e[1m | No Color |
|
||||
$"| Value | Color | (char newline)"
|
||||
$"| ----- | ----- | (char newline)"
|
||||
$"| (fg_black)(bold_on)1;30m(relet) | Black | (char newline)"
|
||||
$"| (fg_red)(bold_on)1;31m(relet) | Red | (char newline)"
|
||||
$"| (fg_green)(bold_on)1;32m(relet) | Green | (char newline)"
|
||||
$"| (fg_yellow)(bold_on)1;33m(relet) | Yellow | (char newline)"
|
||||
$"| (fg_blue)(bold_on)1;34m(relet) | Blue | (char newline)"
|
||||
$"| (fg_purple)(bold_on)1;35m(relet) | Purple | (char newline)"
|
||||
$"| (fg_cyan)(bold_on)1;36m(relet) | Cyan | (char newline)"
|
||||
$"| (fg_white)(bold_on)1;37m(relet) | White | (char newline)"
|
||||
char newline
|
||||
|
||||
# # Underline
|
||||
$" Underline Colors (char newline) (char newline)"
|
||||
|
||||
# | Value | Color |
|
||||
# | -------- | -------- |
|
||||
# | \e[4;30m | Black |
|
||||
# | \e[4;31m | Red |
|
||||
# | \e[4;32m | Green |
|
||||
# | \e[4;33m | Yellow |
|
||||
# | \e[4;34m | Blue |
|
||||
# | \e[4;35m | Purple |
|
||||
# | \e[4;36m | Cyan |
|
||||
# | \e[4;37m | White |
|
||||
# | \e[4m | No Color |
|
||||
$"| Value | Color | (char newline)"
|
||||
$"| ----- | ----- | (char newline)"
|
||||
$"| (fg_black)(underline_on)4;30m(relet) | Black | (char newline)"
|
||||
$"| (fg_red)(underline_on)4;31m(relet) | Red | (char newline)"
|
||||
$"| (fg_green)(underline_on)4;32m(relet) | Green | (char newline)"
|
||||
$"| (fg_yellow)(underline_on)4;33m(relet) | Yellow | (char newline)"
|
||||
$"| (fg_blue)(underline_on)4;34m(relet) | Blue | (char newline)"
|
||||
$"| (fg_purple)(underline_on)4;35m(relet) | Purple | (char newline)"
|
||||
$"| (fg_cyan)(underline_on)4;36m(relet) | Cyan | (char newline)"
|
||||
$"| (fg_white)(underline_on)4;37m(relet) | White | (char newline)"
|
||||
char newline
|
||||
|
||||
# # Background
|
||||
$" Background Colors (char newline) (char newline)"
|
||||
|
||||
# | Value | Color |
|
||||
# | ------ | ------ |
|
||||
# | \e[40m | Black |
|
||||
# | \e[41m | Red |
|
||||
# | \e[42m | Green |
|
||||
# | \e[43m | Yellow |
|
||||
# | \e[44m | Blue |
|
||||
# | \e[45m | Purple |
|
||||
# | \e[46m | Cyan |
|
||||
# | \e[47m | White |
|
||||
$"| Value | Color | (char newline)"
|
||||
$"| ----- | ----- | (char newline)"
|
||||
$"| (bg_black)0;40m(relet)| Black | (char newline)"
|
||||
$"| (bg_red)0;41m(relet)| Red | (char newline)"
|
||||
$"| (bg_green)0;42m(relet)| Green | (char newline)"
|
||||
$"| (bg_yellow)0;43m(relet)| Yellow | (char newline)"
|
||||
$"| (bg_blue)0;44m(relet)| Blue | (char newline)"
|
||||
$"| (bg_purple)0;45m(relet)| Purple | (char newline)"
|
||||
$"| (bg_cyan)0;46m(relet)| Cyan | (char newline)"
|
||||
$"| (bg_white)0;47m(relet)| White | (char newline)"
|
||||
char newline
|
||||
|
||||
# # Expand Background Horizontally
|
||||
|
||||
# | Value | Color |
|
||||
# | ----- | -------- |
|
||||
# | \e[K | No Color |
|
||||
|
||||
# # High Intensty
|
||||
$" High Intensity (char newline) (char newline)"
|
||||
|
||||
# | Value | Color |
|
||||
# | -------- | ------ |
|
||||
# | \e[0;90m | Black |
|
||||
# | \e[0;91m | Red |
|
||||
# | \e[0;92m | Green |
|
||||
# | \e[0;93m | Yellow |
|
||||
# | \e[0;94m | Blue |
|
||||
# | \e[0;95m | Purple |
|
||||
# | \e[0;96m | Cyan |
|
||||
# | \e[0;97m | White |
|
||||
$"| Value | Color | (char newline)"
|
||||
$"| ----- | ----- | (char newline)"
|
||||
$"| (fg_light_black)0;90m(relet) | Black | (char newline)"
|
||||
$"| (fg_light_red)0;91m(relet) | Red | (char newline)"
|
||||
$"| (fg_light_green)0;92m(relet) | Green | (char newline)"
|
||||
$"| (fg_light_yellow)0;93m(relet) | Yellow | (char newline)"
|
||||
$"| (fg_light_blue)0;94m(relet) | Blue | (char newline)"
|
||||
$"| (fg_light_purple)0;95m(relet) | Purple | (char newline)"
|
||||
$"| (fg_light_cyan)0;96m(relet) | Cyan | (char newline)"
|
||||
$"| (fg_light_white)0;97m(relet) | White | (char newline)"
|
||||
char newline
|
||||
|
||||
# # Bold High Intensty
|
||||
$" Bold High Intensity (char newline) (char newline)"
|
||||
|
||||
# | Value | Color |
|
||||
# | -------- | ------ |
|
||||
# | \e[1;90m | Black |
|
||||
# | \e[1;91m | Red |
|
||||
# | \e[1;92m | Green |
|
||||
# | \e[1;93m | Yellow |
|
||||
# | \e[1;94m | Blue |
|
||||
# | \e[1;95m | Purple |
|
||||
# | \e[1;96m | Cyan |
|
||||
# | \e[1;97m | White |
|
||||
$"| Value | Color | (char newline)"
|
||||
$"| ----- | ----- | (char newline)"
|
||||
$"| (fg_light_black)(bold_on)1;90m(relet) | Black | (char newline)"
|
||||
$"| (fg_light_red)(bold_on)1;91m(relet) | Red | (char newline)"
|
||||
$"| (fg_light_green)(bold_on)1;92m(relet) | Green | (char newline)"
|
||||
$"| (fg_light_yellow)(bold_on)1;93m(relet) | Yellow | (char newline)"
|
||||
$"| (fg_light_blue)(bold_on)1;94m(relet) | Blue | (char newline)"
|
||||
$"| (fg_light_purple)(bold_on)1;95m(relet) | Purple | (char newline)"
|
||||
$"| (fg_light_cyan)(bold_on)1;96m(relet) | Cyan | (char newline)"
|
||||
$"| (fg_light_white)(bold_on)1;97m(relet) | White | (char newline)"
|
||||
char newline
|
||||
|
||||
# # High Intensty backgrounds
|
||||
$" High Intensity backgrounds (char newline) (char newline)"
|
||||
|
||||
# | Value | Color |
|
||||
# | --------- | ------ |
|
||||
# | \e[0;100m | Black |
|
||||
# | \e[0;101m | Red |
|
||||
# | \e[0;102m | Green |
|
||||
# | \e[0;103m | Yellow |
|
||||
# | \e[0;104m | Blue |
|
||||
# | \e[0;105m | Purple |
|
||||
# | \e[0;106m | Cyan |
|
||||
# | \e[0;107m | White |
|
||||
$"| Value | Color | (char newline)"
|
||||
$"| ----- | ----- | (char newline)"
|
||||
$"| (bg_light_black)0;100m(relet) | Black | (char newline)"
|
||||
$"| (bg_light_red)0;101m(relet) | Red | (char newline)"
|
||||
$"| (bg_light_green)0;102m(relet) | Green | (char newline)"
|
||||
$"| (bg_light_yellow)0;103m(relet) | Yellow | (char newline)"
|
||||
$"| (bg_light_blue)0;104m(relet) | Blue | (char newline)"
|
||||
$"| (bg_light_purple)0;105m(relet) | Purple | (char newline)"
|
||||
$"| (bg_light_cyan)0;106m(relet) | Cyan | (char newline)"
|
||||
$"| (bg_light_white)0;107m(relet) | White | (char newline)"
|
||||
char newline
|
||||
|
||||
# # Reset
|
||||
|
||||
# | Value | Color |
|
||||
# | ----- | ------ |
|
||||
# | \e[0m | Reset |
|
||||
@@ -0,0 +1,183 @@
|
||||
export def 'from tree' [
|
||||
schema
|
||||
--cmd-len(-c) = 1
|
||||
--selector = {value: 'value', description: 'description', next: 'next'}
|
||||
] {
|
||||
let ctx = $in
|
||||
let argv = $ctx.0
|
||||
| str substring 0..$ctx.1
|
||||
| split row -r '\s+'
|
||||
| range $cmd_len..
|
||||
| where not ($it | str starts-with '-')
|
||||
let menu = $argv
|
||||
| reduce -f {schema: $schema, path: []} {|x, acc|
|
||||
let acc = $acc | update path ($acc.path | append $x)
|
||||
if ($x | is-empty) {
|
||||
$acc
|
||||
} else {
|
||||
match ($acc.schema | describe -d | get type) {
|
||||
record => {
|
||||
if $x in $acc.schema {
|
||||
$acc | merge { schema: ($acc.schema | get $x) }
|
||||
} else {
|
||||
$acc
|
||||
}
|
||||
}
|
||||
list => {
|
||||
let fst = $acc.schema.0? | describe -d | get type
|
||||
if not ($fst in ['list', 'record']) {
|
||||
$acc
|
||||
} else {
|
||||
let r = $acc.schema | filter {|i| ($i | get $selector.value) == $x}
|
||||
if ($r | is-empty) {
|
||||
$acc
|
||||
} else {
|
||||
$acc | merge { schema: ($r | first | get $selector.next) }
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
$acc
|
||||
}
|
||||
}
|
||||
}
|
||||
| update schema {|x|
|
||||
if ($x.schema | describe -d | get type) == 'closure' {
|
||||
do $x.schema $x.path
|
||||
} else {
|
||||
$x.schema
|
||||
}
|
||||
}
|
||||
}
|
||||
match ($menu.schema | describe -d | get type) {
|
||||
record => {
|
||||
$menu.schema
|
||||
| transpose k v
|
||||
| each {|i|
|
||||
if ($i.v | describe -d | get type) == 'string' {
|
||||
{ value: $i.k, description: $i.v }
|
||||
} else {
|
||||
$i.k
|
||||
}
|
||||
}
|
||||
}
|
||||
list => {
|
||||
if ($menu.schema.0? | describe -d | get type) == 'record' {
|
||||
$menu.schema
|
||||
| each {|x| {$selector.value: null, $selector.description: null} | merge $x }
|
||||
| select $selector.value $selector.description
|
||||
| rename value description
|
||||
} else {
|
||||
$menu.schema
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def flare [...args:string@comflare] {
|
||||
print ($args | str join ' -> ')
|
||||
}
|
||||
|
||||
def comflare [...context] {
|
||||
if not ('~/.cache/flare.json' | path exists) {
|
||||
http get https://gist.githubusercontent.com/curran/d2656e98b489648ab3e2071479ced4b1/raw/9f2499d63e971c2110e52b3fa2066ebed234828c/flare-2.json
|
||||
| to json
|
||||
| save ~/.cache/flare.json
|
||||
}
|
||||
let data = open ~/.cache/flare.json
|
||||
$context | from tree -c 2 --selector {value: name, description: value, next: children } [$data]
|
||||
}
|
||||
|
||||
export def math [...args:string@commath] {
|
||||
print ($args | str join ' -> ')
|
||||
}
|
||||
|
||||
def commath [...context] {
|
||||
$context | from tree -c 2 [
|
||||
{
|
||||
value: Count
|
||||
description: closure
|
||||
next: {|path| $path}
|
||||
}
|
||||
{
|
||||
value: PureMathematics
|
||||
next: {
|
||||
NumberSystems: [
|
||||
{ value: NaturalNumbers, description: '1, 2, 3, 4, 5', next: [Arithmetic ] }
|
||||
{ value: Integer, description: '-2, -1, 0, 1, 2' }
|
||||
{ value: RationalNumbers, description: '-7, 1/2, 2.32' }
|
||||
{ value: RealNumbers, description: '-4pi, sqrt(2), e' }
|
||||
{ value: ComplexNumbers, description: '3, i, 4+3i, -4i' }
|
||||
]
|
||||
Structures: {
|
||||
Algebra: {
|
||||
Equation: null
|
||||
LinearAlgebra: [ Vector Matrices ]
|
||||
}
|
||||
NumberTheory: null
|
||||
Combinatorics: [Tree Graph]
|
||||
GroupTheory: null
|
||||
OrderTheory: null
|
||||
}
|
||||
Space: {
|
||||
Geometry: {
|
||||
Trigonometry: null
|
||||
FractalGeometry: null
|
||||
}
|
||||
Topology: null
|
||||
MeasureTheory: null
|
||||
DifferentialGeometry: null
|
||||
}
|
||||
Changes: {
|
||||
Calculus: {
|
||||
Differentials: null
|
||||
Integrals: null
|
||||
Gradients: null
|
||||
}
|
||||
VectorCalculus: null
|
||||
DynamicalSystems: {
|
||||
FluidFlows: null
|
||||
Ecosystems: null
|
||||
ChaosTheory: null
|
||||
}
|
||||
ComplexAnalysis: null
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
value: AppiledMathematics
|
||||
next: {
|
||||
Physics: {
|
||||
TheoreticalPhysics: null
|
||||
}
|
||||
MathematicalChemistry: null
|
||||
Biomathematics: null
|
||||
Engineering : {
|
||||
ControlTheory: null
|
||||
}
|
||||
NumericalAnalysis: null
|
||||
GameTheory: null
|
||||
Economics: null
|
||||
Probability: null
|
||||
Statistics: null
|
||||
MathematicalFinance: null
|
||||
Optimization: null
|
||||
ComputerScience: {
|
||||
MachineLearning: null
|
||||
}
|
||||
Cryptography: null
|
||||
}
|
||||
}
|
||||
{
|
||||
value: Foundations
|
||||
next: {
|
||||
FundamentalRules: { GodelIncompletenessTheorems: null }
|
||||
MathematicalLogic: null
|
||||
SetTheory: null
|
||||
CategoryTheory: null
|
||||
TheoryOfComputation: null
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
113
dot_config/nushell/nu_scripts/modules/cwdhist/mod.nu
Normal file
113
dot_config/nushell/nu_scripts/modules/cwdhist/mod.nu
Normal file
@@ -0,0 +1,113 @@
|
||||
def __cwdhist_menu [] {
|
||||
{
|
||||
name: cwdhist_menu
|
||||
only_buffer_difference: true
|
||||
marker: "| "
|
||||
type: {
|
||||
layout: list
|
||||
page_size: 10
|
||||
}
|
||||
style: {
|
||||
text: green
|
||||
selected_text: green_reverse
|
||||
description_text: yellow
|
||||
}
|
||||
source: { |buffer, position|
|
||||
#$"[($position)]($buffer);(char newline)" | save -a ~/.cache/cwdhist.log
|
||||
let t = ($buffer | split row ' ' | last)
|
||||
if $env.cwd_history_full {
|
||||
open $nu.history-path | query db $"
|
||||
select cwd as value, count\(*) as cnt
|
||||
from history
|
||||
where cwd like '%($t)%'
|
||||
group by cwd
|
||||
order by cnt desc
|
||||
limit 50
|
||||
;"
|
||||
} else {
|
||||
open $env.cwd_history_file | query db $"
|
||||
select cwd as value, count
|
||||
from cwd_history
|
||||
where cwd like '%($t)%'
|
||||
order by count desc
|
||||
limit 50
|
||||
;"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def __cwdhist_keybinding [] {
|
||||
{
|
||||
name: cwdhist_menu
|
||||
modifier: alt
|
||||
keycode: char_o
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: [
|
||||
{ send: menu name: cwdhist_menu }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
def __cwdhist_switching [] {
|
||||
{
|
||||
name: cwdhist_switching
|
||||
modifier: shift_alt
|
||||
keycode: char_o
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: [
|
||||
{ send: ExecuteHostCommand, cmd: '$env.cwd_history_full = (not $env.cwd_history_full)' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
export def empty-sqlite [] {
|
||||
# sqlite3 empty.db "VACUUM;"; cat empty.db | gzip | encode base64
|
||||
'H4sIAAAAAAAAAwsO9MksSVVIyy/KTSxRMGYQYGBkZHBQUGBgYGCEYhhAZhMLGBn0ihbwglgCZOgeBaNgFIyCUTAKRsEoGAWjYBSMglEwCkYBVQAANHgbMAAQAAA='
|
||||
| decode base64 --binary | gzip -d
|
||||
}
|
||||
|
||||
export def 'cwd history delete' [cwd] {
|
||||
open $env.cwd_history_file
|
||||
| query db $"delete from cwd_history where cwd = '($cwd)';"
|
||||
}
|
||||
|
||||
export-env {
|
||||
$env.cwd_history_full = false
|
||||
$env.cwd_history_file = '~/.cache/nu_cwd_history.sqlite'
|
||||
|
||||
if not ($env.cwd_history_file | path exists) {
|
||||
empty-sqlite | save -f $env.cwd_history_file
|
||||
open $env.cwd_history_file | query db "create table if not exists cwd_history (
|
||||
cwd text primary key,
|
||||
count int default 1,
|
||||
recent datetime default (datetime('now', 'localtime'))
|
||||
);"
|
||||
}
|
||||
|
||||
let __cwdhist_hook = {|_, dir|
|
||||
if $dir == $nu.home-path { return }
|
||||
let suffix = (do --ignore-errors { $dir | path relative-to $nu.home-path })
|
||||
let path = if ($suffix | is-empty) {
|
||||
$dir
|
||||
} else {
|
||||
['~', $suffix] | path join
|
||||
}
|
||||
open $env.cwd_history_file
|
||||
| query db $"
|
||||
insert into cwd_history\(cwd)
|
||||
values \('($path)')
|
||||
on conflict\(cwd)
|
||||
do update set
|
||||
count = count + 1,
|
||||
recent = datetime\('now', 'localtime');"
|
||||
}
|
||||
|
||||
$env.config = ($env.config
|
||||
| update hooks.env_change.PWD ($env.config.hooks.env_change.PWD | append $__cwdhist_hook ))
|
||||
|
||||
$env.config = ($env.config
|
||||
| upsert menus ($env.config.menus | append (__cwdhist_menu))
|
||||
| upsert keybindings ($env.config.keybindings | append [(__cwdhist_keybinding) (__cwdhist_switching)])
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
# Function to extract archives with different extensions.
|
||||
export def extract [name:string] {
|
||||
let handlers = [ [extension command];
|
||||
['tar\.bz2|tbz|tbz2' 'tar xvjf']
|
||||
['tar\.gz|tgz' 'tar xvzf']
|
||||
['tar\.xz|txz' 'tar xvf']
|
||||
['tar\.Z' 'tar xvZf']
|
||||
['bz2' 'bunzip2']
|
||||
['deb' 'ar x']
|
||||
['gz' 'gunzip']
|
||||
['pkg' 'pkgutil --expand']
|
||||
['rar' 'unrar x']
|
||||
['tar' 'tar xvf']
|
||||
['xz' 'xz --decompress']
|
||||
['zip|war|jar|nupkg' 'unzip']
|
||||
['Z' 'uncompress']
|
||||
['7z' '7za x']
|
||||
]
|
||||
let maybe_handler = ($handlers | where $name =~ $'\.(($it.extension))$')
|
||||
if ($maybe_handler | is-empty) {
|
||||
error make { msg: "unsupported file extension" }
|
||||
} else {
|
||||
let handler = ($maybe_handler | first)
|
||||
nu -c ($handler.command + ' ' + $name)
|
||||
}
|
||||
}
|
||||
30
dot_config/nushell/nu_scripts/modules/docker/buildah.nu
Normal file
30
dot_config/nushell/nu_scripts/modules/docker/buildah.nu
Normal file
@@ -0,0 +1,30 @@
|
||||
export def "bud img" [] {
|
||||
buildah images
|
||||
| from ssv -a
|
||||
| rename repo tag id created size
|
||||
| upsert size { |i| $i.size | into filesize }
|
||||
}
|
||||
|
||||
export def "bud ls" [] {
|
||||
buildah list
|
||||
| from ssv -a
|
||||
| rename id builder image-id image container
|
||||
}
|
||||
|
||||
export def "bud ps" [] {
|
||||
buildah ps
|
||||
| from ssv -a
|
||||
| rename id builder image-id image container
|
||||
}
|
||||
|
||||
def "nu-complete bud ps" [] {
|
||||
bud ps
|
||||
| select 'CONTAINER ID' "CONTAINER NAME"
|
||||
| rename value description
|
||||
}
|
||||
|
||||
export def "bud rm" [
|
||||
id: string@"nu-complete bud ps"
|
||||
] {
|
||||
buildah rm $id
|
||||
}
|
||||
522
dot_config/nushell/nu_scripts/modules/docker/mod.nu
Normal file
522
dot_config/nushell/nu_scripts/modules/docker/mod.nu
Normal file
@@ -0,0 +1,522 @@
|
||||
export-env {
|
||||
for c in [nerdctl podman docker] {
|
||||
if (which $c | is-not-empty) {
|
||||
$env.docker-cli = $c
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def --wrapped container [...flag] {
|
||||
^$env.docker-cli ...$flag
|
||||
}
|
||||
|
||||
def --wrapped with-flag [...flag] {
|
||||
if ($in | is-empty) { [] } else { [...$flag $in] }
|
||||
}
|
||||
|
||||
def "nu-complete docker ns" [] {
|
||||
if $env.docker-cli == 'nerdctl' {
|
||||
^$env.docker-cli namespace list
|
||||
| from ssv -a
|
||||
| each {|x| { value: $x.NAMES }}
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
# list containers
|
||||
export def container-list [
|
||||
-n: string@"nu-complete docker ns"
|
||||
container?: string@"nu-complete docker containers"
|
||||
--all(-a)
|
||||
] {
|
||||
let cli = $env.docker-cli
|
||||
if ($container | is-empty) {
|
||||
let fmt = '{"id":"{{.ID}}", "image": "{{.Image}}", "name":"{{.Names}}", "cmd":{{.Command}}, "port":"{{.Ports}}", "status":"{{.Status}}", "created":"{{.CreatedAt}}"}'
|
||||
let fmt = if $cli == 'podman' { $fmt | str replace '{{.Command}}' '"{{.Command}}"' | str replace '{{.CreatedAt}}' '{{.Created}}' } else { $fmt }
|
||||
let all = if $all {[-a]} else {[]}
|
||||
^$cli ps ...$all --format $fmt
|
||||
| lines
|
||||
| each {|x|
|
||||
let r = $x | from json
|
||||
let t = $r.created | into datetime
|
||||
$r | upsert created $t
|
||||
}
|
||||
} else {
|
||||
let r = ^$cli ...($n | with-flag -n) inspect $container
|
||||
| from json
|
||||
| get 0
|
||||
let image = $r.Image
|
||||
let img = ^$cli ...($n | with-flag -n) inspect $image
|
||||
| from json
|
||||
| get 0
|
||||
let imgCmd = $img.Config.Cmd?
|
||||
let imgEnv = $img.Config.Env?
|
||||
| reduce -f {} {|i, a|
|
||||
let x = $i | split row '='
|
||||
$a | upsert $x.0 $x.1?
|
||||
}
|
||||
let m = $r.Mounts
|
||||
| reduce -f {} {|i, a|
|
||||
if $i.Type == 'bind' {
|
||||
$a | upsert $i.Source? $i.Destination?
|
||||
} else { $a }
|
||||
}
|
||||
let p = $r.NetworkSettings.Ports? | default {} | transpose k v
|
||||
| reduce -f {} {|i, a| $a | upsert $i.k $"($i.v.HostIp?.0?):($i.v.HostPort?.0?)"}
|
||||
{
|
||||
name: $r.Name?
|
||||
hostname: $r.Config.Hostname?
|
||||
id: $r.Id
|
||||
status: $r.State.Status?
|
||||
image: $image
|
||||
created: ($r.Created | into datetime)
|
||||
ports: $p
|
||||
env: $imgEnv
|
||||
mounts: $m
|
||||
entrypoint: $r.Path?
|
||||
cmd: $imgCmd
|
||||
args: $r.Args
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def parse-img [] {
|
||||
let n = $in | split row ':'
|
||||
let tag = $n.1? | default 'latest'
|
||||
let repo = $n.0 | split row '/'
|
||||
let image = $repo | last
|
||||
let repo = $repo | range 0..-2 | str join '/'
|
||||
{image: $image, tag: $tag, repo: $repo}
|
||||
}
|
||||
|
||||
# select image
|
||||
export def image-select [name] {
|
||||
let n = $name | parse-img
|
||||
let imgs = (image-list)
|
||||
let fs = [image tag repo]
|
||||
for i in 2..0 {
|
||||
let r = $imgs | filter {|x|
|
||||
$fs | range 0..$i | all {|y| ($n | get $y) == ($x | get $y) }
|
||||
}
|
||||
if ($r | is-not-empty) {
|
||||
return ($r | sort-by -r created | first | get name)
|
||||
}
|
||||
}
|
||||
$name
|
||||
}
|
||||
|
||||
# list images
|
||||
export def image-list [
|
||||
-n: string@"nu-complete docker ns"
|
||||
image?: string@"nu-complete docker images"
|
||||
] {
|
||||
if ($image | is-empty) {
|
||||
let fmt = '{"id":"{{.ID}}", "repo": "{{.Repository}}", "tag":"{{.Tag}}", "size":"{{.Size}}" "created":"{{.CreatedAt}}"}'
|
||||
^$env.docker-cli ...($n | with-flag -n) images --format $fmt
|
||||
| lines
|
||||
| each {|x|
|
||||
let x = $x | from json
|
||||
let img = $x.repo | parse-img
|
||||
{
|
||||
name: $"($x.repo):($x.tag)"
|
||||
id: $x.id
|
||||
created: ($x.created | into datetime)
|
||||
size: ($x.size | into filesize)
|
||||
repo: $img.repo
|
||||
image: $img.image
|
||||
tag: $x.tag
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let r = ^$env.docker-cli ...($n | with-flag -n) inspect $image
|
||||
| from json
|
||||
| get 0
|
||||
let e = $r.Config.Env?
|
||||
| reduce -f {} {|i, a|
|
||||
let x = $i | split row '='
|
||||
$a | upsert $x.0 $x.1?
|
||||
}
|
||||
let id = if $env.docker-cli == 'nerdctl' {
|
||||
$r.RepoDigests.0? | split row ':' | get 1 | str substring 0..12
|
||||
} else {
|
||||
$r.Id | str substring 0..12
|
||||
}
|
||||
{
|
||||
id: $id
|
||||
created: ($r.Created | into datetime)
|
||||
author: $r.Author
|
||||
arch: $r.Architecture
|
||||
os: $r.Os
|
||||
size: $r.Size
|
||||
labels: $r.Labels?
|
||||
user: $r.Config.User?
|
||||
env: $e
|
||||
entrypoint: $r.Config.Entrypoint?
|
||||
cmd: $r.Config.Cmd?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete docker ps" [] {
|
||||
^$env.docker-cli ps
|
||||
| from ssv -a
|
||||
| each {|x| {description: $x.NAMES value: $x.'CONTAINER ID'}}
|
||||
}
|
||||
|
||||
def "nu-complete docker containers" [] {
|
||||
^$env.docker-cli ps -a
|
||||
| from ssv -a
|
||||
| each {|i|
|
||||
let st = if ($i.STATUS | str starts-with 'Up') { ' ' } else { '!' }
|
||||
{ id: $i.'CONTAINER ID', name: $i.NAMES, status: $st }
|
||||
}
|
||||
| group-by name
|
||||
| transpose k v
|
||||
| each {|i|
|
||||
let s = ($i.v | length) == 1
|
||||
$i.v | each {|i|
|
||||
if $s {
|
||||
{value: $i.name, description: $"($i.status) ($i.id)"}
|
||||
} else {
|
||||
{value: $i.id, description: $"($i.status) ($i.name)"}
|
||||
}
|
||||
}
|
||||
}
|
||||
| flatten
|
||||
}
|
||||
|
||||
# TODO: filter by description
|
||||
def "nu-complete docker containers b" [] {
|
||||
^$env.docker-cli ps -a
|
||||
| from ssv -a
|
||||
| each {|i|
|
||||
let s = if ($i.STATUS | str starts-with 'Up') { ' ' } else { '!' }
|
||||
{ value: $i.'CONTAINER ID', description: $"($s) ($i.NAMES)" }
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete docker images" [] {
|
||||
^$env.docker-cli images
|
||||
| from ssv
|
||||
| each {|x| $"($x.REPOSITORY):($x.TAG)"}
|
||||
}
|
||||
|
||||
|
||||
# container log
|
||||
export def container-log [
|
||||
container: string@"nu-complete docker containers"
|
||||
-l: int = 100 # line
|
||||
-n: string@"nu-complete docker ns" # namespace
|
||||
] {
|
||||
let l = if $l == 0 { [] } else { [--tail $l] }
|
||||
^$env.docker-cli ...($n | with-flag -n) logs -f ...$l $container
|
||||
}
|
||||
|
||||
export def container-log-trunc [
|
||||
container: string@"nu-complete docker containers"
|
||||
-n: string@"nu-complete docker ns" # namespace
|
||||
] {
|
||||
if $env.docker-cli == 'podman' {
|
||||
print -e $'(ansi yellow)podman(ansi dark_gray) isn’t supported(ansi reset)'
|
||||
} else {
|
||||
let f = ^$env.docker-cli ...($n | with-flag -n) inspect --format='{{.LogPath}}' $container
|
||||
truncate -s 0 $f
|
||||
}
|
||||
}
|
||||
|
||||
# attach container
|
||||
export def --wrapped container-attach [
|
||||
container: string@"nu-complete docker containers"
|
||||
-n: string@"nu-complete docker ns"
|
||||
...args
|
||||
] {
|
||||
let ns = $n | with-flag -n
|
||||
if ($args|is-empty) {
|
||||
^$env.docker-cli ...$ns exec -it $container /bin/sh -c "[ -e /bin/zsh ] && /bin/zsh || [ -e /bin/bash ] && /bin/bash || /bin/sh"
|
||||
} else {
|
||||
^$env.docker-cli ...$ns exec -it $container ...$args
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete docker cp" [cmd: string, offset: int] {
|
||||
let argv = $cmd | str substring ..$offset | split row ' '
|
||||
let p = if ($argv | length) > 2 { $argv | get 2 } else { $argv | get 1 }
|
||||
let container = ^$env.docker-cli ps
|
||||
| from ssv -a
|
||||
| each {|x| {description: $x.'CONTAINER ID' value: $"($x.NAMES):" }}
|
||||
let n = $p | split row ':'
|
||||
if $"($n | get 0):" in ($container | get value) {
|
||||
^$env.docker-cli exec ($n | get 0) sh -c $"ls -dp ($n | get 1)*"
|
||||
| lines
|
||||
| each {|x| $"($n | get 0):($x)"}
|
||||
} else {
|
||||
let files = do -i {
|
||||
ls -a ($"($p)*" | into glob)
|
||||
| each {|x| if $x.type == dir { $"($x.name)/"} else { $x.name }}
|
||||
}
|
||||
$files | append $container
|
||||
}
|
||||
}
|
||||
|
||||
# copy file
|
||||
export def container-copy-file [
|
||||
lhs: string@"nu-complete docker cp",
|
||||
rhs: string@"nu-complete docker cp"
|
||||
] {
|
||||
^$env.docker-cli cp $lhs $rhs
|
||||
}
|
||||
|
||||
# remove container
|
||||
export def container-remove [container: string@"nu-complete docker containers" -n: string@"nu-complete docker ns"] {
|
||||
let cs = ^$env.docker-cli ...($n | with-flag -n) ps -a | from ssv -a | get NAMES
|
||||
if $container in $cs {
|
||||
^$env.docker-cli ...($n | with-flag -n) container rm -f $container
|
||||
} else {
|
||||
print -e $"(ansi grey)container (ansi yellow)($container)(ansi grey) not exist(ansi reset)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# history
|
||||
export def container-history [image: string@"nu-complete docker images" -n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) history --no-trunc $image | from ssv -a
|
||||
}
|
||||
|
||||
|
||||
# save images
|
||||
export def image-save [-n: string@"nu-complete docker ns" ...image: string@"nu-complete docker images"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) save ...$image
|
||||
}
|
||||
|
||||
# load images
|
||||
export def image-load [-n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) load
|
||||
}
|
||||
|
||||
# system prune
|
||||
export def system-prune [-n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) system prune -f
|
||||
}
|
||||
|
||||
# system prune all
|
||||
export def system-prune-all [-n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) system prune --all --force --volumes
|
||||
}
|
||||
|
||||
# remove image
|
||||
export def image-remove [image: string@"nu-complete docker images" -n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) rmi $image
|
||||
}
|
||||
|
||||
# add new tag
|
||||
export def image-tag [from: string@"nu-complete docker images" to: string -n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) tag $from $to
|
||||
}
|
||||
|
||||
# push image
|
||||
export def image-push [
|
||||
image: string@"nu-complete docker images"
|
||||
--tag(-t): string
|
||||
-n: string@"nu-complete docker ns" -i
|
||||
] {
|
||||
let $insecure = if $i {[--insecure-registry]} else {[]}
|
||||
if ($tag | is-empty) {
|
||||
^$env.docker-cli ...($n | with-flag -n) ...$insecure push $image
|
||||
} else {
|
||||
^$env.docker-cli ...($n | with-flag -n) tag $image $tag
|
||||
do -i {
|
||||
^$env.docker-cli ...($n | with-flag -n) ...$insecure push $tag
|
||||
}
|
||||
^$env.docker-cli ...($n | with-flag -n) rmi $tag
|
||||
}
|
||||
}
|
||||
|
||||
# pull image
|
||||
export def image-pull [image -n: string@"nu-complete docker ns" -i] {
|
||||
let $insecure = if $i {[--insecure-registry]} else {[]}
|
||||
^$env.docker-cli ...($n | with-flag -n) ...$insecure pull $image
|
||||
}
|
||||
|
||||
### list volume
|
||||
export def volume-list [-n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) volume ls | from ssv -a
|
||||
}
|
||||
|
||||
def "nu-complete docker volume" [] {
|
||||
^$env.docker-cli volume ls
|
||||
| from ssv -a
|
||||
| get 'VOLUME NAME'
|
||||
}
|
||||
|
||||
# create volume
|
||||
export def volume-create [name: string -n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) volume create $name
|
||||
}
|
||||
|
||||
# inspect volume
|
||||
export def volume-inspect [name: string@"nu-complete docker volume" -n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) volume inspect $name
|
||||
}
|
||||
|
||||
# remove volume
|
||||
export def volume-remove [...name: string@"nu-complete docker volume" -n: string@"nu-complete docker ns"] {
|
||||
^$env.docker-cli ...($n | with-flag -n) volume rm ...$name
|
||||
}
|
||||
|
||||
# dump volume
|
||||
export def volume-dump [
|
||||
name: string@"nu-complete docker volume"
|
||||
--image(-i): string='debian'
|
||||
-n: string@"nu-complete docker ns"
|
||||
] {
|
||||
let id = random chars -l 6
|
||||
^$env.docker-cli ...($n | with-flag -n) ...[
|
||||
run --rm
|
||||
-v $"($name):/tmp/($id)"
|
||||
$image
|
||||
sh -c $'cd /tmp/($id); tar -zcf - *'
|
||||
]
|
||||
}
|
||||
|
||||
# restore volume
|
||||
export def volume-restore [
|
||||
name: string@"nu-complete docker volume"
|
||||
--from(-f): string
|
||||
--image(-i): string='debian'
|
||||
-n: string@"nu-complete docker ns"
|
||||
] {
|
||||
let id = random chars -l 6
|
||||
let src = random chars -l 6
|
||||
^$env.docker-cli ...($n | with-flag -n) ...[
|
||||
run --rm
|
||||
-v $"($name):/tmp/($id)"
|
||||
-v $"(host-path $from):/tmp/($src)"
|
||||
$image
|
||||
sh -c $'cd /tmp/($id); tar -zxf /tmp/($src)'
|
||||
]
|
||||
}
|
||||
|
||||
### run
|
||||
def "nu-complete docker run vol" [] {
|
||||
[
|
||||
$"($env.PWD):/world"
|
||||
$"($env.PWD):/app"
|
||||
$"($env.PWD):/srv"
|
||||
$"($env.HOME)/.config/nvim:/etc/nvim"
|
||||
]
|
||||
}
|
||||
|
||||
def "nu-complete docker run sshkey" [ctx: string, pos: int] {
|
||||
(do { cd ~/.ssh; ls **/*.pub } | get name)
|
||||
}
|
||||
|
||||
def "nu-complete docker run proxy" [] {
|
||||
let hostaddr = do -i { hostname -I | split row ' ' | get 0 }
|
||||
[ $"http://($hostaddr):7890" $"http://($hostaddr):" ]
|
||||
}
|
||||
|
||||
def host-path [path] {
|
||||
match ($path | str substring ..1) {
|
||||
'/' => { $path }
|
||||
'=' => { $path | str substring 1.. }
|
||||
'~' => { [ $env.HOME ($path | str substring 2..) ] | path join }
|
||||
'$' => { $env | get ($path | str substring 1..) }
|
||||
_ => { [ $env.PWD $path ] | path join }
|
||||
}
|
||||
}
|
||||
|
||||
# run
|
||||
export def container-create [
|
||||
--debug(-x)
|
||||
--appimage
|
||||
--netadmin
|
||||
--proxy: string@"nu-complete docker run proxy" # proxy
|
||||
--ssh(-s): string@"nu-complete docker run sshkey" # specify ssh key
|
||||
--sshuser: string=root # default root
|
||||
--cache(-c): string # cache
|
||||
--mnt(-m): string@"nu-complete docker run vol" # mnt
|
||||
--vols(-v): any # { host: container }
|
||||
--ports(-p): any # { 8080: 80 }
|
||||
--envs(-e): any # { FOO: BAR }
|
||||
--daemon(-d)
|
||||
--attach(-a): string@"nu-complete docker containers" # attach
|
||||
--workdir(-w): string # workdir
|
||||
--entrypoint: string # entrypoint
|
||||
--dry-run
|
||||
--with-x
|
||||
--privileged(-P)
|
||||
--namespace(-n): string@"nu-complete docker ns"
|
||||
image: string@"nu-complete docker images" # image
|
||||
...cmd # command args
|
||||
] {
|
||||
let ns = $namespace | with-flag -n
|
||||
let entrypoint = $entrypoint | with-flag --entrypoint
|
||||
let daemon = if $daemon { [-d] } else { [--rm -it] }
|
||||
let mnt = $mnt | with-flag -v
|
||||
let workdir = if ($workdir | is-empty) {[]} else {[-w $workdir -v $"($env.PWD):($workdir)"]}
|
||||
let vols = if ($vols|is-empty) { [] } else { $vols | transpose k v | each {|x| [-v $"(host-path $x.k):($x.v)"]} | flatten }
|
||||
let envs = if ($envs|is-empty) { [] } else { $envs | transpose k v | each {|x| [-e $"($x.k)=($x.v)"]} | flatten }
|
||||
let ports = if ($ports|is-empty) { [] } else { $ports | transpose k v | each {|x| [-p $"($x.k):($x.v)"] } | flatten }
|
||||
let debug = if $debug {[--cap-add=SYS_ADMIN --cap-add=SYS_PTRACE --security-opt seccomp=unconfined]} else {[]}
|
||||
#let appimage = if $appimage {[--device /dev/fuse --security-opt apparmor:unconfined]} else {[]}
|
||||
let privileged = if $privileged {[--privileged]} else {[]}
|
||||
let appimage = if $appimage {[--device /dev/fuse]} else {[]}
|
||||
let netadmin = if $netadmin {[--cap-add=NET_ADMIN --device /dev/net/tun]} else {[]}
|
||||
let with_x = if $with_x {[
|
||||
-e $"DISPLAY=($env.DISPLAY)"
|
||||
-v /tmp/.X11-unix:/tmp/.X11-unix
|
||||
]} else {[]}
|
||||
let ssh = if ($ssh|is-empty) { [] } else {
|
||||
let sshkey = cat ([$env.HOME .ssh $ssh] | path join) | split row ' ' | get 1
|
||||
[-e $"ed25519_($sshuser)=($sshkey)"]
|
||||
}
|
||||
let proxy = if ($proxy|is-empty) { [] } else {
|
||||
[-e $"http_proxy=($proxy)" -e $"https_proxy=($proxy)"]
|
||||
}
|
||||
let attach = if ($attach|is-empty) { [] } else {
|
||||
let c = $"container:($attach)"
|
||||
[--uts $c --ipc $c --pid $c --network $c]
|
||||
}
|
||||
let cache = $cache | with-flag -v
|
||||
let args = [
|
||||
$privileged $entrypoint $attach $daemon
|
||||
$ports $envs $ssh $proxy
|
||||
$debug $appimage $netadmin $with_x
|
||||
$mnt $vols $workdir $cache
|
||||
] | flatten
|
||||
let name = $"($image | split row '/' | last | str replace ':' '-')_(date now | format date %m%d%H%M)"
|
||||
if $dry_run {
|
||||
echo ([docker $ns run --name $name $args $image $cmd] | flatten | str join ' ')
|
||||
} else {
|
||||
^$env.docker-cli ...$ns run --name $name ...$args $image ...($cmd | flatten)
|
||||
}
|
||||
}
|
||||
|
||||
export alias d = container
|
||||
export alias dp = container-list
|
||||
export alias di = image-list
|
||||
export alias dl = container-log
|
||||
export alias dlt = container-log-trunc
|
||||
export alias da = container-attach
|
||||
export alias dcp = container-copy-file
|
||||
export alias dcr = container-remove
|
||||
export alias dh = container-history
|
||||
export alias dsv = image-save
|
||||
export alias dld = image-load
|
||||
export alias dsp = system-prune
|
||||
export alias dspall = system-prune-all
|
||||
export alias drmi = image-remove
|
||||
export alias dt = image-tag
|
||||
export alias dps = image-push
|
||||
export alias dpl = image-pull
|
||||
export alias dvl = volume-list
|
||||
export alias dvc = volume-create
|
||||
export alias dvi = volume-inspect
|
||||
export alias dvr = volume-remove
|
||||
export alias dr = container-create
|
||||
|
||||
export use registry.nu *
|
||||
export use buildah.nu *
|
||||
|
||||
68
dot_config/nushell/nu_scripts/modules/docker/registry.nu
Normal file
68
dot_config/nushell/nu_scripts/modules/docker/registry.nu
Normal file
@@ -0,0 +1,68 @@
|
||||
def "nu-complete registry show" [cmd: string, offset: int] {
|
||||
let new = $cmd | str ends-with ' '
|
||||
let cmd = $cmd | split row ' '
|
||||
let url = $cmd.3?
|
||||
let reg = $cmd.4?
|
||||
let tag = $cmd.5?
|
||||
let auth = if ($env.REGISTRY_TOKEN? | is-not-empty) {
|
||||
[-H $"Authorization: Basic ($env.REGISTRY_TOKEN)"]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
if ($tag | is-empty) and (not $new) or ($reg | is-empty) {
|
||||
curl -sSL ...$auth $"($url)/v2/_catalog"
|
||||
| from json | get repositories
|
||||
} else {
|
||||
curl -sSL ...$auth $"($url)/v2/($reg)/tags/list"
|
||||
| from json | get tags
|
||||
}
|
||||
}
|
||||
|
||||
### docker registry show
|
||||
export def "docker registry show" [
|
||||
url: string
|
||||
reg?: string@"nu-complete registry show"
|
||||
tag?: string@"nu-complete registry show"
|
||||
] {
|
||||
let header = if ($env.REGISTRY_TOKEN? | is-not-empty) {
|
||||
[-H $"Authorization: Basic ($env.REGISTRY_TOKEN)"]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
| append [-H 'Accept: application/vnd.oci.image.manifest.v1+json']
|
||||
if ($reg | is-empty) {
|
||||
curl -sSL ...$header $"($url)/v2/_catalog" | from json | get repositories
|
||||
} else if ($tag | is-empty) {
|
||||
curl -sSL ...$header $"($url)/v2/($reg)/tags/list" | from json | get tags
|
||||
} else {
|
||||
curl -sSL ...$header $"($url)/v2/($reg)/manifests/($tag)" | from json
|
||||
}
|
||||
}
|
||||
|
||||
### docker registry delete
|
||||
export def "docker registry delete" [
|
||||
url: string
|
||||
reg: string@"nu-complete registry show"
|
||||
tag: string@"nu-complete registry show"
|
||||
] {
|
||||
let header = if ($env.REGISTRY_TOKEN? | is-not-empty) {
|
||||
[-H $"Authorization: Basic ($env.REGISTRY_TOKEN)"]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
| append [-H 'Accept: application/vnd.oci.image.manifest.v1+json']
|
||||
#| append [-H 'Accept: application/vnd.docker.distribution.manifest.v2+json']
|
||||
let digest = do -i {
|
||||
curl -sSI ...$header $"($url)/v2/($reg)/manifests/($tag)"
|
||||
| rg docker-content-digest
|
||||
| split row ' '
|
||||
| get 1
|
||||
| str trim
|
||||
}
|
||||
print -e $digest
|
||||
if ($digest | is-not-empty) {
|
||||
curl -sSL -X DELETE ...$header $"($url)/v2/($reg)/manifests/($digest)"
|
||||
} else {
|
||||
'not found'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Duplicates Scripts
|
||||
|
||||
### Definition
|
||||
|
||||
These scripts are used to show how `group-by` can be used to identify duplicate rows. The example shows how that can be used to heuristically find duplicate files.
|
||||
15
dot_config/nushell/nu_scripts/modules/duplicates/example.nu
Normal file
15
dot_config/nushell/nu_scripts/modules/duplicates/example.nu
Normal file
@@ -0,0 +1,15 @@
|
||||
# duplicates example
|
||||
use mod.nu *
|
||||
|
||||
let info = "[{name: "John", lastname: "Doe"}, {name: "John", lastname: "Roe"}, {name: "Jane", lastname: "Soe"}]"
|
||||
print ($info | from json)
|
||||
print ($info | from json | duplicates name)
|
||||
|
||||
#duplicates files example
|
||||
echo A | save A.txt
|
||||
echo A | save B.txt
|
||||
# note that if I used "echo B | save B.txt" the function will give a false positive
|
||||
echo ABC | save C.txt
|
||||
print (ls)
|
||||
print (duplicates files)
|
||||
rm A.txt B.txt C.txt --permanent
|
||||
22
dot_config/nushell/nu_scripts/modules/duplicates/mod.nu
Normal file
22
dot_config/nushell/nu_scripts/modules/duplicates/mod.nu
Normal file
@@ -0,0 +1,22 @@
|
||||
# duplicates returns the rows that correspond to duplicates of the given column.
|
||||
export def duplicates [
|
||||
column: string # Column to look duplicates at
|
||||
--count(-c) # set it to display the number of times the value is repeated.
|
||||
] {
|
||||
group-by {get $column | into string} |
|
||||
transpose |
|
||||
insert count { $in.column1 | flatten | length } |
|
||||
where count > 1 |
|
||||
reject column0 |
|
||||
if ($count | is-empty) { reject count } else { each { $in } } |
|
||||
flatten |
|
||||
flatten
|
||||
}
|
||||
|
||||
# duplicates files recursively finds duplicate files in the current working folder.
|
||||
# It uses a heuristic based on duplicate files having the same size.
|
||||
export def "duplicates files" [] {
|
||||
do -i {ls **/*} | duplicates size
|
||||
}
|
||||
|
||||
|
||||
127
dot_config/nushell/nu_scripts/modules/filesystem/bm.nu
Normal file
127
dot_config/nushell/nu_scripts/modules/filesystem/bm.nu
Normal file
@@ -0,0 +1,127 @@
|
||||
# simple bookmark module
|
||||
|
||||
# Prints general information about bm.
|
||||
export def main [] {
|
||||
print -n (help bm)
|
||||
|
||||
print (
|
||||
[
|
||||
$"(ansi green)Environment(ansi reset):"
|
||||
$" (ansi cyan)BM_PATH(ansi reset) - path to save bookmarks to with ('add' | nu-highlight). Alternatively searches for (ansi cyan)XDG_DATA_HOME(ansi reset) or (ansi cyan)~/.local/share/(ansi reset)"
|
||||
] |
|
||||
str join "\n" |
|
||||
nu-highlight
|
||||
)
|
||||
}
|
||||
|
||||
# List all bookmarked paths
|
||||
export def list [] {
|
||||
let bm_path = (get_path)
|
||||
|
||||
if (not ($bm_path | path exists)) {
|
||||
[] | save $bm_path
|
||||
}
|
||||
open ($bm_path)
|
||||
}
|
||||
|
||||
def os_home [] {
|
||||
if ($nu.os-info.name == "windows" ) {
|
||||
($env.USERPROFILE)
|
||||
} else {
|
||||
($env.HOME)
|
||||
}
|
||||
}
|
||||
|
||||
def get_path [] {
|
||||
$env.BM_PATH? |
|
||||
default (
|
||||
$env.XDG_DATA_HOME? |
|
||||
default (
|
||||
if $nu.os-info.name == windows {
|
||||
($env.USERPROFILE? | path join "bm")
|
||||
} else {
|
||||
($env.HOME? | path join ".local" "share")
|
||||
}
|
||||
)
|
||||
) |
|
||||
if (not ($in | path exists)) {
|
||||
mkdir $in
|
||||
$in
|
||||
} else {
|
||||
$in
|
||||
}|
|
||||
path join "bookmarks.nuon"
|
||||
}
|
||||
|
||||
def save_path [] {
|
||||
$in |
|
||||
update path { str replace (os_home) '~' } |
|
||||
save -f (get_path)
|
||||
}
|
||||
|
||||
# Reset the bookmarks
|
||||
export def reset [] {
|
||||
list |
|
||||
where name == "prev" |
|
||||
save -f (get_path)
|
||||
}
|
||||
|
||||
# Add a new bookmark with an optional name
|
||||
export def add [
|
||||
pth: path # Path to bookmark to.
|
||||
name?: string # Optional name to give to it
|
||||
] {
|
||||
if (($pth | path type) == "dir") and ($pth | path exists) {
|
||||
list |
|
||||
append {name: ($name), path: ($pth)} |
|
||||
save_path
|
||||
}
|
||||
}
|
||||
|
||||
# remove one or more bookmarks
|
||||
export def remove [] {
|
||||
let rm_these = (
|
||||
list |
|
||||
where name != "prev" |
|
||||
input list -m
|
||||
)
|
||||
|
||||
list | where {|it|
|
||||
not $it in $rm_these
|
||||
} |
|
||||
print
|
||||
|
||||
}
|
||||
|
||||
def marks [] {
|
||||
list | each {|it|
|
||||
{
|
||||
value: $it.path,
|
||||
description: $it.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Goto your bookmark
|
||||
export def --env goto [
|
||||
pth: path@marks # Path to "go to"
|
||||
] {
|
||||
let prev = $env.PWD
|
||||
cd $pth
|
||||
change_prev $prev
|
||||
}
|
||||
|
||||
# Experimental use of `input` instead of completion
|
||||
export def --env goto_alternative [] {
|
||||
let prev = $env.PWD
|
||||
list | input list -f | cd $in.path
|
||||
change_prev $prev
|
||||
}
|
||||
|
||||
def change_prev [new_path: path] {
|
||||
( list |
|
||||
where name != "prev"
|
||||
) |
|
||||
append {name: prev, path: $new_path} |
|
||||
save_path
|
||||
}
|
||||
64
dot_config/nushell/nu_scripts/modules/filesystem/expand.nu
Normal file
64
dot_config/nushell/nu_scripts/modules/filesystem/expand.nu
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
# A bash like quick string manipulation script
|
||||
# the script works by creating a list from brace contents, separated by a brace.
|
||||
|
||||
# Expand the given string into a list on braces like bashes brace expansion
|
||||
export def main [
|
||||
input: string # the string to expand.
|
||||
] {
|
||||
listify $input
|
||||
}
|
||||
|
||||
def listify [lst] {
|
||||
try {
|
||||
($lst
|
||||
| parse -r '(?P<left>.*)(?<!\\){(?P<list>.*)(?<!\\)}(?P<right>.*)'
|
||||
| get 0
|
||||
| upsert list { |l|
|
||||
$l.list
|
||||
| split row ","
|
||||
| str trim
|
||||
}
|
||||
| each { |it|
|
||||
$it.list
|
||||
| each { |l|
|
||||
listify $"($it.left)($l)($it.right)"
|
||||
}})
|
||||
| flatten
|
||||
} catch {
|
||||
$lst
|
||||
}
|
||||
}
|
||||
|
||||
export def help [] {
|
||||
print -n ( main -h )
|
||||
|
||||
print (
|
||||
[
|
||||
$"(ansi green)Examples(ansi reset):"
|
||||
$" > (ansi light_green)expand (ansi green)a/{b,c}/d(ansi reset)"
|
||||
$"╭───┬───────╮\n│ 0 │ a/b/d │\n│ 1 │ a/c/d │\n╰───┴───────╯"
|
||||
$" > (ansi light_green)expand (ansi green)\"my {beautiful,ugly} duckling\"(ansi reset)"
|
||||
$"╭───┬────────────────────────╮\n│ 0 │ my beautiful duckling │\n│ 1 │ my ugly duckling │\n╰───┴────────────────────────╯"
|
||||
$" > (ansi light_green)expand (ansi green).config/nushell/config.nu{,on}(ansi reset)"
|
||||
$"╭───┬─────────────────────────────╮\n│ 0 │ .config/nushell/config.nu │\n│ 1 │ .config/nushell/config.nuon │\n╰───┴─────────────────────────────╯"
|
||||
$" > (ansi light_green)expand (ansi green)a/{b,c}/{d,e,f,g} (ansi reset)(ansi purple)|(ansi reset)(ansi light_green) each(ansi reset) (ansi light_green){ |d| (ansi reset)(ansi light_green) mkdir(ansi reset) (ansi purple)$d (ansi reset)(ansi light_green)}(ansi reset);(ansi light_green)tree(ansi reset)"
|
||||
$".
|
||||
`-- a
|
||||
|-- b
|
||||
| |-- d
|
||||
| |-- e
|
||||
| |-- f
|
||||
| `-- g
|
||||
`-- c
|
||||
|-- d
|
||||
|-- e
|
||||
|-- f
|
||||
`-- g
|
||||
|
||||
12 directories, 0 files"
|
||||
] |
|
||||
str join "\n" |
|
||||
nu-highlight
|
||||
)
|
||||
}
|
||||
15
dot_config/nushell/nu_scripts/modules/fnm/README.md
Normal file
15
dot_config/nushell/nu_scripts/modules/fnm/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Fast Node Manager (fnm)
|
||||
|
||||
Enables Nushell support for [Fast Node Manager (fnm)](https://github.com/Schniz/fnm), a fast and simple Node.js version manager. Based on [this GitHub issue](https://github.com/Schniz/fnm/issues/463) and [fnm-nushell](https://github.com/Southclaws/fnm-nushell).
|
||||
|
||||
Requires `fnm` to be installed separately.
|
||||
|
||||
## Install
|
||||
|
||||
Clone this repo or copy the `fnm.nu` file wherever your prefer to keep your Nushell scripts.
|
||||
|
||||
Edit your Nushell config file (`$nu.config-path`) and add the line:
|
||||
|
||||
```nu
|
||||
use /path/to/fnm.nu
|
||||
```
|
||||
39
dot_config/nushell/nu_scripts/modules/fnm/fnm.nu
Normal file
39
dot_config/nushell/nu_scripts/modules/fnm/fnm.nu
Normal file
@@ -0,0 +1,39 @@
|
||||
export-env {
|
||||
def fnm-env [] {
|
||||
mut env_vars = {}
|
||||
let pwsh_vars = (
|
||||
^fnm env --shell power-shell |
|
||||
lines |
|
||||
parse "$env:{key} = \"{value}\""
|
||||
)
|
||||
|
||||
# fnm-prefixed vars
|
||||
for v in ($pwsh_vars | range 1..) {
|
||||
$env_vars = ($env_vars | insert $v.key $v.value)
|
||||
}
|
||||
|
||||
# path
|
||||
let env_used_path = ($env | columns | where {str downcase | $in == "path"} | get 0)
|
||||
let path_value = ($pwsh_vars | get 0.value | split row (char esep))
|
||||
$env_vars = ($env_vars | insert $env_used_path $path_value)
|
||||
|
||||
return $env_vars
|
||||
}
|
||||
|
||||
if not (which fnm | is-empty) {
|
||||
fnm-env | load-env
|
||||
|
||||
if (not ($env | default false __fnm_hooked | get __fnm_hooked)) {
|
||||
$env.__fnm_hooked = true
|
||||
$env.config = ($env | default {} config).config
|
||||
$env.config = ($env.config | default {} hooks)
|
||||
$env.config = ($env.config | update hooks ($env.config.hooks | default {} env_change))
|
||||
$env.config = ($env.config | update hooks.env_change ($env.config.hooks.env_change | default [] PWD))
|
||||
$env.config = ($env.config | update hooks.env_change.PWD ($env.config.hooks.env_change.PWD | append { |before, after|
|
||||
if ('FNM_DIR' in $env) and ([.nvmrc .node-version] | path exists | any { |it| $it }) {
|
||||
(^fnm use); (fnm-env | load-env)
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
5
dot_config/nushell/nu_scripts/modules/formats/README.md
Normal file
5
dot_config/nushell/nu_scripts/modules/formats/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Formatting scripts
|
||||
|
||||
### Definition
|
||||
|
||||
The scripts in this folder are used to help formatting nicely inputs/outputs of nushell.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Convert from contents of /proc/cpuinfo to structured data
|
||||
export def "from cpuinfo" [] {
|
||||
lines
|
||||
| split list ''
|
||||
| each {
|
||||
split column ':'
|
||||
| str trim
|
||||
| update column1 {
|
||||
get column1
|
||||
| str replace -a ' ' '_'
|
||||
}
|
||||
| transpose -r -d
|
||||
| update flags {
|
||||
get flags
|
||||
| split row ' '
|
||||
}
|
||||
| update bugs {
|
||||
get bugs
|
||||
| split row ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Convert from output of dmidecode to structured data
|
||||
export def "from dmidecode" [] {
|
||||
lines
|
||||
| skip until {|x|
|
||||
$x starts-with 'Handle'
|
||||
}
|
||||
| split list ''
|
||||
| each {|entry|
|
||||
let parsed_entry = (
|
||||
$entry
|
||||
| get 0
|
||||
| parse 'Handle {handle}, DMI type {type}, {bytes} bytes'
|
||||
| get 0
|
||||
| insert description ($entry|get 1)
|
||||
| insert values {
|
||||
if ($entry|length) > 2 {
|
||||
if ($entry|get 2|str trim) == 'Header and Data:' {
|
||||
{'header_and_data': ($entry|skip 3|str trim)}
|
||||
} else {
|
||||
$entry
|
||||
| skip 2
|
||||
| split column ':'
|
||||
| str trim
|
||||
| str downcase column1
|
||||
| str replace -a ' ' '_' column1
|
||||
| transpose -r -d
|
||||
}
|
||||
} else {
|
||||
{}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
$parsed_entry
|
||||
}
|
||||
}
|
||||
11
dot_config/nushell/nu_scripts/modules/formats/from-env.nu
Normal file
11
dot_config/nushell/nu_scripts/modules/formats/from-env.nu
Normal file
@@ -0,0 +1,11 @@
|
||||
# Converts a .env file into a record
|
||||
# may be used like this: open .env | load-env
|
||||
# works with quoted and unquoted .env files
|
||||
def "from env" []: string -> record {
|
||||
lines
|
||||
| split column '#' # remove comments
|
||||
| get column1
|
||||
| parse "{key}={value}"
|
||||
| str trim value -c '"' # unquote values
|
||||
| transpose -r -d
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#diacritics map for Polish but the function is universal provided diacritics_map contains mappings for specific language
|
||||
|
||||
# Usage: (remove-diacritics 'Zażółć gęślą jaźń') == Zazolc gesla jazn
|
||||
|
||||
export def main [
|
||||
arg: string
|
||||
] {
|
||||
let diacritics_map = {
|
||||
# Polish
|
||||
"Ą": "A",
|
||||
"ą": "a",
|
||||
"Ć": "C",
|
||||
"ć": "c",
|
||||
"Ę": "E",
|
||||
"ę": "e",
|
||||
"Ł": "L",
|
||||
"ł": "l",
|
||||
"Ń": "N",
|
||||
"ń": "n",
|
||||
"Ó": "O",
|
||||
"ó": "o",
|
||||
"Ś": "S",
|
||||
"ś": "s",
|
||||
"Ż": "Z",
|
||||
"ż": "z",
|
||||
"Ź": "Z",
|
||||
"ź": "z",
|
||||
# German
|
||||
"ä": "ae",
|
||||
"Ä": "Ae",
|
||||
"ö": "oe",
|
||||
"Ö": "Oe",
|
||||
"ü": "ue",
|
||||
"Ü": "Ue",
|
||||
"ß": "ss"
|
||||
}
|
||||
$arg
|
||||
|split chars
|
||||
|each {|char|
|
||||
$diacritics_map
|
||||
|get -i -s $char
|
||||
|default $char
|
||||
}
|
||||
|str join ''
|
||||
}
|
||||
13
dot_config/nushell/nu_scripts/modules/formats/to-ini.nu
Normal file
13
dot_config/nushell/nu_scripts/modules/formats/to-ini.nu
Normal file
@@ -0,0 +1,13 @@
|
||||
# converts records into .ini files
|
||||
export def "to ini" [] {
|
||||
transpose key value
|
||||
| update value {|row|
|
||||
$row.value
|
||||
| transpose key value
|
||||
| format pattern "{key}={value}"
|
||||
| prepend $"[($row.key)]"
|
||||
| str join (char nl)
|
||||
}
|
||||
| get value
|
||||
| str join (char nl)
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
export def number-format [
|
||||
num # Number to format
|
||||
--thousands_delim (-t) = ' ' # Thousands delimiter: number-format 1000 -t ': 1'000
|
||||
--whole_part_length (-w) = 0 # Length of padding whole-part digits: number-format 123 -w 6: 123
|
||||
--decimal_digits (-d) = 0 # Number of digits after decimal delimiter: number-format 1000.1234 -d 2: 1000.12
|
||||
--denom (-D) = "" # Denom `--denom "Wt": number-format 1000 --denom 'Wt': 1000Wt
|
||||
] {
|
||||
|
||||
let parts = (
|
||||
$num
|
||||
| into string
|
||||
| split row "."
|
||||
)
|
||||
|
||||
let whole_part = (
|
||||
$parts.0
|
||||
| split chars
|
||||
| reverse
|
||||
| reduce -f [] {
|
||||
|it, acc| if ((($it.index + 1) mod 3) == 0) {
|
||||
$acc.item
|
||||
| append $it.item
|
||||
| append $thousands_delim
|
||||
} else {
|
||||
$acc.item
|
||||
| append $it.item
|
||||
}
|
||||
}
|
||||
| reverse
|
||||
)
|
||||
|
||||
let whole_part2 = (
|
||||
if ($whole_part | first) == $thousands_delim {
|
||||
($whole_part | skip 1)
|
||||
} else {
|
||||
$whole_part
|
||||
}
|
||||
| str join ''
|
||||
)
|
||||
|
||||
let whole_part3 = (
|
||||
if $whole_part_length == 0 {
|
||||
$whole_part2
|
||||
} else {
|
||||
$whole_part2
|
||||
| fill -w $whole_part_length -c ' ' -a r
|
||||
}
|
||||
)
|
||||
|
||||
let dec_part = (
|
||||
if ($parts | length) == 1 {
|
||||
"0"
|
||||
} else {
|
||||
$parts.1
|
||||
}
|
||||
)
|
||||
|
||||
let dec_part2 = (
|
||||
if $decimal_digits == 0 {
|
||||
""
|
||||
} else {
|
||||
$".($dec_part)" | fill -w ($decimal_digits + 1) -c '0' -a l
|
||||
}
|
||||
)
|
||||
|
||||
let out = $"(ansi green)($whole_part3)($dec_part2)(ansi reset)(ansi green_bold)($denom)(ansi reset)"
|
||||
$out
|
||||
}
|
||||
75
dot_config/nushell/nu_scripts/modules/fun/life.nu
Normal file
75
dot_config/nushell/nu_scripts/modules/fun/life.nu
Normal file
@@ -0,0 +1,75 @@
|
||||
def alive [x_pos: int, y_pos: int, $grid] {
|
||||
let width = ($grid | get width)
|
||||
let height = ($grid | get height)
|
||||
let data = ($grid | get data)
|
||||
|
||||
let $left_x = (if $x_pos == 0 { $width - 1} else { $x_pos - 1})
|
||||
let $right_x = (if $x_pos == ($width - 1) { 0 } else { $x_pos + 1})
|
||||
let $up_y = (if $y_pos == 0 { $height - 1} else { $y_pos - 1})
|
||||
let $down_y = (if $y_pos == ($height - 1) { 0 } else { $y_pos + 1})
|
||||
let $n = ($data | get ($x_pos + $up_y * $width) | into int)
|
||||
let $nw = ($data | get ($left_x + $up_y * $width) | into int)
|
||||
let $w = ($data | get ($left_x + $y_pos * $width) | into int)
|
||||
let $sw = ($data | get ($left_x + $down_y * $width) | into int)
|
||||
let $s = ($data | get ($x_pos + $down_y * $width) | into int)
|
||||
let $se = ($data | get ($right_x + $down_y * $width) | into int)
|
||||
let $e = ($data | get ($right_x + $y_pos * $width) | into int)
|
||||
let $ne = ($data | get ($right_x + $up_y * $width) | into int)
|
||||
|
||||
let total = $n + $nw + $w + $sw + $s + $se + $e + $ne
|
||||
|
||||
let $curr = ($data | get ($x_pos + $y_pos * $width))
|
||||
|
||||
if ($total == 3) or ($total == 2 and $curr) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def generation [$grid] {
|
||||
let width = ($grid | get width)
|
||||
let height = ($grid | get height)
|
||||
let data = ($grid | get data)
|
||||
|
||||
let next_generation = (
|
||||
0..<$height | each {|y|
|
||||
0..<$width | each {|x|
|
||||
alive $x $y $grid
|
||||
}
|
||||
}
|
||||
) | flatten
|
||||
{ width: $width, height : $height, data: $next_generation }
|
||||
}
|
||||
|
||||
def print-grid [$grid] {
|
||||
$grid.data | flatten | group ($grid | get width) | each {|x|
|
||||
$x | each {|item|
|
||||
if $item {
|
||||
"*"
|
||||
} else {
|
||||
"."
|
||||
}
|
||||
} | append (char nl) | str join
|
||||
} | str join ""
|
||||
}
|
||||
|
||||
def main [] {
|
||||
let width = 15
|
||||
let height = 15
|
||||
|
||||
let data = (0..<($width * $height) | each {
|
||||
random bool
|
||||
})
|
||||
|
||||
let grid = { width: $width, height : $height, data: $data }
|
||||
|
||||
print (print-grid $grid)
|
||||
|
||||
1..100 | reduce --fold ($grid) {|it acc|
|
||||
let next_grid = (generation $acc)
|
||||
print $"(char -u '1b')[2J" (print-grid $next_grid)
|
||||
$next_grid
|
||||
} | ignore
|
||||
}
|
||||
|
||||
67
dot_config/nushell/nu_scripts/modules/fun/nyancat.nu
Normal file
67
dot_config/nushell/nu_scripts/modules/fun/nyancat.nu
Normal file
@@ -0,0 +1,67 @@
|
||||
# yay! the nyancat in nushell
|
||||
# based off this C code https://github.com/klange/nyancat
|
||||
|
||||
# each frame has the nyancat with stars flying by and the rainbow waving as it animates
|
||||
let frame0 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>,,,,,,,,>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,>>&&&&&&&&>>>>>>>>&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,&&++++++++&&&&&&&&'''++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,++++++++++++++++++**''+'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,++++++++++++++++++'**'''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,++########++++++++''**''@$$$$$$-'*************',,,,,,,,,,,,,,,,,###################''**'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,####################''''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,##========########====''@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,======================='@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,==;;;;;;;;.=======;;;;'''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''''',,,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;'**'','*',,,,,'*','**',,,,,,,,,,,,,,,,,,,,,;;,,,,,.,,;;;.;;;;,,,'''',,'',,,,,,,'',,'',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame1 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>,,,,,,,,>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,>>&&&&&&&&>>>>>>>>&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,&&++++++++&&&&&&&&+++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,+++++++++++++++++++'+++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,++++++++++++++++++'*'++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,++########++++++++'*''''@$$$$$$-$'*************',,,,,,,,,,,,,,,,###################****'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,###################''**'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,##========########==='''@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,======================='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,==;;;;;;;;========;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;'**','*',,,,,,**','**',,,,,,,,,,,,,,,,,,,,;;,,,.,,,,;;;;;;;;,,,,''',,,'',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame2 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.>>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,++&&&&&&&++++++++&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,##+++++++########++++++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,######################''@$$$$$$-$'*************',,,,,,,,,,,,,,,,###################'''''@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,==#######========#'****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,==================='''='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,;;=======;;;;;;;;======'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,;.;;;;;;;;;;;;;;;;;;;;;'*'''''''''''''''''''',,,,,,,,,,,,,,,,,,,.,.;;;;;;,,,,,,,,;;;;;;'**',**',,,,,,**','**',,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame3 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,>>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,++&&&&&&&++++++++&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,##+++++++########++++++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,#####################'''@$$$$$$-$'*************',,,,,,,,,,,,,,,,###################''**'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,==#######========##****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,=================='*'=='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,;;=======;;;;;;;;=='==='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,;;;;;;;,,,,,,,,;;;;;'**','*',,,,,,'*','**',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,'',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame4 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,&&++++++++&&&&&&&&+++++'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,++++++++++++++++++'''++'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,++########+++++++'**''''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,#################'****''@$$$$$$-'*************',,,,,,,,,,,,,,,,,##################''''*'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,##========########==='''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,======================='@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,==;;;;;;;;========;;;;''@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;''''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;'***'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,;;,,,,,,,,;;;;;;;;,,'**','**,,,,,,'**,'**',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,'',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame5 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$''$$$@@','',,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$'**'-$$@''**',,,,,,,,,,,,,,,,,,&&++++++++&&&&&&&&+++++'@$$$$$$$$'***$$$@'***',,,,,,,,,,,,,,,,,,+++++++++++++++++++'+++'@$$$$$-$$'***''''****',,,,,,,,,,,,,,,,,,++++++++++++++++++'*'++'@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,++########++++++++'*''''@$$$$$$$'*************',,,,,,,,,,,,,,,,,###################****'@$$$$$$-'***.'****.'**',,,,,,,,,,,,,,,,,###################''**'@$-$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,##========########==='''@$$$$$$$'*%%********%%',,,,,,,,,,,,,,,,,======================='@@$$$-$$$'***''''''**',,,,,,,,,,,,,,,,,,==;;;;;;;;========;;;;''@@@$$$$$$$'*********',,,,,,,,,,,,,,,,,,.;;;;;;;;;;;;;;;;;;;;;'*''@@@@@@@@@@''''''''',,,,,,,,,,,,,,,,,,,.;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''*',,,,,,,,,,,,,,,,,,,,,,;;,,,,,,,,;;;;;;;;,,'**','**,,,,,,'**,'**',,,,,,,,,,,,,,,,,,..,.,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame6 = ".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>,,,,,,,>>>>>>>>,,,,,,,'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&>>>>>>>&&&&&&&&>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,++&&&&&&&++++++++&'''&&'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,++++++++++++++++++'*''+'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,++++++++++++++++++'**'''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,##+++++++########++'**''@$$$$$$-'*************',,,,,,,,,,,,,,,,,###################''**'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,####################''''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,==#######========#####''@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,======================='@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,;;=======;;;;;;;;====='''@@@@@@@@@'*********',,,,,,,,,,,.,,,,,,,;;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''''',,,,,,,,,,.,,,.,,,,,;;;;;;;;;;;;;;;;;;;;;'**'','*',,,,,'**,'**',,,,,,,,,,,,,,,,,,,,,,,;;;;;;;,,,,,,,,;;;;'''',,'',,,,,,,'',,'',,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame7 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>,,,,,,,>>>>>>>>,,,,,,,'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&>>>>>>>&&&&&&&&>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,++&&&&&&&++++++++&&&&&&'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,+++++++++++++++++++'+++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,++++++++++++++++++'*'++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,##+++++++########+'*''''@$$$$$$-$'*************',,,,,,,,,,,,,,,,###################****'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,###################''**'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,==#######========####'''@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,======================='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,;;=======;;;;;;;;======''@@@@@@@@@@'*********',,,.,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;'**','*',,,,,,**','**',,,,,,,,,,,,,,,,,,,,,,;;;;;;;,,,,,,,,;;;;;''',,,'',,,,,,''',,''',,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame8 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,...,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,&&++++++++&&&&&&&&+++++'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,++########++++++++#####'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,######################''@$$$$$$-$'*************',,,,,,,,,,,,,,,,###################'''''@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,##========########'****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,==================='''='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,==;;;;;;;;========;;;;;'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;'*'''''''''''''''''''',,,,,,,,,,,,,,,,,,,;;,,,,,,,,;;;;;;;;,,,,,'**',**',,,,,,**'.'**',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,"
|
||||
let frame9 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,>>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,&&++++++++&&&&&&&&+++++'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,++########++++++++#####'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,#####################'''@$$$$$$-$'*************',,,,,,,,,,,,,,,,###################''**'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,##========########=****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,=================='*'=='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,==;;;;;;;;========;';;;'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,;;,,,,,,,,;;;;;;;;,,,,'**','*',,..,.**','**',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,.,''',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,"
|
||||
let frame10 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,++&&&&&&&++++++++&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,+++++++++++++++++++++++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,++++++++++++++++++'''++'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,##+++++++########'**''''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,#################'****''@$$$$$$-'*************',,,,,,,,,,,,,,,,,##################''''*'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,==#######========####'''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,======================='@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,;;=======;;;;;;;;=====''@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;''''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;'***'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,;;;;;;;,,,,,,,,;;;'**'.'**..,,,,'**''**',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,''',''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
let frame11 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$''$$$@@','',,,,,,,,,,,,,,,,,,,&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$'**'-$$@''**',,,,,,,,,,,,,,,,,,++&&&&&&&++++++++&&&&&&'@$$$$$$$$'***$$$@'***',,,,,,,,,,,,,,,,,,+++++++++++++++++++'+++'@$$$$$-$$'***''''****',,,,,,,,,,,,,,,,,,++++++++++++++++++'*'++'@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,##+++++++########+'*''''@$$$$$$$'*************',,,,,,,,,,,,,,,,,###################****'@$$$$$$-'***.'****.'**',,,,,,,,,,,,,,,,,###################''**'@$-$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,==#######========####'''@$$$$$$$'*%%********%%',,,,,,,,,,,,,,,,,======================='@@$$$-$$$'***''''''**',,,,,,,,,,,,,,,,,,;;=======;;;;;;;;=.===''@@@$$$$$$$'*********',,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;.'*''@@@@@@@@@@''''''''',,,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''*',,,,,,,,,,,,,,,,,,,,,,,,;;;;;;;,,,,,,,.;;;'**','**,,,,,,'**''**',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
|
||||
|
||||
|
||||
# this is how to map characters to colors
|
||||
let map = [[symbol color description];
|
||||
[',' '48;5;17m' Blue_background]
|
||||
[. '48;5;231m' White_stars]
|
||||
['\' '48;5;16m' Black_border]
|
||||
['@' '48;5;230m' Tan_poptart]
|
||||
['$' '48;5;175m' Pink_poptart]
|
||||
['-' '48;5;162m' Red_poptart]
|
||||
['>' '48;5;196m' Red_rainbow]
|
||||
['&' '48;5;214m' Orange_rainbow]
|
||||
['+' '48;5;226m' Yellow_Rainbow]
|
||||
['#' '48;5;118m' Green_rainbow]
|
||||
['=' '48;5;33m' Light_blue_rainbow]
|
||||
[';' '48;5;19m' Dark_blue_rainbow]
|
||||
['*' '48;5;240m' Gray_cat_face]
|
||||
['%' '48;5;175m' Pink_cheeks]
|
||||
["'" '48;5;175m' single_quote]
|
||||
]
|
||||
|
||||
# setup the frames and order we want to draw them
|
||||
let frames = [
|
||||
$frame0
|
||||
$frame1
|
||||
$frame2
|
||||
$frame3
|
||||
$frame4
|
||||
$frame5
|
||||
$frame6
|
||||
$frame7
|
||||
$frame8
|
||||
$frame9
|
||||
$frame10
|
||||
$frame11
|
||||
]
|
||||
|
||||
# let's animate
|
||||
# make sure you have your font small like 10 or 12 pt and screen maximized.
|
||||
# you may need to play with the font size to get it working right
|
||||
# it's a little slow - maybe 1 fps but still firmly in the 'fun' category
|
||||
print (ansi cursor_off)
|
||||
|
||||
for frame in $frames {
|
||||
let frame = (echo $frame | split chars | enumerate | each {|char| if $char.index mod 64 == 0 { $"(ansi -e '0m')(char nl)" } else {$"(ansi -e ($map | where symbol == $char.item | get color | get 0))(char sp)"}} | append (ansi -e '0m') | str join)
|
||||
clear
|
||||
print $frame
|
||||
}
|
||||
|
||||
print (ansi cursor_on)
|
||||
|
||||
127
dot_config/nushell/nu_scripts/modules/fun/star.nu
Normal file
127
dot_config/nushell/nu_scripts/modules/fun/star.nu
Normal file
@@ -0,0 +1,127 @@
|
||||
# i found this script on a github issue and wanted to see what nushell would do.
|
||||
# https://github.com/microsoft/terminal/issues/11794
|
||||
|
||||
#########################################################
|
||||
# here's the python version from that issue
|
||||
#########################################################
|
||||
# import math
|
||||
# import os
|
||||
# import sys
|
||||
|
||||
# size = os.popen('stty size', 'r').read().split()
|
||||
# h,w = tuple(int(n) for n in size)
|
||||
# mx = w//2
|
||||
# my = h//2
|
||||
|
||||
# def frame(i):
|
||||
# s = '\033[H'
|
||||
# for y in range(h):
|
||||
# for x in range(w):
|
||||
# dy,dx = y-my,x-mx
|
||||
# a = math.atan2(dy*2,dx) + math.pi
|
||||
# c = (int(a/math.pi*127)+i)%256
|
||||
# s += '\033[38;2;%d;%d;%dm*' % (c,c,c)
|
||||
# return s
|
||||
|
||||
# sys.stdout.write('Generating content...\n')
|
||||
# s = '\033[?25l'
|
||||
# for i in range(512):
|
||||
# s += frame(i)
|
||||
# s += '\033[?25h\033[m\033[H'
|
||||
|
||||
# sys.stdout.write('Starting animation...\n')
|
||||
# sys.stdout.write(s)
|
||||
|
||||
#########################################################
|
||||
# here's the c version from that issue
|
||||
#########################################################
|
||||
# #include <windows.h>
|
||||
# #include <string>
|
||||
# #include <cmath>
|
||||
|
||||
# void main()
|
||||
# {
|
||||
# HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
# DWORD mode;
|
||||
# GetConsoleMode(handle, &mode);
|
||||
# mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
# SetConsoleMode(handle, mode);
|
||||
|
||||
# CONSOLE_SCREEN_BUFFER_INFOEX csbie;
|
||||
# csbie.cbSize = sizeof(csbie);
|
||||
# GetConsoleScreenBufferInfoEx(handle, &csbie);
|
||||
|
||||
# const auto w = csbie.dwSize.X;
|
||||
# const auto h = csbie.srWindow.Bottom - csbie.srWindow.Top + 1;
|
||||
# const auto mx = w/2;
|
||||
# const auto my = h/2;
|
||||
# const auto pi = 3.14159265358979323846;
|
||||
|
||||
# printf("Generating content...\n");
|
||||
# std::string s = "\033[?25l";
|
||||
# for (auto i = 0; i < 512; i++) {
|
||||
# s += "\033[H";
|
||||
# for (auto y = 0; y < h; y++) {
|
||||
# for (auto x = 0; x < w; x++) {
|
||||
# auto dy = y-my;
|
||||
# auto dx = x-mx;
|
||||
# auto a = std::atan2(dy*2,dx) + pi;
|
||||
# auto c = std::to_string((int(a/pi*127)+i)%256);
|
||||
# s += "\033[38;2;"+c+";"+c+";"+c+"m*";
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# s += "\033[?25h\033[m\033[H";
|
||||
|
||||
# printf("Starting animation...\n");
|
||||
# DWORD written = 0;
|
||||
# WriteConsoleA(handle, s.c_str(), s.length(), &written, NULL);
|
||||
# }
|
||||
|
||||
|
||||
use std math
|
||||
|
||||
def atan2 [y x] {
|
||||
if $x > 0 {
|
||||
$y / $x | math arctan
|
||||
} else if $x < 0 {
|
||||
if $y >= 0 {
|
||||
$math.PI + ($y / $x | math arctan)
|
||||
} else {
|
||||
-1 * $math.PI + ($y / $x | math arctan)
|
||||
}
|
||||
} else {
|
||||
if $y >= 0 {
|
||||
$math.PI / 2
|
||||
} else {
|
||||
-1 * $math.PI / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let w = 50
|
||||
let h = 20
|
||||
# if it's fast for your, change w, h to the below lines
|
||||
# let w = (term size).columns - 2
|
||||
# let h = (term size).rows - 2
|
||||
let mx = ($w / 2 | math floor)
|
||||
let my = ($h / 2 | math floor)
|
||||
|
||||
print (ansi -e "?25l")
|
||||
|
||||
for i in 0..512 {
|
||||
let rows = (0..($h) | each {|y|
|
||||
let cols = (0..($w) | each {|x|
|
||||
let dy = ($y - $my)
|
||||
let dx = ($x - $mx)
|
||||
let a = (atan2 ($dy * 2) $dx) + $math.PI
|
||||
let c = ((($a / ($math.PI) * 127) + ($i)) mod 256 | math round)
|
||||
$"(ansi -e '38;2;')($c);($c);($c)m*"
|
||||
})
|
||||
$cols | str join
|
||||
})
|
||||
print ((ansi -e 'H') + ($rows | str join (char nl)))
|
||||
}
|
||||
|
||||
print $"(ansi -e '?25h')(ansi -e 'm')(ansi -e 'H')"
|
||||
55
dot_config/nushell/nu_scripts/modules/fun/wordle.nu
Normal file
55
dot_config/nushell/nu_scripts/modules/fun/wordle.nu
Normal file
@@ -0,0 +1,55 @@
|
||||
# A Terminal Wordle game.
|
||||
# The code is based on https://gist.github.com/huytd/6a1a6a7b34a0d0abcac00b47e3d01513 ,but slightly personalized.
|
||||
|
||||
# a simple termninal Wordle game!
|
||||
export def main [
|
||||
--unlimited(-u) # Play the game in unlimited mode.
|
||||
--max_count(-M) : int = 6 # Give yourself more chances than default
|
||||
--alternative_source(-a) : string = "https://raw.githubusercontent.com/charlesreid1/five-letter-words/master/sgb-words.txt" # Alternative link to provide as a word source
|
||||
] {
|
||||
let words = (if ($alternative_source | str substring 0..4 | str contains "http") {http get $alternative_source} else {open $alternative_source} | from ssv -n)
|
||||
let word = ($words | get (random int 0..($words | length)) | get column1)
|
||||
if ((($words | each {|it| ($it.column1 | str length)}) | where $it != 5 | length) != 0 ) {
|
||||
echo $"(ansi rb)Warning:(ansi reset) The words list contains words that are not length 5"
|
||||
}
|
||||
mut end = false
|
||||
mut guess_count = 0
|
||||
mut avail = "abcdefghijklmnopqrstuvyxwz"
|
||||
while (not ($end)) {
|
||||
$guess_count += 1
|
||||
if ($guess_count <= $max_count or $unlimited) {
|
||||
echo $"(ansi xterm_aquamarine1a)Enter your guess (ansi reset)\((ansi green)($guess_count)(ansi reset)/(ansi yellow)(if ($unlimited) {inf} else {$max_count})(ansi reset)\)"
|
||||
mut guess = (input | str downcase )
|
||||
if (((($words | where column1 =~ $guess) | length) >= 1) and ($guess | str length) == 5) {
|
||||
mut out = ""
|
||||
mut checked = $word
|
||||
for i in ($guess | split chars) -n {
|
||||
if ($i.item == ($word | str substring ($i.index)..($i.index + 1)) ) {
|
||||
$out += $"(ansi green_reverse)($i.item)(ansi reset)"
|
||||
$avail = ($avail | str replace $i.item $"(ansi green_reverse)($i.item)(ansi white_reverse)")
|
||||
$checked = ($checked | str replace $i.item "")
|
||||
} else if ( $i.item in $checked) {
|
||||
$out += $"(ansi yellow_reverse)($i.item)(ansi reset)"
|
||||
$avail = ($avail | str replace $i.item $"(ansi yellow_reverse)($i.item)(ansi white_reverse)")
|
||||
$checked = ($checked | str replace $i.item "")
|
||||
} else {
|
||||
$out += $"(ansi white_reverse)($i.item)(ansi reset)"
|
||||
$avail = ($avail | str replace $i.item "")
|
||||
}
|
||||
}
|
||||
$avail = $"(ansi white_reverse)($avail)(ansi reset)"
|
||||
echo $"($out) possible -> ($avail)"
|
||||
if ($guess == $word) {
|
||||
$end = true
|
||||
echo $"(ansi xterm_green1 )You guessed right!(ansi reset)"
|
||||
}
|
||||
} else {
|
||||
echo "please enter a valid [5 letter] word!"
|
||||
$guess_count -= 1
|
||||
}
|
||||
} else {
|
||||
echo $"(ansi yellow )You loose, the word was: (ansi red)($word)(ansi reset)"
|
||||
$end = true
|
||||
}
|
||||
}
|
||||
}
|
||||
28
dot_config/nushell/nu_scripts/modules/fuzzy/README.md
Normal file
28
dot_config/nushell/nu_scripts/modules/fuzzy/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Fuzzy all the things
|
||||
|
||||
### Purpose
|
||||
|
||||
This contains a few scripts that add fuzzy search interfaces to built-in nu functionalities. Often you
|
||||
want to search commands/your history interactively, which is where [fzf](https://github.com/junegunn/fzf) excels at.
|
||||
|
||||
|
||||
### How to use
|
||||
|
||||
`./fuzzy_history_search.nu` searches your command history and, after pressing `enter`, copies the selected command into the clipboard
|
||||
`./fuzzy_command_search.nu` searches both commands and subcommands for both a) names and b) their description, and, after pressing `enter`, copies the selected command into the clipboard
|
||||
|
||||
To use them in your day-to-day workflow, add
|
||||
|
||||
```
|
||||
source <absolute-path-to-nu_scripts>/fuzzy/fuzzy_history_search.nu
|
||||
source <absolute-path-to-nu_scripts>/fuzzy/fuzzy_command_search.nu
|
||||
```
|
||||
|
||||
to your `config.nu`
|
||||
|
||||
It's likely a good idea to also add some short and sweet aliases, e.g.
|
||||
|
||||
```
|
||||
alias hi = fuzzy-history-search
|
||||
alias hf = fuzzy-command-search
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
const tablen = 8
|
||||
|
||||
# calculate required tabs/spaces to get a nicely aligned table
|
||||
def pad-tabs [input_name max_indent] {
|
||||
let input_length = ($input_name | str length)
|
||||
let required_tabs = $max_indent - ($input_length / $tablen | into int)
|
||||
seq 0 $required_tabs | reduce -f "" {|it, acc| $acc + (char tab)}
|
||||
}
|
||||
|
||||
# fuzzy search a) commands b) subcommands
|
||||
# on selection, will display `help` for the commands
|
||||
# and paste command into clipboard for you to paste right away
|
||||
|
||||
|
||||
export def fuzzy-command-search [] {
|
||||
let max_len = (help commands | each { $in.name | str length } | math max)
|
||||
let max_indent = ($max_len / $tablen | into int)
|
||||
let command = ((help commands | each {|it|
|
||||
let name = ($it.name | str trim | ansi strip)
|
||||
$"($name)(pad-tabs $name $max_indent)($it.usage)"
|
||||
}) | str join (char nl) | fzf | split column (char tab) | get column1.0)
|
||||
if ($command | is-not-empty) {
|
||||
help $command
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export def fuzzy-history-search [] { cat $nu.history-path | fzf | clip }
|
||||
14
dot_config/nushell/nu_scripts/modules/git/README.md
Normal file
14
dot_config/nushell/nu_scripts/modules/git/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Git Scripts
|
||||
|
||||
### Definition
|
||||
|
||||
These scripts should be used to demonstrate how combine the power of nushell with git commands.
|
||||
|
||||
### Aliases
|
||||
If you find some of these scripts useful you can add them as aliases in your git config file.
|
||||
|
||||
For instance you can create a nushell script in your computer and define in your git config file an alias that call that script:
|
||||
```
|
||||
[alias]
|
||||
bcl = !nu \"D:\\Tools\\gitalias_bcl.nu\"
|
||||
```
|
||||
146
dot_config/nushell/nu_scripts/modules/git/git.nu
Normal file
146
dot_config/nushell/nu_scripts/modules/git/git.nu
Normal file
@@ -0,0 +1,146 @@
|
||||
export def _git_stat [n] {
|
||||
do -i {
|
||||
git log -n $n --pretty=»¦«%h --stat
|
||||
| lines
|
||||
| reduce -f { c: '', r: [] } {|it, acc|
|
||||
if ($it | str starts-with '»¦«') {
|
||||
$acc | upsert c ($it | str substring 6.. )
|
||||
} else if ($it | find -r '[0-9]+ file.+change' | is-empty) {
|
||||
$acc
|
||||
} else {
|
||||
let x = (
|
||||
$it
|
||||
| split row ','
|
||||
| each {|x| $x
|
||||
| str trim
|
||||
| parse -r "(?P<num>[0-9]+) (?P<col>.+)"
|
||||
| get 0
|
||||
}
|
||||
| reduce -f {sha: $acc.c file:0 ins:0 del:0} {|i,a|
|
||||
let col = if ($i.col | str starts-with 'file') {
|
||||
'file'
|
||||
} else {
|
||||
$i.col | str substring ..3
|
||||
}
|
||||
let num = ($i.num | into int)
|
||||
$a | upsert $col $num
|
||||
}
|
||||
)
|
||||
$acc | upsert r ($acc.r | append $x)
|
||||
}
|
||||
}
|
||||
| get r
|
||||
}
|
||||
}
|
||||
|
||||
export def _git_log [v num] {
|
||||
let stat = if $v {
|
||||
_git_stat $num
|
||||
} else { {} }
|
||||
let r = (do -i {
|
||||
git log -n $num --pretty=%h»¦«%s»¦«%aN»¦«%aE»¦«%aD
|
||||
| lines
|
||||
| split column "»¦«" sha message author email date
|
||||
| each {|x| ($x| upsert date ($x.date | into datetime))}
|
||||
})
|
||||
if $v {
|
||||
$r | merge $stat | reverse
|
||||
} else {
|
||||
$r | reverse
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete git log" [] {
|
||||
git log -n 32 --pretty=%h»¦«%s
|
||||
| lines
|
||||
| split column "»¦«" value description
|
||||
| each {|x| $x | update value $"($x.value)"}
|
||||
}
|
||||
|
||||
def "nu-complete git branches" [] {
|
||||
git branch
|
||||
| lines
|
||||
| filter {|x| not ($x | str starts-with '*')}
|
||||
| each {|x| $"($x|str trim)"}
|
||||
}
|
||||
|
||||
export def gl [
|
||||
commit?: string@"nu-complete git log"
|
||||
--verbose(-v)
|
||||
--num(-n):int=32
|
||||
] {
|
||||
if ($commit|is-empty) {
|
||||
_git_log $verbose $num
|
||||
} else {
|
||||
git log --stat -p -n 1 $commit
|
||||
}
|
||||
}
|
||||
|
||||
export def glv [
|
||||
commit?: string@"nu-complete git log"
|
||||
--num(-n):int=32
|
||||
] {
|
||||
if ($commit|is-empty) {
|
||||
_git_log true $num
|
||||
} else {
|
||||
git log --stat -p -n 1 $commit
|
||||
}
|
||||
}
|
||||
|
||||
export def gco [branch: string@"nu-complete git branches"] {
|
||||
git checkout $branch
|
||||
}
|
||||
|
||||
export def gbD [branch: string@"nu-complete git branches"] {
|
||||
git branch -D $branch
|
||||
}
|
||||
|
||||
export def gpp! [] {
|
||||
git pull
|
||||
git add --all
|
||||
git commit -v -a --no-edit --amend
|
||||
git push --force
|
||||
}
|
||||
|
||||
export def gha [] {
|
||||
git log --pretty=%h»¦«%aN»¦«%s»¦«%aD
|
||||
| lines
|
||||
| split column "»¦«" sha1 committer desc merged_at
|
||||
| histogram committer merger
|
||||
| sort-by merger
|
||||
| reverse
|
||||
}
|
||||
|
||||
export def gsq [] {
|
||||
git reflog expire --all --expire=now
|
||||
git gc --prune=now --aggressive
|
||||
}
|
||||
|
||||
def "nu-complete git remotes" [] {
|
||||
^git remote | lines | each { |line| $line | str trim }
|
||||
}
|
||||
|
||||
export def gr [remote?: string@"nu-complete git remotes"] {
|
||||
let remote = if ($remote|is-empty) { 'origin' } else { $remote }
|
||||
git remote show $remote
|
||||
}
|
||||
|
||||
export def grh [commit: string@"nu-complete git log"] {
|
||||
git reset $commit
|
||||
}
|
||||
|
||||
export def gf [
|
||||
branch: string@"nu-complete git branches"
|
||||
remote?: string@"nu-complete git remotes"
|
||||
] {
|
||||
let remote = if ($remote|is-empty) { 'origin' } else { $remote }
|
||||
git fetch $remote $branch
|
||||
}
|
||||
|
||||
export def gm [branch:string@"nu-complete git branches"] {
|
||||
git merge $branch
|
||||
}
|
||||
|
||||
export def grb [branch:string@"nu-complete git branches"] {
|
||||
git rebase (gstat).branch $branch
|
||||
}
|
||||
15
dot_config/nushell/nu_scripts/modules/git/git_branch_age.nu
Normal file
15
dot_config/nushell/nu_scripts/modules/git/git_branch_age.nu
Normal file
@@ -0,0 +1,15 @@
|
||||
# Creates a table listing the branches of a git repository and the day of the last commit
|
||||
export def "git age" [] {
|
||||
git branch |
|
||||
lines |
|
||||
str substring 2.. |
|
||||
wrap name |
|
||||
insert last_commit {
|
||||
get name |
|
||||
each {
|
||||
git show $in --no-patch --format=%as | into datetime
|
||||
}
|
||||
} |
|
||||
sort-by last_commit
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Git branch cleanup
|
||||
|
||||
Remove any local git branches that have been merged and optionally remove any
|
||||
remote branches that have been merged.
|
||||
|
||||
Load with:
|
||||
```nushell
|
||||
source modules/git/git_branch_cleanup.nu
|
||||
```
|
||||
|
||||
To remove merged branches:
|
||||
```nushell
|
||||
git branch-cleanup
|
||||
```
|
||||
|
||||
To keep merged branches that start with "releases/":
|
||||
|
||||
```nushell
|
||||
git config --local --add branch-cleanup.keep 'releases/.*'
|
||||
```
|
||||
|
||||
Keep branch patterns are space-separated
|
||||
171
dot_config/nushell/nu_scripts/modules/git/git_branch_cleanup.nu
Normal file
171
dot_config/nushell/nu_scripts/modules/git/git_branch_cleanup.nu
Normal file
@@ -0,0 +1,171 @@
|
||||
# Adapted from original by Yorick Sijsling
|
||||
#
|
||||
# Adapted from bash version `git cleanup-repo` by Rob Miller <rob@bigfish.co.uk>
|
||||
# https://gist.github.com/robmiller/5133264
|
||||
|
||||
# Delete local (and optionally remote) merged branches
|
||||
#
|
||||
# Set branch-cleanup.keep locally to a space-separated list of branch patterns to keep
|
||||
export def "git branch-cleanup" [
|
||||
upstream: string@remotes = "origin" # Upstream remote repository
|
||||
] {
|
||||
let current_branch = current_branch
|
||||
let default_branch = get_default_branch $"refs/remotes/($upstream)/HEAD"
|
||||
let keep = get_keep
|
||||
|
||||
# Switch to the default branch
|
||||
switch_branch $default_branch
|
||||
|
||||
# Make sure we're working with the most up-to-date version of the default
|
||||
# branch.
|
||||
run-external "git" "fetch"
|
||||
|
||||
# Prune obsolete remote tracking branches. These are branches that we
|
||||
# once tracked, but have since been deleted on the remote.
|
||||
run-external "git" "remote" "prune" $upstream
|
||||
|
||||
# Delete local branches that have been fully merged into the default branch
|
||||
list_merged $upstream $default_branch $keep
|
||||
| each {|branch|
|
||||
delete_local $branch
|
||||
}
|
||||
|
||||
# Again with remote branches
|
||||
let merged_on_remote = list_merged --remote $upstream $default_branch $keep
|
||||
|
||||
if not ( $merged_on_remote | is-empty ) {
|
||||
print "The following remote branches are fully merged and will be removed:"
|
||||
|
||||
$merged_on_remote
|
||||
| each {||
|
||||
print $"\t($in)"
|
||||
}
|
||||
|
||||
print ""
|
||||
|
||||
if ( input --suppress-output "Continue (y/N)? " | str trim ) == "y" {
|
||||
$merged_on_remote
|
||||
| each {|branch|
|
||||
delete_remote $upstream $branch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_branch $current_branch
|
||||
}
|
||||
|
||||
# The current branch name
|
||||
def current_branch [] {
|
||||
run-external "git" "branch" "--show-current"
|
||||
| into string
|
||||
| str trim
|
||||
}
|
||||
|
||||
# Delete a local branch
|
||||
def delete_local [
|
||||
branch: string # Branch to delete
|
||||
] {
|
||||
run-external "git" "branch" "--delete" $branch
|
||||
}
|
||||
|
||||
# Delete a remote branch
|
||||
def delete_remote [
|
||||
upstream: string # Repository to delete from
|
||||
branch: string # branch to delete
|
||||
] {
|
||||
run-external "git" "push" "--quiet" "--delete" $upstream $branch
|
||||
}
|
||||
|
||||
# Get the default branch
|
||||
def get_default_branch [
|
||||
upstream: string # Repository to get the upstream branch name from
|
||||
] {
|
||||
let args = [
|
||||
"--short"
|
||||
$upstream
|
||||
]
|
||||
|
||||
run-external "git" "symbolic-ref" ...$args
|
||||
| str trim
|
||||
| path basename
|
||||
}
|
||||
|
||||
# Get the local set of branches to always keep
|
||||
def get_keep [] {
|
||||
let keep = run-external "git" "config" "--local" "--get" "branch-cleanup.keep"
|
||||
|
||||
if ( $keep | is-empty ) {
|
||||
return []
|
||||
}
|
||||
|
||||
$keep
|
||||
| str trim
|
||||
| split column " "
|
||||
| get column1
|
||||
}
|
||||
|
||||
# List all the branches that have been merged fully into the default branch.
|
||||
#
|
||||
# We use the remote default branch here, just in case our local default branch is out of date.
|
||||
def list_merged [
|
||||
--remote # List remote branches (local default)
|
||||
upstream: string # Upstream repository
|
||||
branch: string # Default branch
|
||||
keep: list<string> # Patterns to keep. The default branch and HEAD will be added
|
||||
] {
|
||||
mut args = [
|
||||
"--list"
|
||||
"--merged" $"($upstream)/($branch)"
|
||||
]
|
||||
|
||||
if $remote {
|
||||
$args = ( $args | append [
|
||||
"--format" "%(refname:lstrip=3)"
|
||||
"--remote"
|
||||
])
|
||||
} else {
|
||||
$args = ( $args | append [
|
||||
"--format" "%(refname:lstrip=2)"
|
||||
])
|
||||
}
|
||||
|
||||
let args = $args
|
||||
|
||||
let keep = (
|
||||
$keep
|
||||
| append [
|
||||
"HEAD",
|
||||
$branch,
|
||||
]
|
||||
)
|
||||
|
||||
run-external "git" "branch" ...$args
|
||||
| lines
|
||||
| filter {|branch|
|
||||
$keep
|
||||
| all {|pattern|
|
||||
$branch !~ $'\A($pattern)\z'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def remotes [] {
|
||||
run-external "git" "remote" "-v"
|
||||
| parse "{value}\t{description} ({operation})"
|
||||
| select value description
|
||||
| uniq
|
||||
| sort
|
||||
}
|
||||
|
||||
# Switch to a different branch
|
||||
def switch_branch [
|
||||
branch: string
|
||||
] {
|
||||
let args = [
|
||||
"--quiet"
|
||||
"--no-guess"
|
||||
$branch
|
||||
]
|
||||
|
||||
run-external "git" "switch" ...$args
|
||||
}
|
||||
89
dot_config/nushell/nu_scripts/modules/gitv2/README.md
Normal file
89
dot_config/nushell/nu_scripts/modules/gitv2/README.md
Normal file
@@ -0,0 +1,89 @@
|
||||
Consider putting related commands together, such as `push` and `pull`,
|
||||
to decide how to execute based on the current environment or specified parameters.
|
||||
|
||||
This mode is more convenient,
|
||||
but more difficult to implement in traditional shells such as zsh.
|
||||
|
||||
In nushell it's very easy.
|
||||
|
||||
In this way, the commands that need to be memorized will be greatly reduced,
|
||||
and the parameters can be automatically completed.
|
||||
In the most common scenarios, it is even possible to omit the parameter.
|
||||
|
||||
In contrast, the behavior of commands requires fine-tuning to be intuitive.
|
||||
(there may still be some unreasonable places that need to be adjusted)
|
||||
|
||||
I tried to tidy part of it, and it is basically usable.
|
||||
(The goal is to organize all aliases to where they should go)
|
||||
|
||||
### gs
|
||||
Git status and stash.
|
||||
|
||||
### gl
|
||||
Git log and show.
|
||||
|
||||
### gb
|
||||
About the branch.
|
||||
|
||||
Create branch if it doesn't exist,
|
||||
switch otherwise (branch are automatically completed),
|
||||
use -d to delete.
|
||||
|
||||
If there is no branch as an argument, the branch is displayed.
|
||||
|
||||
### gp
|
||||
Pull, push and other related to remote repositories
|
||||
|
||||
> We assume that the upstream and downstream branches keep the same name and do not operate across branches.
|
||||
|
||||
- `--clone` to clone
|
||||
- `--submodule` submodule update and submodule init (with `--init`)
|
||||
- `--force` push --force (assume `pull --force` doesn't make sense)
|
||||
- `--init` git init
|
||||
- `--override` just used to trigger a github actions event (in fact, webhooks can also be used)
|
||||
- `--set-upstream` push --set-upstream
|
||||
- if branch is specified, it is `git fetch` (let's assume you don't like pulling from a different branch)
|
||||
- finally, if no branch and above parameters are specified
|
||||
- `git pull` to update.
|
||||
- if `ahead`, `git push` will be executed.
|
||||
|
||||
### ga
|
||||
Git add, rm and restore. about files.
|
||||
|
||||
Use `ga` because git add has the highest execution frequency,
|
||||
and `ga` is the most convenient input.
|
||||
|
||||
- `--delete` git rm
|
||||
- `--restore` git restore
|
||||
- git add
|
||||
|
||||
### gc
|
||||
Git commit
|
||||
|
||||
### gd
|
||||
Git diff
|
||||
|
||||
### gm
|
||||
Git merge and rebase
|
||||
|
||||
- `--rebase` git rebase
|
||||
- git merge
|
||||
|
||||
### gcp
|
||||
Git cherry-pick
|
||||
|
||||
### gr
|
||||
Git reset
|
||||
|
||||
### grmt
|
||||
Git remote
|
||||
|
||||
### gbs
|
||||
Git bisect
|
||||
|
||||
## changelog
|
||||
|
||||
#### 2023-05-18
|
||||
- `gp -u` can omit branch
|
||||
- delete `grb`
|
||||
- improve the premise in the description
|
||||
689
dot_config/nushell/nu_scripts/modules/gitv2/mod.nu
Normal file
689
dot_config/nushell/nu_scripts/modules/gitv2/mod.nu
Normal file
@@ -0,0 +1,689 @@
|
||||
use argx
|
||||
|
||||
def agree [
|
||||
prompt
|
||||
--default-not (-n)
|
||||
] {
|
||||
let prompt = if ($prompt | str ends-with '!') {
|
||||
$'(ansi red)($prompt)(ansi reset)'
|
||||
} else {
|
||||
$'($prompt)'
|
||||
}
|
||||
(if $default_not { [no yes] } else { [yes no] } | input list $prompt) == 'yes'
|
||||
}
|
||||
|
||||
def tips [ msg ] {
|
||||
print -e $"(ansi light_gray)($msg)(ansi reset)"
|
||||
}
|
||||
|
||||
def --wrapped with-flag [...flag] {
|
||||
if ($in | is-empty) { [] } else { [...$flag $in] }
|
||||
}
|
||||
|
||||
# git status
|
||||
export def gs [] {
|
||||
git status
|
||||
}
|
||||
|
||||
# git stash
|
||||
export def gst [
|
||||
--apply (-a)
|
||||
--clear (-c)
|
||||
--drop (-d)
|
||||
--list (-l)
|
||||
--pop (-p)
|
||||
--show (-s)
|
||||
--all (-A)
|
||||
--include-untracked (-i)
|
||||
] {
|
||||
if $apply {
|
||||
git stash apply
|
||||
} else if $clear {
|
||||
git stash clear
|
||||
} else if $drop {
|
||||
git stash drop
|
||||
} else if $list {
|
||||
git stash list
|
||||
} else if $pop {
|
||||
git stash pop
|
||||
} else if $show {
|
||||
git stash show --text
|
||||
} else if $all {
|
||||
git stash --all ...(if $include_untracked {[--include-untracked]} else {[]})
|
||||
} else {
|
||||
git stash
|
||||
}
|
||||
}
|
||||
|
||||
# git log
|
||||
export def gl [
|
||||
commit?: string@"nu-complete git log"
|
||||
--verbose(-v)
|
||||
--num(-n):int=32
|
||||
] {
|
||||
if ($commit|is-empty) {
|
||||
_git_log $verbose $num
|
||||
} else {
|
||||
git log --stat -p -n 1 $commit
|
||||
}
|
||||
}
|
||||
|
||||
# git branch
|
||||
export def gb [
|
||||
branch?: string@"nu-complete git branches"
|
||||
--remote (-r)='origin': string@"nu-complete git remotes"
|
||||
--delete (-d)
|
||||
--no-merged (-n)
|
||||
] {
|
||||
let bs = git branch | lines | each {|x| $x | str substring 2..}
|
||||
if $delete {
|
||||
let remote_branches = (remote_branches)
|
||||
if ($branch | is-empty) {
|
||||
let dels = if $no_merged { gb } else {
|
||||
gb
|
||||
| where { $in.merged | is-not-empty }
|
||||
}
|
||||
| where { ($in.remote | is-empty) and ($in.current | is-empty) }
|
||||
| each {|x|
|
||||
let pf = if ($x.current | is-empty) { " " } else { $"(ansi cyan)* " }
|
||||
let nm = if ($x.merged | is-not-empty ) { $"(ansi green)☑ " } else { " " }
|
||||
$x | insert display $"($nm)($pf)(ansi reset)($x.branch)"
|
||||
}
|
||||
if ($dels | is-empty) {
|
||||
tips "no branches to delete"
|
||||
return
|
||||
}
|
||||
let $dels = $dels
|
||||
| input list -d display --multi
|
||||
| get branch
|
||||
for b in $dels {
|
||||
tips $"delete (ansi yellow)($b)"
|
||||
git branch -D $b
|
||||
}
|
||||
if ($dels | is-not-empty) and (agree 'delete remote branch?!') {
|
||||
for b in ($dels | filter { $"($remote)/($in)" in $remote_branches }) {
|
||||
tips $"delete (ansi yellow)($remote)/($b)"
|
||||
git branch -D -r $'($remote)/($b)'
|
||||
git push $remote -d $b
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if $branch in $bs and (agree 'branch will be delete!') {
|
||||
git branch -D $branch
|
||||
}
|
||||
if $"($remote)/($branch)" in $remote_branches and (agree 'delete remote branch?!') {
|
||||
git branch -D -r $'($remote)/($branch)'
|
||||
git push $remote -d $branch
|
||||
}
|
||||
}
|
||||
} else if ($branch | is-empty) {
|
||||
let merged = git branch --merged
|
||||
| lines
|
||||
| each { $in | parse -r '\s*\*?\s*(?<b>[^\s]+)' | get 0.b }
|
||||
{
|
||||
local: (git branch)
|
||||
remote: (git branch --remote)
|
||||
}
|
||||
| transpose k v
|
||||
| each {|x|
|
||||
$x.v | lines
|
||||
| each {|n|
|
||||
let n = $n | parse -r '\s*(?<c>\*)?\s*(?<b>[^\s]+)( -> )?(?<r>[^\s]+)?' | get 0
|
||||
let c = if ($n.c | is-empty) { null } else { true }
|
||||
let r = if ($n.r | is-empty) { null } else { $n.r }
|
||||
let m = if $n.b in $merged { true } else { null }
|
||||
let rm = if $x.k == 'remote' { true } else { null }
|
||||
{ current: $c, remote: $rm, branch: $n.b, ref: $r, merged: $m }
|
||||
}
|
||||
}
|
||||
| flatten
|
||||
} else if $branch in $bs {
|
||||
git checkout $branch
|
||||
} else {
|
||||
if (agree 'create new branch?') {
|
||||
git checkout -b $branch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# git clone, init
|
||||
export def --env gn [
|
||||
repo?: string@"nu-complete git branches"
|
||||
local?: path
|
||||
--submodule (-s) # git submodule
|
||||
--init (-i) # git init
|
||||
] {
|
||||
if $init {
|
||||
if ($repo | is-empty) {
|
||||
git init --initial-branch main
|
||||
} else {
|
||||
git init $repo --initial-branch main
|
||||
cd $repo
|
||||
}
|
||||
if $submodule {
|
||||
git submodule init
|
||||
}
|
||||
} else {
|
||||
let local = if ($local | is-empty) {
|
||||
$repo | path basename | split row '.' | get 0
|
||||
} else {
|
||||
$local
|
||||
}
|
||||
git clone ...(if $submodule {[--recurse-submodules]} else {[]}) $repo $local
|
||||
cd $local
|
||||
}
|
||||
}
|
||||
|
||||
# edit .gitignore
|
||||
export def gig [--empty-dir] {
|
||||
if $empty_dir {
|
||||
[
|
||||
'# Ignore everything in this directory'
|
||||
'*'
|
||||
'# Except this file'
|
||||
'!.gitignore'
|
||||
] | str join (char newline) | save .gitignore
|
||||
} else {
|
||||
^$env.EDITOR $"(git rev-parse --show-toplevel)/.gitignore"
|
||||
}
|
||||
}
|
||||
|
||||
# git pull, push and switch
|
||||
export def gp [
|
||||
branch?: string@"nu-complete git branches"
|
||||
--remote (-r)='origin': string@"nu-complete git remotes"
|
||||
--force (-f) # git push -f
|
||||
--override
|
||||
--submodule (-s) # git submodule
|
||||
--init (-i) # git init
|
||||
--merge (-m) # git pull (no)--rebase
|
||||
--autostash (-a) # git pull --autostash
|
||||
--back-to-prev (-b) # back to branch
|
||||
] {
|
||||
if $submodule {
|
||||
git submodule update
|
||||
} else if $override {
|
||||
git pull --rebase
|
||||
git add --all
|
||||
git commit -v -a --no-edit --amend
|
||||
git push --force
|
||||
} else {
|
||||
let m = if $merge { [] } else { [--rebase] }
|
||||
let a = if $autostash {[--autostash]} else {[]}
|
||||
let prev = (_git_status).branch
|
||||
let branch = if ($branch | is-empty) { $prev } else { $branch }
|
||||
let branch_repr = $'(ansi yellow)($branch)(ansi light_gray)'
|
||||
let lbs = git branch | lines | each { $in | str substring 2..}
|
||||
let rbs = (remote_branches)
|
||||
if $"($remote)/($branch)" in $rbs {
|
||||
if $branch in $lbs {
|
||||
let bmsg = $'both local and remote have ($branch_repr) branch'
|
||||
if $force {
|
||||
tips $'($bmsg), with `--force`, push'
|
||||
git branch -u $'($remote)/($branch)' $branch
|
||||
git push --force
|
||||
} else {
|
||||
tips $'($bmsg), pull'
|
||||
if $prev != $branch {
|
||||
tips $'switch to ($branch_repr)'
|
||||
git checkout $branch
|
||||
}
|
||||
git pull ...$m ...$a
|
||||
}
|
||||
} else {
|
||||
tips $"local doesn't have ($branch_repr) branch, fetch"
|
||||
git checkout -b $branch
|
||||
git fetch $remote $branch
|
||||
git branch -u $'($remote)/($branch)' $branch
|
||||
git pull ...$m ...$a -v
|
||||
}
|
||||
} else {
|
||||
let bmsg = $"remote doesn't have ($branch_repr) branch"
|
||||
let force = if $force {[--force]} else {[]}
|
||||
if $branch in $lbs {
|
||||
tips $'($bmsg), set upstream and push'
|
||||
git checkout $branch
|
||||
} else {
|
||||
tips $'($bmsg), create and push'
|
||||
git checkout -b $branch
|
||||
}
|
||||
git push ...$force --set-upstream $remote $branch
|
||||
}
|
||||
|
||||
if $back_to_prev {
|
||||
git checkout $prev
|
||||
}
|
||||
|
||||
let s = (_git_status)
|
||||
if $s.ahead > 0 {
|
||||
tips 'remote is behind, push'
|
||||
git push
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# git add, rm and restore
|
||||
export def ga [
|
||||
file?: path
|
||||
--all (-A)
|
||||
--patch (-p)
|
||||
--update (-u)
|
||||
--verbose (-v)
|
||||
--delete (-d) # git rm
|
||||
--cached (-c)
|
||||
--force (-f)
|
||||
--restore (-r) # git restore
|
||||
--staged (-s)
|
||||
--source (-o): string
|
||||
] {
|
||||
if $delete {
|
||||
let c = if $cached {[--cached]} else {[]}
|
||||
let f = if $force {[--force]} else {[]}
|
||||
git rm ...$c ...$f -r $file
|
||||
} else if $restore {
|
||||
let o = $source | with-flag --source
|
||||
let s = if $staged {[--staged]} else {[]}
|
||||
let file = if ($file | is-empty) { [.] } else { [$file] }
|
||||
git restore ...$o ...$s ...$file
|
||||
} else {
|
||||
let a = if $all {[--all]} else {[]}
|
||||
let p = if $patch {[--patch]} else {[]}
|
||||
let u = if $update {[--update]} else {[]}
|
||||
let v = if $verbose {[--verbose]} else {[]}
|
||||
let f = if $force {[--force]} else {[]}
|
||||
let file = if ($file | is-empty) { [.] } else { [$file] }
|
||||
git add ...([$a $p $u $v $f $file] | flatten)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# git commit
|
||||
export def gc [
|
||||
message?: string
|
||||
--all (-A)
|
||||
--amend (-a)
|
||||
--keep (-k)
|
||||
] {
|
||||
let m = $message | with-flag -m
|
||||
let a = if $all {[--all]} else {[]}
|
||||
let n = if $amend {[--amend]} else {[]}
|
||||
let k = if $keep {[--no-edit]} else {[]}
|
||||
git commit -v ...$m ...$a ...$n ...$k
|
||||
}
|
||||
|
||||
# git diff
|
||||
export def gd [
|
||||
file?: path
|
||||
--cached (-c) # cached
|
||||
--word-diff (-w) # word-diff
|
||||
--staged (-s) # staged
|
||||
] {
|
||||
let w = if $word_diff {[--word-diff]} else {[]}
|
||||
let c = if $cached {[--cached]} else {[]}
|
||||
let s = if $staged {[--staged]} else {[]}
|
||||
git diff ...$c ...$s ...$w ...($file | with-flag)
|
||||
}
|
||||
|
||||
# git merge
|
||||
export def gm [
|
||||
branch?: string@"nu-complete git branches"
|
||||
--abort (-a)
|
||||
--continue (-c)
|
||||
--quit (-q)
|
||||
--no-squash (-n) # git merge (no)--squash
|
||||
] {
|
||||
let x = if $no_squash { [] } else { [--squash] }
|
||||
if ($branch | is-empty) {
|
||||
git merge ...$x $"origin/(git_main_branch)"
|
||||
} else {
|
||||
git merge ...$x $branch
|
||||
}
|
||||
if not $no_squash {
|
||||
git commit -v
|
||||
}
|
||||
}
|
||||
|
||||
# git rebase
|
||||
# TODO: --onto: (commit_id)
|
||||
export def gr [
|
||||
branch?: string@"nu-complete git branches"
|
||||
--interactive (-i)
|
||||
--onto (-o): string
|
||||
--abort (-a)
|
||||
--continue (-c)
|
||||
--skip (-s)
|
||||
--quit (-q)
|
||||
] {
|
||||
if $abort {
|
||||
git rebase --abort
|
||||
} else if $continue {
|
||||
git rebase --continue
|
||||
} else if $skip {
|
||||
git rebase --skip
|
||||
} else if $quit {
|
||||
git rebase --quit
|
||||
} else if ($onto | is-not-empty) {
|
||||
git rebase --onto $branch
|
||||
} else {
|
||||
let i = if $interactive {[--interactive]} else {[]}
|
||||
if ($branch | is-empty) {
|
||||
git rebase ...$i (git_main_branch)
|
||||
} else {
|
||||
git rebase ...$i $branch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# git cherry-pick
|
||||
export def gcp [
|
||||
commit?: string@"nu-complete git log all"
|
||||
--abort (-a)
|
||||
--continue (-c)
|
||||
--skip (-s)
|
||||
--quit (-q)
|
||||
] {
|
||||
if $abort {
|
||||
git cherry-pick --abort
|
||||
} else if $continue {
|
||||
git cherry-pick --continue
|
||||
} else if $skip {
|
||||
git cherry-pick --skip
|
||||
} else if $quit {
|
||||
git cherry-pick --quit
|
||||
} else {
|
||||
git cherry-pick $commit
|
||||
}
|
||||
}
|
||||
|
||||
# copy file from other branch
|
||||
export def gcf [
|
||||
branch: string@"nu-complete git branches"
|
||||
...file: string@"nu-complete git branch files"
|
||||
] {
|
||||
^git checkout $branch $file
|
||||
}
|
||||
|
||||
# git reset
|
||||
export def grs [
|
||||
commit?: string@"nu-complete git log"
|
||||
--hard (-h)
|
||||
--clean (-c)
|
||||
] {
|
||||
let h = if $hard {[--hard]} else {[]}
|
||||
let cm = $commit | with-flag
|
||||
git reset ...$h ...$cm
|
||||
if $clean {
|
||||
git clean -fd
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# git remote
|
||||
export def grm [
|
||||
remote?: string@"nu-complete git remotes"
|
||||
uri?: string
|
||||
--add (-a)
|
||||
--rename (-r)
|
||||
--delete (-d)
|
||||
--update (-u)
|
||||
--set (-s)
|
||||
] {
|
||||
if ($remote | is-empty) {
|
||||
git remote -v
|
||||
} else if $add {
|
||||
git remote add $remote $uri
|
||||
} else if $set {
|
||||
git remote set-url $remote $uri
|
||||
} else if $rename {
|
||||
let old = $remote
|
||||
let new = $uri
|
||||
git remote rename $old $new
|
||||
} else if $delete {
|
||||
git remote remove $remote
|
||||
} else if $update {
|
||||
git remote update $remote
|
||||
} else {
|
||||
git remote show $remote
|
||||
}
|
||||
}
|
||||
|
||||
# git bisect
|
||||
export def gbs [
|
||||
--bad (-b)
|
||||
--good (-g)
|
||||
--reset (-r)
|
||||
--start (-s)
|
||||
] {
|
||||
if $good {
|
||||
git bisect good
|
||||
} else if $bad {
|
||||
git bisect bad
|
||||
} else if $reset {
|
||||
git bisect reset
|
||||
} else if $start {
|
||||
git bisect start
|
||||
} else {
|
||||
git bisect
|
||||
}
|
||||
}
|
||||
|
||||
export def gha [] {
|
||||
git log --pretty=%h»¦«%aN»¦«%s»¦«%aD
|
||||
| lines
|
||||
| split column "»¦«" sha1 committer desc merged_at
|
||||
| histogram committer merger
|
||||
| sort-by merger
|
||||
| reverse
|
||||
}
|
||||
|
||||
export def ggc [] {
|
||||
git reflog expire --all --expire=now
|
||||
git gc --prune=now --aggressive
|
||||
}
|
||||
|
||||
export alias gcl = git config --list
|
||||
export alias gsw = git switch
|
||||
export alias gswc = git switch -c
|
||||
export alias gts = git tag -s
|
||||
|
||||
export def _git_status [] {
|
||||
# TODO: show-stash
|
||||
let raw_status = do -i { git --no-optional-locks status --porcelain=2 --branch | lines }
|
||||
|
||||
let stashes = do -i { git stash list | lines | length }
|
||||
|
||||
mut status = {
|
||||
idx_added_staged : 0
|
||||
idx_modified_staged : 0
|
||||
idx_deleted_staged : 0
|
||||
idx_renamed : 0
|
||||
idx_type_changed : 0
|
||||
wt_untracked : 0
|
||||
wt_modified : 0
|
||||
wt_deleted : 0
|
||||
wt_type_changed : 0
|
||||
wt_renamed : 0
|
||||
ignored : 0
|
||||
conflicts : 0
|
||||
ahead : 0
|
||||
behind : 0
|
||||
stashes : $stashes
|
||||
repo_name : no_repository
|
||||
tag : no_tag
|
||||
branch : no_branch
|
||||
remote : ''
|
||||
}
|
||||
|
||||
if ($raw_status | is-empty) { return $status }
|
||||
|
||||
for s in $raw_status {
|
||||
let r = $s | split row ' '
|
||||
match $r.0 {
|
||||
'#' => {
|
||||
match ($r.1 | str substring 7..) {
|
||||
'oid' => {
|
||||
$status.commit_hash = ($r.2 | str substring 0..8)
|
||||
}
|
||||
'head' => {
|
||||
$status.branch = $r.2
|
||||
}
|
||||
'upstream' => {
|
||||
$status.remote = $r.2
|
||||
}
|
||||
'ab' => {
|
||||
$status.ahead = ($r.2 | into int)
|
||||
$status.behind = ($r.3 | into int | math abs)
|
||||
}
|
||||
}
|
||||
}
|
||||
'1'|'2' => {
|
||||
match ($r.1 | str substring 0..1) {
|
||||
'A' => {
|
||||
$status.idx_added_staged += 1
|
||||
}
|
||||
'M' => {
|
||||
$status.idx_modified_staged += 1
|
||||
}
|
||||
'R' => {
|
||||
$status.idx_renamed += 1
|
||||
}
|
||||
'D' => {
|
||||
$status.idx_deleted_staged += 1
|
||||
}
|
||||
'T' => {
|
||||
$status.idx_type_changed += 1
|
||||
}
|
||||
}
|
||||
match ($r.1 | str substring 1..2) {
|
||||
'M' => {
|
||||
$status.wt_modified += 1
|
||||
}
|
||||
'R' => {
|
||||
$status.wt_renamed += 1
|
||||
}
|
||||
'D' => {
|
||||
$status.wt_deleted += 1
|
||||
}
|
||||
'T' => {
|
||||
$status.wt_type_changed += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
'?' => {
|
||||
$status.wt_untracked += 1
|
||||
}
|
||||
'u' => {
|
||||
$status.conflicts += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$status
|
||||
}
|
||||
|
||||
export def _git_log_stat [n] {
|
||||
do -i {
|
||||
git log --reverse -n $n --pretty=»¦«%h --stat
|
||||
| lines
|
||||
| reduce -f { c: '', r: [] } {|it, acc|
|
||||
if ($it | str starts-with '»¦«') {
|
||||
$acc | upsert c ($it | str substring 6.. )
|
||||
} else if ($it | find -r '[0-9]+ file.+change' | is-empty) {
|
||||
$acc
|
||||
} else {
|
||||
let x = $it
|
||||
| split row ','
|
||||
| each {|x| $x
|
||||
| str trim
|
||||
| parse -r "(?<num>[0-9]+) (?<col>.+)"
|
||||
| get 0
|
||||
}
|
||||
| reduce -f {sha: $acc.c file:0 ins:0 del:0} {|i,a|
|
||||
let col = if ($i.col | str starts-with 'file') {
|
||||
'file'
|
||||
} else {
|
||||
$i.col | str substring ..3
|
||||
}
|
||||
let num = $i.num | into int
|
||||
$a | upsert $col $num
|
||||
}
|
||||
$acc | upsert r ($acc.r | append $x)
|
||||
}
|
||||
}
|
||||
| get r
|
||||
}
|
||||
}
|
||||
|
||||
export def _git_log [verbose num] {
|
||||
let r = do -i {
|
||||
git log --reverse -n $num --pretty=%h»¦«%s»¦«%aN»¦«%aE»¦«%aD»¦«%D
|
||||
| lines
|
||||
| split column "»¦«" sha message author email date refs
|
||||
| each {|x|
|
||||
let refs = if ($x.refs | is-empty) {
|
||||
$x.refs
|
||||
} else {
|
||||
$x.refs | split row ", "
|
||||
}
|
||||
$x
|
||||
| update date { $x.date | into datetime }
|
||||
| update refs $refs
|
||||
}
|
||||
}
|
||||
if $verbose {
|
||||
$r | merge ( _git_log_stat $num )
|
||||
} else {
|
||||
$r
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete git log" [] {
|
||||
git log -n 32 --pretty=%h»¦«%s
|
||||
| lines
|
||||
| split column "»¦«" value description
|
||||
| each {|x| $x | update value $"($x.value)"}
|
||||
}
|
||||
|
||||
def "nu-complete git log all" [] {
|
||||
git log --all -n 32 --pretty=%h»¦«%d»¦«%s
|
||||
| lines
|
||||
| split column "»¦«" value branch description
|
||||
| each {|x| $x | update description $"($x.branch) ($x.description)" }
|
||||
}
|
||||
|
||||
def "nu-complete git branch files" [context: string, offset:int] {
|
||||
let token = $context | split row ' '
|
||||
let branch = $token | get 1
|
||||
let files = $token | skip 2
|
||||
git ls-tree -r --name-only $branch
|
||||
| lines
|
||||
| filter {|x| not ($x in $files)}
|
||||
}
|
||||
|
||||
def "nu-complete git branches" [] {
|
||||
git branch
|
||||
| lines
|
||||
| filter {|x| not ($x | str starts-with '*')}
|
||||
| each {|x| $"($x|str trim)"}
|
||||
}
|
||||
|
||||
export def remote_branches [] {
|
||||
git branch -r
|
||||
| lines
|
||||
| str trim
|
||||
| filter {|x| not ($x | str starts-with 'origin/HEAD') }
|
||||
}
|
||||
|
||||
def "nu-complete git remotes" [] {
|
||||
^git remote | lines | each { |line| $line | str trim }
|
||||
}
|
||||
|
||||
def git_main_branch [] {
|
||||
git remote show origin
|
||||
| lines
|
||||
| str trim
|
||||
| find --regex 'HEAD .*?[:: ].+'
|
||||
| first
|
||||
| str replace --regex 'HEAD .*?[:: ](.+)' '$1'
|
||||
}
|
||||
|
||||
105
dot_config/nushell/nu_scripts/modules/history-utils/mod.nu
Normal file
105
dot_config/nushell/nu_scripts/modules/history-utils/mod.nu
Normal file
@@ -0,0 +1,105 @@
|
||||
def quote [...t] {
|
||||
$"'($t | str join '')'"
|
||||
}
|
||||
|
||||
def flatten_fields [args] {
|
||||
let f = $in | default [] | filter {|x| $x | is-not-empty }
|
||||
let prefix = $args.0
|
||||
let inner = $args.1
|
||||
let outer = $args.2
|
||||
if ($f | is-not-empty) {
|
||||
$f
|
||||
| each {|x|
|
||||
if ($x | describe -d).type == list {
|
||||
$x | str join $inner
|
||||
} else {
|
||||
$x
|
||||
}
|
||||
}
|
||||
| str join $outer
|
||||
| do { (if ($prefix | is-empty) {[$in]} else {[$prefix $in]})}
|
||||
} else { [] }
|
||||
}
|
||||
|
||||
def sql [q] {
|
||||
[
|
||||
[$q.select ['select', ' as ', ', ']]
|
||||
[$q.from ['from', ' as ', ' join ']]
|
||||
[$q.where? ['where', ' ', ' and ']]
|
||||
[$q.whereOr? ['or', ' ', ' or ']]
|
||||
[$q.groupBy? ['group by', null, ', ']]
|
||||
[$q.orderBy? ['order by', ' ', ', ']]
|
||||
[$q.limit? ['limit', null, ' offset ']]
|
||||
]
|
||||
| each {|x| $x.0 | flatten_fields $x.1 }
|
||||
| flatten
|
||||
| str join ' '
|
||||
}
|
||||
|
||||
export def 'history timing' [
|
||||
pattern?
|
||||
--exclude(-x): string
|
||||
--num(-n)=10
|
||||
--all(-a)
|
||||
] {
|
||||
open $nu.history-path | query db (sql {
|
||||
from: history
|
||||
where: [
|
||||
"cmd not like 'history timing%'"
|
||||
(if ($pattern | is-not-empty) {[cmd like (quote '%' $pattern '%')]})
|
||||
(if ($exclude | is-not-empty) {[cmd not like (quote '%' $exclude '%')]})
|
||||
(if not $all {[cwd = (quote $env.PWD)]})
|
||||
]
|
||||
orderBy: [[start desc]]
|
||||
select: [
|
||||
[duration_ms duration]
|
||||
[command_line cmd]
|
||||
[start_timestamp start]
|
||||
(if $all {[$"replace\(cwd, '($env.HOME)', '~')" cwd]})
|
||||
[exit_status exit]
|
||||
]
|
||||
limit: $num
|
||||
})
|
||||
| update duration {|x| $x.duration | default 0 | do { $in * 1_000_000 } | into duration }
|
||||
| update start {|x| $x.start | into int | do { $in * 1_000_000 } | into datetime }
|
||||
}
|
||||
|
||||
def "nu-complete history dir" [] {
|
||||
open $nu.history-path | query db (sql {
|
||||
select: [cwd ['count(1)' count]]
|
||||
from: history
|
||||
groupBy: [cwd]
|
||||
orderBy: ['count desc']
|
||||
limit: 20
|
||||
})
|
||||
| rename value description
|
||||
| update value {|x| $x.value | str replace $env.HOME '~' }
|
||||
}
|
||||
|
||||
export def 'history top' [
|
||||
num=10
|
||||
--before (-b): duration
|
||||
--dir (-d)
|
||||
--path(-p): list<string@"nu-complete history dir">
|
||||
] {
|
||||
open $nu.history-path | query db (sql {
|
||||
from: history
|
||||
select: [
|
||||
(if $dir {[$"replace\(cwd, '($env.HOME)', '~')" cwd]} else {[command_line cmd]})
|
||||
['count(1)' count]
|
||||
]
|
||||
where: [
|
||||
(if ($before | is-not-empty) {
|
||||
let ts = (date now) - $before | into int | do { $in / 1_000_000 }
|
||||
[start_timestamp > $ts]
|
||||
})
|
||||
(if ($path | is-not-empty) {
|
||||
let ps = $path | path expand | each { quote $in } | str join ', '
|
||||
[cwd in '(' $ps ')']
|
||||
})
|
||||
]
|
||||
groupBy: [(if $dir {'cwd'} else {'cmd'})]
|
||||
orderBy: [[count desc]]
|
||||
limit: $num
|
||||
})
|
||||
}
|
||||
30
dot_config/nushell/nu_scripts/modules/jc/mod.nu
Normal file
30
dot_config/nushell/nu_scripts/modules/jc/mod.nu
Normal file
@@ -0,0 +1,30 @@
|
||||
# Run `jc` (Json Converter)
|
||||
#
|
||||
# This module provides a wrapper around the `jc` command line tool and automatically
|
||||
# parses its output into a structured data format.
|
||||
#
|
||||
# Dependencies:
|
||||
# * `jc`
|
||||
#
|
||||
# Installation:
|
||||
# 1. Install the `jc` command line: https://kellyjonbrazil.github.io/jc/#installation
|
||||
# 2. Import this module in your `config.nu`: `import ~/.local/share/nu_scripts/modules/jc/`
|
||||
export def --wrapped main [...args]: [any -> table, any -> record, any -> string] {
|
||||
let run = (^jc ...$args | complete)
|
||||
|
||||
if $run.exit_code != 0 {
|
||||
error make {
|
||||
msg: $run.stderr,
|
||||
label: {
|
||||
text: "jc execution failed",
|
||||
span: (metadata $args).span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if '--help' in $args or '-h' in $args {
|
||||
$run.stdout
|
||||
} else {
|
||||
$run.stdout | from json
|
||||
}
|
||||
}
|
||||
178
dot_config/nushell/nu_scripts/modules/kubernetes/complete.nu
Normal file
178
dot_config/nushell/nu_scripts/modules/kubernetes/complete.nu
Normal file
@@ -0,0 +1,178 @@
|
||||
use argx
|
||||
use utils.nu *
|
||||
|
||||
export def "nu-complete kube ctx" [] {
|
||||
let k = (kube-config)
|
||||
let cache = $'($env.HOME)/.cache/nu-complete/k8s/($k.path | path basename).json'
|
||||
let data = ensure-cache-by-lines $cache $k.path { ||
|
||||
let clusters = $k.data | get clusters | select name cluster.server
|
||||
let data = $k.data
|
||||
| get contexts
|
||||
| reduce -f {completion:[], mx_ns: 0, mx_cl: 0} {|x, a|
|
||||
let ns = if ($x.context.namespace? | is-empty) { '' } else { $x.context.namespace }
|
||||
let max_ns = $ns | str length
|
||||
let cluster = $"($x.context.user)@($clusters | where name == $x.context.cluster | get cluster_server.0)"
|
||||
let max_cl = $cluster | str length
|
||||
$a
|
||||
| upsert mx_ns (if $max_ns > $a.mx_ns { $max_ns } else $a.mx_ns)
|
||||
| upsert mx_cl (if $max_cl > $a.mx_cl { $max_cl } else $a.mx_cl)
|
||||
| upsert completion ($a.completion | append {value: $x.name, ns: $ns, cluster: $cluster})
|
||||
}
|
||||
{completion: $data.completion, max: {ns: $data.mx_ns, cluster: $data.mx_cl}}
|
||||
}
|
||||
|
||||
$data.completion | each {|x|
|
||||
let ns = $x.ns | fill -a l -w $data.max.ns -c ' '
|
||||
let cl = $x.cluster | fill -a l -w $data.max.cluster -c ' '
|
||||
{value: $x.value, description: $"\t($ns) ($cl)"}
|
||||
}
|
||||
}
|
||||
|
||||
export def "nu-complete kube ns" [] {
|
||||
kubectl get namespaces
|
||||
| from ssv -a
|
||||
| each {|x|
|
||||
{value: $x.NAME, description: $"($x.AGE)\t($x.STATUS)"}
|
||||
}
|
||||
}
|
||||
|
||||
export def "nu-complete kube kind" [] {
|
||||
let ctx = (kube-config)
|
||||
let cache = $'($env.HOME)/.cache/nu-complete/k8s-api-resources/($ctx.data.current-context).json'
|
||||
ensure-cache-by-lines $cache $ctx.path {||
|
||||
kubectl api-resources | from ssv -a
|
||||
| each {|x| {value: $x.NAME description: $x.SHORTNAMES} }
|
||||
| append (kubectl get crd | from ssv -a | get NAME | wrap value)
|
||||
}
|
||||
}
|
||||
|
||||
export def "nu-complete kube res" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let kind = $ctx | get _args.1
|
||||
let ns = if ($ctx.namespace? | is-empty) { [] } else { [-n $ctx.namespace] }
|
||||
kubectl get ...$ns $kind | from ssv -a | get NAME
|
||||
}
|
||||
|
||||
export def "nu-complete kube res via name" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let kind = $env.KUBERNETES_RESOURCE_ABBR | get ($ctx | get _args.0 | str substring (-1..))
|
||||
let ns = if ($ctx.namespace? | is-empty) { [] } else { [-n $ctx.namespace] }
|
||||
kubectl get ...$ns $kind | from ssv -a | get NAME
|
||||
}
|
||||
|
||||
export def "nu-complete kube jsonpath" [context: string] {
|
||||
let ctx = $context | argx parse
|
||||
let kind = $ctx | get _args.1
|
||||
let res = $ctx | get _args.2
|
||||
let path = $ctx.jsonpath?
|
||||
let ns = if ($ctx.namespace? | is-empty) { [] } else { [-n $ctx.namespace] }
|
||||
mut r = []
|
||||
if ($path | is-empty) {
|
||||
if ($context | str ends-with '-p ') {
|
||||
$r = ['.']
|
||||
} else {
|
||||
$r = ['']
|
||||
}
|
||||
} else if ($path | str starts-with '.') {
|
||||
let row = $path | split row '.'
|
||||
let p = $row | range ..-2 | str join '.'
|
||||
if ($p | is-empty) {
|
||||
$r = ( kubectl get ...$ns -o json $kind $res
|
||||
| from json
|
||||
| columns
|
||||
| each {|x| $'($p).($x)'}
|
||||
)
|
||||
} else {
|
||||
let m = kubectl get ...$ns $kind $res $"--output=jsonpath={($p)}" | from json
|
||||
let l = $row | last
|
||||
let c = do -i {$m | get $l}
|
||||
if ($c | is-not-empty) and ($c | describe | str substring 0..5) == 'table' {
|
||||
$r = (0..(($c | length) - 1) | each {|x| $'($p).($l)[($x)]'})
|
||||
} else {
|
||||
$r = ($m | columns | each {|x| $'($p).($x)'})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$r = ['']
|
||||
}
|
||||
$r
|
||||
}
|
||||
|
||||
|
||||
export def "nu-complete kube nodes" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
kubectl get nodes -o wide | from ssv -a
|
||||
| each {|x| {value: $x.NAME, description: $"($x.INTERNAL-IP)(char tab)($x.ROLES)"} }
|
||||
}
|
||||
|
||||
export def "nu-complete kube deploys" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let ns = $ctx.namespace? | with-flag -n
|
||||
kubectl get ...$ns deployments | from ssv -a | get NAME
|
||||
}
|
||||
|
||||
export def "nu-complete kube deploys and pods" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let ns = $ctx.namespace? | with-flag -n
|
||||
let all_pods = ($ctx.a? | default false) or ($ctx.all-pods? | default false)
|
||||
if $all_pods or ($ctx._pos.pod? | default '' | str ends-with '-') {
|
||||
kubectl get ...$ns pods | from ssv -a | get NAME
|
||||
} else {
|
||||
kubectl get ...$ns deployments | from ssv -a | get NAME | each {|x| $"($x)-"}
|
||||
}
|
||||
}
|
||||
|
||||
export def "nu-complete kube ctns" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let ns = $ctx.namespace? | with-flag -n
|
||||
let pod = $ctx | get _args.1
|
||||
kubectl get ...$ns pod $pod -o jsonpath={.spec.containers[*].name} | split row ' '
|
||||
}
|
||||
|
||||
export def "nu-complete port forward type" [] {
|
||||
[pod svc]
|
||||
}
|
||||
|
||||
export def "nu-complete kube port" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let kind = $ctx | get _args.1
|
||||
let ns = if ($ctx.namespace? | is-empty) { [] } else { [-n $ctx.namespace] }
|
||||
let res = $ctx | get _args.2
|
||||
if ($kind | str starts-with 's') {
|
||||
kubectl get ...$ns svc $res --output=jsonpath="{.spec.ports}"
|
||||
| from json
|
||||
| each {|x| {value: $x.port description: $x.name} }
|
||||
} else {
|
||||
kubectl get ...$ns pods $res --output=jsonpath="{.spec.containers[].ports}"
|
||||
| from json
|
||||
| each {|x| {value: $x.containerPort description: $x.name?} }
|
||||
}
|
||||
}
|
||||
|
||||
export def "nu-complete kube cp" [cmd: string, offset: int] {
|
||||
let ctx = $cmd | str substring ..$offset | argx parse
|
||||
let p = $ctx._args | get (($ctx._args | length) - 1)
|
||||
let ns = $ctx.namespace? | with-flag -n
|
||||
let c = $ctx.container? | with-flag -c
|
||||
let ctn = kubectl get pod ...$ns | from ssv -a | each {|x| {description: $x.READY value: $"($x.NAME):" }}
|
||||
let n = $p | split row ':'
|
||||
if $"($n | get 0):" in ($ctn | get value) {
|
||||
kubectl exec ...$ns ($n | get 0) ...$c -- sh -c $"ls -dp ($n | get 1)*"
|
||||
| lines
|
||||
| each {|x| $"($n | get 0):($x)"}
|
||||
} else {
|
||||
let files = do -i { ls -a ($"($p)*" | into glob)
|
||||
| each {|x| if $x.type == dir { $"($x.name)/"} else { $x.name }}
|
||||
}
|
||||
$files | append $ctn
|
||||
}
|
||||
}
|
||||
|
||||
export def "nu-complete kube kind with image" [] {
|
||||
[
|
||||
deployment daemonset statefulset
|
||||
pod replicationcontroller
|
||||
cronjob replicaset
|
||||
]
|
||||
}
|
||||
|
||||
155
dot_config/nushell/nu_scripts/modules/kubernetes/compose.nu
Normal file
155
dot_config/nushell/nu_scripts/modules/kubernetes/compose.nu
Normal file
@@ -0,0 +1,155 @@
|
||||
# kubernetes to docker-compose
|
||||
export def kube-compose [--without-service(-s)] {
|
||||
let a = $in
|
||||
let dpl = $a | where kind == 'Deployment'
|
||||
mut dpl_svc = {}
|
||||
mut svc = {}
|
||||
if not $without_service {
|
||||
let svcs = $a | where kind == 'Service'
|
||||
for s in $svcs {
|
||||
for d in $dpl {
|
||||
let dl = $d.metadata.labels?
|
||||
let ss = $s.spec.selector?
|
||||
mut p = true
|
||||
for x in ($ss | transpose k v) {
|
||||
if (not ($x.k in $dl)) or (($dl | get $x.k) != $x.v) {
|
||||
$p = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if $p {
|
||||
let dn = $d.metadata.name
|
||||
let dv = if $dn in $dpl_svc {
|
||||
$dpl_svc | get $dn
|
||||
} else { [] }
|
||||
$dpl_svc = ($dpl_svc | upsert $dn ($dv | append $s.metadata.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
$svc = ($svcs
|
||||
| reduce -f {} {|i, a|
|
||||
$a | upsert $i.metadata.name $i.spec.ports
|
||||
})
|
||||
}
|
||||
let dpl_svc = $dpl_svc
|
||||
let svc = $svc
|
||||
|
||||
let cm = $a | where kind == 'ConfigMap'
|
||||
| reduce -f {} {|i,a|
|
||||
let p = ['.kcmp', 'ConfigMap', $i.metadata.name] | path join
|
||||
mkdir $p
|
||||
for f in ($i.data | transpose k v) {
|
||||
$f.v | save -f ([$p $f.k] | path join)
|
||||
}
|
||||
$a | insert $i.metadata.name $p
|
||||
}
|
||||
let sec = $a | where kind == 'Secret'
|
||||
| reduce -f {} {|i,a|
|
||||
let p = ['.kcmp', 'Secret', $i.metadata.name] | path join
|
||||
mkdir $p
|
||||
for f in ($i.data | transpose k v) {
|
||||
$f.v | decode base64 | save -f ([$p $f.k] | path join)
|
||||
}
|
||||
$a | insert $i.metadata.name $p
|
||||
}
|
||||
let pv = $a | where kind == 'PersistentVolume'
|
||||
| reduce -f {} {|i,a| $a | insert $i.metadata.name $i.spec.local?.path? }
|
||||
let pvc = $a | where kind == 'PersistentVolumeClaim'
|
||||
| reduce -f {} {|i,a| $a | insert $i.metadata.name ($pv | get $i.spec.volumeName) }
|
||||
|
||||
let services = $dpl
|
||||
| each {|x|
|
||||
let d = $x.metadata.name
|
||||
let s = if not $without_service {
|
||||
$dpl_svc
|
||||
| get $d
|
||||
| each {|z| $svc | get $z}
|
||||
| flatten
|
||||
| each {|z| [$z.port $z.targetPort] }
|
||||
}
|
||||
|
||||
let v = $x.spec.template.spec.volumes?
|
||||
| reduce -f {} {|i,a|
|
||||
$a | insert $i.name $i
|
||||
}
|
||||
|
||||
$x.spec.template.spec.containers?
|
||||
| default []
|
||||
| each {|y|
|
||||
let ca = $y.securityContext?.capabilities?.add?
|
||||
let cd = $y.securityContext?.capabilities?.drop?
|
||||
let v = $y.volumeMounts?
|
||||
| default []
|
||||
| each {|z|
|
||||
let sp = $z.subPath? | default ''
|
||||
let s = $v | get $z.name
|
||||
let s = if ($s.hostPath? | is-not-empty) {
|
||||
$s.hostPath.path
|
||||
} else if ($s.path? | is-not-empty) {
|
||||
$s.path
|
||||
} else if ($s.persistentVolumeClaim?.claimName? | is-not-empty) {
|
||||
$pvc | get $s.persistentVolumeClaim.claimName
|
||||
} else if ($s.configMap?.name? | is-not-empty) {
|
||||
['.'
|
||||
($cm | get $s.configMap.name)
|
||||
$sp
|
||||
] | path join
|
||||
} else if ($s.secret?.secretName? | is-not-empty) {
|
||||
['.'
|
||||
($sec | get $s.secret.secretName)
|
||||
$sp
|
||||
] | path join
|
||||
} else {
|
||||
$s
|
||||
}
|
||||
let m = [$z.mountPath $sp] | path join
|
||||
$"($s):($m)"
|
||||
}
|
||||
let s = if $without_service {
|
||||
$y.ports? | default [] | each {|x| $"($x.containerPort):($x.containerPort)"}
|
||||
} else {
|
||||
$s | each {|x|
|
||||
if ($x.1 | find -r '[^0-9]' | is-empty) {
|
||||
$"($x.0):($x.1)"
|
||||
} else {
|
||||
mut p = ''
|
||||
for i in ($y.ports? | default []) {
|
||||
if $i.name == $x.1 {
|
||||
$p = $i.containerPort
|
||||
break
|
||||
}
|
||||
}
|
||||
$"($x.0):($p)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
name: $"($d)_($y.name)"
|
||||
image: $y.image
|
||||
environment: ($y.env? | reduce -f {} {|i,a| $a | insert $i.name $i.value?})
|
||||
ports: $s
|
||||
entrypoint: $y.command?
|
||||
command: $y.args?
|
||||
cap_add: $ca
|
||||
cap_drop: $cd
|
||||
volumes: $v
|
||||
}
|
||||
| transpose k v
|
||||
| reduce -f {} {|i,a|
|
||||
if ($i.v | is-empty) {
|
||||
$a
|
||||
} else {
|
||||
$a | insert $i.k $i.v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
| flatten
|
||||
| reduce -f {} {|i,a|
|
||||
$a | insert $i.name ($i | reject name)
|
||||
}
|
||||
|
||||
{ version: '3.8', services: $services}
|
||||
| to yaml
|
||||
}
|
||||
58
dot_config/nushell/nu_scripts/modules/kubernetes/conf.nu
Normal file
58
dot_config/nushell/nu_scripts/modules/kubernetes/conf.nu
Normal file
@@ -0,0 +1,58 @@
|
||||
use complete.nu *
|
||||
|
||||
export def 'kconf import' [name: string, path: string] {
|
||||
let k = (kube-config)
|
||||
mut d = $k.data
|
||||
let i = cat $path | from yaml
|
||||
let c = {
|
||||
context: {
|
||||
cluster: $name,
|
||||
namespace: default,
|
||||
user: $name
|
||||
}
|
||||
name: $name,
|
||||
}
|
||||
$d.clusters = (upsert_row $d.clusters name [] $name ($i.clusters.0 | upsert name $name))
|
||||
$d.users = (upsert_row $d.users name [] $name ($i.users.0 | upsert name $name))
|
||||
$d.contexts = (upsert_row $d.contexts name [] $name $c)
|
||||
$d | to yaml
|
||||
}
|
||||
|
||||
export def 'kconf delete' [name: string@"nu-complete kube ctx"] {
|
||||
let kc = (kube-config)
|
||||
let d = $kc.data
|
||||
let ctx = $d | get contexts | where name == $name | get 0
|
||||
let rctx = $d | get contexts | where name != $name
|
||||
let user = if ($ctx.context.user in ($rctx | get context.user)) {
|
||||
$d | get users
|
||||
} else {
|
||||
$d | get users | where name != $ctx.context.user
|
||||
}
|
||||
let cluster = if ($ctx.context.cluster in ($rctx | get context.cluster)) {
|
||||
$d | get clusters
|
||||
} else {
|
||||
$d | get clusters | where name != $ctx.context.cluster
|
||||
}
|
||||
$d
|
||||
| update contexts $rctx
|
||||
| update users $user
|
||||
| update clusters $cluster
|
||||
| to yaml
|
||||
}
|
||||
|
||||
export def 'kconf export' [name: string@"nu-complete kube ctx"] {
|
||||
let d = (kube-config).data
|
||||
let ctx = $d | get contexts | where name == $name | get 0
|
||||
let user = $d | get users | where name == $ctx.context.user
|
||||
let cluster = $d | get clusters | where name == $ctx.context.cluster
|
||||
{
|
||||
apiVersion: 'v1',
|
||||
current-context: $ctx.name,
|
||||
kind: Config,
|
||||
clusters: $cluster,
|
||||
preferences: {},
|
||||
contexts: [$ctx],
|
||||
users: $user,
|
||||
} | to yaml
|
||||
}
|
||||
|
||||
188
dot_config/nushell/nu_scripts/modules/kubernetes/env.nu
Normal file
188
dot_config/nushell/nu_scripts/modules/kubernetes/env.nu
Normal file
@@ -0,0 +1,188 @@
|
||||
export-env {
|
||||
$env.KUBERNETES_SCHEMA_URL = $"file:///($env.HOME)/.config/kubernetes-json-schema/all.json"
|
||||
$env.KUBERNETES_RESOURCE_ABBR = {
|
||||
s: services
|
||||
d: deployments
|
||||
p: pods
|
||||
}
|
||||
let id = {
|
||||
name: [metadata name]
|
||||
kind: [kind {|x|$x| str downcase}]
|
||||
apiVersion: [apiVersion]
|
||||
labels: [metadata labels]
|
||||
created: [metadata creationTimestamp {|x|$x | into datetime}]
|
||||
}
|
||||
let ids = {...$id, namespace: [metadata namespace] }
|
||||
$env.KUBERNETES_REFINE = {
|
||||
_namespace: [
|
||||
kube-system kube-node-lease kube-public
|
||||
kube-flannel istio-system ingress-nginx
|
||||
]
|
||||
shortnames: {
|
||||
sc: storageclasses
|
||||
ing: ingresses
|
||||
vs: virtualservices
|
||||
gw: gateways.networking.istio.io
|
||||
gtw: gateways
|
||||
dr: destinationrules
|
||||
ev: events
|
||||
cj: cronjobs
|
||||
hpa: horizontalpodautoscalers
|
||||
sts: statefulsets
|
||||
rs: replicasets
|
||||
deploy: deployments
|
||||
ds: daemonsets
|
||||
crd: customresourcedefinitions
|
||||
svc: services
|
||||
sa: serviceaccounts
|
||||
quota: resourcequotas
|
||||
rc: replicationcontrollers
|
||||
po: pods
|
||||
pv: persistentvolumes
|
||||
pvc: persistentvolumeclaims
|
||||
no: nodes
|
||||
ns: namespaces
|
||||
ep: endpoints
|
||||
cm: configmaps
|
||||
}
|
||||
cluster_resources: {
|
||||
namespaces: {
|
||||
...$id
|
||||
}
|
||||
}
|
||||
cluster_status: {
|
||||
|
||||
}
|
||||
status: {
|
||||
deployments: {
|
||||
conditions: {
|
||||
_: [status conditions]
|
||||
type: [type]
|
||||
reason: [reason]
|
||||
message: [message]
|
||||
}
|
||||
}
|
||||
pods: {
|
||||
...$ids
|
||||
image: [spec containers image]
|
||||
containers: {
|
||||
_: [spec containers]
|
||||
name: [name]
|
||||
image: [image]
|
||||
serviceAccount: [serviceAccount]
|
||||
env: [env]
|
||||
args: [args]
|
||||
ports: [ports]
|
||||
volumeMounts: [volumeMounts]
|
||||
node: [nodeName]
|
||||
nodeSelector: [nodeSelector]
|
||||
}
|
||||
hostIP: [status hostIP]
|
||||
podIP: [status podIP]
|
||||
phase: [status phase]
|
||||
startTime: [status startTime]
|
||||
conditions: {
|
||||
_: [status conditions]
|
||||
type: [type]
|
||||
reason: [reason]
|
||||
message: [message]
|
||||
}
|
||||
}
|
||||
}
|
||||
resources: {
|
||||
deployments: {
|
||||
...$ids
|
||||
replicas: [spec replicas]
|
||||
containers: {
|
||||
_: [spec template spec containers]
|
||||
name: [name]
|
||||
labels: [metadata labels]
|
||||
image: [image]
|
||||
imagePullPolicy: [imagePullPolicy]
|
||||
env: [env]
|
||||
ports: [ports]
|
||||
resources: [resources]
|
||||
args: [args]
|
||||
label: [label]
|
||||
replicas: [replicas]
|
||||
}
|
||||
}
|
||||
services: {
|
||||
...$ids
|
||||
type: [spec type]
|
||||
clusterIP: [spec clusterIP]
|
||||
ports: [spec ports]
|
||||
selector: [spec selector]
|
||||
sessionAffinity: [sessionAffinity]
|
||||
}
|
||||
configmaps: {
|
||||
...$ids
|
||||
data: [data]
|
||||
}
|
||||
secrets: {
|
||||
...$ids
|
||||
data: [data]
|
||||
type: [type]
|
||||
}
|
||||
gateways: {
|
||||
...$ids
|
||||
addresses: [spec addresses]
|
||||
gatewayClassName: [spec gatewayClassName]
|
||||
listeners: {
|
||||
_: [spec listeners]
|
||||
name: [name]
|
||||
hostname: [hostname]
|
||||
port: [port]
|
||||
protocol: [protocol]
|
||||
tls: [tls]
|
||||
}
|
||||
|
||||
}
|
||||
httproutes: {
|
||||
...$ids
|
||||
hostnames: [spec hostnames]
|
||||
parentRefs: [spec parentRefs name]
|
||||
rules: {
|
||||
_: [spec rules]
|
||||
backend: {
|
||||
_: [backendRefs]
|
||||
name: [name]
|
||||
port: [port]
|
||||
weight: [weight]
|
||||
}
|
||||
matches: {
|
||||
_: [matches]
|
||||
type: [path type]
|
||||
value: [path value]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
virtualservices.networking.istio.io: {
|
||||
...$ids
|
||||
http: [spec http]
|
||||
gateways: {
|
||||
_: [spec gateways]
|
||||
hosts: {
|
||||
_: [spec hosts]
|
||||
}
|
||||
}
|
||||
}
|
||||
gateways.networking.istio.io: {
|
||||
...$ids
|
||||
selector: [spec selector]
|
||||
servers: [spec servers]
|
||||
|
||||
}
|
||||
ingresses: {
|
||||
...$ids
|
||||
annotations: [metadata annotations]
|
||||
rules: {
|
||||
_: [spec rules]
|
||||
host: [host]
|
||||
http: [http]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
125
dot_config/nushell/nu_scripts/modules/kubernetes/helm.nu
Normal file
125
dot_config/nushell/nu_scripts/modules/kubernetes/helm.nu
Normal file
@@ -0,0 +1,125 @@
|
||||
use complete.nu *
|
||||
use utils.nu *
|
||||
use argx
|
||||
|
||||
export def record-to-set-json [value] {
|
||||
$value | transpose k v
|
||||
| each {|x| $"($x.k)=($x.v | to json -r)"}
|
||||
| str join ','
|
||||
}
|
||||
|
||||
def "nu-complete helm list" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
kgh -n $ctx.namespace? | each {|x| {value: $x.name description: $x.updated} }
|
||||
}
|
||||
|
||||
def "nu-complete helm charts" [context: string, offset: int] {
|
||||
let ctx = $context | argx parse
|
||||
let path = $ctx | get _pos.chart?
|
||||
let paths = do -i { ls ($"($path)*" | into glob) | each {|x| if $x.type == dir { $"($x.name)/"} else { $x.name }} }
|
||||
helm repo list | from ssv -a | rename value description
|
||||
| append $paths
|
||||
}
|
||||
|
||||
|
||||
# helm list and get
|
||||
export def kgh [
|
||||
name?: string@"nu-complete helm list"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--manifest (-m)
|
||||
--values(-v)
|
||||
--all (-a)
|
||||
] {
|
||||
if ($name | is-empty) {
|
||||
let ns = if $all { [--all] } else { $namespace | with-flag -n }
|
||||
helm list ...$ns --output json
|
||||
| from json
|
||||
| update updated {|x|
|
||||
$x.updated
|
||||
| str substring ..-4
|
||||
| into datetime -f '%Y-%m-%d %H:%M:%S.%f %z'
|
||||
}
|
||||
} else {
|
||||
if $manifest {
|
||||
helm get manifest $name ...($namespace | with-flag -n)
|
||||
} else if $values {
|
||||
helm get values $name ...($namespace | with-flag -n)
|
||||
} else {
|
||||
helm get notes $name ...($namespace | with-flag -n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# helm install or upgrade via values file
|
||||
export def kah [
|
||||
name: string@"nu-complete helm list"
|
||||
chart: string@"nu-complete helm charts"
|
||||
valuefile: path
|
||||
--values (-v): any
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--ignore-image (-i) # for kdh
|
||||
] {
|
||||
let update = $name in (
|
||||
helm list ...($namespace | with-flag -n) --output json
|
||||
| from json | get name
|
||||
)
|
||||
let act = if $update { [upgrade] } else { [install] }
|
||||
let values = if ($values | is-empty) { [] } else { [--set-json (record-to-set-json $values)] }
|
||||
helm ...$act $name $chart -f $valuefile ...$values ...($namespace | with-flag -n)
|
||||
}
|
||||
|
||||
# helm diff
|
||||
export def kdh [
|
||||
name: string@"nu-complete helm list"
|
||||
chart: string@"nu-complete helm charts"
|
||||
valuefile: path
|
||||
--values (-v): any
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--ignore-image (-i)
|
||||
--has-plugin (-h)
|
||||
] {
|
||||
if $has_plugin {
|
||||
helm diff $name $chart -f $valuefile ...($namespace | with-flag -n)
|
||||
} else {
|
||||
let update = $name in (
|
||||
helm list ...($namespace | with-flag -n) --output json
|
||||
| from json | get name
|
||||
)
|
||||
if not $update {
|
||||
echo "new installation"
|
||||
return
|
||||
}
|
||||
|
||||
let values = if ($values | is-empty) { [] } else { [--set-json (record-to-set-json $values)] }
|
||||
let target = $'/tmp/($chart | path basename).($name).out.yaml'
|
||||
helm template --debug $name $chart -f $valuefile ...$values ...($namespace | with-flag -n) | save -f $target
|
||||
if $ignore_image {
|
||||
do -i { yq -i ea 'del(.spec.template.spec.containers.[].image)' $target }
|
||||
}
|
||||
kubectl diff -f $target
|
||||
}
|
||||
}
|
||||
|
||||
# helm delete
|
||||
export def kdelh [
|
||||
name: string@"nu-complete helm list"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
helm uninstall $name ...($namespace | with-flag -n)
|
||||
}
|
||||
|
||||
# helm template
|
||||
export def kh [
|
||||
chart: string@"nu-complete helm charts"
|
||||
valuefile: path
|
||||
--values (-v): any
|
||||
--namespace (-n): string@"nu-complete kube ns"='test'
|
||||
--app (-a): string='test'
|
||||
] {
|
||||
let values = if ($values | is-empty) { [] } else { [--set-json (record-to-set-json $values)] }
|
||||
let target = $valuefile | split row '.' | range ..-2 | append [out yaml] | str join '.'
|
||||
if (not ($target | path exists)) and (([yes no] | input list $'create ($target)?') in [no]) { return }
|
||||
helm template --debug $app $chart -f $valuefile ...$values ...($namespace | with-flag -n)
|
||||
| save -f $target
|
||||
}
|
||||
|
||||
573
dot_config/nushell/nu_scripts/modules/kubernetes/mod.nu
Normal file
573
dot_config/nushell/nu_scripts/modules/kubernetes/mod.nu
Normal file
@@ -0,0 +1,573 @@
|
||||
export-env {
|
||||
use env.nu *
|
||||
}
|
||||
|
||||
### ctx
|
||||
export def "kube-config" [] {
|
||||
let file = if ($env.KUBECONFIG? | is-empty) { $"($env.HOME)/.kube/config" } else { $env.KUBECONFIG }
|
||||
{ path: $file, data: (cat $file | from yaml) }
|
||||
}
|
||||
|
||||
use utils.nu *
|
||||
use complete.nu *
|
||||
|
||||
export use refine.nu *
|
||||
export use helm.nu *
|
||||
export use conf.nu *
|
||||
export use resources.nu *
|
||||
export use compose.nu *
|
||||
|
||||
def krefine [kind] {
|
||||
let obj = $in
|
||||
let conf = $env.KUBERNETES_REFINE
|
||||
let kind = if $kind in $conf.shortnames {
|
||||
$conf.shortnames | get $kind
|
||||
} else {
|
||||
$kind
|
||||
}
|
||||
let tg = [cluster_resources cluster_status resources status]
|
||||
| reduce -f {} {|i,a|
|
||||
let r = $conf | get $i
|
||||
if $kind in $r {
|
||||
$a | merge ($r | get $kind)
|
||||
} else {
|
||||
$a
|
||||
}
|
||||
}
|
||||
if ($tg | is-empty) {
|
||||
$obj
|
||||
} else {
|
||||
refine $tg $obj
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# kubectl apply -f
|
||||
export def kaf [file: path] {
|
||||
kubectl apply -f $file
|
||||
}
|
||||
|
||||
# kubectl diff -f
|
||||
export def kdf [file: path] {
|
||||
kubectl diff -f $file
|
||||
}
|
||||
|
||||
# kubectl delete -f
|
||||
export def kdelf [file: path] {
|
||||
kubectl delete -f $file
|
||||
}
|
||||
|
||||
# kubectl apply -k (kustomize)
|
||||
export def kak [file: path] {
|
||||
kubectl apply -k $file
|
||||
}
|
||||
|
||||
# kubectl diff -k (kustomize)
|
||||
export def kdk [file: path] {
|
||||
kubectl diff -k $file
|
||||
}
|
||||
|
||||
# kubectl delete -k (kustomize)
|
||||
export def kdelk [file: path] {
|
||||
kubectl delete -k $file
|
||||
}
|
||||
|
||||
# kubectl kustomize (template)
|
||||
export def kk [file: path] {
|
||||
kubectl kustomize $file
|
||||
}
|
||||
|
||||
|
||||
|
||||
# kubectl change context
|
||||
export def kcc [context: string@"nu-complete kube ctx"] {
|
||||
kubectl config use-context $context
|
||||
}
|
||||
|
||||
# kubectl (change) namespace
|
||||
export def kn [namespace: string@"nu-complete kube ns"] {
|
||||
if not ($namespace in (kubectl get namespace | from ssv -a | get NAME)) {
|
||||
if ([no yes] | input list $"namespace '($namespace)' doesn't exist, create it?") in [yes] {
|
||||
kubectl create namespace $namespace
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
kubectl config set-context --current $"--namespace=($namespace)"
|
||||
}
|
||||
|
||||
# kubectl change context clone
|
||||
export def --env kccc [name: string@"nu-complete kube ctx"] {
|
||||
let dist = $"($env.HOME)/.kube/config.d"
|
||||
mkdir $dist
|
||||
kconf export $name | save -fr $"($dist)/($name)"
|
||||
$env.KUBECONFIG = $"($dist)/($name)"
|
||||
}
|
||||
|
||||
|
||||
# kubectl get
|
||||
export def kg [
|
||||
kind: string@"nu-complete kube kind"
|
||||
resource?: string@"nu-complete kube res"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--jsonpath (-p): string@"nu-complete kube jsonpath"
|
||||
--selector (-l): string
|
||||
--verbose (-v)
|
||||
--watch (-w)
|
||||
--wide (-W)
|
||||
--all (-a)
|
||||
] {
|
||||
let n = if $all {
|
||||
[-A]
|
||||
} else if ($namespace | is-empty) {
|
||||
[]
|
||||
} else {
|
||||
[-n $namespace]
|
||||
}
|
||||
if ($resource | is-empty) {
|
||||
let l = $selector | with-flag -l
|
||||
if ($jsonpath | is-empty) {
|
||||
let wide = if $wide {[-o wide]} else {[]}
|
||||
if $verbose {
|
||||
kubectl get -o json ...$n $kind ...$l | from json
|
||||
| get items
|
||||
| krefine $kind
|
||||
} else if $watch {
|
||||
kubectl get ...$n $kind ...$l ...$wide --watch
|
||||
} else {
|
||||
kubectl get ...$n $kind ...$l ...$wide | from ssv -a | normalize-column-names
|
||||
}
|
||||
} else {
|
||||
kubectl get ...$n $kind $"--output=jsonpath={($jsonpath)}" | from json
|
||||
}
|
||||
} else {
|
||||
let o = kubectl get ...$n $kind $resource -o json | from json
|
||||
if $verbose { $o } else { $o | krefine $kind }
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl describe
|
||||
export def kd [
|
||||
kind: string@"nu-complete kube kind"
|
||||
resource: string@"nu-complete kube res"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
kubectl describe ...($namespace | with-flag -n) $kind $resource
|
||||
}
|
||||
|
||||
# kubectl create
|
||||
export def kc [
|
||||
kind: string@"nu-complete kube kind"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
name:string
|
||||
] {
|
||||
kubectl create ...($namespace | with-flag -n) $kind $name
|
||||
}
|
||||
|
||||
# kubectl get -o yaml
|
||||
export def ky [
|
||||
kind: string@"nu-complete kube kind"
|
||||
resource: string@"nu-complete kube res"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
kubectl get ...($namespace | with-flag -n) -o yaml $kind $resource
|
||||
}
|
||||
|
||||
# kubectl edit
|
||||
export def ke [
|
||||
kind: string@"nu-complete kube kind"
|
||||
resource?: string@"nu-complete kube res"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--selector(-l): string
|
||||
] {
|
||||
let n = $namespace | with-flag -n
|
||||
let r = if ($selector | is-empty) { $resource } else {
|
||||
let res = kubectl get $kind ...$n -l $selector | from ssv -a | each {|x| $x.NAME}
|
||||
if ($res | length) == 1 {
|
||||
$res.0
|
||||
} else if ($res | length) == 0 {
|
||||
return
|
||||
} else {
|
||||
$res | input list $'select ($kind) '
|
||||
}
|
||||
}
|
||||
kubectl edit ...$n $kind $r
|
||||
}
|
||||
|
||||
# kubectl delete
|
||||
export def kdel [
|
||||
kind: string@"nu-complete kube kind"
|
||||
resource: string@"nu-complete kube res"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--force(-f)
|
||||
] {
|
||||
kubectl delete ...($namespace | with-flag -n) ...(if $force {[--grace-period=0 --force]} else {[]}) $kind $resource
|
||||
}
|
||||
|
||||
|
||||
# kubectl get nodes
|
||||
export def kgno [] {
|
||||
kubectl get nodes -o wide | from ssv -a
|
||||
| rename name status roles age version internal-ip external-ip os kernel runtime
|
||||
}
|
||||
|
||||
# kubectl get pods
|
||||
export def kgp [
|
||||
pod?: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--jsonpath (-p): string@"nu-complete kube jsonpath"
|
||||
--selector (-l): string
|
||||
--all (-a)
|
||||
] {
|
||||
if ($pod | is-not-empty) {
|
||||
kg pods -n $namespace $pod
|
||||
} else if $all {
|
||||
kg pods -a --wide
|
||||
} else {
|
||||
kg pods -n $namespace -p $jsonpath -l $selector --wide $pod
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl get pods --watch
|
||||
export def kwp [
|
||||
pod?: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--selector (-l): string
|
||||
] {
|
||||
kg pods -n $namespace -w -l $selector --wide $pod
|
||||
}
|
||||
|
||||
# kubectl edit pod
|
||||
export def kep [
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
pod: string@"nu-complete kube res via name"
|
||||
--selector (-l): string
|
||||
] {
|
||||
ke -n $namespace pod -l $selector $pod
|
||||
}
|
||||
|
||||
# kubectl describe pod
|
||||
export def kdp [
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
pod: string@"nu-complete kube res via name"
|
||||
] {
|
||||
kd -n $namespace pod $pod
|
||||
}
|
||||
|
||||
# kubectl attach (exec -it)
|
||||
export def --wrapped ka [
|
||||
pod?: string@"nu-complete kube deploys and pods"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--container(-c): string@"nu-complete kube ctns"
|
||||
--selector(-l): string
|
||||
--all-pods(-a) # for completion
|
||||
...args
|
||||
] {
|
||||
let n = $namespace | with-flag -n
|
||||
let pod = if ($selector | is-empty) {
|
||||
if ($pod | str ends-with '-') {
|
||||
$"deployment/($pod | str trim --char '-' --right)"
|
||||
} else {
|
||||
$pod
|
||||
}
|
||||
} else {
|
||||
let pods = kubectl get pods $n -o wide -l $selector
|
||||
| from ssv -a
|
||||
| where STATUS == Running
|
||||
| select NAME IP NODE
|
||||
| rename name ip node
|
||||
if ($pods | length) == 1 {
|
||||
($pods.0).name
|
||||
} else if ($pods | length) == 0 {
|
||||
return
|
||||
} else {
|
||||
($pods | input list 'select pod ').name
|
||||
}
|
||||
}
|
||||
let c = if ($container | is-empty) {
|
||||
if ($selector | is-empty) { [] } else {
|
||||
let cs = kgp -n $n $pod -p '.spec.containers[*].name' | split row ' '
|
||||
let ctn = if ($cs | length) == 1 {
|
||||
$cs.0
|
||||
} else {
|
||||
$cs | input list 'select container '
|
||||
}
|
||||
[-c $ctn]
|
||||
}
|
||||
} else {
|
||||
[-c $container]
|
||||
}
|
||||
kubectl exec ...$n -it $pod ...$c -- ...(if ($args|is-empty) {['bash']} else { $args })
|
||||
}
|
||||
|
||||
# kubectl logs
|
||||
export def kl [
|
||||
pod: string@"nu-complete kube deploys and pods"
|
||||
--namespace(-n): string@"nu-complete kube ns"
|
||||
--container(-c): string@"nu-complete kube ctns"
|
||||
--follow(-f)
|
||||
--previous(-p)
|
||||
--all-pods(-a) # for completion
|
||||
] {
|
||||
let n = $namespace | with-flag -n
|
||||
let c = $container | with-flag -c
|
||||
let f = if $follow {[-f]} else {[]}
|
||||
let p = if $previous {[-p]} else {[]}
|
||||
let trg = if ($pod | str ends-with '-') {
|
||||
$"deployment/($pod | str substring ..-1)"
|
||||
} else {
|
||||
$pod
|
||||
}
|
||||
kubectl logs ...$n ...$f ...$p $trg ...$c
|
||||
}
|
||||
|
||||
# kubectl port-forward
|
||||
export def kpf [
|
||||
kind: string@"nu-complete port forward type"
|
||||
target: string@"nu-complete kube res"
|
||||
port: string@"nu-complete kube port"
|
||||
--local (-l): string
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
let ns = $namespace | with-flag -n
|
||||
let port = if ($local | is-empty) { $port } else { $"($local):($port)" }
|
||||
kubectl port-forward ...$ns $"($kind)/($target)" $port
|
||||
}
|
||||
|
||||
# kubectl cp
|
||||
export def kcp [
|
||||
lhs: string@"nu-complete kube cp"
|
||||
rhs: string@"nu-complete kube cp"
|
||||
--container (-c): string@"nu-complete kube ctns"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
kubectl cp ...($namespace | with-flag -n) $lhs ...($container | with-flag -c) $rhs
|
||||
}
|
||||
|
||||
# kubectl get services
|
||||
export def kgs [
|
||||
service?: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--jsonpath (-p): string@"nu-complete kube jsonpath"
|
||||
--selector (-l): string
|
||||
] {
|
||||
if ($service | is-empty) {
|
||||
kg services -n $namespace -p $jsonpath -l $selector $service
|
||||
} else {
|
||||
kg services -n $namespace $service
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl edit service
|
||||
export def kes [
|
||||
service?: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--selector (-l): string
|
||||
] {
|
||||
ke -n $namespace service -l $selector $service
|
||||
}
|
||||
|
||||
# kubectl delete service
|
||||
export def kdels [
|
||||
service: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
kdel -n $namespace service $service
|
||||
}
|
||||
|
||||
# kubectl get deployments
|
||||
export def kgd [
|
||||
deployment?: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--jsonpath (-p): string@"nu-complete kube jsonpath"
|
||||
--selector (-l): string
|
||||
] {
|
||||
kg -n $namespace deployments -p $jsonpath -l $selector $deployment
|
||||
}
|
||||
|
||||
# kubectl edit deployment
|
||||
export def ked [
|
||||
deployment?: string@"nu-complete kube res via name"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--selector (-l): string
|
||||
] {
|
||||
ke -n $namespace deployments -l $selector $deployment
|
||||
}
|
||||
|
||||
def "nu-complete num9" [] { [0 1 2 3] }
|
||||
# kubectl scale deployment
|
||||
export def ksd [
|
||||
deployment: string@"nu-complete kube deploys"
|
||||
num: string@"nu-complete num9"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
if ($num | into int) > 9 {
|
||||
"too large"
|
||||
} else {
|
||||
let ns = $namespace | with-flag -n
|
||||
kubectl scale ...$ns deployments $deployment --replicas $num
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl scale deployment with reset
|
||||
export def ksdr [
|
||||
deployment: string@"nu-complete kube deploys"
|
||||
num: int@"nu-complete num9"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
if $num > 9 {
|
||||
"too large"
|
||||
} else if $num <= 0 {
|
||||
"too small"
|
||||
} else {
|
||||
let ns = $namespace | with-flag -n
|
||||
kubectl scale ...$ns deployments $deployment --replicas 0
|
||||
kubectl scale ...$ns deployments $deployment --replicas $num
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl set image
|
||||
export def ksi [
|
||||
kind: string@"nu-complete kube kind with image"
|
||||
resource: string@"nu-complete kube res"
|
||||
--namespace(-n): string@"nu-complete kube ns"
|
||||
act?: any
|
||||
] {
|
||||
let ns = $namespace | with-flag -n
|
||||
let path = match $kind {
|
||||
_ => '.spec.template.spec.containers[*]'
|
||||
}
|
||||
let name = kubectl get ...$ns $kind $resource -o $"jsonpath={($path).name}" | split row ' '
|
||||
let image = kubectl get ...$ns $kind $resource -o $"jsonpath={($path).image}" | split row ' '
|
||||
let list = $name | zip $image | reduce -f {} {|it,acc| $acc | insert $it.0 $it.1 }
|
||||
if ($act | describe -d).type == 'closure' {
|
||||
let s = do $act $list
|
||||
if ($s | describe -d).type == 'record' {
|
||||
let s = $s | transpose k v | each {|x| $"($x.k)=($x.v)"}
|
||||
kubectl ...$ns set image $"($kind)/($resource)" ...$s
|
||||
}
|
||||
} else {
|
||||
$list
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl redistribution deployment
|
||||
export def krd [
|
||||
deployment: string@"nu-complete kube deploys"
|
||||
...nodes: string@"nu-complete kube nodes"
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
] {
|
||||
let ns = $namespace | with-flag -n
|
||||
let nums = kubectl get nodes | from ssv -a | length
|
||||
kubectl scale ...$ns deployments $deployment --replicas $nums
|
||||
let labels = kubectl get ...$ns deploy $deployment --output=json
|
||||
| from json
|
||||
| get spec.selector.matchLabels
|
||||
| transpose k v
|
||||
| each {|x| $"($x.k)=($x.v)"}
|
||||
| str join ','
|
||||
let pods = kubectl get ...$ns pods -l $labels -o wide | from ssv -a
|
||||
for p in ($pods | where NODE not-in $nodes) {
|
||||
kubectl delete ...$ns pod --grace-period=0 --force $p.NAME
|
||||
}
|
||||
kubectl scale ...$ns deployments $deployment --replicas ($pods | where NODE in $nodes | length)
|
||||
}
|
||||
|
||||
# kubectl rollout status deployment
|
||||
export alias krsd = kubectl rollout status deployment
|
||||
# kubectl get rs
|
||||
export alias kgrs = kubectl get rs
|
||||
|
||||
# kubectl rollout history
|
||||
export def krhd [
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--revision (-v): int
|
||||
deployment: string@"nu-complete kube res via name"
|
||||
] {
|
||||
let ns = $namespace | with-flag -n
|
||||
let v = if ($revision|is-empty) { [] } else { [ $"--revision=($revision)" ] }
|
||||
kubectl ...$ns rollout history $"deployment/($deployment)" ...$v
|
||||
}
|
||||
|
||||
# kubectl rollout undo
|
||||
export def krud [
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--revision (-v): int
|
||||
deployment: string@"nu-complete kube res via name"
|
||||
] {
|
||||
let ns = $namespace | with-flag -n
|
||||
let v = if ($revision|is-empty) { [] } else { [ $"--to-revision=($revision)" ] }
|
||||
kubectl ...$ns rollout undo $"deployment/($deployment)" ...$v
|
||||
}
|
||||
export alias ksss = kubectl scale statefulset
|
||||
export alias krsss = kubectl rollout status statefulset
|
||||
|
||||
# kubectl top pod
|
||||
export def ktp [
|
||||
--namespace (-n): string@"nu-complete kube ns"
|
||||
--all(-a)
|
||||
] {
|
||||
if $all {
|
||||
kubectl top pod -A | from ssv -a | rename namespace name cpu mem
|
||||
| each {|x|
|
||||
{
|
||||
namespace: $x.namespace
|
||||
name: $x.name
|
||||
cpu: ($x.cpu| str substring ..-1 | into float)
|
||||
mem: ($x.mem | str substring ..-2 | into float)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let ns = $namespace | with-flag -n
|
||||
kubectl top pod ...$ns | from ssv -a | rename name cpu mem
|
||||
| each {|x|
|
||||
{
|
||||
name: $x.name
|
||||
cpu: ($x.cpu| str substring ..-1 | into float)
|
||||
mem: ($x.mem | str substring ..-2 | into float)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# kubectl top node
|
||||
export def ktno [] {
|
||||
kubectl top node | from ssv -a | rename name cpu pcpu mem pmem
|
||||
| each {|x| {
|
||||
name: $x.name
|
||||
cpu: ($x.cpu| str substring ..-1 | into float)
|
||||
cpu%: (($x.pcpu| str substring ..-1 | into float) / 100)
|
||||
mem: ($x.mem | str substring ..-2 | into float)
|
||||
mem%: (($x.pmem | str substring ..-1 | into float) / 100)
|
||||
} }
|
||||
}
|
||||
|
||||
###
|
||||
export def "kclean evicted" [] {
|
||||
kubectl get pods -A
|
||||
| from ssv -a
|
||||
| where STATUS == Evicted
|
||||
| each { |x| kdel pod -n $x.NAMESPACE $x.NAME }
|
||||
}
|
||||
|
||||
### FIXME:
|
||||
export def "kclean stucked ns" [ns: string] {
|
||||
kubectl get namespace $ns -o json \
|
||||
| tr -d "\n"
|
||||
| sed 's/\"finalizers\": \[[^]]\+\]/\"finalizers\": []/' \
|
||||
| kubectl replace --raw /api/v1/namespaces/$1/finalize -f -
|
||||
}
|
||||
|
||||
export alias "kclean finalizer" = kubectl patch -p '{\"metadata\":{\"finalizers\":null}}'
|
||||
|
||||
export alias "kadm check" = kubeadm certs check-expiration
|
||||
export alias "kadm renew" = kubeadm certs renew all
|
||||
|
||||
### cert-manager
|
||||
export def kgcert [] {
|
||||
kubectl get certificates -o wide | from ssv | rename certificates
|
||||
kubectl get certificaterequests -o wide | from ssv | rename certificaterequests
|
||||
kubectl get order.acme -o wide | from ssv | rename order.acme
|
||||
kubectl get challenges.acme -o wide | from ssv | rename challenges.acme
|
||||
}
|
||||
|
||||
61
dot_config/nushell/nu_scripts/modules/kubernetes/refine.nu
Normal file
61
dot_config/nushell/nu_scripts/modules/kubernetes/refine.nu
Normal file
@@ -0,0 +1,61 @@
|
||||
def safe_get [path obj] {
|
||||
mut r = $obj
|
||||
mut ps = $path
|
||||
loop {
|
||||
if ($ps | length) < 1 { break }
|
||||
if $r == null { break }
|
||||
let p = $ps | first
|
||||
|
||||
if ($p | describe -d).type == closure {
|
||||
$r = ($r | do $p $r)
|
||||
$ps = ($ps | range 1..)
|
||||
continue
|
||||
}
|
||||
|
||||
match ($r | describe -d).type {
|
||||
record => {
|
||||
if $p in $r {
|
||||
$r = ($r | get $p)
|
||||
} else {
|
||||
$r = null
|
||||
}
|
||||
}
|
||||
list => {
|
||||
let ps = $ps
|
||||
return ($r | each {|x| safe_get $ps $x })
|
||||
}
|
||||
_ => {
|
||||
$r = null
|
||||
}
|
||||
}
|
||||
$ps = ($ps | range 1..)
|
||||
}
|
||||
$r
|
||||
}
|
||||
|
||||
def extract [tg obj] {
|
||||
$tg
|
||||
| transpose k v
|
||||
| reduce -f {} {|i,a|
|
||||
match ($i.v | describe -d).type {
|
||||
list => {
|
||||
let c = safe_get $i.v $obj
|
||||
$a | upsert $i.k $c
|
||||
}
|
||||
record => {
|
||||
let o = safe_get $i.v._ $obj
|
||||
let t = $i.v | reject _
|
||||
$a | upsert $i.k (main $t $o)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def main [tg obj] {
|
||||
if ($obj | describe -d).type == list {
|
||||
$obj | each {|x| extract $tg $x }
|
||||
} else {
|
||||
extract $tg $obj
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use complete *
|
||||
|
||||
### refine kubernetes resources
|
||||
export def kube-refine [
|
||||
...namespace: string@"nu-complete kube ns"
|
||||
--kind(-k): list<string@"nu-complete kube kind">
|
||||
] {
|
||||
use lg
|
||||
let config = $env.KUBERNETES_REFINE
|
||||
|
||||
let nsf = if ($namespace | is-empty) {
|
||||
{|x| $x not-in $config._namespace }
|
||||
} else {
|
||||
{|x| $x in $namespace}
|
||||
}
|
||||
let cns = kubectl get namespace
|
||||
| from ssv -a
|
||||
| get NAME
|
||||
| filter $nsf
|
||||
|
||||
let resource = kubectl get crd | from ssv | get NAME
|
||||
let resource = kubectl api-resources | from ssv -a | get NAME | append $resource
|
||||
let resource = if ($kind | is-empty) {
|
||||
$resource
|
||||
} else {
|
||||
$resource
|
||||
| filter {|x| $x in $kind }
|
||||
}
|
||||
|
||||
mut data = []
|
||||
if ($namespace | is-empty) {
|
||||
lg level 4 {stage: cluster}
|
||||
for p in ($config.cluster_resources | transpose k v) {
|
||||
if $p.k not-in $resource { continue }
|
||||
lg level 3 {kind: $p.k} list
|
||||
let rs = kubectl get $p.k | from ssv -a | get NAME
|
||||
for r in $rs {
|
||||
lg level 1 {kind: $p.k, name: $r} collect
|
||||
let obj = kubectl get $p.k $r --output=json | from json
|
||||
let pyl = refine $p.v $obj
|
||||
$data ++= $pyl
|
||||
}
|
||||
}
|
||||
}
|
||||
lg level 4 {stage: namespace}
|
||||
for p in ($config.resources | transpose k v) {
|
||||
if $p.k not-in $resource { continue }
|
||||
for ns in $cns {
|
||||
lg level 2 {kind: $p.k, ns: $ns} list
|
||||
let rs = kubectl get $p.k --namespace $ns | from ssv -a | get NAME
|
||||
for r in $rs {
|
||||
lg level 0 {kind: $p.k, ns: $ns, name: $r} collect
|
||||
let obj = kubectl get $p.k --namespace $ns $r --output=json | from json
|
||||
let pyl = refine $p.v $obj
|
||||
$data ++= $pyl
|
||||
}
|
||||
}
|
||||
}
|
||||
$data
|
||||
}
|
||||
|
||||
89
dot_config/nushell/nu_scripts/modules/kubernetes/utils.nu
Normal file
89
dot_config/nushell/nu_scripts/modules/kubernetes/utils.nu
Normal file
@@ -0,0 +1,89 @@
|
||||
export def ensure-cache-by-lines [cache path action] {
|
||||
let ls = do -i { open $path | lines | length }
|
||||
if ($ls | is-empty) { return false }
|
||||
let lc = do -i { open $cache | get lines}
|
||||
if not (($cache | path exists) and ($lc | is-not-empty) and ($ls == $lc)) {
|
||||
mkdir ($cache | path dirname)
|
||||
{
|
||||
lines: $ls
|
||||
payload: (do $action)
|
||||
} | save -f $cache
|
||||
}
|
||||
(open $cache).payload
|
||||
}
|
||||
|
||||
export def normalize-column-names [ ] {
|
||||
let i = $in
|
||||
let cols = $i | columns
|
||||
mut t = $i
|
||||
for c in $cols {
|
||||
$t = ($t | rename -c {$c: ($c | str downcase | str replace ' ' '_')})
|
||||
}
|
||||
$t
|
||||
}
|
||||
|
||||
export def --wrapped with-flag [...flag] {
|
||||
if ($in | is-empty) { [] } else { [...$flag $in] }
|
||||
}
|
||||
|
||||
export def `kcache flush` [] {
|
||||
rm -rf ~/.cache/nu-complete/k8s/
|
||||
nu-complete kube ctx
|
||||
rm -rf ~/.cache/nu-complete/k8s-api-resources/
|
||||
}
|
||||
|
||||
export def kube-shortnames [] {
|
||||
kubectl api-resources | from ssv -a
|
||||
| where SHORTNAMES != ''
|
||||
| reduce -f {} {|i,a|
|
||||
$i.SHORTNAMES
|
||||
| split row ','
|
||||
| reduce -f {} {|j,b|
|
||||
$b | insert $j $i.NAME
|
||||
}
|
||||
| merge $a
|
||||
}
|
||||
}
|
||||
|
||||
export def parse_cellpath [path] {
|
||||
$path | split row '.' | each {|x|
|
||||
if ($x | find --regex "^[0-9]+$" | is-empty) {
|
||||
$x
|
||||
} else {
|
||||
$x | into int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def get_cellpath [record path] {
|
||||
$path | reduce -f $record {|it, acc| $acc | get $it }
|
||||
}
|
||||
|
||||
export def set_cellpath [record path value] {
|
||||
if ($path | length) > 1 {
|
||||
$record | upsert ($path | first) {|it|
|
||||
set_cellpath ($it | get ($path | first)) ($path | range 1..) $value
|
||||
}
|
||||
} else {
|
||||
$record | upsert ($path | last) $value
|
||||
}
|
||||
}
|
||||
|
||||
export def upsert_row [table col mask id value] {
|
||||
# let value = ($mask | reduce -f $value {|it, acc|
|
||||
# let path = (parse_cellpath $it)
|
||||
# set_cellpath $value $path (get_cellpath $table $path)
|
||||
# })
|
||||
if $id in ($table | get $col) {
|
||||
$table | each {|x|
|
||||
if ($x | get $col) == $id {
|
||||
$value
|
||||
} else {
|
||||
$x
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$table | append $value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
source language/playground/lib.nu
|
||||
@@ -0,0 +1,54 @@
|
||||
export def main [topic, closure] {
|
||||
with-env {N: 5 REJECT: slow } {
|
||||
print (echo $topic " tests" (char newline) | str join)
|
||||
|
||||
do $closure
|
||||
}
|
||||
}
|
||||
|
||||
export def scene [
|
||||
topic: any
|
||||
--tag: string
|
||||
closure: closure
|
||||
] {
|
||||
print $" ($topic)(char newline)"
|
||||
do $closure
|
||||
}
|
||||
|
||||
export def play [
|
||||
topic: any
|
||||
--tag: string
|
||||
closure: closure
|
||||
] {
|
||||
let is_tag_empty = ($tag | is-empty);
|
||||
let should_run_all = ($env | get -i RUN_ALL | default false);
|
||||
|
||||
if $is_tag_empty {
|
||||
do $closure $topic
|
||||
} else {
|
||||
if $tag == $env.REJECT and $should_run_all {
|
||||
$" ($topic) ... (ansi yellow)skipped(ansi reset) (char newline)"
|
||||
} else {
|
||||
do $closure $topic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def expect [
|
||||
topic: string
|
||||
actual: list<any>
|
||||
--to-be: list<any>
|
||||
] {
|
||||
let are_equal = (($actual | length) == ($to_be | length)) and ($actual | zip $to_be | all {|case|
|
||||
$case.0 == $case.1
|
||||
}
|
||||
)
|
||||
|
||||
let line = (if true == $are_equal {
|
||||
$"(ansi green)ok(ansi reset)(char newline)"
|
||||
} else {
|
||||
$"(ansi red)failed(ansi reset)(char newline)"
|
||||
}
|
||||
)
|
||||
$" ($topic) ... ($line)"
|
||||
}
|
||||
1
dot_config/nushell/nu_scripts/modules/language/std.nu
Normal file
1
dot_config/nushell/nu_scripts/modules/language/std.nu
Normal file
@@ -0,0 +1 @@
|
||||
source language/std/date.nu
|
||||
@@ -0,0 +1,7 @@
|
||||
export def "date local" [now] {
|
||||
insert time {|value|
|
||||
let converted = ($now | date to-timezone $value.tz);
|
||||
|
||||
$converted | format date '%c'
|
||||
}
|
||||
}
|
||||
34
dot_config/nushell/nu_scripts/modules/language/tests/date.nu
Normal file
34
dot_config/nushell/nu_scripts/modules/language/tests/date.nu
Normal file
@@ -0,0 +1,34 @@
|
||||
use ../playground *
|
||||
use ../std/date.nu *
|
||||
|
||||
def mock-now [] {
|
||||
"2021-08-29 03:31:21" | into datetime
|
||||
}
|
||||
|
||||
def people [] {
|
||||
[
|
||||
[ 'name', 'tz'];
|
||||
[ 'andres', 'America/Guayaquil']
|
||||
[ 'fdncred', 'US/Central']
|
||||
]
|
||||
}
|
||||
|
||||
playground "std/date" {
|
||||
|
||||
scene 'command: "date local"' {
|
||||
|
||||
play "adds times in local timezone" {|topic|
|
||||
|
||||
let expected_times = [
|
||||
"Sun Aug 29 03:31:21 2021"
|
||||
"Sun Aug 29 03:31:21 2021"
|
||||
] | into datetime;
|
||||
let actual = (people | date local (mock-now) | get time | into datetime)
|
||||
|
||||
expect $topic $actual --to-be $expected_times
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
114
dot_config/nushell/nu_scripts/modules/lg/mod.nu
Normal file
114
dot_config/nushell/nu_scripts/modules/lg/mod.nu
Normal file
@@ -0,0 +1,114 @@
|
||||
def get_settings [] {
|
||||
{
|
||||
level: ($env.lg.level? | default 2)
|
||||
file: ($env.lg.file?)
|
||||
}
|
||||
}
|
||||
|
||||
export-env {
|
||||
$env.lg = {
|
||||
prefix: ['TRC' 'DBG' 'INF' 'WRN' 'ERR' 'CRT']
|
||||
index: {
|
||||
trc: 0
|
||||
dbg: 1
|
||||
inf: 2 msg: 2
|
||||
wrn: 3
|
||||
err: 4
|
||||
crt: 5
|
||||
}
|
||||
theme: {
|
||||
console: {
|
||||
level : (['navy' 'teal' 'xgreen' 'xpurplea' 'olive' 'maroon'] | each { ansi $in })
|
||||
delimiter: $'(ansi grey39)│'
|
||||
fg: (ansi light_gray)
|
||||
bg: (ansi grey39)
|
||||
terminal: (ansi reset)
|
||||
}
|
||||
file: {
|
||||
level : ['' '' '' '' '' '']
|
||||
delimiter: '│'
|
||||
fg: ''
|
||||
bg: ''
|
||||
terminal: (char newline)
|
||||
}
|
||||
}
|
||||
line_formatter: {|theme, align, max_key_len| {|y|
|
||||
let k = if $align { $y.k | fill -a r -w $max_key_len } else { $y.k }
|
||||
$" ($theme.bg)($k) = ($theme.fg)($y.v | to json -r)"
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
def parse_msg [args] {
|
||||
let time = date now | format date '%FT%T.%3f'
|
||||
let s = $args
|
||||
| reduce -f {tag: {}, txt:[]} {|x, acc|
|
||||
if ($x | describe -d).type == 'record' {
|
||||
$acc | update tag ($acc.tag | merge $x)
|
||||
} else {
|
||||
$acc | update txt ($acc.txt | append $x)
|
||||
}
|
||||
}
|
||||
{time: $time, txt: $s.txt, tag: $s.tag }
|
||||
}
|
||||
|
||||
export def --wrapped level [
|
||||
level
|
||||
...args
|
||||
--multiline(-m)
|
||||
--label: string
|
||||
--setting: any
|
||||
] {
|
||||
let setting = if ($setting | is-empty) { get_settings } else { $setting }
|
||||
let target = if ($setting.file? | is-empty) { 'console' } else { 'file' }
|
||||
let theme = $env.lg.theme | get $target
|
||||
let output = if ($setting.file? | is-empty) {{ print -e $in }} else {{ $in | save -af $setting.file }}
|
||||
let msg = parse_msg $args
|
||||
|
||||
let time = $"($theme.level | get $level)($msg.time)"
|
||||
let label = if ($label | is-empty) { '' } else { $"($theme.fg)($label)" }
|
||||
let txt = $msg.txt | str join ' '
|
||||
let txt = if ($txt | is-empty) { '' } else { $"($theme.fg)($txt)" }
|
||||
let tag = $msg.tag | transpose k v
|
||||
let r = if $multiline {
|
||||
let align = $target == 'console'
|
||||
let mkl = if $align { $tag | get k | each { $in | str length } | math max }
|
||||
let body = $tag
|
||||
| each (do $env.lg.line_formatter $theme $align $mkl)
|
||||
| str join (char newline)
|
||||
let head = [$time $label $txt]
|
||||
| filter {|x| $x | is-not-empty }
|
||||
| str join $theme.delimiter
|
||||
[$head $body] | str join (char newline)
|
||||
} else {
|
||||
let tag = $tag
|
||||
| each {|y| $"($theme.bg)($y.k)=($theme.fg)($y.v)"}
|
||||
| str join ' '
|
||||
[$time $label $tag $txt]
|
||||
| filter {|x| $x | is-not-empty }
|
||||
| str join $theme.delimiter
|
||||
}
|
||||
$r + $theme.terminal | do $output
|
||||
}
|
||||
|
||||
def 'nu-complete log-prefix' [] {
|
||||
$env.lg.index | columns
|
||||
}
|
||||
|
||||
export def --wrapped main [
|
||||
level: string@'nu-complete log-prefix'
|
||||
--multiline(-m)
|
||||
...args
|
||||
] {
|
||||
let setting = get_settings
|
||||
let lv = $env.lg.index | get $level
|
||||
if $lv < $setting.level {
|
||||
return
|
||||
}
|
||||
let label = $env.lg.prefix | get $lv
|
||||
if $multiline {
|
||||
level $lv ...$args --label $label --setting $setting --multiline
|
||||
} else {
|
||||
level $lv ...$args --label $label --setting $setting
|
||||
}
|
||||
}
|
||||
16
dot_config/nushell/nu_scripts/modules/lint_directories.nu
Normal file
16
dot_config/nushell/nu_scripts/modules/lint_directories.nu
Normal file
@@ -0,0 +1,16 @@
|
||||
# List any directory that does not follow a SemVer naming pattern
|
||||
# For example
|
||||
# - 1.0.1 is a valid directory name.
|
||||
# - yeah_whatever_linter is not a valid directory name.
|
||||
def ls-incorrect-dirs [] {
|
||||
ls | where type == dir and name != 'scripts' | find --invert --regex '(\d+\.){2,}\d$' --columns [name]
|
||||
}
|
||||
let incorrect_count = (ls-incorrect-dirs | length);
|
||||
if $incorrect_count > 0 {
|
||||
print $"The following directories are named incorrectly: (char newline)"
|
||||
print (ls-incorrect-dirs)
|
||||
exit 1
|
||||
|
||||
} else {
|
||||
exit 0
|
||||
}
|
||||
24
dot_config/nushell/nu_scripts/modules/log/log.nu
Normal file
24
dot_config/nushell/nu_scripts/modules/log/log.nu
Normal file
@@ -0,0 +1,24 @@
|
||||
def logtime [msg act] {
|
||||
let start = (date now)
|
||||
let result = (do $act)
|
||||
let period = ((date now) - $start
|
||||
| into duration --unit ns
|
||||
| into string
|
||||
| str replace ' ' '')
|
||||
|
||||
echo $'($start | format date '%Y-%m-%d_%H:%M:%S%z')(char tab)($period)(char tab)($msg)(char newline)'
|
||||
| save -a ~/.cache/nushell/time.log
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
export def timelog [] {
|
||||
open ~/.cache/nushell/time.log
|
||||
| from tsv -n
|
||||
| rename start duration message
|
||||
| each {|x|
|
||||
$x
|
||||
| update start ($x.start | into datetime -f '%Y-%m-%d_%H:%M:%S%z')
|
||||
| update duration ($x.duration | into duration)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
export def ls-hidden [
|
||||
--dir(-d):any # The directory you want to list
|
||||
] {
|
||||
let dir = if ($dir | is-empty) { "." } else { $dir }
|
||||
ls -a $dir | filter { ($in.name | into string | str starts-with '.') }
|
||||
}
|
||||
12
dot_config/nushell/nu_scripts/modules/ls_mods/ls-less.nu
Normal file
12
dot_config/nushell/nu_scripts/modules/ls_mods/ls-less.nu
Normal file
@@ -0,0 +1,12 @@
|
||||
# An attempt at trying to put ls into a paging mode
|
||||
export def ls-less [
|
||||
--dir(-d):any # The directory you want to list
|
||||
] {
|
||||
let is_empty = ($dir | is-empty)
|
||||
if $is_empty {
|
||||
nu -c 'ls' | less -r
|
||||
} else {
|
||||
let command = $"ls ($dir)"
|
||||
nu -c $command | less -r
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
alias relet = ansi -e '0m' # really reset but there are external commands for reset already
|
||||
|
||||
alias fg_black = ansi -e '30m'
|
||||
alias fg_red = ansi -e '31m'
|
||||
alias fg_green = ansi -e '32m'
|
||||
alias fg_yellow = ansi -e '33m'
|
||||
alias fg_blue = ansi -e '34m'
|
||||
alias fg_magenta = ansi -e '35m'
|
||||
alias fg_purple = ansi -e '35m'
|
||||
alias fg_cyan = ansi -e '36m'
|
||||
alias fg_white = ansi -e '37m'
|
||||
|
||||
alias fg_dark_gray = ansi -e '90m'
|
||||
alias fg_light_black = ansi -e '90m'
|
||||
alias fg_light_red = ansi -e '91m'
|
||||
alias fg_light_green = ansi -e '92m'
|
||||
alias fg_light_yellow = ansi -e '93m'
|
||||
alias fg_light_blue = ansi -e '94m'
|
||||
alias fg_light_magenta = ansi -e '95m'
|
||||
alias fg_light_purple = ansi -e '95m'
|
||||
alias fg_light_cyan = ansi -e '96m'
|
||||
alias fg_light_gray = ansi -e '97m'
|
||||
alias fg_light_white = ansi -e '97m'
|
||||
|
||||
# A ls command that approximates the ls -sh command in bash
|
||||
export def ls-wide2 [
|
||||
--dir(-d):any # The directory you want to list
|
||||
--columns(-c):int # The number of columns in your output
|
||||
] {
|
||||
let is_dir_empty = ($dir | is-empty)
|
||||
let is_columns_empty = ($columns | is-empty)
|
||||
let ls_data = (if $is_dir_empty { ls } else { ls $dir })
|
||||
let max_fname_size = ($ls_data | get name | into string | str length | math max)
|
||||
let max_fsize_size = ($ls_data | get size | into string | str length | math max)
|
||||
($ls_data) | enumerate | each { |file|
|
||||
let clr_file = (colorize $file.item.name)
|
||||
let clr_size = (echo $file.item.size | into string)
|
||||
let new_line = (if $is_columns_empty {
|
||||
if (($file.index + 1) mod 3) == 0 {
|
||||
char newline
|
||||
}
|
||||
} else {
|
||||
if (($file.index + 1) mod $columns) == 0 {
|
||||
char newline
|
||||
}
|
||||
})
|
||||
$"($clr_file | fill -a l -c ' ' -w $max_fname_size) ($clr_size | fill -a r -c ' ' -w $max_fsize_size) ($new_line)"
|
||||
} | str join
|
||||
}
|
||||
|
||||
def colorize [thing:any] {
|
||||
let thing_as_string = (echo $thing | into string)
|
||||
let ext = (echo $thing_as_string | path parse | get extension)
|
||||
let is_empty = ($ext | is-empty)
|
||||
|
||||
if $is_empty {
|
||||
$"(fg_cyan)($thing)(relet)"
|
||||
} else {
|
||||
if $ext == "nu" {
|
||||
$"(fg_light_magenta)($thing)(relet)"
|
||||
} else {
|
||||
$"(fg_light_green)($thing)(relet)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def colorit [] {
|
||||
print (colorize 123)
|
||||
print (colorize " 123.456")
|
||||
print (colorize " file.nu")
|
||||
|
||||
# These all work
|
||||
print $"(fg_light_green)abc(relet)"
|
||||
print $"(fg_cyan)def(relet)"
|
||||
}
|
||||
47
dot_config/nushell/nu_scripts/modules/ls_mods/ls-wide.nu
Normal file
47
dot_config/nushell/nu_scripts/modules/ls_mods/ls-wide.nu
Normal file
@@ -0,0 +1,47 @@
|
||||
# A ls command that approximates the ls -sh command in bash
|
||||
export def ls-wide [
|
||||
--path(-p):string # The path you want to list
|
||||
--columns(-c):int # The number of columns in your output
|
||||
] {
|
||||
let is_columns_empty = ($columns | is-empty)
|
||||
let is_path_empty = ($path | is-empty)
|
||||
let columns_default = 3
|
||||
|
||||
if $is_path_empty {
|
||||
if $is_columns_empty {
|
||||
run_ls "." $columns_default
|
||||
} else {
|
||||
run_ls "." $columns
|
||||
}
|
||||
} else {
|
||||
if $is_columns_empty {
|
||||
run_ls $path $columns_default
|
||||
} else {
|
||||
run_ls $path $columns
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def run_ls [
|
||||
path:string
|
||||
columns:int
|
||||
] {
|
||||
let max_fname_size = (ls $path | get name | into string | str length | math max)
|
||||
let max_fsize_size = (ls $path | get size | into string | str length | math max)
|
||||
let is_columns_empty = ($columns | is-empty)
|
||||
|
||||
ls $path | enumerate | each { |file|
|
||||
let the_file = ($file.item.name | into string | fill -a l -c ' ' -w $max_fname_size)
|
||||
let the_size = ($file.item.size | into string | fill -a r -c ' ' -w $max_fsize_size)
|
||||
let new_line = (if $is_columns_empty {
|
||||
if ($file.index + 1) mod 3 == 0 {
|
||||
char newline
|
||||
}
|
||||
} else {
|
||||
if ($file.index + 1) mod $columns == 0 {
|
||||
char newline
|
||||
}
|
||||
})
|
||||
$"($the_file) ($the_size) ($new_line)"
|
||||
} | str join
|
||||
}
|
||||
18
dot_config/nushell/nu_scripts/modules/maintainer_time.nu
Normal file
18
dot_config/nushell/nu_scripts/modules/maintainer_time.nu
Normal file
@@ -0,0 +1,18 @@
|
||||
let m_table = (
|
||||
[
|
||||
['name', 'tz', 'time'];
|
||||
['andres' 'America/Guayaquil' ' ']
|
||||
['fdncred' 'US/Central' ' ']
|
||||
['gedge' 'US/Eastern' ' ']
|
||||
['jt' 'NZ' ' ']
|
||||
['wycats' 'US/Pacific' ' ']
|
||||
['kubouch' 'Europe/Helsinki' ' ']
|
||||
['elferherrera' 'Europe/London' ' ']
|
||||
['storm' 'US/Pacific' ' ']
|
||||
]
|
||||
)
|
||||
let now = (date now)
|
||||
$m_table | update time {|row|
|
||||
$now | date to-timezone ($row | get tz) | format date '%c'
|
||||
}
|
||||
|
||||
32
dot_config/nushell/nu_scripts/modules/make_readme_table.nu
Normal file
32
dot_config/nushell/nu_scripts/modules/make_readme_table.nu
Normal file
@@ -0,0 +1,32 @@
|
||||
# A Script to try and create the table for the readme.md file
|
||||
# | Category | File |
|
||||
# | ---------------- | ----------------------------------------------------------------------------- |
|
||||
# | coloring | [24bit-1.nu](./coloring\24bit-1.nu) |
|
||||
# | coloring | [color_table.nu](./coloring\color_table.nu) |
|
||||
# | coloring | [color_tables.nu](./coloring\color_tables.nu) |
|
||||
# | coloring | [gradient.nu](./coloring\gradient.nu) |
|
||||
|
||||
# Right now there is still manual manipulation in order to update the README.md
|
||||
# Hopefully, in the future someone will contribute a script to make this automatic.
|
||||
|
||||
let nu_files = (ls **/*.nu)
|
||||
let nu_table = ($nu_files |
|
||||
get name |
|
||||
wrap File |
|
||||
insert Category { |it|
|
||||
let cat = ($it.File | path dirname)
|
||||
if $cat == "" {
|
||||
"not assigned yet"
|
||||
} else {
|
||||
$cat
|
||||
}
|
||||
} | where Category !~ ".git" | select Category File | sort-by Category)
|
||||
|
||||
# Let's fix the file now
|
||||
let nu_table = ($nu_table | update File { |it|
|
||||
let file_path = ($it.File | into string | str replace '\' '/' --all)
|
||||
let file_name = ($file_path | path basename)
|
||||
$"[($file_name)](char lparen)./($file_path)(char rparen)"
|
||||
})
|
||||
|
||||
echo $nu_table | to md --pretty
|
||||
289
dot_config/nushell/nu_scripts/modules/maths/math_functions.nu
Normal file
289
dot_config/nushell/nu_scripts/modules/maths/math_functions.nu
Normal file
@@ -0,0 +1,289 @@
|
||||
#Root with a custom denominator
|
||||
export def root [ denominator, num ] {
|
||||
$num ** ( 1 / $denominator ) | math round -p 10
|
||||
}
|
||||
|
||||
#Cube root
|
||||
export def croot [num] {
|
||||
$num ** ( 1 / 3 ) | math round -p 10
|
||||
}
|
||||
|
||||
#Root with a custom scaler and denominator
|
||||
export def aroot [ scaler, denominator, num] {
|
||||
$num ** ($scaler / $denominator) | math round -p 10
|
||||
}
|
||||
|
||||
#calculate delta of the quadratic function
|
||||
export def delta [ a,#x^2 factor
|
||||
b, #x factor
|
||||
c #the rest
|
||||
] {
|
||||
( $b ** 2 ) - ( 4 * $a * $c)
|
||||
}
|
||||
|
||||
#Factorial of the given number
|
||||
export def fact [num: int] {
|
||||
if $num >= 0 {
|
||||
if $num < 2 {
|
||||
$num
|
||||
} else {
|
||||
seq 2 $num | math product
|
||||
}
|
||||
} else {
|
||||
error make -u {msg: "can only calculate non-negative integers"}
|
||||
}
|
||||
}
|
||||
|
||||
#Calculate roots of the quadratic function: ax^2+bx+x
|
||||
export def q_roots [
|
||||
a # x^2
|
||||
b # x
|
||||
c # independent term
|
||||
] {
|
||||
let d = $b ** 2 - 4 * $a * $c
|
||||
if $d > 0 {
|
||||
let s = ($d | math sqrt)
|
||||
let r1 = (($s - $b) / (2 * $a))
|
||||
let r2 = (0 - (($s + $b) / (2 * $a)))
|
||||
|
||||
echo $"root #1: ($r1)"
|
||||
echo $"root #2: ($r2)"
|
||||
} else if $d == 0 {
|
||||
let s = ($d | math sqrt)
|
||||
let r = (($s - $b) / (2 * $a))
|
||||
|
||||
echo $"root: ($r)"
|
||||
} else {
|
||||
let s = ((0 - $d) | math sqrt)
|
||||
let r = ((0 - $b) / (2 * $a))
|
||||
let i = ($s / (2 * $a))
|
||||
|
||||
echo $"root #1: ($r) + ($i)*i"
|
||||
echo $"root #2: ($r) - ($i)*i"
|
||||
}
|
||||
}
|
||||
|
||||
#Check if integer is prime
|
||||
export def isprime [n: int] {
|
||||
let max = ($n | math sqrt | math ceil)
|
||||
|
||||
let flag = ([[isPrime];[true]] | update isPrime {if ($n mod 2) == 0 { false } else { seq 3 1 $max | each { |it| if ($n mod $it) == 0 { false }}}})
|
||||
|
||||
if ($flag.isPrime.0 | is-empty) { echo 'prime' } else { echo 'not prime' }
|
||||
}
|
||||
|
||||
#Prime list <= n
|
||||
export def primelist [n: int] {
|
||||
let primes = [2 3]
|
||||
|
||||
let primes2 = (seq 5 2 $n | each {|it| if (isprime $it) == 'prime' {$it}})
|
||||
|
||||
$primes | append $primes2
|
||||
}
|
||||
|
||||
#Multiplication table of n till max
|
||||
export def mtable [n: int, max: int] {
|
||||
seq 1 $max | each {|it| echo $"($it)*($n) = ($n * $it)"}
|
||||
}
|
||||
|
||||
#Check if year is leap
|
||||
export def isleap [year: int] {
|
||||
if ( (($year mod 4) == 0 and ($year mod 100) != 0) or ($year mod 400) == 0 ) { echo "It is a leap year." } else { echo "It is not a leap year."}
|
||||
}
|
||||
|
||||
#Greatest common divisor (gcd) between 2 integers
|
||||
export def gcd [a: int, b:int] {
|
||||
if $a < $b {
|
||||
gcd $b $a
|
||||
} else if $b == 0 {
|
||||
$a
|
||||
} else {
|
||||
gcd $b ($a mod $b)
|
||||
}
|
||||
}
|
||||
|
||||
#Least common multiple (lcm) between 2 integers
|
||||
export def lcm [a: int, b:int] {
|
||||
if $a == $b and $b == 0 {
|
||||
0
|
||||
} else {
|
||||
$a * ($b / (gcd $a $b))
|
||||
}
|
||||
}
|
||||
|
||||
#Decimal number to custom base representation
|
||||
export def dec2base [
|
||||
n: string #decimal number
|
||||
b: string #base in [2,16]
|
||||
] {
|
||||
let base = if ( ($b | into int) < 2 or ($b | into int) > 16 ) {
|
||||
echo "Wrong base, it must be an integer between 2 and 16"
|
||||
10
|
||||
} else {
|
||||
$b | into int
|
||||
}
|
||||
|
||||
let number = ($n | into int)
|
||||
|
||||
let chars = ['0' '1' '2' '3' '4' '5' '6' '7' '8' '9' 'A' 'B' 'C' 'D' 'E' 'F']
|
||||
|
||||
if $number == 0 {
|
||||
''
|
||||
} else {
|
||||
let newNumber = (($number - ($number mod $base)) / $base)
|
||||
|
||||
[(dec2base $newNumber $base) ($chars | get ($number mod $base))] | str join
|
||||
}
|
||||
}
|
||||
|
||||
# Scale list to [a,b] interval
|
||||
export def scale-minmax [a, b,input?] {
|
||||
let x = if ($input | is-empty) {$in} else {$input}
|
||||
|
||||
let min = ($x | math min)
|
||||
let max = ($x | math max)
|
||||
|
||||
$x | each {|it| ((($it - $min) / ($max - $min)) * ($b - $a) + $a) }
|
||||
}
|
||||
|
||||
# Scale every column of a table (separately) to [a,b] interval
|
||||
export def scale-minmax-table [a, b,input?] {
|
||||
let x = if ($input | is-empty) {$in} else {$input}
|
||||
let n_cols = ($x | transpose | length)
|
||||
let name_cols = ($x | transpose | column2 0)
|
||||
|
||||
0..($n_cols - 1)
|
||||
| each {|i|
|
||||
($x | column2 $i) | scale-minmax $a $b | wrap ($name_cols | get $i)
|
||||
} | reduce {|it, acc| $acc | merge {$it}}
|
||||
}
|
||||
|
||||
|
||||
# compute the cartesian product of any number of lists
|
||||
#
|
||||
# basically, if you give `iter cartesian product` *n* lists, from *i_1* to *i_n*,
|
||||
# it will compute recursively the cartesian product of the first one with the
|
||||
# `iter cartesian product` of the rest, i.e. if we call CP the two-set cartesian
|
||||
# product and ICP the multi cartesian product here, we have
|
||||
#
|
||||
# *ICP(i_1, i_2, ..., i_n) == CP(i_1, ICP(i_2, ..., i_n))*
|
||||
#
|
||||
# # Example
|
||||
#```nushell
|
||||
# use std ["assert equal" "iter iter cartesian product"]
|
||||
#
|
||||
# let res = (
|
||||
# iter cartesian product [1, 2] [3, 4]
|
||||
# )
|
||||
#
|
||||
# assert equal $res [
|
||||
# [1, 3],
|
||||
# [1, 4],
|
||||
# [2, 3],
|
||||
# [2, 4],
|
||||
# ]
|
||||
# ```
|
||||
export def "cartesian product" [
|
||||
...iters: list<any> # the iterables you want the cartesian product of
|
||||
]: nothing -> list<list<any>> {
|
||||
def aux [a: list<list<any>>]: nothing -> list<list<any>> {
|
||||
if ($a | is-empty) {
|
||||
return []
|
||||
}
|
||||
|
||||
let head = $a | first
|
||||
let tail = aux ($a | skip 1)
|
||||
|
||||
if ($head | is-empty) {
|
||||
return $tail
|
||||
} else if ($tail | is-empty) {
|
||||
return $head
|
||||
}
|
||||
|
||||
$head | each {|h| $tail | each {|t| [$h, $t]}} | flatten | each { flatten }
|
||||
}
|
||||
|
||||
aux $iters
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
def cartesian_product [] {
|
||||
use std assert
|
||||
|
||||
# emptyness
|
||||
assert equal (cartesian product [] []) []
|
||||
assert equal (cartesian product []) []
|
||||
assert equal (cartesian product) []
|
||||
|
||||
# symmetry
|
||||
assert equal (cartesian product [1, 2] []) [1, 2]
|
||||
assert equal (cartesian product [] [1, 2]) [1, 2]
|
||||
# NOTE: `cartesian product` might not preserve the order of the elements produced
|
||||
assert equal (
|
||||
cartesian product [1, 2] [3, 4] | each { sort } | sort
|
||||
) (
|
||||
cartesian product [3, 4] [1, 2] | each { sort } | sort
|
||||
)
|
||||
|
||||
assert equal (
|
||||
cartesian product [1, 2] [3, 4]
|
||||
) [
|
||||
[1, 3], [1, 4], [2, 3], [2, 4]
|
||||
]
|
||||
|
||||
assert equal (
|
||||
cartesian product [1, 2] [3, 4] [5, 6]
|
||||
) [
|
||||
[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]
|
||||
]
|
||||
}
|
||||
|
||||
# `ways-to-add-up-to $n` is a list of all possible strictly-positive-integer sums that add up to `$n`
|
||||
#
|
||||
# # Example
|
||||
# `ways-to-add-up-to 4` will be `[[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]]` because $4$
|
||||
# can be obtained as follows:
|
||||
# $$
|
||||
# 4 = 1 + 1 + 1 + 1
|
||||
# = 1 + 1 + 2
|
||||
# = 1 + 3
|
||||
# = 2 + 2
|
||||
# = 4
|
||||
# $$
|
||||
export def ways-to-add-up-to [n: int]: [ nothing -> list<list<int>> ] {
|
||||
if $n == 0 {
|
||||
return []
|
||||
} else if $n == 1 {
|
||||
return [[1]]
|
||||
}
|
||||
|
||||
ways-to-add-up-to ($n - 1)
|
||||
| each { |it|
|
||||
let a = $it | append [1]
|
||||
let b = seq 0 ($it | length | $in - 1) | each { |i| $it | update $i { $in + 1 } }
|
||||
[$a] ++ $b
|
||||
}
|
||||
| flatten
|
||||
| each { sort }
|
||||
| uniq
|
||||
}
|
||||
|
||||
#[test]
|
||||
def test [] {
|
||||
use std assert
|
||||
for it in [
|
||||
[n, expected];
|
||||
|
||||
[0, []],
|
||||
[1, [[1]]],
|
||||
[2, [[1, 1], [2]]],
|
||||
[2, [[1, 1], [2]]],
|
||||
[3, [[1, 1, 1], [1, 2], [3]]],
|
||||
[4, [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]],
|
||||
[5, [[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 4], [2, 3], [5]]],
|
||||
] {
|
||||
assert equal (ways-to-add-up-to $it.n | sort) ($it.expected | sort)
|
||||
}
|
||||
print "tests passed"
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
# Remoting
|
||||
This module provide convenient way to manage multiple remote clients.
|
||||
|
||||
## Prerequisites
|
||||
* Both `ssh` and `ssh script` require ssh to be installed on the host
|
||||
* `ssh script` requires nushell to be installed on the client
|
||||
* `ssh` can work both with and without nushell installed on the client however having it installed enables more sophisticated interaction between host and clients
|
||||
* `wake` requires wakeonlan to be installed on the host and clients to be configured to accept Wake on Lan magic packets
|
||||
|
||||
## `ssh` function
|
||||
This function serves as a wrapper around standard ssh command.
|
||||
|
||||
Function accepts following arguments:
|
||||
* name - Name of the client as specified in the config. This parameter is required (autocompletion enabled)
|
||||
* args - command to run on the client. If not provided ssh starts an interactive session with the client. If provided and specified client has nushell configured output will be returned as nushell table on the host allowing further parsing. If provided and specified client does not have nushell configured output will be passed back as is
|
||||
## `ssh script` function
|
||||
This function executes a nushell script on a client that has nushell configured.
|
||||
|
||||
Function accepts following arguments:
|
||||
* name - Name of the client as specified in the config. This parameter is required (autocompletion enabled)
|
||||
* script - Name of the script to be executed on the client. This parameter is required The script must be available in current scope in order to be used (autocompletion enabled)
|
||||
* args - Arguments to be passed to the script. Named parameters should be put in quotes to avoid parsing errors like this: `ssh script my-host my-script '--arg value'`
|
||||
|
||||
## `wake` function
|
||||
This function wakes specified clients via Wake on Lan.
|
||||
|
||||
Function accepts following arguments:
|
||||
* names - Name of clients to be woken up as specified in the config. (autocompletion enabled)
|
||||
|
||||
|
||||
## Config
|
||||
Client config is kept within (non-exported) `hosts` function as a list of records. Each record should contain following fields:
|
||||
|
||||
| Parameter | Is required? | Usage | Type |
|
||||
|-----------|----------------------------------------|------------------------------|--------|
|
||||
| name | Required | DNS name of the client | string |
|
||||
| domain | Either domain or IP must be specified | DNS domain of the client | string |
|
||||
| ip | Either domain or IP must be specified | IP address of the client | string |
|
||||
| username | Required | Username used for connection | string |
|
||||
| port | Required | SSH port | int |
|
||||
| mac | Required only for `wake` | MAC address of the client | string |
|
||||
| nu | Required | Whether nushell is installed | bool |
|
||||
|
||||
Example configuration records:
|
||||
* {name: 'host1', domain: 'nushell.sh', ip: '', username: 'username', port: 22, mac: 'AA:BB:CC:DD:EE;FF', nu: false}
|
||||
* {name: 'host2', domain: '', ip: '192.168.0.1', username: 'username', port: 2222, mac: '', nu: true}
|
||||
@@ -0,0 +1,98 @@
|
||||
# internal function that holds the host data. We could store it in a yaml file as well but that would require nushell to read it from disk every single time
|
||||
def hosts [] {
|
||||
[
|
||||
# Put your config here
|
||||
]
|
||||
}
|
||||
def "nu-complete wol" [] {
|
||||
hosts
|
||||
|where mac != ''
|
||||
|get name
|
||||
}
|
||||
|
||||
def "nu-complete nu" [] {
|
||||
hosts
|
||||
|where nu
|
||||
|get name
|
||||
}
|
||||
|
||||
def "nu-complete hosts" [] {
|
||||
hosts
|
||||
|get name
|
||||
}
|
||||
|
||||
def "nu-complete scripts" [] {
|
||||
scope commands
|
||||
|where is_custom
|
||||
|get -i command
|
||||
}
|
||||
|
||||
# Returns ssh connection as url to be consumed by original ssh command
|
||||
def get-url [
|
||||
host: record
|
||||
] {
|
||||
if 'ip' in ($host|columns) {
|
||||
echo $"ssh://($host.username)@($host.ip):($host.port)"
|
||||
} else {
|
||||
echo $"ssh://($host.username)@($host.name).($host.domain):($host.port)"
|
||||
}
|
||||
}
|
||||
|
||||
# Connect over ssh to one of predefined hosts, execute nushell commands and parse them on the host
|
||||
export def ssh [
|
||||
hostname: string@"nu-complete hosts" # name of the host you want to connect to
|
||||
...args # commands you wish to run on the host
|
||||
] {
|
||||
let host = (hosts|where name == $hostname|get -i 0)
|
||||
if ($host.nu) {
|
||||
if ($args|length) > 0 {
|
||||
^ssh (get-url $host) (build-string ($args|str join ' ') '|to json -r')|from json
|
||||
} else {
|
||||
^ssh (get-url $host)
|
||||
}
|
||||
} else {
|
||||
^ssh (get-url $host) $args
|
||||
}
|
||||
}
|
||||
|
||||
# Connect over ssh to one of predefined hosts, execute nushell script with arguments passed from the host
|
||||
export def "ssh script" [
|
||||
hostname: string@"nu-complete nu" # name of the host you want to connect to
|
||||
script: string@"nu-complete scripts" # name of the script
|
||||
...args # arguments you wish to pass to the script in key=value format
|
||||
] {
|
||||
let span = (metadata $script).span
|
||||
if $script in (scope commands|where is_custom|get command) {
|
||||
|
||||
let host = (hosts|where name == $hostname|get 0)
|
||||
let full_command = (build-string (view-source $script) '; ' $script ' ' ($args|str join ' ') '|to json -r')
|
||||
^ssh (get-url $host) ($full_command)|from json
|
||||
|
||||
} else {
|
||||
error make {
|
||||
msg: $"($script) is not a custom command, use regular ssh command instead"
|
||||
label: {
|
||||
text: "Not a custom command",
|
||||
start: $span.start,
|
||||
end: $span.end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# Turns on specified hosts using Wake on Lan
|
||||
export def wake [
|
||||
...names: string@"nu-complete wol" # list of host names to wake
|
||||
] {
|
||||
hosts
|
||||
|where name in $names
|
||||
|each {|host|
|
||||
if $host.mac != '' {
|
||||
echo $"Waking ($host.name)"
|
||||
wakeonlan $host.mac|ignore
|
||||
} else {
|
||||
error make {
|
||||
msg: $"($host.name) does not support Wake on Lan"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
The `sockets` command returns a table containing information on network sockets and the processes they belong to.
|
||||
It is basically a join of the tables produced by the `lsof` command, and the nushell `ps` command.
|
||||
|
||||
<img width="1486" alt="image" src="https://user-images.githubusercontent.com/52205/196287615-00e46f8e-06ed-45ce-8fe7-a5c5f38afaaa.png">
|
||||
@@ -0,0 +1,32 @@
|
||||
export def sockets [--abbreviate-java-class-paths (-j)] {
|
||||
let input = (^lsof +c 0xFFFF -i -n -P)
|
||||
let header = ($input | lines
|
||||
| take 1
|
||||
| each { str downcase | str replace ' name$' ' name state' })
|
||||
let body = ($input | lines
|
||||
| skip 1
|
||||
| each { str replace '([^)])$' '$1 (NONE)' | str replace ' \((.+)\)$' ' $1' })
|
||||
[$header] | append $body
|
||||
| to text
|
||||
| detect columns
|
||||
| upsert 'pid' { |r| $r.pid | into int }
|
||||
| rename --column { name: connection }
|
||||
| reject 'command'
|
||||
| join-table (ps -l) 'pid' 'pid'
|
||||
| if $abbreviate_java_class_paths {
|
||||
upsert 'classpath' { |r| $r.command | java-cmd classpath }
|
||||
| upsert 'command' { |r| $r.command | java-cmd abbreviate-classpath }
|
||||
} else { $in }
|
||||
}
|
||||
|
||||
export def 'java-cmd classpath' [] {
|
||||
str replace '.* -classpath +(.+\.jar) +.*' '$1' | split row ':'
|
||||
}
|
||||
|
||||
export def 'java-cmd abbreviate-classpath' [] {
|
||||
str replace '[^ ]*\.jar' '*.jar'
|
||||
}
|
||||
|
||||
export def join-table [table: table, left_on: string, right_on: string] {
|
||||
dfr into df | join ($table | dfr into df) $left_on $right_on | dfr into nu
|
||||
}
|
||||
136
dot_config/nushell/nu_scripts/modules/network/ssh.nu
Normal file
136
dot_config/nushell/nu_scripts/modules/network/ssh.nu
Normal file
@@ -0,0 +1,136 @@
|
||||
export def ensure-cache [cache paths action] {
|
||||
mut cfgs = []
|
||||
for i in $paths {
|
||||
let cs = (do -i {ls ($i | into glob)})
|
||||
if ($cs | is-not-empty) {
|
||||
$cfgs = ($cfgs | append $cs)
|
||||
}
|
||||
}
|
||||
let cfgs = $cfgs
|
||||
let ts = ($cfgs | sort-by modified | reverse | get 0.modified)
|
||||
if ($ts | is-empty) { return false }
|
||||
let tc = (do -i { ls $cache | get 0.modified })
|
||||
if not (($cache | path exists) and ($ts < $tc)) {
|
||||
mkdir ($cache | path dirname)
|
||||
do $action | save -f $cache
|
||||
}
|
||||
open $cache
|
||||
}
|
||||
|
||||
export def 'str max-length' [] {
|
||||
$in | reduce -f 0 {|x, a|
|
||||
if ($x|is-empty) { return $a }
|
||||
let l = ($x | str length)
|
||||
if $l > $a { $l } else { $a }
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete ssh host" [] {
|
||||
rg -LNI '^Host [a-z0-9_\-\.]+' ~/.ssh | lines | each {|x| $x | split row ' '| get 1}
|
||||
}
|
||||
|
||||
export def parse-ssh-file [group] {
|
||||
$in
|
||||
| parse -r '(?<k>Host|HostName|User|Port|IdentityFile)\s+(?<v>.+)'
|
||||
| append { k: Host, v: null}
|
||||
| reduce -f { rst: [], item: {Host: null} } {|it, acc|
|
||||
if $it.k == 'Host' {
|
||||
$acc | upsert rst ($acc.rst | append $acc.item)
|
||||
| upsert item { Host : $it.v, HostName: null, Port: null, User: null, IdentityFile: null, Group: $group }
|
||||
} else {
|
||||
$acc | upsert item ($acc.item | upsert $it.k $it.v)
|
||||
}
|
||||
}
|
||||
| get rst
|
||||
| where {|x| not (($x.Host | is-empty) or $x.Host =~ '\*')}
|
||||
}
|
||||
|
||||
export def ssh-list [] {
|
||||
rg -L -l 'Host' ~/.ssh
|
||||
| lines
|
||||
| each {|x| cat $x | parse-ssh-file $x}
|
||||
| flatten
|
||||
}
|
||||
|
||||
def fmt-group [p] {
|
||||
$p | str replace $"($env.HOME)/.ssh/" ''
|
||||
}
|
||||
|
||||
def "ssh-hosts" [] {
|
||||
let cache = $'($env.HOME)/.cache/nu-complete/ssh.json'
|
||||
ensure-cache $cache [~/.ssh/config ~/.ssh/config*/* ] { ||
|
||||
let data = (ssh-list | each {|x|
|
||||
let uri = $"($x.User)@($x.HostName):($x.Port)"
|
||||
{
|
||||
value: $x.Host,
|
||||
uri: $uri,
|
||||
group: $"(fmt-group $x.Group)",
|
||||
identfile: $"($x.IdentityFile)",
|
||||
}
|
||||
})
|
||||
|
||||
let max = {
|
||||
value: ($data.value | str max-length),
|
||||
uri: ($data.uri | str max-length),
|
||||
group: ($data.group | str max-length),
|
||||
identfile: ($data.identfile | str max-length),
|
||||
}
|
||||
|
||||
{max: $max, completion: $data}
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete ssh" [] {
|
||||
let data = (ssh-hosts)
|
||||
$data.completion
|
||||
| each { |x|
|
||||
let uri = ($x.uri | fill -a l -w $data.max.uri -c ' ')
|
||||
let group = ($x.group | fill -a l -w $data.max.group -c ' ')
|
||||
let id = ($x.identfile | fill -a l -w $data.max.identfile -c ' ')
|
||||
{value: $x.value, description: $"\t($uri) ($group) ($id)" }
|
||||
}
|
||||
}
|
||||
|
||||
export extern main [
|
||||
host: string@"nu-complete ssh" # host
|
||||
...cmd # cmd
|
||||
-v # verbose
|
||||
-i: string # key
|
||||
-p: int # port
|
||||
-N # n
|
||||
-T # t
|
||||
-L # l
|
||||
-R # r
|
||||
-D # d
|
||||
-J: string # j
|
||||
-W: string # w
|
||||
]
|
||||
|
||||
|
||||
def "nu-complete scp" [cmd: string, offset: int] {
|
||||
let argv = ($cmd | str substring ..$offset | split row ' ')
|
||||
let p = if ($argv | length) > 2 { $argv | get 2 } else { $argv | get 1 }
|
||||
let ssh = (ssh-hosts | get completion
|
||||
| each {|x| {value: $"($x.value):" description: $x.uri} }
|
||||
)
|
||||
let n = ($p | split row ':')
|
||||
if $"($n | get 0):" in ($ssh | get value) {
|
||||
^ssh ($n | get 0) $"sh -c 'ls -dp ($n | get 1)*'"
|
||||
| lines
|
||||
| each {|x| $"($n | get 0):($x)"}
|
||||
} else {
|
||||
let files = (do -i {
|
||||
ls -a ($"($p)*" | into glob)
|
||||
| each {|x| if $x.type == dir { $"($x.name)/"} else { $x.name }}
|
||||
})
|
||||
$files | append $ssh
|
||||
}
|
||||
}
|
||||
|
||||
export def --wrapped scp [
|
||||
lhs: string@"nu-complete scp",
|
||||
rhs: string@"nu-complete scp"
|
||||
...opts
|
||||
] {
|
||||
^scp -r ...$opts $lhs $rhs
|
||||
}
|
||||
68
dot_config/nushell/nu_scripts/modules/nix/README.md
Normal file
68
dot_config/nushell/nu_scripts/modules/nix/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Nix
|
||||
|
||||
Commands for working with [nix/nixos](https://nixos.org/).
|
||||
|
||||
### ns
|
||||
Shorthand search (`nix search nixpkgs ...`) with much nicer output.
|
||||
```shell
|
||||
❯ > nix search nixpkgs diesel
|
||||
* legacyPackages.x86_64-linux.diesel-cli (2.1.0)
|
||||
Database tool for working with Rust projects that use Diesel
|
||||
|
||||
* legacyPackages.x86_64-linux.diesel-cli-ext (0.3.13)
|
||||
Provides different tools for projects using the diesel_cli
|
||||
```
|
||||
```shell
|
||||
❯ > ns diesel
|
||||
╭───┬────────────────┬──────────────────────────────────────────────────────────────┬─────────╮
|
||||
│ # │ package │ description │ version │
|
||||
├───┼────────────────┼──────────────────────────────────────────────────────────────┼─────────┤
|
||||
│ 0 │ diesel-cli │ Database tool for working with Rust projects that use Diesel │ 2.1.0 │
|
||||
│ 1 │ diesel-cli-ext │ Provides different tools for projects using the diesel_cli │ 0.3.13 │
|
||||
├───┼────────────────┼──────────────────────────────────────────────────────────────┼─────────┤
|
||||
│ # │ package │ description │ version │
|
||||
╰───┴────────────────┴──────────────────────────────────────────────────────────────┴─────────╯
|
||||
```
|
||||
|
||||
### activation-script
|
||||
|
||||
Shows changed packages after running `nixos-rebuild switch/boot` and change in total size of installed packages. Changes that don't affect the installed size are filtered out. Intended to be added to `configuration.nix` of `NixOS`.
|
||||
|
||||
```
|
||||
╭────┬──────────────────┬───────────────────────┬────────┬────────────╮
|
||||
│ # │ Package │ Old │ New │ Diff │
|
||||
├────┼──────────────────┼───────────────────────┼────────┼────────────┤
|
||||
│ 0 │ nushell │ 0.94.1 │ 0.95.0 │ 192.1 KiB │
|
||||
│ 1 │ hyprland │ 0.41.1 │ 0.41.2 │ 52.9 KiB │
|
||||
│ 2 │ qtdeclarative │ 6.7.1 │ 6.7.2 │ 36.2 KiB │
|
||||
│ 3 │ linux │ 6.9.6 │ 6.9.7 │ 17.7 KiB │
|
||||
│ 4 │ qtbase │ 6.7.1 │ 6.7.2 │ 16.1 KiB │
|
||||
│ 5 │ networkmanager │ 1.48.0 │ 1.48.2 │ 8.3 KiB │
|
||||
│ 6 │ wireplumber │ 0.5.3 │ 0.5.4 │ -21.4 KiB │
|
||||
│ 7 │ libbacktrace │ 0-unstable-2024-03-02 │ ∅ │ -110.4 KiB │
|
||||
│ 8 │ woff2 │ 1.0.2 │ ∅ │ -155.5 KiB │
|
||||
│ 9 │ libmanette │ 0.2.7 │ ∅ │ -226.0 KiB │
|
||||
│ 10 │ webkitgtk │ 2.44.2+abi=6.0 │ ∅ │ -147.6 MiB │
|
||||
│ 11 │ telegram-desktop │ 5.1.8 │ ∅ │ -219.4 MiB │
|
||||
│ 12 │ │ │ │ │
|
||||
│ 13 │ │ │ Total: │ -367.2 MiB │
|
||||
╰────┴──────────────────┴───────────────────────┴────────┴────────────╯
|
||||
```
|
||||
|
||||
### nufetch
|
||||
|
||||
nu alternative to `neofetch`/`hyfetch`.
|
||||
```
|
||||
╭──────────┬───────────────────────────────────╮
|
||||
│ kernel │ 6.11.0 │
|
||||
│ nu │ 0.98.0 │
|
||||
│ │ ╭─────────────┬────────┬────────╮ │
|
||||
│ packages │ │ environment │ number │ size │ │
|
||||
│ │ ├─────────────┼────────┼────────┤ │
|
||||
│ │ │ system │ 825 │ 5.7 GB │ │
|
||||
│ │ │ sperber │ 352 │ 1.5 GB │ │
|
||||
│ │ │ steam │ 929 │ 5.4 GB │ │
|
||||
│ │ ╰─────────────┴────────┴────────╯ │
|
||||
│ uptime │ 3hr 1min 18sec │
|
||||
╰──────────┴───────────────────────────────────╯
|
||||
```
|
||||
10
dot_config/nushell/nu_scripts/modules/nix/activation-script
Normal file
10
dot_config/nushell/nu_scripts/modules/nix/activation-script
Normal file
@@ -0,0 +1,10 @@
|
||||
### add to configuration.nix
|
||||
|
||||
nix.settings.experimental-features = ["nix-command"];
|
||||
|
||||
system.activationScripts.diff = ''
|
||||
if [[ -e /run/current-system ]]; then
|
||||
${pkgs.nushell}/bin/nu -c "let diff_closure = (${pkgs.nix}/bin/nix store diff-closures /run/current-system '$systemConfig'); let table = (\$diff_closure | lines | where \$it =~ KiB | where \$it =~ → | parse -r '^(?<Package>\S+): (?<Old>[^,]+)(?:.*) → (?<New>[^,]+)(?:.*), (?<DiffBin>.*)$' | insert Diff { get DiffBin | ansi strip | into filesize } | sort-by -r Diff | reject DiffBin); if (\$table | get Diff | is-not-empty) { print \"\"; \$table | append [[Package Old New Diff]; [\"\" \"\" \"\" \"\"]] | append [[Package Old New Diff]; [\"\" \"\" \"Total:\" (\$table | get Diff | math sum) ]] | print; print \"\" }"
|
||||
fi
|
||||
'';
|
||||
|
||||
18
dot_config/nushell/nu_scripts/modules/nix/nix.nu
Normal file
18
dot_config/nushell/nu_scripts/modules/nix/nix.nu
Normal file
@@ -0,0 +1,18 @@
|
||||
# Search nixpkgs and provide table output
|
||||
export def ns [
|
||||
term: string # Search target.
|
||||
] {
|
||||
|
||||
let info = (
|
||||
sysctl -n kernel.arch kernel.ostype
|
||||
| lines
|
||||
| {arch: ($in.0|str downcase), ostype: ($in.1|str downcase)}
|
||||
)
|
||||
|
||||
nix search --json nixpkgs $term
|
||||
| from json
|
||||
| transpose package description
|
||||
| flatten
|
||||
| select package description version
|
||||
| update package {|row| $row.package | str replace $"legacyPackages.($info.arch)-($info.ostype)." ""}
|
||||
}
|
||||
8
dot_config/nushell/nu_scripts/modules/nix/nufetch.nu
Normal file
8
dot_config/nushell/nu_scripts/modules/nix/nufetch.nu
Normal file
@@ -0,0 +1,8 @@
|
||||
export def main [] {
|
||||
{
|
||||
"kernel": $nu.os-info.kernel_version,
|
||||
"nu": $env.NU_VERSION,
|
||||
"packages": (ls /etc/profiles/per-user | select name | prepend [[name];["/run/current-system/sw"]] | each { insert "number" (nix path-info --recursive ($in | get name) | lines | length) | insert "size" ( nix path-info -S ($in | get name) | parse -r '\s(.*)' | get capture0.0 | into filesize) | update "name" ($in | get name | parse -r '.*/(.*)' | get capture0.0 | if $in == "sw" {"system"} else {$in}) | rename "environment"}),
|
||||
"uptime": (sys host).uptime
|
||||
}
|
||||
}
|
||||
133
dot_config/nushell/nu_scripts/modules/nvim/mod.nu
Normal file
133
dot_config/nushell/nu_scripts/modules/nvim/mod.nu
Normal file
@@ -0,0 +1,133 @@
|
||||
## neovim configurations
|
||||
# local vcs_root = require('lspconfig.util').root_pattern('.git/')
|
||||
# function HookPwdChanged(after, before)
|
||||
# vim.b.pwd = after
|
||||
# local git_dir = vcs_root(after)
|
||||
# vim.api.nvim_command('silent tcd! '..(git_dir or after))
|
||||
# end
|
||||
|
||||
# function OppositePwd()
|
||||
# local tab = vim.api.nvim_get_current_tabpage()
|
||||
# local wins = vim.api.nvim_tabpage_list_wins(tab)
|
||||
# local cwin = vim.api.nvim_tabpage_get_win(tab)
|
||||
# for _, w in ipairs(wins) do
|
||||
# if cwin ~= w then
|
||||
# local b = vim.api.nvim_win_get_buf(w)
|
||||
# local pwd = vim.b[b].pwd
|
||||
# if pwd then return pwd end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
# function ReadTempDrop(path, action)
|
||||
# vim.api.nvim_command(action or 'botright vnew')
|
||||
# local win = vim.api.nvim_get_current_win()
|
||||
# local buf = vim.api.nvim_create_buf(true, true)
|
||||
# vim.api.nvim_win_set_buf(win, buf)
|
||||
# vim.api.nvim_command('read '..path)
|
||||
# vim.fn.delete(path)
|
||||
# end
|
||||
|
||||
|
||||
def nvim_tcd [] {
|
||||
[
|
||||
{|before, after|
|
||||
if ($env.NVIM? | is-not-empty) {
|
||||
nvim --headless --noplugin --server $env.NVIM --remote-send $"<cmd>lua HookPwdChanged\('($after)', '($before)')<cr>"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# nvim tcd
|
||||
export def tcd [path?: string] {
|
||||
let after = if ($path | is-empty) {
|
||||
$env.PWD
|
||||
} else {
|
||||
$path
|
||||
}
|
||||
nvim --headless --noplugin --server $env.NVIM --remote-send $"<cmd>lua HookPwdChanged\('($after)', '($env.PWD)')<cr>"
|
||||
}
|
||||
|
||||
export-env {
|
||||
$env.config = ( $env.config | upsert hooks.env_change.PWD { |config|
|
||||
let o = ($config | get -i hooks.env_change.PWD)
|
||||
let val = (nvim_tcd)
|
||||
if $o == null {
|
||||
$val
|
||||
} else {
|
||||
$o | append $val
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
# drop stdout to nvim buf
|
||||
export def drop [] {
|
||||
if ($env.NVIM? | is-empty) {
|
||||
echo $in
|
||||
} else {
|
||||
let c = $in
|
||||
let temp = (mktemp -t nuvim.XXXXXXXX|str trim)
|
||||
$c | save -f $temp
|
||||
nvim --headless --noplugin --server $env.NVIM --remote-send $"<cmd>lua ReadTempDrop\('($temp)')<cr>"
|
||||
}
|
||||
}
|
||||
|
||||
export def nvim-lua [...expr: string] {
|
||||
if ($env.NVIM? | is-empty) {
|
||||
echo "not found nvim instance"
|
||||
} else {
|
||||
nvim --headless --noplugin --server $env.NVIM --remote-send $'<cmd>lua vim.g.remote_expr_lua = ($expr|str join " ")<cr>'
|
||||
do -i { nvim --headless --noplugin --server $env.NVIM --remote-expr 'g:remote_expr_lua' } | complete | get stderr
|
||||
}
|
||||
}
|
||||
|
||||
export def opwd [] {
|
||||
nvim-lua 'OppositePwd()'
|
||||
}
|
||||
|
||||
export def nve [action ...file] {
|
||||
if ($env.NVIM? | is-empty) {
|
||||
nvim ...$file
|
||||
} else {
|
||||
let af = $file
|
||||
| each {|f|
|
||||
if ($f|str substring ..1) in ['/', '~'] {
|
||||
$f
|
||||
} else {
|
||||
$"($env.PWD)/($f)"
|
||||
}
|
||||
}
|
||||
let action = if ($file | is-empty) { $action | str replace -r 'sp.*$' 'new' } else { $action }
|
||||
let cmd = $"<cmd>($action) ($af|str join ' ')<cr>"
|
||||
nvim --headless --noplugin --server $env.NVIM --remote-send $cmd
|
||||
}
|
||||
}
|
||||
|
||||
export alias e = nve vsplit
|
||||
export alias v = nve vsplit
|
||||
export alias c = nve split
|
||||
export alias x = nve tabnew
|
||||
|
||||
export def nvs [port: int=9999] {
|
||||
nvim --headless --listen $"0.0.0.0:($port)"
|
||||
}
|
||||
|
||||
export def nvc [
|
||||
addr: string
|
||||
--gui(-g)
|
||||
] {
|
||||
if $gui {
|
||||
let gs = {
|
||||
neovide: [--maximized --server $addr]
|
||||
}
|
||||
for g in ($gs | transpose prog args) {
|
||||
if (which $g.prog | is-not-empty) {
|
||||
^$g.prog ...$g.args
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nvim --remote-ui --server $addr
|
||||
}
|
||||
}
|
||||
5
dot_config/nushell/nu_scripts/modules/parsing/README.md
Normal file
5
dot_config/nushell/nu_scripts/modules/parsing/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Parsing Scripts
|
||||
|
||||
### Definition
|
||||
|
||||
These scripts should be used to demonstrate how to parse any file format, including `json`, `csv`, etc. Also, perhaps parsing of `external` commands. For example, on Windows, perhaps we could wrap `ipconfig.exe` so that the output was more nushell friendly.
|
||||
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"name": "Brunello Cucinelli",
|
||||
"shoes": [
|
||||
{ "name": "tasselled black low-top lace-up", "price": 1000 },
|
||||
{ "name": "tasselled green low-top lace-up", "price": 1100 },
|
||||
{ "name": "plain beige suede moccasin", "price": 950 },
|
||||
{ "name": "plain olive suede moccasin", "price": 1050 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Gucci",
|
||||
"shoes": [
|
||||
{ "name": "red leather laced sneakers", "price": 800 },
|
||||
{ "name": "black leather laced sneakers", "price": 900 }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
def look_for [word] {
|
||||
open sample_andres.json |
|
||||
flatten |
|
||||
flatten |
|
||||
insert comp {
|
||||
get shoes_name |
|
||||
split row " " |
|
||||
enumerate | each {
|
||||
[[idx, loc]; [$in.index, ($in.item | str index-of $word)]]
|
||||
} | flatten
|
||||
} |
|
||||
flatten |
|
||||
where comp.loc >= 0 |
|
||||
flatten |
|
||||
update idx { $in + 1 } |
|
||||
reject name price loc |
|
||||
rename nameWords targetWordIndex
|
||||
}
|
||||
|
||||
print (look_for "leather" | to json --indent 4)
|
||||
print (look_for "low-top" | to json --indent 4)
|
||||
31
dot_config/nushell/nu_scripts/modules/prompt/README.md
Normal file
31
dot_config/nushell/nu_scripts/modules/prompt/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Prompt Scripts
|
||||
|
||||
### Definition
|
||||
|
||||
These scripts should be used to draw a custom command prompt in nushell. They can include anything that we think is appropriate for prompts such as `git` commands, `starship`, `oh-my-posh`, etc.
|
||||
|
||||
#### starship.nu
|
||||
|
||||
File is in [starship](./starship.nu)
|
||||
|
||||
This describe how to use starship to make a leftprompt, the repo of starship is [here](https://github.com/starship/starship).
|
||||
|
||||
This script set the output of starship as leftprompt
|
||||
|
||||

|
||||
|
||||
#### shell_space.nu
|
||||
|
||||
File is in [shell_space](./shell_space.nu)
|
||||
|
||||
Use the function of shells in nu, you can view the function with the command following
|
||||
|
||||
```
|
||||
help shells
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### jalon-git.nu
|
||||
From https://github.com/JalonWong/nushell-prompt
|
||||

|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user