mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 06:30:08 +02:00
Refactor error make
(#10923)
- Replaced `start`/`end` with span. - Fixed standard library. - Add `help` option. - Add a couple more errors for invalid record types. Resolve #10914 # Description # User-Facing Changes - **BREAKING CHANGE:** `error make` now takes in `span` instead of `start`/`end`: ```Nushell error make { msg: "Message" label: { text: "Label text" span: (metadata $var).span } } ``` - `error make` now has a `help` argument for custom error help.
This commit is contained in:
@ -28,9 +28,8 @@
|
||||
# ```
|
||||
# def "assert even" [number: int] {
|
||||
# assert ($number mod 2 == 0) --error-label {
|
||||
# start: (metadata $number).span.start,
|
||||
# end: (metadata $number).span.end,
|
||||
# text: $"($number) is not an even number",
|
||||
# span: (metadata $number).span,
|
||||
# }
|
||||
# }
|
||||
# ```
|
||||
@ -40,13 +39,11 @@ export def main [
|
||||
--error-label: record # Label for `error make` if you want to create a custom assert
|
||||
] {
|
||||
if $condition { return }
|
||||
let span = (metadata $condition).span
|
||||
error make {
|
||||
msg: ($message | default "Assertion failed."),
|
||||
label: ($error_label | default {
|
||||
text: "It is not true.",
|
||||
start: $span.start,
|
||||
end: $span.end
|
||||
span: (metadata $condition).span,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -75,8 +72,7 @@ export def main [
|
||||
# ```
|
||||
# def "assert not even" [number: int] {
|
||||
# assert not ($number mod 2 == 0) --error-label {
|
||||
# start: (metadata $number).span.start,
|
||||
# end: (metadata $number).span.end,
|
||||
# span: (metadata $number).span,
|
||||
# text: $"($number) is an even number",
|
||||
# }
|
||||
# }
|
||||
@ -93,8 +89,7 @@ export def not [
|
||||
msg: ($message | default "Assertion failed."),
|
||||
label: ($error_label | default {
|
||||
text: "It is not false.",
|
||||
start: $span.start,
|
||||
end: $span.end
|
||||
span: $span,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -114,8 +109,7 @@ export def error [
|
||||
] {
|
||||
let error_raised = (try { do $code; false } catch { true })
|
||||
main ($error_raised) $message --error-label {
|
||||
start: (metadata $code).span.start
|
||||
end: (metadata $code).span.end
|
||||
span: (metadata $code).span
|
||||
text: (
|
||||
"There were no error during code execution:\n"
|
||||
+ $" (view source $code)"
|
||||
@ -134,8 +128,10 @@ export def error [
|
||||
# > assert equal 1 2 # fails
|
||||
export def equal [left: any, right: any, message?: string] {
|
||||
main ($left == $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
"These are not equal.\n"
|
||||
+ $" Left : '($left | to nuon --raw)'\n"
|
||||
@ -155,8 +151,10 @@ export def equal [left: any, right: any, message?: string] {
|
||||
# > assert not equal 7 7 # fails
|
||||
export def "not equal" [left: any, right: any, message?: string] {
|
||||
main ($left != $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: $"These are both '($left | to nuon --raw)'."
|
||||
}
|
||||
}
|
||||
@ -172,8 +170,10 @@ export def "not equal" [left: any, right: any, message?: string] {
|
||||
# > assert less or equal 1 0 # fails
|
||||
export def "less or equal" [left: any, right: any, message?: string] {
|
||||
main ($left <= $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
"The condition *left <= right* is not satisfied.\n"
|
||||
+ $" Left : '($left)'\n"
|
||||
@ -192,8 +192,10 @@ export def "less or equal" [left: any, right: any, message?: string] {
|
||||
# > assert less 1 1 # fails
|
||||
export def less [left: any, right: any, message?: string] {
|
||||
main ($left < $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
"The condition *left < right* is not satisfied.\n"
|
||||
+ $" Left : '($left)'\n"
|
||||
@ -212,8 +214,10 @@ export def less [left: any, right: any, message?: string] {
|
||||
# > assert greater 2 2 # fails
|
||||
export def greater [left: any, right: any, message?: string] {
|
||||
main ($left > $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
"The condition *left > right* is not satisfied.\n"
|
||||
+ $" Left : '($left)'\n"
|
||||
@ -233,8 +237,10 @@ export def greater [left: any, right: any, message?: string] {
|
||||
# > assert greater or equal 1 2 # fails
|
||||
export def "greater or equal" [left: any, right: any, message?: string] {
|
||||
main ($left >= $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
"The condition *left < right* is not satisfied.\n"
|
||||
+ $" Left : '($left)'\n"
|
||||
@ -254,8 +260,10 @@ alias "core length" = length
|
||||
# > assert length [0] 3 # fails
|
||||
export def length [left: list, right: int, message?: string] {
|
||||
main (($left | core length) == $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
"This does not have the correct length:\n"
|
||||
+ $" value : ($left | to nuon --raw)\n"
|
||||
@ -276,8 +284,10 @@ alias "core str contains" = str contains
|
||||
# > assert str contains "arst" "k" # fails
|
||||
export def "str contains" [left: string, right: string, message?: string] {
|
||||
main ($left | core str contains $right) $message --error-label {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
span: {
|
||||
start: (metadata $left).span.start
|
||||
end: (metadata $right).span.end
|
||||
}
|
||||
text: (
|
||||
$"This does not contain '($right)'.\n"
|
||||
+ $" value: ($left | to nuon --raw)"
|
||||
|
@ -31,7 +31,7 @@ export def --env add [
|
||||
let exp = ($p | path expand)
|
||||
if ($exp | path type) != 'dir' {
|
||||
let span = (metadata $p).span
|
||||
error make {msg: "not a directory", label: {text: "not a directory", start: $span.start, end: $span.end } }
|
||||
error make {msg: "not a directory", label: {text: "not a directory", span: $span } }
|
||||
}
|
||||
$abspaths = ($abspaths | append $exp)
|
||||
}
|
||||
@ -106,8 +106,7 @@ export def --env goto [shell?: int] {
|
||||
msg: $"(ansi red_bold)invalid_shell_index(ansi reset)"
|
||||
label: {
|
||||
text: $"`shell` should be between 0 and (($env.DIRS_LIST | length) - 1)"
|
||||
start: $span.start
|
||||
end: $span.end
|
||||
span: $span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,9 +107,18 @@ export def datetime-diff [
|
||||
earlier: datetime # earlier (starting) datetime
|
||||
] {
|
||||
if $earlier > $later {
|
||||
let start = (metadata $later).span.start
|
||||
let start = (metadata $later).span.start
|
||||
let end = (metadata $earlier).span.end
|
||||
error make {msg: "Incompatible arguments", label: {start:$start, end:$end, text:$"First datetime must be >= second, but was actually ($later - $earlier) less than it."}}
|
||||
error make {
|
||||
msg: "Incompatible arguments",
|
||||
label: {
|
||||
span: {
|
||||
start: $start
|
||||
end: $end
|
||||
}
|
||||
text: $"First datetime must be >= second, but was actually ($later - $earlier) less than it."
|
||||
}
|
||||
}
|
||||
}
|
||||
let from_expanded = ($later | date to-timezone utc | date to-record)
|
||||
let to_expanded = ($earlier | date to-timezone utc | date to-record)
|
||||
|
@ -7,8 +7,7 @@ def throw-error [error: string, msg: string, span: record] {
|
||||
msg: ($error | error-fmt)
|
||||
label: {
|
||||
text: $msg
|
||||
start: $span.start
|
||||
end: $span.end
|
||||
span: $span
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -762,11 +761,10 @@ You can also learn more at (ansi default_italic)(ansi light_cyan_underline)https
|
||||
|
||||
let span = (metadata $item | get span)
|
||||
error make {
|
||||
msg: ("std::help::item_not_found" | error-fmt)
|
||||
msg: ("std::help::item_not_found" | error-fmt)
|
||||
label: {
|
||||
text: "item not found"
|
||||
start: $span.start
|
||||
end: $span.end
|
||||
span: $span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,8 +237,7 @@ def log-level-deduction-error [
|
||||
$" Available log levels in $env.LOG_LEVEL:"
|
||||
($env.LOG_LEVEL | to text | lines | each {|it| $" ($it)" } | to text)
|
||||
] | str join "\n")
|
||||
start: $span.start
|
||||
end: $span.end
|
||||
span: $span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,8 +45,7 @@ export def --env "path add" [
|
||||
if ($paths | is-empty) or ($paths | length) == 0 {
|
||||
error make {msg: "Empty input", label: {
|
||||
text: "Provide at least one string or a record",
|
||||
start: $span.start,
|
||||
end: $span.end
|
||||
span: $span
|
||||
}}
|
||||
}
|
||||
|
||||
@ -64,8 +63,7 @@ export def --env "path add" [
|
||||
if null in $paths or ($paths | is-empty) {
|
||||
error make {msg: "Empty input", label: {
|
||||
text: $"Received a record, that does not contain a ($nu.os-info.name) key",
|
||||
start: $span.start,
|
||||
end: $span.end
|
||||
span: $span
|
||||
}}
|
||||
}
|
||||
|
||||
@ -326,8 +324,7 @@ export def repeat [
|
||||
msg: $"(ansi red_bold)invalid_argument(ansi reset)"
|
||||
label: {
|
||||
text: $"n should be a positive integer, found ($n)"
|
||||
start: $span.start
|
||||
end: $span.end
|
||||
span: $span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,8 +94,7 @@ def throw-error [error: record] {
|
||||
msg: $"(ansi red)($error.msg)(ansi reset)"
|
||||
label: {
|
||||
text: ($error.label)
|
||||
start: $error.span.start
|
||||
end: $error.span.end
|
||||
span: $error.span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,18 @@ export def xaccess [
|
||||
# 1. String with tag name. Finds all children with specified name. Equivalent to `child::A` in xpath
|
||||
# 2. `*` string. Get all children without any filter. Equivalent to `descendant` in xpath
|
||||
# 3. Int. Select n-th among nodes selected by previous path. Equivalent to `(...)[1]` in xpath, but is indexed from 0.
|
||||
# 4. Closure. Predicate accepting entry. Selects all entries among nodes selected by previous path for which predicate returns true.
|
||||
# 4. Closure. Predicate accepting entry. Selects all entries among nodes selected by previous path for which predicate returns true.
|
||||
] {
|
||||
let input = $in
|
||||
if ($path | is-empty) {
|
||||
let path_span = (metadata $path).span
|
||||
error make {msg: 'Empty path provided'
|
||||
label: {text: 'Use a non-empty list of path steps'
|
||||
start: $path_span.start end: $path_span.end}}
|
||||
error make {
|
||||
msg: 'Empty path provided'
|
||||
label: {
|
||||
text: 'Use a non-empty list of path steps'
|
||||
span: $path_span
|
||||
}
|
||||
}
|
||||
}
|
||||
# In xpath first element in path is applied to root element
|
||||
# this way it is possible to apply first step to root element
|
||||
@ -38,9 +42,13 @@ export def xaccess [
|
||||
},
|
||||
$type => {
|
||||
let step_span = (metadata $step).span
|
||||
error make {msg: $'Incorrect path step type ($type)'
|
||||
label: {text: 'Use a string or int as a step'
|
||||
start: $step_span.start end: $step_span.end}}
|
||||
error make {
|
||||
msg: $'Incorrect path step type ($type)'
|
||||
label: {
|
||||
text: 'Use a string or int as a step'
|
||||
span: $step_span
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,9 +139,13 @@ def xupdate-internal [ path: list updater: closure ] {
|
||||
},
|
||||
$type => {
|
||||
let step_span = (metadata $step).span
|
||||
error make {msg: $'Incorrect path step type ($type)'
|
||||
label: {text: 'Use a string or int as a step'
|
||||
start: $step_span.start end: $step_span.end}}
|
||||
error make {
|
||||
msg: $'Incorrect path step type ($type)'
|
||||
label: {
|
||||
text: 'Use a string or int as a step'
|
||||
span: $step_span
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,7 +158,7 @@ export def xupdate [
|
||||
# 1. String with tag name. Finds all children with specified name. Equivalent to `child::A` in xpath
|
||||
# 2. `*` string. Get all children without any filter. Equivalent to `descendant` in xpath
|
||||
# 3. Int. Select n-th among nodes selected by previous path. Equivalent to `(...)[1]` in xpath, but is indexed from 0.
|
||||
# 4. Closure. Predicate accepting entry. Selects all entries among nodes selected by previous path for which predicate returns true.
|
||||
# 4. Closure. Predicate accepting entry. Selects all entries among nodes selected by previous path for which predicate returns true.
|
||||
updater: closure # A closure used to transform entries matching path.
|
||||
] {
|
||||
{tag:? attributes:? content: [$in]} | xupdate-internal $path $updater | get content.0
|
||||
@ -157,7 +169,7 @@ export def xupdate [
|
||||
# Possible types are 'tag', 'text', 'pi' and 'comment'
|
||||
export def xtype [] {
|
||||
let input = $in
|
||||
if (($input | describe) == 'string' or
|
||||
if (($input | describe) == 'string' or
|
||||
($input.tag? == null and $input.attributes? == null and ($input.content? | describe) == 'string')) {
|
||||
'text'
|
||||
} else if $input.tag? == '!' {
|
||||
@ -177,10 +189,10 @@ export def xinsert [
|
||||
# 1. String with tag name. Finds all children with specified name. Equivalent to `child::A` in xpath
|
||||
# 2. `*` string. Get all children without any filter. Equivalent to `descendant` in xpath
|
||||
# 3. Int. Select n-th among nodes selected by previous path. Equivalent to `(...)[1]` in xpath, but is indexed from 0.
|
||||
# 4. Closure. Predicate accepting entry. Selects all entries among nodes selected by previous path for which predicate returns true.
|
||||
# 4. Closure. Predicate accepting entry. Selects all entries among nodes selected by previous path for which predicate returns true.
|
||||
new_entry: record # A new entry to insert into `content` field of record at specified position
|
||||
position?: int # Position to insert `new_entry` into. If specified inserts entry at given position (or end if
|
||||
# position is greater than number of elements) in content of all entries of input matched by
|
||||
# position is greater than number of elements) in content of all entries of input matched by
|
||||
# path. If not specified inserts at the end.
|
||||
] {
|
||||
$in | xupdate $path {|entry|
|
||||
@ -197,7 +209,7 @@ export def xinsert [
|
||||
$entry.content | insert $position $new_entry
|
||||
}
|
||||
|
||||
|
||||
|
||||
{tag: $entry.tag attributes: $entry.attributes content: $new_content}
|
||||
},
|
||||
_ => (error make {msg: 'Can insert entry only into content of a tag node'})
|
||||
|
Reference in New Issue
Block a user