Report similar names for builtins that user is searching for
This commit is contained in:
parent
92e5c3169c
commit
719e8d4f26
@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### 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
|
- Suggestions which command line parameters user may wanted to use
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
// TODO: Command line parameters full documentation in other then man pages format. Maybe HTML generation?
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <io.h>
|
#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 << pretty::begin_error << "musique: error:" << pretty::end;
|
||||||
std::cerr << " cannot find documentation for given builtin" << std::endl;
|
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);
|
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";
|
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;
|
decltype(std::optional(all_parameters.begin())) previous = std::nullopt;
|
||||||
|
|
||||||
for (auto it = all_parameters.begin();; ++it) {
|
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())) {
|
if (it == all_parameters.end() || (previous && it->handler_ptr() != (*previous)->handler_ptr())) {
|
||||||
auto &e = **previous;
|
auto &e = **previous;
|
||||||
switch (e.arguments()) {
|
switch (e.arguments()) {
|
||||||
break; case 0: std::cerr << '\n';
|
break; case 0: out << '\n';
|
||||||
break; case 1: std::cerr << " ARG\n";
|
break; case 1: out << " ARG\n";
|
||||||
break; default: unreachable();
|
break; default: unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << " "
|
out << prefix << find_documentation_for_handler(e.handler_ptr()).*handler << "\n\n";
|
||||||
<< find_documentation_for_handler(e.handler_ptr()).short_documentation
|
|
||||||
<< "\n\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it == all_parameters.end()) {
|
if (it == all_parameters.end()) {
|
||||||
@ -376,12 +382,24 @@ void cmd::usage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (previous && (**previous).handler_ptr() == it->handler_ptr()) {
|
if (previous && (**previous).handler_ptr() == it->handler_ptr()) {
|
||||||
std::cerr << ", " << it->name;
|
out << ", " << it->name;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << " " << pretty::begin_bold << it->name << pretty::end;
|
first(out, it->name);
|
||||||
}
|
}
|
||||||
previous = it;
|
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);
|
std::exit(2);
|
||||||
}
|
}
|
||||||
@ -411,11 +429,28 @@ SUBCOMMANDS
|
|||||||
Musique is an interpreted, interactive, musical domain specific programming language
|
Musique is an interpreted, interactive, musical domain specific programming language
|
||||||
that allows for algorythmic music composition, live-coding and orchestra performing.
|
that allows for algorythmic music composition, live-coding and orchestra performing.
|
||||||
.SH SUBCOMMANDS
|
.SH SUBCOMMANDS
|
||||||
TODO
|
All subcommands can be expressed in three styles: -i arg -j -k
|
||||||
.SH ENVIROMENT
|
.I or
|
||||||
TODO: NO_COLORS env
|
--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
|
.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
|
.SH EXAMPLES
|
||||||
.TP
|
.TP
|
||||||
musique \-c "play (c5 + up 12)"
|
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
|
Play Ode to Joy written as Musique source code in examples/ode-to-joy.mq
|
||||||
)troff";
|
)troff";
|
||||||
|
|
||||||
|
|
||||||
std::exit(0);
|
std::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,12 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
std::optional<std::string_view> find_documentation_for_builtin(std::string_view builtin_name);
|
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
|
#endif
|
||||||
|
@ -70,6 +70,28 @@ std::optional<std::string_view> find_documentation_for_builtin(std::string_view
|
|||||||
}
|
}
|
||||||
return std::nullopt;
|
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):
|
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"
|
return f"{builtin.implementation}_doc"
|
||||||
|
|
||||||
with open(output_path, "w") as out:
|
with open(output_path, "w") as out:
|
||||||
print("#include <array>", file=out)
|
includes = [
|
||||||
print("#include <musique/interpreter/builtin_function_documentation.hh>\n", file=out)
|
"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
|
# 1. Generate strings with documentation
|
||||||
for builtin in builtins:
|
for builtin in builtins:
|
||||||
|
Loading…
Reference in New Issue
Block a user