From b2e6609367ef6613cd2ab2d63d491caa3dc32ee7 Mon Sep 17 00:00:00 2001 From: Fabian Boehm Date: Mon, 2 Dec 2024 19:01:16 +0100 Subject: [PATCH] builtin random: Be less strict about arguments This now allows: - Same argument (`random 5 5`) - Swapped ends (`random 10 2`) - One possibility (`random 0 5 4`) This makes it easier to use with numbers generated elsewhere instead of hard-coded, so you don't need to check as much before running it. Fixes #10879 --- CHANGELOG.rst | 1 + src/builtins/random.rs | 18 +++++------------- tests/checks/random.fish | 12 ++++-------- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ecca5dbec..4593c6c87 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -110,6 +110,7 @@ Scripting improvements - Universal variables can now store strings containing invalid Unicode codepoints (:issue:`10313`). - A new ``path basename -E`` option that causes it to return the basename ("filename" with the directory prefix removed) with the final extension (if any) also removed. This is a shorter version of ``path change-extension "" (path basename $foo)`` (:issue:`10521`). - A new ``math --scale-mode`` option to select ``truncate``, ``round``, ``floor``, ``ceiling`` as you wish; the default value is ``truncate``. (:issue:`9117`). +- ``random`` is now less strict about its arguments, allowing a start larger or equal to the end. (:issue:`10879`) Interactive improvements ------------------------ diff --git a/src/builtins/random.rs b/src/builtins/random.rs index f854aef62..5d5c70bdd 100644 --- a/src/builtins/random.rs +++ b/src/builtins/random.rs @@ -135,22 +135,14 @@ pub fn random(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> O } } - if end <= start { - streams - .err - .append(wgettext_fmt!("%ls: END must be greater than START\n", cmd,)); - return STATUS_INVALID_ARGS; - } + let (start, end) = if start <= end { + (start, end) + } else { + (end, start) + }; // Using abs_diff() avoids an i64 overflow if start is i64::MIN and end is i64::MAX let possibilities = end.abs_diff(start) / step; - if possibilities == 0 { - streams.err.append(wgettext_fmt!( - "%ls: range contains only one possible value\n", - cmd, - )); - return STATUS_INVALID_ARGS; - } let rand = { let mut engine = RNG.lock().unwrap(); diff --git a/tests/checks/random.fish b/tests/checks/random.fish index 712313686..43f111c56 100644 --- a/tests/checks/random.fish +++ b/tests/checks/random.fish @@ -12,16 +12,12 @@ random $diff_max #CHECKERR: random: 18446744073709551614: invalid integer random -- 1 2 3 4 #CHECKERR: random: too many arguments -random -- 10 -10 -#CHECKERR: random: END must be greater than START random -- 10 $diff_max #CHECKERR: random: 18446744073709551614: invalid integer random -- 1 1d random -- 1 1c 10 #CHECKERR: random: 1d: invalid integer #CHECKERR: random: 1c: invalid integer -random -- 10 10 -#CHECKERR: random: END must be greater than START random -- 1 - 10 #CHECKERR: random: -: invalid integer random -- 1 -1 10 @@ -30,10 +26,6 @@ random -- 1 $min 10 #CHECKERR: random: -9223372036854775807: invalid integer random -- 1 0 10 #CHECKERR: random: STEP must be a positive integer -random -- 1 11 10 -#CHECKERR: random: range contains only one possible value -random -- 0 $diff_max $max -#CHECKERR: random: range contains only one possible value random choice #CHECKERR: random: nothing to choose from random choic a b c @@ -42,6 +34,7 @@ random choic a b c function check_boundaries if not test "$argv[1]" -ge "$argv[2]" -a "$argv[1]" -le "$argv[3]" printf "Unexpected: %s <= %s <= %s not verified\n" $argv[2] $argv[1] $argv[3] >&2 + status print-stack-trace return 1 end end @@ -55,6 +48,7 @@ function check_contains printf "Unexpected: %s not among possibilities" $argv[1] >&2 printf " %s" $argv[2..-1] >&2 printf "\n" >&2 + status print-stack-trace return 1 end end @@ -73,6 +67,7 @@ for i in (seq 10) test_range 0 10 test_range -10 -1 test_range -10 10 + test_range 5 5 test_range 0 $max test_range $min -1 @@ -89,6 +84,7 @@ for i in (seq 10) check_contains (random -- $min $close_max 0) $min -1 check_contains (random -- $min $max $max) $min 0 $max check_contains (random -- $min $diff_max $max) $min $max + check_contains (random -- 5 0) 0 1 2 3 4 5 test_step 0 $i 10 test_step -5 $i 5