mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 14:15:53 +02:00
Move std-rfc
into Nushell (#15042)
Move `std-rfc` into Nushell. `use std-rfc/<submodule>` now works "out-of-the-box"
This commit is contained in:
136
crates/nu-std/std-rfc/str/mod.nu
Normal file
136
crates/nu-std/std-rfc/str/mod.nu
Normal file
@ -0,0 +1,136 @@
|
||||
# Removes common indent from a multi-line string based on the number of spaces on the last line.
|
||||
#
|
||||
# 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 dedent [
|
||||
--tabs (-t)
|
||||
]: string -> string {
|
||||
let string = $in
|
||||
|
||||
if ($string !~ $'^\s*(char lsep)') {
|
||||
return (error make {
|
||||
msg: 'First line must be empty'
|
||||
})
|
||||
}
|
||||
|
||||
if ($string !~ $'(char lsep)[ \t]*$') {
|
||||
return (error make {
|
||||
msg: 'Last line must contain only whitespace indicating the dedent'
|
||||
})
|
||||
}
|
||||
|
||||
# Get indent characters from the last line
|
||||
let indent_chars = $string
|
||||
| str replace -r $"\(?s\).*(char lsep)\([ \t]*\)$" '$1'
|
||||
|
||||
# Skip the first and last lines
|
||||
let lines = (
|
||||
$string
|
||||
| lines
|
||||
| skip
|
||||
| # Only drop if there is whitespace. Otherwise, `lines`
|
||||
| # drops a 0-length line anyway
|
||||
| if ($indent_chars | str length) > 0 { drop } else {}
|
||||
| enumerate
|
||||
| rename lineNumber text
|
||||
)
|
||||
|
||||
# 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 {
|
||||
# Skip lines with whitespace-only
|
||||
if $line.text like '^\s*$' { continue }
|
||||
# Error if any line doesn't start with enough indentation
|
||||
if ($line.text | parse -r $"^\(($indent_chars)\)" | get capture0?.0?) != $indent_chars {
|
||||
error make {
|
||||
msg: $"Line ($line.lineNumber + 1) must have an indent of ($indent_chars | str length) or more."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lines
|
||||
| each {|line|
|
||||
# Don't operate on lines containing only whitespace
|
||||
if ($line.text not-like '^\s*$') {
|
||||
$line.text | str replace $indent_chars ''
|
||||
} else {
|
||||
$line.text
|
||||
}
|
||||
}
|
||||
| str join (char line_sep)
|
||||
}
|
||||
|
||||
# Remove common indent from a multi-line string based on the line with the smallest indent
|
||||
#
|
||||
# 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 unindent [
|
||||
--tabs (-t) # String uses tabs instead of spaces for indentation
|
||||
]: string -> string {
|
||||
let indent_char = match $tabs {
|
||||
true => '\t'
|
||||
false => ' '
|
||||
}
|
||||
|
||||
let text = (
|
||||
$in
|
||||
| # Remove the first line if it is only whitespace (tabs or spaces)
|
||||
| str replace -r $'^[ \t]*(char lsep)' ''
|
||||
| # Remove the last line if it is only whitespace (tabs or spaces)
|
||||
| str replace -r $'(char lsep)[ \t]*$' ''
|
||||
)
|
||||
|
||||
# Early return if there is only a single, empty (other than whitespace) line
|
||||
if ($text like '^[ \t]*$') {
|
||||
return $text
|
||||
}
|
||||
|
||||
let minimumIndent = (
|
||||
$text
|
||||
| lines
|
||||
| # Ignore indentation in any line that is only whitespace
|
||||
| where $it not-like '^[ \t]*$'
|
||||
| # Replaces the text with its indentation
|
||||
| each {
|
||||
str replace -r $"^\(($indent_char)*\).*" '$1'
|
||||
| str length
|
||||
}
|
||||
| math min
|
||||
)
|
||||
|
||||
let indent_chars = ('' | fill -c $indent_char -w $minimumIndent)
|
||||
|
||||
$text
|
||||
| str replace -r --all $"\(?m\)^($indent_chars)" ''
|
||||
}
|
Reference in New Issue
Block a user