mirror of
https://github.com/nushell/nushell.git
synced 2025-08-17 23:19:49 +02:00
feat(std-rfc/str): add str align
(#16062)
This commit is contained in:
@@ -129,3 +129,54 @@ export def unindent [
|
||||
$text
|
||||
| str replace -r --all $"\(?m\)^($indent_chars)" ''
|
||||
}
|
||||
|
||||
alias "str align" = align
|
||||
|
||||
# Aligns each line in the input string to have the target in the same column through padding
|
||||
@example "Align variable assignments" { [ "one = 1", "two = 2", "three = 3", "four = 4", "five = 5" ] | str align '=' } --result r#'one = 1
|
||||
two = 2
|
||||
three = 3
|
||||
four = 4
|
||||
five = 5'#
|
||||
@example "Align variable assignments to the center" { [ "one = 1", "two = 2", "three = 3", "four = 4", "five = 5" ] | str align '=' --center } --result r#' one = 1
|
||||
two = 2
|
||||
three = 3
|
||||
four = 4
|
||||
five = 5'#
|
||||
export def align [
|
||||
target:string # Substring to align
|
||||
--char (-c) = " " # Character to use for padding
|
||||
--center (-C) # Add padding at the beginning of the line instead of before the target
|
||||
--range (-r): range # The range of lines to align
|
||||
]: [string -> string, list<string> -> string] {
|
||||
# noop on empty string
|
||||
if ($in | is-empty) { return "" }
|
||||
let $input = $in | to text | lines
|
||||
|
||||
let $indexes = (
|
||||
$input
|
||||
| enumerate
|
||||
| each {|x|
|
||||
if $x.index in ($range | default 0..) {
|
||||
$x.item | str index-of $target
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
)
|
||||
let $max = $indexes | math max
|
||||
|
||||
$input
|
||||
| zip $indexes
|
||||
| each {|x|
|
||||
# Fold adding a `$char` at the index until they are in the same column
|
||||
# If the substring is not in the line, the index is -1 and it is left as it is
|
||||
seq 1 (if $x.1 == -1 { 0 } else { $max - $x.1 })
|
||||
| reduce -f ($x.0 | split chars) {|_, acc|
|
||||
let $idx = if $center { 0 } else { $x.1 }
|
||||
$acc | insert $idx $char
|
||||
}
|
||||
| str join
|
||||
}
|
||||
| str join (char nl)
|
||||
}
|
||||
|
@@ -291,3 +291,139 @@ def str-unindent_whitespace_works_with_tabs [] {
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_simple [] {
|
||||
let actual = [
|
||||
"let a = 1"
|
||||
"let max = 2"
|
||||
"let very_long_variable_name = 3"
|
||||
] | str align '='
|
||||
|
||||
let expected = [
|
||||
"let a = 1"
|
||||
"let max = 2"
|
||||
"let very_long_variable_name = 3"
|
||||
] | str join "\n"
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_center [] {
|
||||
let actual = [
|
||||
"a = 1"
|
||||
"max = 2"
|
||||
"very_long_variable_name = 3"
|
||||
] | str align '=' --center
|
||||
|
||||
let expected = [
|
||||
" a = 1"
|
||||
" max = 2"
|
||||
"very_long_variable_name = 3"
|
||||
] | str join "\n"
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_with_range [] {
|
||||
let actual = r#'match 5 {
|
||||
1.. => { print "More than zero" }
|
||||
0 => { print "Zero" }
|
||||
-1 => { print "Negative one" }
|
||||
-119283 => { print "Very negative" }
|
||||
}'# | str align '=>' --range 2..
|
||||
|
||||
let expected = r#'match 5 {
|
||||
1.. => { print "More than zero" }
|
||||
0 => { print "Zero" }
|
||||
-1 => { print "Negative one" }
|
||||
-119283 => { print "Very negative" }
|
||||
}'# | lines | str join "\n"
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_ignore_lines_with_no_target [] {
|
||||
let actual = [
|
||||
"let a = 1"
|
||||
"let max = 2"
|
||||
"# comment"
|
||||
] | str align '='
|
||||
|
||||
let expected = [
|
||||
"let a = 1"
|
||||
"let max = 2"
|
||||
"# comment"
|
||||
] | str join "\n"
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_use_different_char [] {
|
||||
let actual = [
|
||||
"=>"
|
||||
"=====>"
|
||||
] | str align '>' -c '='
|
||||
|
||||
let expected = [
|
||||
"=====>"
|
||||
"=====>"
|
||||
] | str join "\n"
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_multiple_target_in_line [] {
|
||||
let actual = [
|
||||
"print test # Hello # World"
|
||||
"print hello there # test"
|
||||
] | str align '#'
|
||||
|
||||
let expected = [
|
||||
"print test # Hello # World"
|
||||
"print hello there # test"
|
||||
] | str join "\n"
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_no_target [] {
|
||||
|
||||
let expected = [
|
||||
"print test # Hello # World"
|
||||
"print hello there # test"
|
||||
] | str join "\n"
|
||||
|
||||
let actual = $expected | str align '='
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_empty_target_noop [] {
|
||||
|
||||
let expected = [
|
||||
"print test # Hello # World"
|
||||
"print hello there # test"
|
||||
] | str join "\n"
|
||||
|
||||
let actual = $expected | str align ''
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
||||
@test
|
||||
def str-align_empty_input_noop [] {
|
||||
|
||||
let expected = ""
|
||||
|
||||
let actual = [] | str align '='
|
||||
|
||||
assert equal $actual $expected
|
||||
}
|
||||
|
Reference in New Issue
Block a user