mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-08-03 07:37:47 +00:00
Deprecate the nu_scripts
version of stdlib-candidate
(#1042)
Deprecates the existing `stdlib-candidate` directories in `nu_scripts` since `std-rfc` has now transitioned to the main repo. Updates readme and renamed directories.
This commit is contained in:
parent
a31f8490fb
commit
5869e0b529
53 changed files with 18 additions and 40 deletions
|
@ -0,0 +1,3 @@
|
|||
# std-lib candidate
|
||||
|
||||
This is the deprecated `stdlib-candidate` module. Please see the [new version](https://github.com/nushell/nu_scripts/tree/main/stdlib-candidate). If you have a submission here, you can move it to the new repo. Please refer to the [README](https://github.com/nushell/nu_scripts/blob/main/stdlib-candidate/README.md) there for the process.
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
name: "std-rfc"
|
||||
description: "Official candidates for Nushell standard library"
|
||||
documentation: "https://github.com/nushell/nu_scripts/blob/main/stdlib-candidate/std-rfc/README.md"
|
||||
license: "https://github.com/nushell/nu_scripts/blob/main/LICENSE"
|
||||
version: 0.3.0
|
||||
type: "module"
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
# A proposal for improving the original `std bench` command by @amtoine
|
||||
# https://github.com/nushell/nushell/blob/31f3d2f6642b585f0d88192724723bf0ce330ecf/crates/nu-std/std/mod.nu#L134
|
||||
|
||||
# round an integer amount of nanoseconds to 4th digit and convert to a real duration
|
||||
def "from ns" [] {
|
||||
if $in == 0 {0} else { #math log errors on 0
|
||||
math round -p (3 - ($in | math log 10 | math floor)) # rounds to 4th digit including, with maximum relative err 0.05%
|
||||
| math round # second math round as a fix for `> 123456 | math round -p -5` = 99999.99999999999
|
||||
}
|
||||
| into duration
|
||||
}
|
||||
|
||||
# run a piece of `nushell` code multiple times and measure the time of execution.
|
||||
#
|
||||
# this command returns a benchmark report of the following form:
|
||||
# ```
|
||||
# record<
|
||||
# mean: duration
|
||||
# min: duration
|
||||
# max: duration
|
||||
# std: duration
|
||||
# times: list<duration>
|
||||
# >
|
||||
# ```
|
||||
#
|
||||
# > **Note**
|
||||
# > `std bench --pretty` will return a `string`.
|
||||
#
|
||||
# # Examples
|
||||
# measure the performance of simple addition
|
||||
# > bench {1 + 2}
|
||||
# ╭──────┬───────────╮
|
||||
# │ mean │ 716ns │
|
||||
# │ min │ 583ns │
|
||||
# │ max │ 4µs 541ns │
|
||||
# │ std │ 549ns │
|
||||
# ╰──────┴───────────╯
|
||||
#
|
||||
# get a pretty benchmark report
|
||||
# > bench {1 + 2} --pretty
|
||||
# 716ns ± 76.67%
|
||||
#
|
||||
# measure the performance of simple addition with 1ms delay and output each timing
|
||||
# > bench {sleep 1ms; 1 + 2} --rounds 2 --timings | table -e
|
||||
# ╭───────┬───────────────╮
|
||||
# │ mean │ 1ms 272µs │
|
||||
# │ min │ 1ms 259µs │
|
||||
# │ max │ 1ms 285µs │
|
||||
# │ std │ 13µs 370ns │
|
||||
# │ │ ╭───────────╮ │
|
||||
# │ times │ │ 1ms 285µs │ │
|
||||
# │ │ │ 1ms 259µs │ │
|
||||
# │ │ ╰───────────╯ │
|
||||
# ╰───────┴───────────────╯
|
||||
export def main [
|
||||
code: closure # the piece of `nushell` code to measure the performance of
|
||||
--rounds (-n): int = 50 # the number of benchmark rounds (hopefully the more rounds the less variance)
|
||||
--verbose (-v) # be more verbose (namely prints the progress)
|
||||
--pretty # shows the results in human-readable format: "<mean> +/- <stddev>"
|
||||
--timings (-t) # list all rounds' timings in a `times` field
|
||||
] {
|
||||
let times = seq 1 $rounds
|
||||
| each {|i|
|
||||
if $verbose { print -n $"($i) / ($rounds)\r" }
|
||||
timeit { do $code } | into int | into float
|
||||
}
|
||||
|
||||
if $verbose { print $"($rounds) / ($rounds)" }
|
||||
|
||||
{
|
||||
mean: ($times | math avg | from ns)
|
||||
min: ($times | math min | from ns)
|
||||
max: ($times | math max | from ns)
|
||||
std: ($times | math stddev | from ns)
|
||||
}
|
||||
| if $pretty {
|
||||
$"($in.mean) ± (($in.std / $in.mean) * 100 | math round -p 2)%"
|
||||
} else {
|
||||
if $timings {
|
||||
merge { times: ($times | each { from ns }) }
|
||||
} else {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
# Rename bulk input files in parallel using a closure.
|
||||
#
|
||||
# The reason behind this command is quite simple:
|
||||
# - Sometimes one receives a bunch of files with integer ids: 1, 2, 3, ...
|
||||
# - These ids come rarely with padding... i.e. 1 instead of 001 when there are 3-digit ids
|
||||
# - This means that file with id 9 will be sorted way after file with id 1000
|
||||
#
|
||||
# This command allows to do such a task!
|
||||
#
|
||||
# Examples:
|
||||
# Rename `.mise.toml` files to `.mise.local.toml` recursively
|
||||
# > glob **/.mise.toml | bulk-rename { str append .local }
|
||||
#
|
||||
# Rename files in `/foo` with a name that has an id to have 3 digits with 0-padding
|
||||
# > ls /foo | bulk-rename { |path|
|
||||
# if $path.input.type == file {
|
||||
# $path.stem | parse "some_format_{id}"
|
||||
# | get 0
|
||||
# | update id { fill --alignment r --character 0 --width 3 }
|
||||
# | $"some_format_($in.id)"
|
||||
# }
|
||||
# # else skip dirs
|
||||
# }
|
||||
export def main [
|
||||
update_stem: closure, # The code to rename the file stem: receives the old stem as input and a record param with both `stem` and `input` keys
|
||||
--verbose (-v), # Show which files were renamed, if any
|
||||
--no-execute (-n) # Do not make any changes; add --verbose to see what would be made
|
||||
]: [list<any> -> nothing, list<any> -> table<old: path new: path>] {
|
||||
let renamed = par-each --keep-order { |input|
|
||||
let update_or_keep_stem = { |parts|
|
||||
do $update_stem { stem: $in input: $input } | default $parts.stem
|
||||
}
|
||||
let old = if ($input | describe) == string {
|
||||
$input
|
||||
} else {
|
||||
$input.name # convenience for ls
|
||||
}
|
||||
let new = $old | path parse | update stem $update_or_keep_stem | path join
|
||||
if $new != $old {
|
||||
if not $no_execute {
|
||||
mv --force --verbose=$verbose $old $new
|
||||
}
|
||||
{ old: $old new: $new }
|
||||
}
|
||||
}
|
||||
if $verbose {
|
||||
$renamed
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# A command to flatten many levels by using recursion
|
||||
# by @jturner 2/10/21
|
||||
# Example: sys | flatter 3
|
||||
def flatter [levels:int] {
|
||||
let input = $in
|
||||
if $levels > 0 {
|
||||
$input | columns | reduce -f $input {|it acc| $acc | flatten $it } | flatter ($levels - 1)
|
||||
} else {
|
||||
$input
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
# A small script to auto-update nushell in linux
|
||||
# requires nushell 0.36.0 or greater
|
||||
def get-latest-linux [] {
|
||||
# fetch the information about the latest release
|
||||
let metadata = (http get https://api.github.com/repos/nushell/nushell/releases/latest)
|
||||
let release_name = ($metadata | get name | split row ' ' | first)
|
||||
# get the body that shows information about this release
|
||||
let body = ($metadata | get body)
|
||||
# find the linux download
|
||||
let asset_info = ($metadata | get assets | where name =~ 'x86_64-linux-gnu-full.tar.gz' | first)
|
||||
# construct the url
|
||||
let download_url = ($asset_info | get browser_download_url)
|
||||
|
||||
let file_name = ($asset_info | get name)
|
||||
# tell you what i'm doing
|
||||
print $"Release name is ($release_name)(char newline)(char newline)"
|
||||
print $"($body)(char newline)(char newline)Downloading and following redirects ..."
|
||||
# fetch follows redirects now
|
||||
http get $download_url | save $file_name
|
||||
# tell you what i'm doing
|
||||
print $"(char newline)Extracting ($file_name) to /tmp(char newline)"
|
||||
# extract the tar file to the temp folder
|
||||
tar -xf ($file_name) -C /tmp
|
||||
# parse the $file_name to get the folder
|
||||
# echo nu_0_31_0_linux.tar.gz | path parse | get stem | path parse | get stem
|
||||
# echo nu_0_31_0_linux.tar.gz | split column '.' | get Column1
|
||||
# now get the file name using the path commands. it was a little tricky because
|
||||
# there are two extensions .tar and .gz
|
||||
let root_file_name = ($file_name | path parse | get stem | path parse | get stem)
|
||||
# update our progress
|
||||
print $"Copying files from /tmp/($root_file_name)/*/* to ~/.cargo/bin(char newline)"
|
||||
# this is for testing so it doesn't overwrite my real nu. this should really
|
||||
# be a parameter
|
||||
mkdir release
|
||||
# construct the copy from and to paths
|
||||
let cp_from_path = $"/tmp/($root_file_name)/**/*"
|
||||
let cp_to_path = "./release"
|
||||
# actually run the cp command
|
||||
# we may want to make this overwrite and not prompt
|
||||
cp ($cp_from_path) ($cp_to_path)
|
||||
# exec ~/.cargo/bin/nu
|
||||
print $"Starting nushell(char nl)"
|
||||
exec ./release/nu
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
# replace all insignificant digits with 0
|
||||
#
|
||||
# | Significant Digits | Maximum Relative Error |
|
||||
# |--------------------|------------------------|
|
||||
# | 1 | 50% |
|
||||
# | 2 | 5% |
|
||||
# | 3 | 0.5% |
|
||||
# | 4 | 0.05% |
|
||||
# | 5 | 0.005% |
|
||||
# | 6 | 0.0005% |
|
||||
#
|
||||
# > 0.0000012346789 | significant-digits 2
|
||||
# 0.0000012
|
||||
#
|
||||
# > 1.2346789 | significant-digits 3
|
||||
# 1.23
|
||||
#
|
||||
# > 123456789.89 | significant-digits 5
|
||||
# 123450000
|
||||
#
|
||||
# > 1sec / 3 | math significant-digits
|
||||
# 333ms
|
||||
export def 'significant-digits' [
|
||||
n: int = 3 # a number of significant digits
|
||||
]: [int -> int, float -> float, duration -> duration] {
|
||||
let $input = $in
|
||||
let $type = $input | describe
|
||||
|
||||
let $num = match $type {
|
||||
'duration' => {$input | into int}
|
||||
_ => {$input}
|
||||
}
|
||||
|
||||
let insignif_position = $num
|
||||
| if $in == 0 {
|
||||
0 # it's impoosbile to calculate `math log` from 0, thus 0 errors here
|
||||
} else {
|
||||
math abs
|
||||
| math log 10
|
||||
| math floor
|
||||
| $n - 1 - $in
|
||||
}
|
||||
|
||||
|
||||
# See the note below the code for an explanation of the construct used.
|
||||
let scaling_factor = 10 ** ($insignif_position | math abs)
|
||||
|
||||
let res = $num
|
||||
| if $insignif_position > 0 {
|
||||
$in * $scaling_factor
|
||||
} else {
|
||||
$in / $scaling_factor
|
||||
}
|
||||
| math floor
|
||||
| if $insignif_position <= 0 {
|
||||
$in * $scaling_factor
|
||||
} else {
|
||||
$in / $scaling_factor
|
||||
}
|
||||
|
||||
match $type {
|
||||
'duration' => {$res | into duration}
|
||||
'int' => {$res | into int}
|
||||
_ => {$res}
|
||||
}
|
||||
}
|
||||
|
||||
# I started with `10.0 ** $insignif_position`, but it was sometimes producing
|
||||
# not rounded digits in `$num / $scaling_factor` if `$insignif_position` was negative
|
||||
# like with
|
||||
# > 3456789 | math round --precision -5
|
||||
# 3499999.9999999995
|
||||
# so I use what I have now.
|
|
@ -0,0 +1,12 @@
|
|||
# Modules
|
||||
export module record/
|
||||
export module str/
|
||||
export module math/
|
||||
|
||||
# Commands
|
||||
export use bulk-rename.nu *
|
||||
export use set-env.nu *
|
||||
export use bench.nu
|
||||
export use script-parsing.nu [ parse-arg ]
|
||||
export use conversions *
|
||||
export use tables *
|
|
@ -0,0 +1,110 @@
|
|||
# This is a port of powershells $psstyle
|
||||
# found here https://github.com/PowerShell/PowerShell/blob/5f3dd938b792e1a395fd011ac1461246db7c0e1f/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs
|
||||
|
||||
# Example Usage
|
||||
# echo (fg_blue) Darren (relet) ' ' Schroeder | str collect
|
||||
# More examples in the short_list.nu script
|
||||
|
||||
alias fmt_error = ansi -e '31;1m'
|
||||
alias fmt_warning = ansi -e '33;1m'
|
||||
alias fmt_verbose = ansi -e '33;1m'
|
||||
alias fmt_debug = ansi -e '33;1m'
|
||||
alias fmt_format_accent = ansi -e '32;1m'
|
||||
alias fmt_error_accent = ansi -e '36;1m'
|
||||
|
||||
alias relet = ansi -e '0m' # really reset but there are external commands for reset already
|
||||
alias blink_off = ansi -e '25m'
|
||||
alias blink_on = ansi -e '5m'
|
||||
alias bold_off = ansi -e '22m'
|
||||
alias bold_on = ansi -e '1m'
|
||||
alias hidden_on = ansi -e '8m'
|
||||
alias hidden_off = ansi -e '28m'
|
||||
alias reverse_on = ansi -e '7m'
|
||||
alias reverse_off = ansi -e '27m'
|
||||
alias italic_off = ansi -e '23m'
|
||||
alias italic_on = ansi -e '3m'
|
||||
alias underline_off = ansi -e '24m'
|
||||
alias underline_on = ansi -e '4m'
|
||||
alias strikethrough_off = ansi -e '29m'
|
||||
alias strikethrough_on = ansi -e '9m'
|
||||
|
||||
# this doesn't work right. i need to have an (ansi escape) defined but i don't think there is one
|
||||
#def format_hyperlink [link text] {echo [(ansi -o '8;;') $link '\' $text (ansi -o '8;;') '\'] | str collect }
|
||||
|
||||
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'
|
||||
|
||||
# construct a rgb foreground color
|
||||
def fg_from_rgb [
|
||||
red:int # red component 0-255
|
||||
green:int # green component 0-255
|
||||
blue:int # blue component 0-255
|
||||
] {
|
||||
echo [(ansi -e '38;2;') $red ';' $green ';' $blue 'm'] | str join
|
||||
}
|
||||
|
||||
alias bg_black = ansi -e '40m'
|
||||
alias bg_red = ansi -e '41m'
|
||||
alias bg_green = ansi -e '42m'
|
||||
alias bg_yellow = ansi -e '43m'
|
||||
alias bg_blue = ansi -e '44m'
|
||||
alias bg_magenta = ansi -e '45m'
|
||||
alias bg_purple = ansi -e '45m'
|
||||
alias bg_cyan = ansi -e '46m'
|
||||
alias bg_white = ansi -e '47m'
|
||||
|
||||
alias bg_dark_gray = ansi -e '100m'
|
||||
alias bg_light_black = ansi -e '100m'
|
||||
alias bg_light_red = ansi -e '101m'
|
||||
alias bg_light_green = ansi -e '102m'
|
||||
alias bg_light_yellow = ansi -e '103m'
|
||||
alias bg_light_magenta = ansi -e '105m'
|
||||
alias bg_light_purple = ansi -e '105m'
|
||||
alias bg_light_blue = ansi -e '104m'
|
||||
alias bg_light_cyan = ansi -e '106m'
|
||||
alias bg_light_gray = ansi -e '107m'
|
||||
alias bg_light_white = ansi -e '107m'
|
||||
|
||||
alias bg_expand = ansi -e 'K'
|
||||
|
||||
# construct a rgb background color
|
||||
def bg_from_rgb [
|
||||
red:int # red component 0-255
|
||||
green:int # green component 0-255
|
||||
blue:int # blue component 0-255
|
||||
] {
|
||||
$"(ansi -e '48;2;')($red);($green);($blue)m"
|
||||
}
|
||||
|
||||
# Get a foreground color from an index value 0-255
|
||||
def fg_from_index [
|
||||
idx:int # index value 0-255
|
||||
] {
|
||||
$"(ansi -e '38;5;')($idx)m"
|
||||
}
|
||||
|
||||
# Get a background color from an index value 0-255
|
||||
def bg_from_index [
|
||||
idx:int # index value 0-255
|
||||
] {
|
||||
$"(ansi -e '48;5;')($idx)m"
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
# A print command that concatenates arguments together with an optional separator
|
||||
# By default there will be no newline
|
||||
def print1 [
|
||||
--separator(-s):any # Optional separator (not yet flagged as optional?)
|
||||
...rest # All of the parameters
|
||||
] {
|
||||
let is_empty = ($separator | is-empty)
|
||||
let num_of_rest = ($rest | length)
|
||||
$rest | enumerate | each { |param|
|
||||
if $is_empty {
|
||||
$param.item
|
||||
} else {
|
||||
if $num_of_rest > ($param.index + 1) {
|
||||
$"($param.item)($separator)"
|
||||
} else {
|
||||
$param.item
|
||||
}
|
||||
}
|
||||
} | into string | str join
|
||||
}
|
||||
|
||||
# > print 1 2 3 "four" -s '--'
|
||||
# 1--2--3--four
|
||||
|
||||
# > print 1 2 3 "four"
|
||||
# 123four
|
||||
|
||||
# An alternate print command that concatenates arguments together with an optional separator.
|
||||
# This one uses str collect instead of build-string.
|
||||
# By default there will be no newline
|
||||
def print2 [
|
||||
--separator(-s):any # Optional separator (not yet flagged as optional?)
|
||||
...rest # All of the parameters
|
||||
] {
|
||||
let is_empty = ($separator | is-empty)
|
||||
let num_of_rest = ($rest | length)
|
||||
if $is_empty {
|
||||
$rest | into string | str join
|
||||
} else {
|
||||
$rest | into string | str join $separator
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# A print command that concatenates arguments together with an optional separator.
|
||||
# This print command will also concatenate tables like [1 2 3] as well as most other primitives
|
||||
# since the into string command has been updated with wider support.
|
||||
def print3 [
|
||||
--separator(-s):any # Optional separator (not yet flagged as optional?)
|
||||
--flat(-f) # If tables are found, flatten them
|
||||
...rest # All of the parameters
|
||||
] {
|
||||
let sep_empty = ($separator | is-empty)
|
||||
let num_of_rest = ($rest | length)
|
||||
let flat = ($flat | is-empty)
|
||||
$rest | enumerate | each { |param|
|
||||
if $sep_empty {
|
||||
if ((echo $param.item | str length) > 1) and $flat {
|
||||
let flatter = ($param.item | flatten | into string | str join)
|
||||
$flatter
|
||||
} else {
|
||||
$param.item
|
||||
}
|
||||
} else {
|
||||
if $num_of_rest > ($param.index + 1) {
|
||||
if ($param.item | length) > 1 and $flat {
|
||||
let flatter = ($param.item | flatten | into string | str join $separator)
|
||||
$"($flatter)($separator)"
|
||||
} else {
|
||||
$"($param.item)($separator)"
|
||||
}
|
||||
} else {
|
||||
if ($param.item | length) > 1 and $flat {
|
||||
let flatter = ($param.item | flatten | into string | str join $separator)
|
||||
$flatter
|
||||
} else {
|
||||
$param.item
|
||||
}
|
||||
}
|
||||
}
|
||||
} | str join
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
# Record module
|
||||
|
||||
A module to manipulate nu's records.
|
||||
|
||||
## `record list merge`
|
||||
|
||||
### Input/output types:
|
||||
|
||||
|#|input|output|
|
||||
|-|-|-|
|
||||
|1|list\<record>|record|
|
||||
|
||||
### Example
|
||||
|
||||
```nu
|
||||
> [{a:1} {b:2} {c:3}] | record list merge
|
||||
╭───┬───╮
|
||||
│ a │ 1 │
|
||||
│ b │ 2 │
|
||||
│ c │ 3 │
|
||||
╰───┴───╯
|
||||
```
|
||||
|
||||
## `record filter-name predicate`
|
||||
|
||||
Filter a record by validating fields name with a predicate.
|
||||
|
||||
### Input/output types:
|
||||
|
||||
|#|input|output|
|
||||
|-|-|-|
|
||||
|1|record|record|
|
||||
|
||||
## Arguments
|
||||
|
||||
* `pred`: Predicate closure that checks fields name
|
||||
|
||||
### Example
|
||||
|
||||
```nu
|
||||
> $env | record filter-name predicate { $in | str contains VS}
|
||||
╭───────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ VSCODE_GIT_ASKPASS_EXTRA_ARGS │ --ms-enable-electron-run-as-node │
|
||||
│ VSCODE_GIT_ASKPASS_MAIN │ /Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass-main.js │
|
||||
│ VSCODE_GIT_ASKPASS_NODE │ /Applications/Visual Studio Code.app/Contents/Frameworks/Code Helper (Plugin).app/Contents/MacOS/Code Helper (Plugin) │
|
||||
│ VSCODE_GIT_IPC_HANDLE │ /var/folders/_x/25cgjd3n2sn62x6jfc9ccjjw0000gn/T/vscode-git-56538693f8.sock │
|
||||
╰───────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
## `record filter-name text`
|
||||
|
||||
Filter a record by validating fields name with text.
|
||||
|
||||
### Input/output types:
|
||||
|
||||
|#|input|output|
|
||||
|-|-|-|
|
||||
|1|record|record|
|
||||
|
||||
## Arguments
|
||||
|
||||
* `filter`: Text to match with
|
||||
* `--regex(-r)`: Match by regex
|
||||
|
||||
### Examples
|
||||
|
||||
```nu
|
||||
> $env | record filter-name text VS
|
||||
╭───────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ VSCODE_GIT_ASKPASS_EXTRA_ARGS │ --ms-enable-electron-run-as-node │
|
||||
│ VSCODE_GIT_ASKPASS_MAIN │ /Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass-main.js │
|
||||
│ VSCODE_GIT_ASKPASS_NODE │ /Applications/Visual Studio Code.app/Contents/Frameworks/Code Helper (Plugin).app/Contents/MacOS/Code Helper (Plugin) │
|
||||
│ VSCODE_GIT_IPC_HANDLE │ /var/folders/_x/25cgjd3n2sn62x6jfc9ccjjw0000gn/T/vscode-git-56538693f8.sock │
|
||||
╰───────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
> $env | record filter-name text --regex V.*S
|
||||
╭───────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │ ╭──────┬──────────────────────────────────╮ │
|
||||
│ ENV_CONVERSIONS │ │ │ ╭─────────────┬────────────────╮ │ │
|
||||
│ │ │ PATH │ │ from_string │ <Closure 1399> │ │ │
|
||||
│ │ │ │ │ to_string │ <Closure 1401> │ │ │
|
||||
│ │ │ │ ╰─────────────┴────────────────╯ │ │
|
||||
│ │ │ │ ╭─────────────┬────────────────╮ │ │
|
||||
│ │ │ Path │ │ from_string │ <Closure 1403> │ │ │
|
||||
│ │ │ │ │ to_string │ <Closure 1405> │ │ │
|
||||
│ │ │ │ ╰─────────────┴────────────────╯ │ │
|
||||
│ │ ╰──────┴──────────────────────────────────╯ │
|
||||
│ LC_TERMINAL_VERSION │ 3.4.22 │
|
||||
│ NU_VERSION │ 0.87.0 │
|
||||
│ PROMPT_INDICATOR_VI_INSERT │ <Closure 1395> │
|
||||
│ TERM_PROGRAM_VERSION │ 1.84.2 │
|
||||
│ VSCODE_GIT_ASKPASS_EXTRA_ARGS │ --ms-enable-electron-run-as-node │
|
||||
│ VSCODE_GIT_ASKPASS_MAIN │ /Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass-main.js │
|
||||
│ VSCODE_GIT_ASKPASS_NODE │ /Applications/Visual Studio Code.app/Contents/Frameworks/Code Helper (Plugin).app/Contents/MacOS/Code Helper (Plugin) │
|
||||
│ VSCODE_GIT_IPC_HANDLE │ /var/folders/_x/25cgjd3n2sn62x6jfc9ccjjw0000gn/T/vscode-git-56538693f8.sock │
|
||||
╰───────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
## `record filter-value predicate`
|
||||
|
||||
Filter a record by validating fields value with predicate.
|
||||
|
||||
### Input/output types:
|
||||
|
||||
|#|input|output|
|
||||
|-|-|-|
|
||||
|1|record|record|
|
||||
|
||||
## Arguments
|
||||
|
||||
* `pred`: Predicate closure that checks fields value
|
||||
|
||||
### Example
|
||||
|
||||
```nu
|
||||
> {a:1 b:2 c:3 d:4} | record filter-value predicate { $in mod 2 == 0 }
|
||||
╭───┬───╮
|
||||
│ b │ 2 │
|
||||
│ d │ 4 │
|
||||
╰───┴───╯
|
||||
```
|
|
@ -0,0 +1,46 @@
|
|||
# Merge a list of records
|
||||
export def "list merge" []: list<record> -> record {
|
||||
let list = $in
|
||||
mut result = {}
|
||||
for $obj in $list {
|
||||
$result = ($result | merge $obj)
|
||||
}
|
||||
$result
|
||||
}
|
||||
|
||||
# Filter fields name by predicate
|
||||
export def "filter-name predicate" [
|
||||
pred: closure # Predicate closure that checks fields name
|
||||
]: record -> record {
|
||||
let $obj_input = $in
|
||||
$obj_input
|
||||
| columns
|
||||
| where { $in | do $pred }
|
||||
| each {|input|
|
||||
{ $input: ($obj_input | get $input) }
|
||||
}
|
||||
| list merge
|
||||
}
|
||||
|
||||
# Filter fields name by text checking
|
||||
export def "filter-name text" [
|
||||
filter: string # Text to match with
|
||||
--regex(-r) # Match by regex
|
||||
]: record -> record {
|
||||
let obj = $in
|
||||
$obj | filter-name predicate { not ($in | (if $regex {find -r $filter} else {find $filter}) | is-empty) }
|
||||
}
|
||||
|
||||
# Filter fields value by predicate
|
||||
export def "filter-value predicate" [
|
||||
pred: closure # Predicate closure that checks fields value
|
||||
]: record -> record {
|
||||
let $obj_input = $in
|
||||
$obj_input
|
||||
| columns
|
||||
| where {|col| $obj_input | get $col | do $pred }
|
||||
| each {|input|
|
||||
{ $input: ($obj_input | get $input) }
|
||||
}
|
||||
| list merge
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
# helps parsing CLI arguments for Nushell scripts
|
||||
#
|
||||
# the following Nushell script does not make sense to be used as an external
|
||||
# command because there is no such thing as a `list<string>` in Bash for
|
||||
# instance.
|
||||
# ```nushell
|
||||
# def main [x: list<int>] {
|
||||
# print $x
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# one needs to write something less strict at parse-time and thus looses type
|
||||
# information...
|
||||
# ```nushell
|
||||
# def main [
|
||||
# x: string, # list<int>
|
||||
# ] {
|
||||
# print $x
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# it's possible to write a much stronger script with `parse-arg`
|
||||
# ```nushell
|
||||
# def main [
|
||||
# x: string, # list<int>
|
||||
# ] {
|
||||
# let x = $x | parse-arg (metadata $x).span "list<int>" # the script would crash if either
|
||||
# # `$x: string` is not valid NUON or if
|
||||
# # the resulting value is not a `list<int>`
|
||||
# print $x # here, `$x` is a `list<int>` as intended
|
||||
# }
|
||||
# ```
|
||||
export def parse-arg [
|
||||
span: record<start: int, end: int>, # the span of the input variable
|
||||
expected_type: string, # the expected type for the input variable
|
||||
]: [ string -> any ] {
|
||||
let val = try {
|
||||
$in | from nuon
|
||||
} catch {
|
||||
error make {
|
||||
msg: $"(ansi red_bold)invalid NUON(ansi reset)",
|
||||
label: {
|
||||
text: "invalid NUON",
|
||||
span: $span,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if ($val | describe) != $expected_type {
|
||||
error make {
|
||||
msg: $"(ansi red_bold)bad type(ansi reset)",
|
||||
label: {
|
||||
text: $"type: ($val | describe)",
|
||||
span: $span,
|
||||
},
|
||||
help: $"expected ($expected_type)",
|
||||
}
|
||||
}
|
||||
|
||||
$val
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
# Gracefully set an environment variable or merge a nested option.
|
||||
#
|
||||
# Examples:
|
||||
# Set $env.NUPM_HOME
|
||||
# > set-env NUPM_HOME $'($nu.home-path)/.local/share/nupm'
|
||||
#
|
||||
# Add to $env.NU_LIB_DIRS
|
||||
# > set-env --append NU_LIB_DIRS $'($env.NUPM_HOME)/modules'
|
||||
#
|
||||
# Set a nested config option
|
||||
# > set-env config.filesize.metric true
|
||||
#
|
||||
# Add a config hook
|
||||
# > set-env -a config.hooks.pre_prompt 'ellie | print'
|
||||
export def --env main [
|
||||
field: cell-path # The environment variable name or nested option cell path
|
||||
value: any # The value to set or append
|
||||
--append (-a) # Append to the previous value or wrap in a new list
|
||||
]: nothing -> nothing {
|
||||
def 'get or' [default field] {
|
||||
get --ignore-errors $field | default $default
|
||||
}
|
||||
let value = if $append {
|
||||
$env | get or [] $field | append $value
|
||||
} else {
|
||||
$value
|
||||
}
|
||||
let field = $field | to text | split row .
|
||||
let value = match $field {
|
||||
[_] => $value
|
||||
[$root, ..$field] => {
|
||||
let field = $field | into cell-path
|
||||
$env | get or {} $root | upsert $field $value
|
||||
}
|
||||
}
|
||||
load-env { ($field | first): $value }
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
# Removes common indent from a multi-line string based on the number of spaces on the last line.
|
||||
#
|
||||
# A.k.a. Unindent
|
||||
#
|
||||
# Example - Two leading spaces are removed from all lines:
|
||||
#
|
||||
# > let s = "
|
||||
# Heading
|
||||
# Indented Line
|
||||
# Another Indented Line
|
||||
#
|
||||
# Another Heading
|
||||
# "
|
||||
# > $a | str dedent
|
||||
#
|
||||
# Heading
|
||||
# Indented Line
|
||||
# Another Indented Line
|
||||
#
|
||||
# Another Heading
|
||||
export def main []: string -> string {
|
||||
let string = $in
|
||||
|
||||
if ($string | describe) != "string" {
|
||||
let span = (view files | last)
|
||||
error make {
|
||||
msg: 'Requires multi-line string as pipeline input'
|
||||
label: {
|
||||
text: "err::pipeline_input"
|
||||
span: {
|
||||
start: $span.start
|
||||
end: $span.end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($string !~ '^\s*\n') {
|
||||
return (error make {
|
||||
msg: 'First line must be empty'
|
||||
})
|
||||
}
|
||||
|
||||
if ($string !~ '\n\s*$') {
|
||||
return (error make {
|
||||
msg: 'Last line must contain only whitespace indicating the dedent'
|
||||
})
|
||||
}
|
||||
|
||||
# Get number of spaces on the last line
|
||||
let indent = $string
|
||||
| str replace -r '(?s).*\n( *)$' '$1'
|
||||
| str length
|
||||
|
||||
# Skip the first and last lines
|
||||
let lines = (
|
||||
$string
|
||||
| str replace -r '(?s)^[^\n]*\n(.*)\n[^\n]*$' '$1'
|
||||
# Use `split` instead of `lines`, since `lines` will
|
||||
# drop legitimate trailing empty lines
|
||||
| split row "\n"
|
||||
| enumerate
|
||||
| rename lineNumber text
|
||||
)
|
||||
|
||||
let spaces = ('' | fill -c ' ' -w $indent)
|
||||
|
||||
# Has to be done outside the replacement block or the error
|
||||
# is converted to text. This is probably a Nushell bug, and
|
||||
# this code can be recombined with the next iterator when
|
||||
# the Nushell behavior is fixed.
|
||||
for line in $lines {
|
||||
if ($line.text !~ '^\s*$') and ($line.text | str index-of --range 0..($indent) $spaces) == -1 {
|
||||
error make {
|
||||
msg: $"Line ($line.lineNumber + 1) must be indented by ($indent) or more spaces."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lines
|
||||
| each {|line|
|
||||
# Don't operate on lines containing only whitespace
|
||||
if ($line.text !~ '^\s*$') {
|
||||
$line.text | str replace $spaces ''
|
||||
} else {
|
||||
$line.text
|
||||
}
|
||||
}
|
||||
| to text
|
||||
# Remove the trailing newline which indicated
|
||||
# indent level
|
||||
| str replace -r '(?s)(.*)\n$' '$1'
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export use xpend.nu *
|
||||
export use dedent *
|
|
@ -0,0 +1,39 @@
|
|||
# Append a suffix to an input string or list of strings.
|
||||
#
|
||||
# Examples:
|
||||
# Output 'hello world'
|
||||
# > 'hello' | str append ' world'
|
||||
#
|
||||
# Output file names suffixed with '_world'
|
||||
# > ls | get name | str append _world
|
||||
export def append [
|
||||
suffix: string
|
||||
]: [string -> string, list<string> -> list<string>] {
|
||||
let input = $in
|
||||
let append = { $in + $suffix }
|
||||
if ($input | describe) == string {
|
||||
$input | do $append
|
||||
} else {
|
||||
$input | each $append
|
||||
}
|
||||
}
|
||||
|
||||
# Prepend a prefix to an input string or list of strings.
|
||||
#
|
||||
# Examples:
|
||||
# Output 'hello world'
|
||||
# > 'world' | str prepend 'hello '
|
||||
#
|
||||
# Output file names prefixed with 'hello_'
|
||||
# > ls | get name | str prepend hello_
|
||||
export def prepend [
|
||||
prefix: string
|
||||
]: [string -> string, list<string> -> list<string>] {
|
||||
let input = $in
|
||||
let prepend = { $prefix + $in }
|
||||
if ($input | describe) == string {
|
||||
$input | do $prepend
|
||||
} else {
|
||||
$input | each $prepend
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
use std assert
|
||||
use ../std-rfc bench
|
||||
|
||||
export def "test bench-timings" [] {
|
||||
let $test = bench {1 + 2} --rounds 3 --timings | get times | length
|
||||
assert equal $test 3
|
||||
}
|
||||
|
||||
export def "test bench-pretty" [] {
|
||||
let $test = (bench {1 + 2} --rounds 3 --pretty) =~ '\d.* ± \d'
|
||||
assert equal $test true
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
use std assert
|
||||
use ../std-rfc 'bulk-rename'
|
||||
|
||||
const fixture = [
|
||||
.gitignore
|
||||
Cargo.toml
|
||||
LICENSE
|
||||
README.md
|
||||
src
|
||||
test.nu
|
||||
]
|
||||
|
||||
export def 'test ls' [] {
|
||||
let expects = [
|
||||
.gitignore # hidden by ls
|
||||
_Cargo.toml
|
||||
_LICENSE
|
||||
_README.md
|
||||
_src
|
||||
_test.nu
|
||||
]
|
||||
test $expects {
|
||||
ls $in | bulk-rename { '_' + $in }
|
||||
}
|
||||
}
|
||||
|
||||
export def 'test --no-execute' [] {
|
||||
test $fixture {
|
||||
ls $in | bulk-rename --no-execute { '_' + $in }
|
||||
}
|
||||
}
|
||||
|
||||
export def 'test --verbose' [] {
|
||||
let expects = [
|
||||
# .gitignore unchanged
|
||||
_Cargo.toml
|
||||
_LICENSE
|
||||
_README.md
|
||||
_src
|
||||
_test.nu
|
||||
]
|
||||
let renamed = test $fixture {
|
||||
# Note: Currently failing due to Nushell core #13267
|
||||
# Remove the 'sort' once it is fixed
|
||||
# ls $in | bulk-rename --verbose --no-execute { '_' + $in }
|
||||
ls $in | bulk-rename --verbose --no-execute { '_' + $in } | sort
|
||||
}
|
||||
assert equal ($renamed.new | each { path basename }) $expects
|
||||
}
|
||||
|
||||
export def 'test skip-extensions' [] {
|
||||
let expects = [
|
||||
.gitignore
|
||||
Cargo.toml
|
||||
LICENSE.txt # changed
|
||||
README.md
|
||||
src.txt # changed
|
||||
test.nu
|
||||
]
|
||||
test $expects {
|
||||
ls $in | bulk-rename { |path|
|
||||
if $path.input.name ends-with $path.stem {
|
||||
$path.stem + .txt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def 'test glob' [] {
|
||||
let expects = [
|
||||
LICENSE # skipped
|
||||
_.gitignore
|
||||
_Cargo.toml
|
||||
_README.md
|
||||
_test.nu
|
||||
src # skipped
|
||||
]
|
||||
test $expects {
|
||||
glob ($in | path join *.*) | bulk-rename { '_' + $in }
|
||||
}
|
||||
}
|
||||
|
||||
def test [expects: list<string> command: closure] {
|
||||
let test_dir = $nu.temp-path | path join (random uuid)
|
||||
def actual-files [] {
|
||||
ls --all --short-names $test_dir | get name | sort
|
||||
}
|
||||
# before
|
||||
mkdir $test_dir
|
||||
$fixture | each { |name| touch ($test_dir | path join $name) }
|
||||
assert equal (actual-files) $fixture
|
||||
# test
|
||||
let renamed = $test_dir | do $command
|
||||
assert equal (actual-files) $expects
|
||||
# after
|
||||
rm --recursive --force $test_dir
|
||||
$renamed
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
use std assert
|
||||
use ../std-rfc/math
|
||||
|
||||
#[test]
|
||||
export def "test significant-digits-decimals" [] {
|
||||
assert equal (0.0000012346789 | math significant-digits 2) 0.0000012
|
||||
assert equal (11 / 3 | math significant-digits 6) 3.66666
|
||||
assert not equal (0.0000012346789 | math significant-digits 2) 0.00000123
|
||||
assert equal (1.999999 | math significant-digits 1) 1.0
|
||||
}
|
||||
|
||||
#[test]
|
||||
export def "test significant-digits-duration" [] {
|
||||
assert equal (2min / 7 | math significant-digits 3) 17100000000ns
|
||||
assert equal (1sec | math significant-digits 3) 1000000000ns
|
||||
}
|
||||
|
||||
#[test]
|
||||
export def "test significant-digits-ints" [] {
|
||||
assert equal (123456 | math significant-digits 2) 120000
|
||||
}
|
||||
|
||||
export def "test significant-digits-0" [] {
|
||||
assert equal (0 | math significant-digits 2) 0
|
||||
}
|
||||
|
||||
export def "test significant-digits-negative" [] {
|
||||
assert equal (-1.23456789 | math significant-digits 5) (-1.2346)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export module bulk-rename.nu
|
||||
export module record.nu
|
||||
export module str_xpend.nu
|
||||
export module math.nu
|
||||
export module bench.nu
|
||||
export module script-parsing.nu
|
||||
export module str_dedent.nu
|
||||
export module conversions.nu
|
||||
export module tables.nu
|
|
@ -0,0 +1,20 @@
|
|||
use std assert
|
||||
use ../std-rfc record
|
||||
|
||||
export def "test list_merge" [] {
|
||||
assert equal ([{a:1} {b:2} {c:3} {d:4}] | record list merge) {a:1 b:2 c:3 d:4}
|
||||
}
|
||||
|
||||
export def "test filter-name predicate" [] {
|
||||
assert equal ({aa:1 ab:2 ba:3 bb:4 ca:5 cb:6} | record filter-name predicate {$in | str contains a}) {aa:1 ab:2 ba:3 ca:5}
|
||||
}
|
||||
|
||||
export def "test filter-name text" [] {
|
||||
assert equal ({aa:1 ab:2 ba:3 bb:4 ca:5 cb:6} | record filter-name text a) {aa:1 ab:2 ba:3 ca:5}
|
||||
assert equal ({aa:1 ab:2 ba:3 bb:4 ca:5 cb:6} | record filter-name text -r ^a) {aa:1 ab:2}
|
||||
assert equal ({aa:1 ab:2 ba:3 bb:4 ca:5 cb:6} | record filter-name text -r ^A) {}
|
||||
}
|
||||
|
||||
export def "test filter-value predicate" [] {
|
||||
assert equal ({aa:1 ab:2 ba:3 bb:4 ca:5 cb:6} | record filter-value predicate { $in mod 2 == 0 }) {ab:2 bb:4 cb:6}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
use std assert
|
||||
use ../std-rfc parse-arg
|
||||
|
||||
const SPAN = { start: 0, end: 0 }
|
||||
|
||||
export def "test parse-arg ok" [] {
|
||||
const TEST_CASES = [
|
||||
[ input, type, expected ];
|
||||
|
||||
[ "123", "int", 123 ],
|
||||
[ "[1, 2, 3]", "list<int>", [1, 2, 3] ],
|
||||
[ "'spam'", "string", "spam" ],
|
||||
[
|
||||
"{ a: 1, b: 'egg', c: false }",
|
||||
"record<a: int, b: string, c: bool>",
|
||||
{ a: 1, b: 'egg', c: false },
|
||||
],
|
||||
]
|
||||
|
||||
for t in $TEST_CASES {
|
||||
assert equal ($t.input | parse-arg $SPAN $t.type) $t.expected
|
||||
}
|
||||
}
|
||||
|
||||
export def "test parse-arg err" [] {
|
||||
const TEST_CASES = [
|
||||
[ input, type ];
|
||||
|
||||
[ "{ invalid NUON", "" ],
|
||||
[ "[1, 2, 3]", "string" ],
|
||||
]
|
||||
|
||||
for t in $TEST_CASES {
|
||||
let msg = $"test case: input: '($t.input)', type: ($t.type)"
|
||||
assert error { $t.input | parse-arg $SPAN $t.type } $msg
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
use std assert
|
||||
use ../std-rfc str
|
||||
|
||||
export def "test str dedent" [] {
|
||||
|
||||
# Test 1:
|
||||
# Should start with "Heading" in the first character position
|
||||
# Should not end with a line-break
|
||||
# The blank line has no extra spaces
|
||||
assert equal (
|
||||
do {
|
||||
let s = "
|
||||
Heading
|
||||
|
||||
one
|
||||
two
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
) "Heading\n\n one\n two"
|
||||
|
||||
# Test 2:
|
||||
# Same as #1, but the blank line has leftover whitespace
|
||||
# indentation (16 spaces) which is left in the result
|
||||
assert equal (
|
||||
do {
|
||||
let s = "
|
||||
Heading
|
||||
|
||||
one
|
||||
two
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
) "Heading\n \n one\n two"
|
||||
|
||||
# Test 3:
|
||||
# Same, but with a single tab character on the "blank" line
|
||||
assert equal (
|
||||
do {
|
||||
let s = "
|
||||
Heading
|
||||
\t
|
||||
one
|
||||
two
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
) "Heading\n\t\n one\n two"
|
||||
|
||||
# Test 4:
|
||||
# Ends with line-break
|
||||
assert equal (
|
||||
do {
|
||||
let s = "
|
||||
Heading
|
||||
|
||||
one
|
||||
two
|
||||
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
) "Heading\n\n one\n two\n"
|
||||
|
||||
# Test 5:
|
||||
# Identity - Returns the original string sans first and last empty lines
|
||||
# No other whitespace should be removed
|
||||
assert equal (
|
||||
do {
|
||||
let s = "\n Identity \n"
|
||||
$s | str dedent
|
||||
}
|
||||
) " Identity "
|
||||
|
||||
# Test 6:
|
||||
# Error - Does not contain an empty first line
|
||||
assert error {||
|
||||
let s = "Error"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 6.1:
|
||||
# Error - Does not contain an empty first line
|
||||
assert error {||
|
||||
let s = "Error\n \nTesting\n"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 7:
|
||||
# Error - Does not contain an empty last line
|
||||
assert error {||
|
||||
let s = "
|
||||
Error"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 7.1:
|
||||
# Error - Does not contain an empty last line
|
||||
assert error {||
|
||||
let s = "
|
||||
|
||||
Error"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 8:
|
||||
# Error - Line 1 does not have enough indentation
|
||||
assert error {||
|
||||
let s = "
|
||||
Line 1
|
||||
Line 2
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 8:
|
||||
# Error - Line 2 does not have enough indentation
|
||||
assert error {||
|
||||
let s = "
|
||||
Line 1
|
||||
Line 2
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 9:
|
||||
# Error - Line does not have enough indentation
|
||||
assert error {||
|
||||
let s = "
|
||||
Line
|
||||
"
|
||||
$s | str dedent
|
||||
}
|
||||
|
||||
# Test 10:
|
||||
# "Hidden" whitespace on the first line is allowed
|
||||
assert equal (
|
||||
do {
|
||||
let s = " \t \n Identity \n"
|
||||
$s | str dedent
|
||||
}
|
||||
) " Identity "
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
use std assert
|
||||
use ../std-rfc str
|
||||
|
||||
export def "test append" [] {
|
||||
assert equal ("foo" | str append "/") "foo/"
|
||||
assert equal (["foo", "bar", "baz"] | str append "/") ["foo/", "bar/", "baz/"]
|
||||
}
|
||||
|
||||
export def "test prepend" [] {
|
||||
assert equal ("foo" | str prepend "/") "/foo"
|
||||
assert equal (["foo", "bar", "baz"] | str prepend "/") ["/foo", "/bar", "/baz"]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue