Report similar names for builtins that user is searching for

This commit is contained in:
Robert Bendun 2023-03-05 01:10:43 +01:00
parent 92e5c3169c
commit 719e8d4f26
4 changed files with 88 additions and 19 deletions

View File

@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Builtin documentation for builtin functions display from repl and command line.
- Builtin documentation for builtin functions display from repl and command line (`musique doc <builtin>`)
- Man documentation for commandline interface builtin (`musique man`)
- Suggestions which command line parameters user may wanted to use
### Changed

View File

@ -15,6 +15,8 @@
#include <utility>
#include <variant>
// TODO: Command line parameters full documentation in other then man pages format. Maybe HTML generation?
#ifdef _WIN32
extern "C" {
#include <io.h>
@ -53,6 +55,11 @@ static Requires_Argument show_docs = [](std::string_view builtin) {
}
std::cerr << pretty::begin_error << "musique: error:" << pretty::end;
std::cerr << " cannot find documentation for given builtin" << std::endl;
std::cerr << "Similar ones are:" << std::endl;
for (auto similar : similar_names_to_builtin(builtin)) {
std::cerr << " " << similar << '\n';
}
std::exit(1);
};
@ -347,11 +354,12 @@ void cmd::print_close_matches(std::string_view arg)
std::cout << "\nInvoke 'musique help' to read more about available commands\n";
}
void cmd::usage()
static inline void iterate_over_documentation(
std::ostream& out,
std::string_view Documentation_For_Handler_Entry::* handler,
std::string_view prefix,
std::ostream&(*first)(std::ostream&, std::string_view name))
{
std::cerr << "usage: " << pretty::begin_bold << "musique" << pretty::end << " [subcommand]...\n";
std::cerr << " where available subcommands are:\n";
decltype(std::optional(all_parameters.begin())) previous = std::nullopt;
for (auto it = all_parameters.begin();; ++it) {
@ -361,14 +369,12 @@ void cmd::usage()
if (it == all_parameters.end() || (previous && it->handler_ptr() != (*previous)->handler_ptr())) {
auto &e = **previous;
switch (e.arguments()) {
break; case 0: std::cerr << '\n';
break; case 1: std::cerr << " ARG\n";
break; case 0: out << '\n';
break; case 1: out << " ARG\n";
break; default: unreachable();
}
std::cerr << " "
<< find_documentation_for_handler(e.handler_ptr()).short_documentation
<< "\n\n";
out << prefix << find_documentation_for_handler(e.handler_ptr()).*handler << "\n\n";
}
if (it == all_parameters.end()) {
@ -376,12 +382,24 @@ void cmd::usage()
}
if (previous && (**previous).handler_ptr() == it->handler_ptr()) {
std::cerr << ", " << it->name;
out << ", " << it->name;
} else {
std::cerr << " " << pretty::begin_bold << it->name << pretty::end;
first(out, it->name);
}
previous = it;
}
}
void cmd::usage()
{
std::cerr << "usage: " << pretty::begin_bold << "musique" << pretty::end << " [subcommand]...\n";
std::cerr << " where available subcommands are:\n";
iterate_over_documentation(std::cerr, &Documentation_For_Handler_Entry::short_documentation, " ",
[](std::ostream& out, std::string_view name) -> std::ostream&
{
return out << " " << pretty::begin_bold << name << pretty::end;
});
std::exit(2);
}
@ -411,11 +429,28 @@ SUBCOMMANDS
Musique is an interpreted, interactive, musical domain specific programming language
that allows for algorythmic music composition, live-coding and orchestra performing.
.SH SUBCOMMANDS
TODO
.SH ENVIROMENT
TODO: NO_COLORS env
All subcommands can be expressed in three styles: -i arg -j -k
.I or
--i=arg --j --k
.I or
i arg j k
)troff";
iterate_over_documentation(std::cout, &Documentation_For_Handler_Entry::long_documentation, {},
[](std::ostream& out, std::string_view name) -> std::ostream&
{
return out << ".TP\n" << name;
});
std::cout << R"troff(.SH ENVIROMENT
.TP
NO_COLOR
This enviroment variable overrides standard Musique color behaviour.
When it's defined, it disables colors and ensures they are not enabled.
.SH FILES
TODO: History file
.TP
History file
History file for interactive mode is kept in XDG_DATA_HOME (or similar on other operating systems).
.SH EXAMPLES
.TP
musique \-c "play (c5 + up 12)"
@ -425,7 +460,6 @@ musique run examples/ode-to-joy.mq
Play Ode to Joy written as Musique source code in examples/ode-to-joy.mq
)troff";
std::exit(0);
}

View File

@ -3,7 +3,12 @@
#include <optional>
#include <string_view>
#include <vector>
std::optional<std::string_view> find_documentation_for_builtin(std::string_view builtin_name);
/// Returns top 4 similar names to required
std::vector<std::string_view> similar_names_to_builtin(std::string_view builtin_name);
#endif

View File

@ -70,6 +70,28 @@ std::optional<std::string_view> find_documentation_for_builtin(std::string_view
}
return std::nullopt;
}
std::vector<std::string_view> similar_names_to_builtin(std::string_view builtin_name)
{
auto minimum_distance = std::numeric_limits<int>::max();
std::array<std::pair<std::string_view, std::string_view>, 4> closest;
std::partial_sort_copy(
names_to_documentation.begin(), names_to_documentation.end(),
closest.begin(), closest.end(),
[&minimum_distance, builtin_name](auto const& lhs, auto const& rhs) {
auto const lhs_score = edit_distance(builtin_name, lhs.first);
auto const rhs_score = edit_distance(builtin_name, rhs.first);
minimum_distance = std::min({ minimum_distance, lhs_score, rhs_score });
return lhs_score < rhs_score;
}
);
std::vector<std::string_view> result;
result.resize(4);
std::transform(closest.begin(), closest.end(), result.begin(), [](auto const& p) { return p.first; });
return result;
}
"""
def warning(*args, prefix: str | None = None):
@ -238,8 +260,15 @@ def generate_cpp_documentation(builtins: typing.Iterable[Builtin], output_path:
return f"{builtin.implementation}_doc"
with open(output_path, "w") as out:
print("#include <array>", file=out)
print("#include <musique/interpreter/builtin_function_documentation.hh>\n", file=out)
includes = [
"algorithm",
"array",
"edit_distance.hh",
"musique/interpreter/builtin_function_documentation.hh",
"vector",
]
for include in includes:
print(f"#include <{include}>", file=out)
# 1. Generate strings with documentation
for builtin in builtins: