From 57fcd4e0c433b13046cb7891ef4533f9172fbbe7 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Tue, 22 Oct 2024 19:20:43 -0400 Subject: [PATCH] fix(OptionParser): correct error message when flag has underscores Given this scenario: `OptionParser.parse!(["--foo_bar", "baz"], strict: [foo_bar: :string])` the current error message is: ``` ** (OptionParser.ParseError) 1 error found! --foo_bar : Missing argument of type string (elixir 1.17.2) lib/option_parser.ex:301: OptionParser.parse!/2 iex:5: (file) ``` This PR fixes it to instead be ``` ** (OptionParser.ParseError) 1 error found! --foo_bar : Unknown option. Did you mean --foo-bar? (elixir 1.17.2) lib/option_parser.ex:301: OptionParser.parse!/2 iex:5: (file) ``` --- lib/elixir/lib/option_parser.ex | 8 +++++++- lib/elixir/test/elixir/option_parser_test.exs | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/elixir/lib/option_parser.ex b/lib/elixir/lib/option_parser.ex index 5d62eb2bc74..de355ea4bd3 100644 --- a/lib/elixir/lib/option_parser.ex +++ b/lib/elixir/lib/option_parser.ex @@ -865,7 +865,13 @@ defmodule OptionParser do defp format_error({option, nil}, opts, types) do if type = get_type(option, opts, types) do - "#{option} : Missing argument of type #{type}" + if String.contains?(option, "_") do + msg = "#{option} : Unknown option" + + msg <> ". Did you mean #{String.replace(option, "_", "-")}?" + else + "#{option} : Missing argument of type #{type}" + end else msg = "#{option} : Unknown option" diff --git a/lib/elixir/test/elixir/option_parser_test.exs b/lib/elixir/test/elixir/option_parser_test.exs index c589a116575..39df43bdcb0 100644 --- a/lib/elixir/test/elixir/option_parser_test.exs +++ b/lib/elixir/test/elixir/option_parser_test.exs @@ -109,6 +109,15 @@ defmodule OptionParserTest do end end + test "parse!/2 raises an exception for an unknown option using strict when it is only off by underscores" do + msg = "1 error found!\n--docs_bar : Unknown option. Did you mean --docs-bar?" + + assert_raise OptionParser.ParseError, msg, fn -> + argv = ["--source", "from_docs/", "--docs_bar", "show"] + OptionParser.parse!(argv, strict: [source: :string, docs_bar: :string]) + end + end + test "parse!/2 raises an exception when an option is of the wrong type" do assert_raise OptionParser.ParseError, fn -> argv = ["--bad", "opt", "foo", "-o", "bad", "bar"]