1
Fork 0
mirror of https://github.com/RGBCube/nu_scripts synced 2025-08-02 15:17:47 +00:00
nu_scripts/stdlib-candidate-archive/stdlib-candidate-older/std-rfc/str/dedent/mod.nu
Douglas 5869e0b529
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.
2025-02-09 14:34:40 -06:00

93 lines
No EOL
2.4 KiB
Text

# 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'
}