cmake -E: Add CLI argument spell checking

Use Levenshtein distance to track when the user may have made a typo in
an argument to `cmake -E` (i.e., an invalid mode; mode sub-arguments
are not tracked).
This commit is contained in:
Tyler Yankee
2026-09-11 08:23:37 -04:00
parent 7dacfea25d
commit dd44b41cbe
5 changed files with 27 additions and 0 deletions
+1
View File
@@ -16,6 +16,7 @@ skip =
Source/CursesDialog/form/*,
Source/kwsys/*,
Tests/RunCMake/CPack/tests/DMG_SLA/German.*,
Tests/RunCMake/CommandLine/RunCMakeTest.cmake,
Tests/RunCMake/ParseImplicitData/*.input,
Tests/RunCMake/cmake_language/call_typo_function.cmake,
Tests/StringFileTest/test.utf8,
+20
View File
@@ -2518,6 +2518,26 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
return 1;
}
std::vector<std::string> availableCommands =
CommandLineHelpEntryNames(AvailableCommands);
#if defined(_WIN32) && !defined(__CYGWIN__)
cm::append(availableCommands,
CommandLineHelpEntryNames(AvailableWindowsCommands));
#endif
// Some commands above only fall through to here when they were
// matched by name but had the wrong number/form of arguments; only
// offer a suggestion when the name itself is not recognized.
if (std::find(availableCommands.begin(), availableCommands.end(),
args[1]) == availableCommands.end()) {
std::string error = cmStrCat("Unknown command \"", args[1], "\".");
std::string const suggestion =
cmFindClosestString(args[1], availableCommands);
if (!suggestion.empty()) {
error = cmStrCat(error, " Did you mean \"", suggestion, "\"?");
}
cmSystemTools::Error(error);
}
}
CMakeCommandUsage(args[0]);
@@ -0,0 +1,4 @@
^CMake Error: Unknown command "enviroment"\. Did you mean "environment"\?
CMake Error: cmake version .*
Usage: .* -E <command> \[arguments\.\.\.\]
Available commands:
@@ -61,6 +61,7 @@ run_cmake_command(U-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -U)
run_cmake_command(U-no-src ${CMAKE_COMMAND} -B DummyBuildDir -U VAR)
run_cmake_command(Uno-src ${CMAKE_COMMAND} -B DummyBuildDir -UVAR)
run_cmake_command(E-no-arg ${CMAKE_COMMAND} -E)
run_cmake_command(E_unknown-command-did-you-mean ${CMAKE_COMMAND} -E enviroment)
run_cmake_command(E_capabilities ${CMAKE_COMMAND} -E capabilities)
run_cmake_command(E_capabilities-arg ${CMAKE_COMMAND} -E capabilities --extra-arg)
run_cmake_command(E_compare_files-different-eol ${CMAKE_COMMAND} -E compare_files ${RunCMake_SOURCE_DIR}/compare_files/lf ${RunCMake_SOURCE_DIR}/compare_files/crlf)