From 3d001b7ba63a12f23083aadc3da5ff54c4524a65 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 14:57:55 +0200 Subject: [PATCH 01/10] Require recent cmdliner in test and dev packages The project is getting too expensive to maintain if we want to test across all versions of upstream backend. It's been a while since cmdliner 2.0 went out, it is time to adopt it in cmdlang. Note that we still aim to support the translation to work with older versions as long as the API remains compatible. However we'll be migrating our test suite to use the latest cmdliner major version only (follow up commits). --- cmdlang-dev.opam | 2 +- cmdlang-tests.opam | 2 +- cmdlang-to-cmdliner.opam | 6 ++++++ cmdlang-to-cmdliner.opam.template | 6 ++++++ dune-project | 8 ++------ src/cmdlang-to-cmdliner/translate.mli | 8 +++++++- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/cmdlang-dev.opam b/cmdlang-dev.opam index 49791ef..9386c5c 100644 --- a/cmdlang-dev.opam +++ b/cmdlang-dev.opam @@ -18,7 +18,7 @@ depends: [ "cmdlang-to-base" {= version} "cmdlang-to-climate" {= version} "cmdlang-to-cmdliner" {= version} - "cmdliner" {>= "1.3.0" & < "2.0"} + "cmdliner" {>= "2.1.1"} "conf-jq" "dune-build-info" {>= "3.17"} "mdx" {>= "2.4"} diff --git a/cmdlang-tests.opam b/cmdlang-tests.opam index 3a97806..10be710 100644 --- a/cmdlang-tests.opam +++ b/cmdlang-tests.opam @@ -17,7 +17,7 @@ depends: [ "cmdlang-to-base" {= version} "cmdlang-to-climate" {= version} "cmdlang-to-cmdliner" {= version} - "cmdliner" {>= "1.3.0" & < "2.0"} + "cmdliner" {>= "2.1.1"} "core" {>= "v0.17"} "core_unix" {>= "v0.17"} "dune-build-info" {>= "3.17"} diff --git a/cmdlang-to-cmdliner.opam b/cmdlang-to-cmdliner.opam index c0ab9d6..64c67c9 100644 --- a/cmdlang-to-cmdliner.opam +++ b/cmdlang-to-cmdliner.opam @@ -35,6 +35,12 @@ description: """\ specified with [cmdlang] into [cmdliner] commands suitable for execution. +This library aims to remain as compatible as possible with older +versions of [cmdliner], down to [1.3]. However, it is only actively +tested against the version of [cmdliner] used by this project's own +test suite (currently [>= 2.1.1]), so older versions are no longer +verified by CI. + [cmdliner]: https://github.com/dbuenzli/cmdliner """ diff --git a/cmdlang-to-cmdliner.opam.template b/cmdlang-to-cmdliner.opam.template index 5129cf7..9d2800c 100644 --- a/cmdlang-to-cmdliner.opam.template +++ b/cmdlang-to-cmdliner.opam.template @@ -4,6 +4,12 @@ description: """\ specified with [cmdlang] into [cmdliner] commands suitable for execution. +This library aims to remain as compatible as possible with older +versions of [cmdliner], down to [1.3]. However, it is only actively +tested against the version of [cmdliner] used by this project's own +test suite (currently [>= 2.1.1]), so older versions are no longer +verified by CI. + [cmdliner]: https://github.com/dbuenzli/cmdliner """ diff --git a/dune-project b/dune-project index f501be7..b15a3c0 100644 --- a/dune-project +++ b/dune-project @@ -101,9 +101,7 @@ (cmdlang-to-cmdliner (= :version)) (cmdliner - (and - (>= 1.3.0) - (< 2.0))) + (>= 2.1.1)) (core (>= v0.17)) (core_unix @@ -159,9 +157,7 @@ (cmdlang-to-cmdliner (= :version)) (cmdliner - (and - (>= 1.3.0) - (< 2.0))) + (>= 2.1.1)) conf-jq (dune-build-info (>= 3.17)) diff --git a/src/cmdlang-to-cmdliner/translate.mli b/src/cmdlang-to-cmdliner/translate.mli index e88f720..1bc9154 100644 --- a/src/cmdlang-to-cmdliner/translate.mli +++ b/src/cmdlang-to-cmdliner/translate.mli @@ -4,7 +4,13 @@ (*_ SPDX-License-Identifier: MIT *) (*_********************************************************************************) -(** Translate cmdlang parsers to cmdliner. *) +(** Translate cmdlang parsers to cmdliner. + + This library aims to remain as compatible as possible with older + versions of [cmdliner], down to [1.3]. However, it is only actively + tested against the version of [cmdliner] used by this project's own test + suite (currently [>= 2.1.1]), so older versions are no longer verified + by CI. *) (** {1 Param} *) From 9d4814329a8604939774d641009fe549cc234a28 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:11:04 +0200 Subject: [PATCH 02/10] Promote new display of errors in tests using cmdliner >= 2.0 This is a mechanical change where we promoted the new output emitted by the new version of cmdliner. There are a few more changes require which are left out of scope of that commit because they will require a bit more care, related to prefix of command and argument being no longer accepted (follow up work). --- doc/docs/tutorials/getting-started/README.md | 14 +++---- test/cmdlang-to-cmdliner/test__param.ml | 8 +++- test/cram/basic.t | 34 +++++++---------- test/cram/enum.t | 16 ++++---- test/cram/group.t | 20 +++++----- test/cram/named-with-default.t | 32 ++++++++-------- test/expect/test__flag.ml | 20 ++++------ test/expect/test__invalid_pos_opt.ml | 10 ++--- test/expect/test__named.ml | 10 ++--- test/expect/test__negative_int_args.ml | 10 ++--- test/expect/test__param.ml | 39 ++++++++------------ test/expect/test__pos.ml | 15 +++----- 12 files changed, 100 insertions(+), 128 deletions(-) diff --git a/doc/docs/tutorials/getting-started/README.md b/doc/docs/tutorials/getting-started/README.md index f54b838..85b07ae 100644 --- a/doc/docs/tutorials/getting-started/README.md +++ b/doc/docs/tutorials/getting-started/README.md @@ -264,7 +264,7 @@ NAME my-calculator - A simple calculator. SYNOPSIS - my-calculator [--op=OP] [--verbose] [OPTION]… a b + my-calculator --op=OP [--verbose] [OPTION]… a b ARGUMENTS a (required) @@ -308,19 +308,17 @@ Additionally, we don't need to worry about handling invalid usages, this is done ```sh $ ./my-calculator --op=not-found 1 2.5 -my-calculator: option '--op': invalid value 'not-found', expected either - 'add' or 'mul' -Usage: my-calculator [--op=OP] [--verbose] [OPTION]… a b -Try 'my-calculator --help' for more information. +Usage: my-calculator [--help] --op=OP [--verbose] [OPTION]… a b +my-calculator: option --op: invalid value not-found, expected either add or + mul [124] ``` ```sh $ ./my-calculator --op=add true 2.5 -my-calculator: a argument: invalid value 'true', expected a floating point +Usage: my-calculator [--help] --op=OP [--verbose] [OPTION]… a b +my-calculator: a argument: invalid value true, expected a floating point number -Usage: my-calculator [--op=OP] [--verbose] [OPTION]… a b -Try 'my-calculator --help' for more information. [124] ``` diff --git a/test/cmdlang-to-cmdliner/test__param.ml b/test/cmdlang-to-cmdliner/test__param.ml index 1945894..1a2959f 100644 --- a/test/cmdlang-to-cmdliner/test__param.ml +++ b/test/cmdlang-to-cmdliner/test__param.ml @@ -18,8 +18,12 @@ let%expect_test "param" = conv Command.Param.int [%sexp_of: int] [ ""; "a"; "0"; "42"; "-17" ]; [%expect {| - ("" (Error (Msg "invalid value '', expected an integer"))) - (a (Error (Msg "invalid value 'a', expected an integer"))) + ("" ( + Error ( + Msg "\027[31minvalid\027[m value \027[01m\027[m, expected an integer"))) + (a ( + Error ( + Msg "\027[31minvalid\027[m value \027[01ma\027[m, expected an integer"))) (0 (Ok 0)) (42 (Ok 42)) (-17 (Ok -17)) diff --git a/test/cram/basic.t b/test/cram/basic.t index 40b3aa7..555fd56 100644 --- a/test/cram/basic.t +++ b/test/cram/basic.t @@ -190,9 +190,8 @@ flags. [124] $ ./main_cmdliner.exe basic int -13 - ./main_cmdliner.exe: unknown option '-1'. - Usage: ./main_cmdliner.exe basic int [OPTION]… INT - Try './main_cmdliner.exe basic int --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic int [--help] [OPTION]… INT + ./main_cmdliner.exe: unknown option -1 [124] $ ./main_stdlib_runner.exe basic int -13 @@ -315,9 +314,8 @@ flags. [124] $ ./main_cmdliner.exe basic float -13.8 - ./main_cmdliner.exe: unknown option '-1'. - Usage: ./main_cmdliner.exe basic float [OPTION]… FLOAT - Try './main_cmdliner.exe basic float --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic float [--help] [OPTION]… FLOAT + ./main_cmdliner.exe: unknown option -1 [124] $ ./main_stdlib_runner.exe basic float -13.8 @@ -454,10 +452,9 @@ And run it too. [124] $ ./main_cmdliner.exe basic bool True - ./main_cmdliner.exe: BOOL argument: invalid value 'True', either 'true' or - 'false' - Usage: ./main_cmdliner.exe basic bool [OPTION]… BOOL - Try './main_cmdliner.exe basic bool --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic bool [--help] [OPTION]… BOOL + ./main_cmdliner.exe: BOOL argument: invalid value True, expected either true + or false [124] $ ./main_stdlib_runner.exe basic bool True @@ -497,10 +494,9 @@ Invalid entry. [124] $ ./main_cmdliner.exe basic bool Not_a_bool - ./main_cmdliner.exe: BOOL argument: invalid value 'Not_a_bool', either 'true' - or 'false' - Usage: ./main_cmdliner.exe basic bool [OPTION]… BOOL - Try './main_cmdliner.exe basic bool --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic bool [--help] [OPTION]… BOOL + ./main_cmdliner.exe: BOOL argument: invalid value Not_a_bool, expected either + true or false [124] $ ./main_stdlib_runner.exe basic bool Not_a_bool @@ -595,9 +591,8 @@ And run it too. foo.txt $ ./main_cmdliner.exe basic file foo.txt - ./main_cmdliner.exe: FILE argument: no 'foo.txt' file or directory - Usage: ./main_cmdliner.exe basic file [OPTION]… FILE - Try './main_cmdliner.exe basic file --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic file [--help] [OPTION]… FILE + ./main_cmdliner.exe: FILE argument: no foo.txt file or directory [124] $ ./main_stdlib_runner.exe basic file foo.txt @@ -631,9 +626,8 @@ Same when the file actually exists /bogus/bar $ ./main_cmdliner.exe basic file /bogus/bar - ./main_cmdliner.exe: FILE argument: no '/bogus/bar' file or directory - Usage: ./main_cmdliner.exe basic file [OPTION]… FILE - Try './main_cmdliner.exe basic file --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic file [--help] [OPTION]… FILE + ./main_cmdliner.exe: FILE argument: no /bogus/bar file or directory [124] $ ./main_stdlib_runner.exe basic file /bogus/bar diff --git a/test/cram/enum.t b/test/cram/enum.t index 9a32ad0..b449172 100644 --- a/test/cram/enum.t +++ b/test/cram/enum.t @@ -138,10 +138,9 @@ Cmdliner. red $ ./main_cmdliner.exe enum pos INVALID - ./main_cmdliner.exe: COLOR argument: invalid value 'INVALID', expected one of - 'red', 'green' or 'blue' - Usage: ./main_cmdliner.exe enum pos [OPTION]… COLOR - Try './main_cmdliner.exe enum pos --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe enum pos [--help] [OPTION]… COLOR + ./main_cmdliner.exe: COLOR argument: invalid value INVALID, expected one of + red, green or blue [124] $ ./main_cmdliner.exe enum named --help=plain @@ -149,7 +148,7 @@ Cmdliner. ./main_cmdliner.exe-enum-named - Print color. SYNOPSIS - ./main_cmdliner.exe enum named [--color=COLOR] [OPTION]… + ./main_cmdliner.exe enum named --color=COLOR [OPTION]… OPTIONS --color=COLOR (required) @@ -183,10 +182,9 @@ Cmdliner. red $ ./main_cmdliner.exe enum named --color INVALID - ./main_cmdliner.exe: option '--color': invalid value 'INVALID', expected one - of 'red', 'green' or 'blue' - Usage: ./main_cmdliner.exe enum named [--color=COLOR] [OPTION]… - Try './main_cmdliner.exe enum named --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe enum named [--help] --color=COLOR [OPTION]… + ./main_cmdliner.exe: option --color: invalid value INVALID, expected one of + red, green or blue [124] Stdlib runner. diff --git a/test/cram/group.t b/test/cram/group.t index d4395b4..5cd7562 100644 --- a/test/cram/group.t +++ b/test/cram/group.t @@ -133,9 +133,9 @@ What happens when that group is run: [1] $ ./main_cmdliner.exe basic - ./main_cmdliner.exe: required COMMAND name is missing, must be one of 'bool', 'file', 'float', 'int' or 'string'. - Usage: ./main_cmdliner.exe basic COMMAND … - Try './main_cmdliner.exe basic --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe basic [--help] COMMAND … + ./main_cmdliner.exe: required COMMAND name is missing, must be one of bool, + file, float, int or string [124] $ ./main_stdlib_runner.exe basic @@ -266,9 +266,8 @@ What happens when that group with a default is run: [124] $ ./main_cmdliner.exe group + Usage: ./main_cmdliner.exe group [--help] [COMMAND] … ./main_cmdliner.exe: required argument STRING is missing - Usage: ./main_cmdliner.exe group [COMMAND] … - Try './main_cmdliner.exe group --help' or './main_cmdliner.exe --help' for more information. [124] $ ./main_stdlib_runner.exe group @@ -299,9 +298,8 @@ With cmdliner, this particular default command is not supported because the positional argument is interpreted as an unknown command: $ ./main_cmdliner.exe group World - ./main_cmdliner.exe: unknown command 'World', must be 'a'. - Usage: ./main_cmdliner.exe group [COMMAND] … - Try './main_cmdliner.exe group --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe group [--help] [COMMAND] … + ./main_cmdliner.exe: unknown command World. Must be a [124] The recommended way to handle this in cmdliner is to add the special '--' token, such as in: @@ -345,9 +343,9 @@ default, when it is invoked with an invalid subcommand name. [124] $ ./main_cmdliner.exe invalid - ./main_cmdliner.exe: unknown command 'invalid', must be one of 'basic', 'doc', 'enum', 'flags', 'group', 'named' or 'return'. - Usage: ./main_cmdliner.exe COMMAND … - Try './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe [--help] COMMAND … + ./main_cmdliner.exe: unknown command invalid. Must be one of basic, doc, + enum, flags, group, named or return [124] $ ./main_stdlib_runner.exe invalid diff --git a/test/cram/named-with-default.t b/test/cram/named-with-default.t index 4fe65c4..6db6005 100644 --- a/test/cram/named-with-default.t +++ b/test/cram/named-with-default.t @@ -217,9 +217,9 @@ functions or parsers generated from modules with utils. [124] $ ./main_cmdliner.exe named with-default create --who=C - ./main_cmdliner.exe: option '--who': "C": invalid E.t - Usage: ./main_cmdliner.exe named with-default create [--who=(A|B)] [OPTION]… - Try './main_cmdliner.exe named with-default create --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe named with-default create [--help] [--who=(A|B)] + [OPTION]… + ./main_cmdliner.exe: option --who: "C": invalid E.t [124] $ ./main_stdlib_runner.exe named with-default create --who C @@ -330,11 +330,11 @@ Named-with-default with a stringable parameter. Named_with_default__stringable SYNOPSIS - ./main_cmdliner.exe named with-default stringable [--who=VAL] + ./main_cmdliner.exe named with-default stringable [--who=VALUE] [OPTION]… OPTIONS - --who=VAL (absent=my-id) + --who=VALUE (absent=my-id) identifier. COMMON OPTIONS @@ -413,10 +413,10 @@ Named-with-default with a validated string parameter. Named_with_default__validated SYNOPSIS - ./main_cmdliner.exe named with-default validated [--who=VAL] [OPTION]… + ./main_cmdliner.exe named with-default validated [--who=VALUE] [OPTION]… OPTIONS - --who=VAL (absent=0000) + --who=VALUE (absent=0000) 4 letters alphanumerical identifier. COMMON OPTIONS @@ -490,10 +490,10 @@ Invalid entry for the validated string parameter. [124] $ ./main_cmdliner.exe named with-default validated --who foo - ./main_cmdliner.exe: option '--who': "foo": invalid 4 letters alphanumerical + Usage: ./main_cmdliner.exe named with-default validated [--help] + [--who=VALUE] [OPTION]… + ./main_cmdliner.exe: option --who: "foo": invalid 4 letters alphanumerical identifier - Usage: ./main_cmdliner.exe named with-default validated [--who=VAL] [OPTION]… - Try './main_cmdliner.exe named with-default validated --help' or './main_cmdliner.exe --help' for more information. [124] $ ./main_stdlib_runner.exe named with-default validated --who foo @@ -614,9 +614,9 @@ Named-with-default with a comma-separated string parameter. [124] $ ./main_cmdliner.exe named with-default pos-int -x blah - ./main_cmdliner.exe: option '-x': Not an int - Usage: ./main_cmdliner.exe named with-default pos-int [-x X] [OPTION]… - Try './main_cmdliner.exe named with-default pos-int --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe named with-default pos-int [--help] [-x X] + [OPTION]… + ./main_cmdliner.exe: option -x: Not an int [124] $ ./main_stdlib_runner.exe named with-default pos-int -x blah @@ -652,9 +652,9 @@ Named-with-default with a comma-separated string parameter. [124] $ ./main_cmdliner.exe named with-default pos-int -x 0 - ./main_cmdliner.exe: option '-x': Strictly positive int expected - Usage: ./main_cmdliner.exe named with-default pos-int [-x X] [OPTION]… - Try './main_cmdliner.exe named with-default pos-int --help' or './main_cmdliner.exe --help' for more information. + Usage: ./main_cmdliner.exe named with-default pos-int [--help] [-x X] + [OPTION]… + ./main_cmdliner.exe: option -x: Strictly positive int expected [124] $ ./main_stdlib_runner.exe named with-default pos-int -x 0 diff --git a/test/expect/test__flag.ml b/test/expect/test__flag.ml index 7594cf7..924a0e3 100644 --- a/test/expect/test__flag.ml +++ b/test/expect/test__flag.ml @@ -47,9 +47,8 @@ let%expect_test "flag" = -h, --help Show this help message. Unknown argument name: -p ----------------------------------------------------- Cmdliner - test: unknown option '-p'. - Usage: test [--print-hello] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [--print-hello] [OPTION]… + test: unknown option -p ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -81,9 +80,8 @@ let%expect_test "flag" = -h, --help Show this help message. Unknown argument name: -p ----------------------------------------------------- Cmdliner - test: unknown option '-p', did you mean '--print-hello'? - Usage: test [--print-hello] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [--print-hello] [OPTION]… + test: unknown option -p. Did you mean --print-hello? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -173,9 +171,8 @@ let%expect_test "1-letter-flag" = -h, --help Show this help message. Single-character names must only be specified with a single dash. "--p" is not allowed as it has two dashes but only one character. ----------------------------------------------------- Cmdliner - test: unknown option '--p', did you mean '-p'? - Usage: test [-p] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [-p] [OPTION]… + test: unknown option --p. Did you mean -p? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -439,9 +436,8 @@ let%expect_test "user provided dashes" = Failure "Error in argument spec: Attempted to use \"-a\" as an argument name. \"-a\" is not a valid argument name because it begins with a dash which is not allowed.")) ----------------------------------------------------- Cmdliner - test: unknown option '-a'. - Usage: test [---a] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [---a] [OPTION]… + test: unknown option -a ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( diff --git a/test/expect/test__invalid_pos_opt.ml b/test/expect/test__invalid_pos_opt.ml index 42951e3..e1828ee 100644 --- a/test/expect/test__invalid_pos_opt.ml +++ b/test/expect/test__invalid_pos_opt.ml @@ -44,9 +44,8 @@ let%expect_test "invalid_pos_sequence" = -h, --help Show this help message. Missing required positional argument at position 1. ----------------------------------------------------- Cmdliner - test: required argument STRING is missing - Usage: test [OPTION]… [STRING] STRING - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… [STRING] STRING + test: required argument STRING is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing anonymous argument: STRING") @@ -118,9 +117,8 @@ let%expect_test "cmdliner" = run [ "B" ]; [%expect {| - ./main.exe: required argument STRING is missing - Usage: ./main.exe [OPTION]… [STRING] STRING - Try './main.exe --help' for more information. + Usage: ./main.exe [--help] [OPTION]… [STRING] STRING + ./main.exe: required argument STRING is missing 124 |}]; () diff --git a/test/expect/test__named.ml b/test/expect/test__named.ml index d18fe21..0827c4c 100644 --- a/test/expect/test__named.ml +++ b/test/expect/test__named.ml @@ -24,9 +24,8 @@ let%expect_test "named" = -h, --help Show this help message. Missing required named argument: --who ----------------------------------------------------- Cmdliner - test: required option --who is missing - Usage: test [--who=WHO] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] --who=WHO [OPTION]… + test: required option --who is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing required flag: --who") @@ -82,9 +81,8 @@ let%expect_test "1-letter-named" = -h, --help Show this help message. Missing required named argument: -w ----------------------------------------------------- Cmdliner - test: required option -w is missing - Usage: test [-w WHO] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] -w WHO [OPTION]… + test: required option -w is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing required flag: -w") diff --git a/test/expect/test__negative_int_args.ml b/test/expect/test__negative_int_args.ml index f14c5c2..2430833 100644 --- a/test/expect/test__negative_int_args.ml +++ b/test/expect/test__negative_int_args.ml @@ -59,9 +59,8 @@ let%expect_test "negative positional" = -h, --help Show this help message. Unknown argument name: -1 ----------------------------------------------------- Cmdliner - test: unknown option '-1'. - Usage: test [OPTION]… INT - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… INT + test: unknown option -1 ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -128,9 +127,8 @@ let%expect_test "negative named" = ----------------------------------------------------- Climate negative ----------------------------------------------------- Cmdliner - test: unknown option '-1'. - Usage: test [-n INT] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] -n INT [OPTION]… + test: unknown option -1 ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command negative diff --git a/test/expect/test__param.ml b/test/expect/test__param.ml index 7c4479a..c235c76 100644 --- a/test/expect/test__param.ml +++ b/test/expect/test__param.ml @@ -57,9 +57,8 @@ let%expect_test "int" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "not-an-int" (not an int) ----------------------------------------------------- Cmdliner - test: INT argument: invalid value 'not-an-int', expected an integer - Usage: test [OPTION]… INT - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… INT + test: INT argument: invalid value not-an-int, expected an integer ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -120,10 +119,9 @@ let%expect_test "float" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "not-an-number" (not an float) ----------------------------------------------------- Cmdliner - test: FLOAT argument: invalid value 'not-an-number', expected a floating - point number - Usage: test [OPTION]… FLOAT - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… FLOAT + test: FLOAT argument: invalid value not-an-number, expected a floating point + number ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -184,9 +182,8 @@ let%expect_test "bool" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "not-a-bool" (not an bool) ----------------------------------------------------- Cmdliner - test: BOOL argument: invalid value 'not-a-bool', either 'true' or 'false' - Usage: test [OPTION]… BOOL - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… BOOL + test: BOOL argument: invalid value not-a-bool, expected either true or false ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -222,9 +219,8 @@ let%expect_test "file" = ----------------------------------------------------- Climate foo.txt ----------------------------------------------------- Cmdliner - test: FILE argument: no 'foo.txt' file or directory - Usage: test [OPTION]… FILE - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… FILE + test: FILE argument: no foo.txt file or directory ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command foo.txt @@ -297,9 +293,8 @@ let%expect_test "enumerated" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "Not_an_e" (valid values are: A, B) ----------------------------------------------------- Cmdliner - test: invalid value 'Not_an_e', expected either 'A' or 'B' - Usage: test [OPTION]… ARG - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… ENUM + test: ENUM argument: invalid value Not_an_e, expected either A or B ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -421,9 +416,8 @@ let%expect_test "validated_string" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid id ----------------------------------------------------- Cmdliner - test: invalid id - Usage: test [OPTION]… ARG - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… VALUE + test: VALUE argument: invalid id ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -546,10 +540,9 @@ let%expect_test "comma_separated" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "Not_an_e" (valid values are: A, B) ----------------------------------------------------- Cmdliner - test: invalid element in list ('Not_an_e'): invalid value 'Not_an_e', - expected either 'A' or 'B' - Usage: test [OPTION]… ARG - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… ENUM[,…] + test: ENUM[,…] argument: invalid element in list (Not_an_e): invalid value + Not_an_e, expected either A or B ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( diff --git a/test/expect/test__pos.ml b/test/expect/test__pos.ml index dd428e8..698c1b7 100644 --- a/test/expect/test__pos.ml +++ b/test/expect/test__pos.ml @@ -26,9 +26,8 @@ let%expect_test "pos" = -h, --help Show this help message. Missing required positional argument at position 0. ----------------------------------------------------- Cmdliner - test: required argument WHO is missing - Usage: test [OPTION]… WHO - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… WHO + test: required argument WHO is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing anonymous argument: WHO") @@ -69,9 +68,8 @@ let%expect_test "skipping-pos" = Failure "Error in argument spec: Attempted to declare a parser with a gap in its positional arguments. No parser would interpret the argument at position 0 but there is a parser for at least one argument at a higher position.")) ----------------------------------------------------- Cmdliner - test: required argument WHO is missing - Usage: test [OPTION]… WHO - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… WHO + test: required argument WHO is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Translation Raised" ( @@ -93,9 +91,8 @@ let%expect_test "skipping-pos" = Failure "Error in argument spec: Attempted to declare a parser with a gap in its positional arguments. No parser would interpret the argument at position 0 but there is a parser for at least one argument at a higher position.")) ----------------------------------------------------- Cmdliner - test: required argument WHO is missing - Usage: test [OPTION]… WHO - Try 'test --help' for more information. + Usage: test [--help] [OPTION]… WHO + test: required argument WHO is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Translation Raised" ( From 580ef3024f3a36a95ac3ed3b4ca42f361da38fdd Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:18:34 +0200 Subject: [PATCH 03/10] Disable ANSI char in cmdliner test expect traces This is a tradeof: we miss some behavior of the backend, and we gain more readability and stability of the tests. --- dune | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dune b/dune index 92e4d5b..8107a99 100644 --- a/dune +++ b/dune @@ -1,4 +1,9 @@ (env (dev (odoc - (warnings fatal)))) + (warnings fatal)) + ;; Since cmdliner 2.0, error and help messages use ANSI-styled. This makes our + ;; expect and cram tests depend on the ambient environment of whoever runs + ;; them. Force plain output so corrected files are stable across environments. + (env-vars + (NO_COLOR "1")))) From 68661354003c51643feb664aaddb1262bb145bfc Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:20:06 +0200 Subject: [PATCH 04/10] Promote new NO_COLOR output in tests --- test/expect/test__flag.ml | 8 +++---- test/expect/test__invalid_pos_opt.ml | 8 +++---- test/expect/test__named.ml | 8 +++---- test/expect/test__negative_int_args.ml | 8 +++---- test/expect/test__param.ml | 33 +++++++++++++------------- test/expect/test__pos.ml | 12 +++++----- 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/test/expect/test__flag.ml b/test/expect/test__flag.ml index 924a0e3..e70f874 100644 --- a/test/expect/test__flag.ml +++ b/test/expect/test__flag.ml @@ -47,8 +47,8 @@ let%expect_test "flag" = -h, --help Show this help message. Unknown argument name: -p ----------------------------------------------------- Cmdliner - Usage: test [--help] [--print-hello] [OPTION]… - test: unknown option -p + Usage: test [--help] [--print-hello] [OPTION]… + test: unknown option '-p' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -80,8 +80,8 @@ let%expect_test "flag" = -h, --help Show this help message. Unknown argument name: -p ----------------------------------------------------- Cmdliner - Usage: test [--help] [--print-hello] [OPTION]… - test: unknown option -p. Did you mean --print-hello? + Usage: test [--help] [--print-hello] [OPTION]… + test: unknown option '-p'. Did you mean '--print-hello'? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( diff --git a/test/expect/test__invalid_pos_opt.ml b/test/expect/test__invalid_pos_opt.ml index e1828ee..2d50f9a 100644 --- a/test/expect/test__invalid_pos_opt.ml +++ b/test/expect/test__invalid_pos_opt.ml @@ -44,8 +44,8 @@ let%expect_test "invalid_pos_sequence" = -h, --help Show this help message. Missing required positional argument at position 1. ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… [STRING] STRING - test: required argument STRING is missing + Usage: test [--help] [OPTION]… [STRING] STRING + test: required argument STRING is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing anonymous argument: STRING") @@ -117,8 +117,8 @@ let%expect_test "cmdliner" = run [ "B" ]; [%expect {| - Usage: ./main.exe [--help] [OPTION]… [STRING] STRING - ./main.exe: required argument STRING is missing + Usage: ./main.exe [--help] [OPTION]… [STRING] STRING + ./main.exe: required argument STRING is missing 124 |}]; () diff --git a/test/expect/test__named.ml b/test/expect/test__named.ml index 0827c4c..7732c34 100644 --- a/test/expect/test__named.ml +++ b/test/expect/test__named.ml @@ -24,8 +24,8 @@ let%expect_test "named" = -h, --help Show this help message. Missing required named argument: --who ----------------------------------------------------- Cmdliner - Usage: test [--help] --who=WHO [OPTION]… - test: required option --who is missing + Usage: test [--help] --who=WHO [OPTION]… + test: required option --who is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing required flag: --who") @@ -81,8 +81,8 @@ let%expect_test "1-letter-named" = -h, --help Show this help message. Missing required named argument: -w ----------------------------------------------------- Cmdliner - Usage: test [--help] -w WHO [OPTION]… - test: required option -w is missing + Usage: test [--help] -w WHO [OPTION]… + test: required option -w is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing required flag: -w") diff --git a/test/expect/test__negative_int_args.ml b/test/expect/test__negative_int_args.ml index 2430833..c289526 100644 --- a/test/expect/test__negative_int_args.ml +++ b/test/expect/test__negative_int_args.ml @@ -59,8 +59,8 @@ let%expect_test "negative positional" = -h, --help Show this help message. Unknown argument name: -1 ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… INT - test: unknown option -1 + Usage: test [--help] [OPTION]… INT + test: unknown option '-1' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -127,8 +127,8 @@ let%expect_test "negative named" = ----------------------------------------------------- Climate negative ----------------------------------------------------- Cmdliner - Usage: test [--help] -n INT [OPTION]… - test: unknown option -1 + Usage: test [--help] -n INT [OPTION]… + test: unknown option '-1' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command negative diff --git a/test/expect/test__param.ml b/test/expect/test__param.ml index c235c76..9aec3fb 100644 --- a/test/expect/test__param.ml +++ b/test/expect/test__param.ml @@ -57,8 +57,8 @@ let%expect_test "int" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "not-an-int" (not an int) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… INT - test: INT argument: invalid value not-an-int, expected an integer + Usage: test [--help] [OPTION]… INT + test: INT argument: invalid value 'not-an-int', expected an integer ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -119,9 +119,9 @@ let%expect_test "float" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "not-an-number" (not an float) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… FLOAT - test: FLOAT argument: invalid value not-an-number, expected a floating point - number + Usage: test [--help] [OPTION]… FLOAT + test: FLOAT argument: invalid value 'not-an-number', expected a floating + point number ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -182,8 +182,9 @@ let%expect_test "bool" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "not-a-bool" (not an bool) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… BOOL - test: BOOL argument: invalid value not-a-bool, expected either true or false + Usage: test [--help] [OPTION]… BOOL + test: BOOL argument: invalid value 'not-a-bool', expected either 'true' or + 'false' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -219,8 +220,8 @@ let%expect_test "file" = ----------------------------------------------------- Climate foo.txt ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… FILE - test: FILE argument: no foo.txt file or directory + Usage: test [--help] [OPTION]… FILE + test: FILE argument: no 'foo.txt' file or directory ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command foo.txt @@ -293,8 +294,8 @@ let%expect_test "enumerated" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "Not_an_e" (valid values are: A, B) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… ENUM - test: ENUM argument: invalid value Not_an_e, expected either A or B + Usage: test [--help] [OPTION]… ENUM + test: ENUM argument: invalid value 'Not_an_e', expected either 'A' or 'B' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -416,8 +417,8 @@ let%expect_test "validated_string" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid id ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… VALUE - test: VALUE argument: invalid id + Usage: test [--help] [OPTION]… VALUE + test: VALUE argument: invalid id ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -540,9 +541,9 @@ let%expect_test "comma_separated" = -h, --help Show this help message. Failed to parse the argument at position 0: invalid value: "Not_an_e" (valid values are: A, B) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… ENUM[,…] - test: ENUM[,…] argument: invalid element in list (Not_an_e): invalid value - Not_an_e, expected either A or B + Usage: test [--help] [OPTION]… ENUM[,…] + test: ENUM[,…] argument: invalid element in list ('Not_an_e'): invalid + value 'Not_an_e', expected either 'A' or 'B' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( diff --git a/test/expect/test__pos.ml b/test/expect/test__pos.ml index 698c1b7..80f988a 100644 --- a/test/expect/test__pos.ml +++ b/test/expect/test__pos.ml @@ -26,8 +26,8 @@ let%expect_test "pos" = -h, --help Show this help message. Missing required positional argument at position 0. ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… WHO - test: required argument WHO is missing + Usage: test [--help] [OPTION]… WHO + test: required argument WHO is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" "missing anonymous argument: WHO") @@ -68,8 +68,8 @@ let%expect_test "skipping-pos" = Failure "Error in argument spec: Attempted to declare a parser with a gap in its positional arguments. No parser would interpret the argument at position 0 but there is a parser for at least one argument at a higher position.")) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… WHO - test: required argument WHO is missing + Usage: test [--help] [OPTION]… WHO + test: required argument WHO is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Translation Raised" ( @@ -91,8 +91,8 @@ let%expect_test "skipping-pos" = Failure "Error in argument spec: Attempted to declare a parser with a gap in its positional arguments. No parser would interpret the argument at position 0 but there is a parser for at least one argument at a higher position.")) ----------------------------------------------------- Cmdliner - Usage: test [--help] [OPTION]… WHO - test: required argument WHO is missing + Usage: test [--help] [OPTION]… WHO + test: required argument WHO is missing ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Translation Raised" ( From e9e20258013a2e6e3be3193d2d524fbc0b65a04f Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:23:14 +0200 Subject: [PATCH 05/10] Upgrade behavior changes regarding partial flags --- test/expect/test__flag.ml | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/test/expect/test__flag.ml b/test/expect/test__flag.ml index e70f874..877574b 100644 --- a/test/expect/test__flag.ml +++ b/test/expect/test__flag.ml @@ -98,9 +98,9 @@ let%expect_test "flag" = --help Display this list of options ("Evaluation Failed" ((exit_code 2))) |}]; - (* Partial flags are handled differently by the backends. In [climate], they - are rejected. In [cmdliner] and [core.command], prefixes are interpreted as - full flags. We say more about this in a dedicated section below. *) + (* Partial flags are handled differently by the backends. In [core.command], + prefixes are interpreted as full flags. In the other backends, they are + rejected. We say more about this in a dedicated section below. *) Arg_test.eval_all test { prog = "test"; args = [ "--print" ] }; [%expect {| @@ -112,7 +112,9 @@ let%expect_test "flag" = -h, --help Show this help message. Unknown argument name: --print ----------------------------------------------------- Cmdliner - Hello + Usage: test [--help] [--print-hello] [OPTION]… + test: unknown option '--print' + ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command Hello ----------------------------------------------------- Stdlib_runner @@ -235,10 +237,10 @@ let%expect_test "1-letter-alias" = ----------------------------------------------------- Stdlib_runner Hello |}]; - (* One letter flags may not be called with 2 dashes. However, since [cmdliner] - and [core.command] allow partial flags, if the one letter is actually the - prefix of a long flag name, the two dashes form will be accepted by these - two backend. Beware, this may be confusing. *) + (* One letter flags may not be called with 2 dashes. However, since [core.command] + allow partial flags, if the one letter is actually the prefix of a long + flag name, the two dashes form will be accepted by this backend. Beware, + this may be confusing. *) Arg_test.eval_all test { prog = "test"; args = [ "--p" ] }; [%expect {| @@ -250,7 +252,9 @@ let%expect_test "1-letter-alias" = -h, --help Show this help message. Single-character names must only be specified with a single dash. "--p" is not allowed as it has two dashes but only one character. ----------------------------------------------------- Cmdliner - Hello + Usage: test [--help] [--print-hello] [OPTION]… + test: unknown option '--p'. Did you mean '-p'? + ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command Hello ----------------------------------------------------- Stdlib_runner @@ -312,8 +316,8 @@ let%expect_test "ambiguous prefixes" = ----------------------------------------------------- Stdlib_runner Hello World |}]; - (* When the flags are supplied partially, the backend diverge. If the - prefix is non-ambiguous, [cmdliner] and [core.command] accept it. *) + (* When the flags are supplied partially, the backend diverge. If the prefix is + non-ambiguous, [core.command] accept it. *) Arg_test.eval_all test { prog = "test"; args = [ "--print-hello-w" ] }; [%expect {| @@ -326,7 +330,9 @@ let%expect_test "ambiguous prefixes" = -h, --help Show this help message. Unknown argument name: --print-hello-w ----------------------------------------------------- Cmdliner - Hello World + Usage: test [--help] [--print-hello-world] [--print-hello-you] [OPTION]… + test: unknown option '--print-hello-w' + ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command Hello World ----------------------------------------------------- Stdlib_runner From 06507018f31a148b6adc00c32553ce009909304c Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:28:46 +0200 Subject: [PATCH 06/10] Remaining promotion for display of errors --- test/expect/test__flag.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test/expect/test__flag.ml b/test/expect/test__flag.ml index 877574b..92403e7 100644 --- a/test/expect/test__flag.ml +++ b/test/expect/test__flag.ml @@ -173,8 +173,8 @@ let%expect_test "1-letter-flag" = -h, --help Show this help message. Single-character names must only be specified with a single dash. "--p" is not allowed as it has two dashes but only one character. ----------------------------------------------------- Cmdliner - Usage: test [--help] [-p] [OPTION]… - test: unknown option --p. Did you mean -p? + Usage: test [--help] [-p] [OPTION]… + test: unknown option '--p'. Did you mean '-p'? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -361,9 +361,8 @@ let%expect_test "ambiguous prefixes" = -h, --help Show this help message. Unknown argument name: --print-hello ----------------------------------------------------- Cmdliner - test: option '--print-hello' ambiguous and could be either '--print-hello-world' or '--print-hello-you' - Usage: test [--print-hello-world] [--print-hello-you] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [--print-hello-world] [--print-hello-you] [OPTION]… + test: unknown option '--print-hello' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -442,8 +441,8 @@ let%expect_test "user provided dashes" = Failure "Error in argument spec: Attempted to use \"-a\" as an argument name. \"-a\" is not a valid argument name because it begins with a dash which is not allowed.")) ----------------------------------------------------- Cmdliner - Usage: test [--help] [---a] [OPTION]… - test: unknown option -a + Usage: test [--help] [---a] [OPTION]… + test: unknown option '-a' ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -458,9 +457,8 @@ let%expect_test "user provided dashes" = Failure "Error in argument spec: Attempted to use \"--a\" as an argument name. \"--a\" is not a valid argument name because it begins with a dash which is not allowed.")) ----------------------------------------------------- Cmdliner - test: unknown option '--a', did you mean '----a'? - Usage: test [----a] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [----a] [OPTION]… + test: unknown option '--a'. Did you mean '----a'? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -475,9 +473,8 @@ let%expect_test "user provided dashes" = Failure "Error in argument spec: Attempted to use \"-long\" as an argument name. \"-long\" is not a valid argument name because it begins with a dash which is not allowed.")) ----------------------------------------------------- Cmdliner - test: unknown option '-l', did you mean '---long'? - Usage: test [---long] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [---long] [OPTION]… + test: unknown option '-l'. Did you mean '---long'? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( @@ -492,9 +489,8 @@ let%expect_test "user provided dashes" = Failure "Error in argument spec: Attempted to use \"--long\" as an argument name. \"--long\" is not a valid argument name because it begins with a dash which is not allowed.")) ----------------------------------------------------- Cmdliner - test: unknown option '--long', did you mean '----long'? - Usage: test [----long] [OPTION]… - Try 'test --help' for more information. + Usage: test [--help] [----long] [OPTION]… + test: unknown option '--long'. Did you mean '----long'? ("Evaluation Failed" ((exit_code 124))) ----------------------------------------------------- Core_command ("Evaluation Failed" ( From bd339d7354a9da9e435fc69f45bb7cb6d866e19d Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:29:47 +0200 Subject: [PATCH 07/10] Add changelog entry --- CHANGES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ac14815..da9b547 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,12 @@ +## Unreleased + +### Changed + +- Require `cmdliner >= 2.1.1` for test packages (@mbarbin). +- `cmdlang-to-cmdliner` still targets `cmdliner >= 1.3.0` for broad compatibility, but is no longer tested against versions older than 2.1.1 (@mbarbin). +- Migrated expect and cram tests to `cmdliner.2.1.1`'s revised error/help output (@mbarbin). +- Force `NO_COLOR=1` in the dev build environment so `cmdliner`'s ANSI-styled error and help output doesn't leak into expected traces (@mbarbin). + ## 0.0.11 (2026-05-08) ### Added From 8acc9a5bdb781b6616a66d2f8ea4cfa6f6f8f95c Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:32:46 +0200 Subject: [PATCH 08/10] Promote error messages under NO_COLOR=1 --- doc/docs/tutorials/getting-started/README.md | 6 +++--- test/cram/basic.t | 16 ++++++++-------- test/cram/enum.t | 8 ++++---- test/cram/group.t | 10 +++++----- test/cram/named-with-default.t | 8 ++++---- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/doc/docs/tutorials/getting-started/README.md b/doc/docs/tutorials/getting-started/README.md index 85b07ae..ab1a82e 100644 --- a/doc/docs/tutorials/getting-started/README.md +++ b/doc/docs/tutorials/getting-started/README.md @@ -309,15 +309,15 @@ Additionally, we don't need to worry about handling invalid usages, this is done ```sh $ ./my-calculator --op=not-found 1 2.5 Usage: my-calculator [--help] --op=OP [--verbose] [OPTION]… a b -my-calculator: option --op: invalid value not-found, expected either add or - mul +my-calculator: option '--op': invalid value 'not-found', expected either + 'add' or 'mul' [124] ``` ```sh $ ./my-calculator --op=add true 2.5 Usage: my-calculator [--help] --op=OP [--verbose] [OPTION]… a b -my-calculator: a argument: invalid value true, expected a floating point +my-calculator: a argument: invalid value 'true', expected a floating point number [124] ``` diff --git a/test/cram/basic.t b/test/cram/basic.t index 555fd56..c9a688e 100644 --- a/test/cram/basic.t +++ b/test/cram/basic.t @@ -191,7 +191,7 @@ flags. $ ./main_cmdliner.exe basic int -13 Usage: ./main_cmdliner.exe basic int [--help] [OPTION]… INT - ./main_cmdliner.exe: unknown option -1 + ./main_cmdliner.exe: unknown option '-1' [124] $ ./main_stdlib_runner.exe basic int -13 @@ -315,7 +315,7 @@ flags. $ ./main_cmdliner.exe basic float -13.8 Usage: ./main_cmdliner.exe basic float [--help] [OPTION]… FLOAT - ./main_cmdliner.exe: unknown option -1 + ./main_cmdliner.exe: unknown option '-1' [124] $ ./main_stdlib_runner.exe basic float -13.8 @@ -453,8 +453,8 @@ And run it too. $ ./main_cmdliner.exe basic bool True Usage: ./main_cmdliner.exe basic bool [--help] [OPTION]… BOOL - ./main_cmdliner.exe: BOOL argument: invalid value True, expected either true - or false + ./main_cmdliner.exe: BOOL argument: invalid value 'True', expected either + 'true' or 'false' [124] $ ./main_stdlib_runner.exe basic bool True @@ -495,8 +495,8 @@ Invalid entry. $ ./main_cmdliner.exe basic bool Not_a_bool Usage: ./main_cmdliner.exe basic bool [--help] [OPTION]… BOOL - ./main_cmdliner.exe: BOOL argument: invalid value Not_a_bool, expected either - true or false + ./main_cmdliner.exe: BOOL argument: invalid value 'Not_a_bool', expected + either 'true' or 'false' [124] $ ./main_stdlib_runner.exe basic bool Not_a_bool @@ -592,7 +592,7 @@ And run it too. $ ./main_cmdliner.exe basic file foo.txt Usage: ./main_cmdliner.exe basic file [--help] [OPTION]… FILE - ./main_cmdliner.exe: FILE argument: no foo.txt file or directory + ./main_cmdliner.exe: FILE argument: no 'foo.txt' file or directory [124] $ ./main_stdlib_runner.exe basic file foo.txt @@ -627,7 +627,7 @@ Same when the file actually exists $ ./main_cmdliner.exe basic file /bogus/bar Usage: ./main_cmdliner.exe basic file [--help] [OPTION]… FILE - ./main_cmdliner.exe: FILE argument: no /bogus/bar file or directory + ./main_cmdliner.exe: FILE argument: no '/bogus/bar' file or directory [124] $ ./main_stdlib_runner.exe basic file /bogus/bar diff --git a/test/cram/enum.t b/test/cram/enum.t index b449172..2124a61 100644 --- a/test/cram/enum.t +++ b/test/cram/enum.t @@ -139,8 +139,8 @@ Cmdliner. $ ./main_cmdliner.exe enum pos INVALID Usage: ./main_cmdliner.exe enum pos [--help] [OPTION]… COLOR - ./main_cmdliner.exe: COLOR argument: invalid value INVALID, expected one of - red, green or blue + ./main_cmdliner.exe: COLOR argument: invalid value 'INVALID', expected one of + 'red', 'green' or 'blue' [124] $ ./main_cmdliner.exe enum named --help=plain @@ -183,8 +183,8 @@ Cmdliner. $ ./main_cmdliner.exe enum named --color INVALID Usage: ./main_cmdliner.exe enum named [--help] --color=COLOR [OPTION]… - ./main_cmdliner.exe: option --color: invalid value INVALID, expected one of - red, green or blue + ./main_cmdliner.exe: option '--color': invalid value 'INVALID', expected one + of 'red', 'green' or 'blue' [124] Stdlib runner. diff --git a/test/cram/group.t b/test/cram/group.t index 5cd7562..5d27324 100644 --- a/test/cram/group.t +++ b/test/cram/group.t @@ -134,8 +134,8 @@ What happens when that group is run: $ ./main_cmdliner.exe basic Usage: ./main_cmdliner.exe basic [--help] COMMAND … - ./main_cmdliner.exe: required COMMAND name is missing, must be one of bool, - file, float, int or string + ./main_cmdliner.exe: required COMMAND name is missing, must be one of 'bool', + 'file', 'float', 'int' or 'string' [124] $ ./main_stdlib_runner.exe basic @@ -299,7 +299,7 @@ positional argument is interpreted as an unknown command: $ ./main_cmdliner.exe group World Usage: ./main_cmdliner.exe group [--help] [COMMAND] … - ./main_cmdliner.exe: unknown command World. Must be a + ./main_cmdliner.exe: unknown command 'World'. Must be 'a' [124] The recommended way to handle this in cmdliner is to add the special '--' token, such as in: @@ -344,8 +344,8 @@ default, when it is invoked with an invalid subcommand name. $ ./main_cmdliner.exe invalid Usage: ./main_cmdliner.exe [--help] COMMAND … - ./main_cmdliner.exe: unknown command invalid. Must be one of basic, doc, - enum, flags, group, named or return + ./main_cmdliner.exe: unknown command 'invalid'. Must be one of 'basic', + 'doc', 'enum', 'flags', 'group', 'named' or 'return' [124] $ ./main_stdlib_runner.exe invalid diff --git a/test/cram/named-with-default.t b/test/cram/named-with-default.t index 6db6005..28c7aff 100644 --- a/test/cram/named-with-default.t +++ b/test/cram/named-with-default.t @@ -219,7 +219,7 @@ functions or parsers generated from modules with utils. $ ./main_cmdliner.exe named with-default create --who=C Usage: ./main_cmdliner.exe named with-default create [--help] [--who=(A|B)] [OPTION]… - ./main_cmdliner.exe: option --who: "C": invalid E.t + ./main_cmdliner.exe: option '--who': "C": invalid E.t [124] $ ./main_stdlib_runner.exe named with-default create --who C @@ -492,7 +492,7 @@ Invalid entry for the validated string parameter. $ ./main_cmdliner.exe named with-default validated --who foo Usage: ./main_cmdliner.exe named with-default validated [--help] [--who=VALUE] [OPTION]… - ./main_cmdliner.exe: option --who: "foo": invalid 4 letters alphanumerical + ./main_cmdliner.exe: option '--who': "foo": invalid 4 letters alphanumerical identifier [124] @@ -616,7 +616,7 @@ Named-with-default with a comma-separated string parameter. $ ./main_cmdliner.exe named with-default pos-int -x blah Usage: ./main_cmdliner.exe named with-default pos-int [--help] [-x X] [OPTION]… - ./main_cmdliner.exe: option -x: Not an int + ./main_cmdliner.exe: option '-x': Not an int [124] $ ./main_stdlib_runner.exe named with-default pos-int -x blah @@ -654,7 +654,7 @@ Named-with-default with a comma-separated string parameter. $ ./main_cmdliner.exe named with-default pos-int -x 0 Usage: ./main_cmdliner.exe named with-default pos-int [--help] [-x X] [OPTION]… - ./main_cmdliner.exe: option -x: Strictly positive int expected + ./main_cmdliner.exe: option '-x': Strictly positive int expected [124] $ ./main_stdlib_runner.exe named with-default pos-int -x 0 From b241cd154a9e0ee43f54cef4a3d49b56c7f3c788 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 15:46:21 +0200 Subject: [PATCH 09/10] Another promotion under NO_COLOR=1 This was wasn't tracked by the incremental build but caught by the CI. --- test/cmdlang-to-cmdliner/test__param.ml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/cmdlang-to-cmdliner/test__param.ml b/test/cmdlang-to-cmdliner/test__param.ml index 1a2959f..1945894 100644 --- a/test/cmdlang-to-cmdliner/test__param.ml +++ b/test/cmdlang-to-cmdliner/test__param.ml @@ -18,12 +18,8 @@ let%expect_test "param" = conv Command.Param.int [%sexp_of: int] [ ""; "a"; "0"; "42"; "-17" ]; [%expect {| - ("" ( - Error ( - Msg "\027[31minvalid\027[m value \027[01m\027[m, expected an integer"))) - (a ( - Error ( - Msg "\027[31minvalid\027[m value \027[01ma\027[m, expected an integer"))) + ("" (Error (Msg "invalid value '', expected an integer"))) + (a (Error (Msg "invalid value 'a', expected an integer"))) (0 (Ok 0)) (42 (Ok 42)) (-17 (Ok -17)) From b70f8e54a944912897dec5c28f8b40c7ab60c18c Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 16:09:07 +0200 Subject: [PATCH 10/10] Add alpha repo in CI Requiring [cmdliner >= 2.1.1] in the project causes some incompatibility during CI with [bisect_ppx] whose upstream release requires [cmdliner < 2.0]. There is however a version of bisect_ppx available that is compatible with cmdliner 2.0, released to the alpha repo. This is an attempt to fix the CI jobs currently failing. [ocaml-ci] however lack support for adding opam repo so I am afraid it won't be able to be fixed. --- .github/workflows/ci.yml | 2 +- .github/workflows/deploy-doc.yml | 2 +- .github/workflows/test-deploy-doc.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c97faf..5e0858b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: opam-repositories: | default: https://github.com/ocaml/opam-repository.git mbarbin: https://github.com/mbarbin/opam-repository.git - # alpha: https://github.com/kit-ty-kate/opam-alpha-repository.git + alpha: https://github.com/kit-ty-kate/opam-alpha-repository.git # janestreet-bleeding: https://github.com/janestreet/opam-repository.git # janestreet-bleeding-external: https://github.com/janestreet/opam-repository.git#external-packages diff --git a/.github/workflows/deploy-doc.yml b/.github/workflows/deploy-doc.yml index d9ccc74..129e68f 100644 --- a/.github/workflows/deploy-doc.yml +++ b/.github/workflows/deploy-doc.yml @@ -42,7 +42,7 @@ jobs: opam-repositories: | default: https://github.com/ocaml/opam-repository.git mbarbin: https://github.com/mbarbin/opam-repository.git - # alpha: https://github.com/kit-ty-kate/opam-alpha-repository.git + alpha: https://github.com/kit-ty-kate/opam-alpha-repository.git # janestreet-bleeding: https://github.com/janestreet/opam-repository.git # janestreet-bleeding-external: https://github.com/janestreet/opam-repository.git#external-packages diff --git a/.github/workflows/test-deploy-doc.yml b/.github/workflows/test-deploy-doc.yml index 15a939a..97e1518 100644 --- a/.github/workflows/test-deploy-doc.yml +++ b/.github/workflows/test-deploy-doc.yml @@ -42,7 +42,7 @@ jobs: opam-repositories: | default: https://github.com/ocaml/opam-repository.git mbarbin: https://github.com/mbarbin/opam-repository.git - # alpha: https://github.com/kit-ty-kate/opam-alpha-repository.git + alpha: https://github.com/kit-ty-kate/opam-alpha-repository.git # janestreet-bleeding: https://github.com/janestreet/opam-repository.git # janestreet-bleeding-external: https://github.com/janestreet/opam-repository.git#external-packages