New parameter passing convention
With suggestions on wrong parameter names
This commit is contained in:
parent
deabd1865a
commit
aaf6e6ec0c
@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Builtin documentation for builtin functions display from repl and command line
|
||||||
|
- Suggestions which command line parameters user may wanted to use
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- New parameter passing convention for command line invocation. `musique help` to learn how it changed
|
||||||
|
|
||||||
## [0.4.0]
|
## [0.4.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
5
lib/edit_distance.cc/.gitignore
vendored
Normal file
5
lib/edit_distance.cc/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
test
|
||||||
|
test.cc
|
||||||
|
Makefile
|
||||||
|
.cache
|
||||||
|
compile_commands.json
|
19
lib/edit_distance.cc/LICENSE
Normal file
19
lib/edit_distance.cc/LICENSE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2023 Robert Bendun
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
76
lib/edit_distance.cc/edit_distance.hh
Normal file
76
lib/edit_distance.cc/edit_distance.hh
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2023 Robert Bendun <robert@bendun.cc>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <concepts>
|
||||||
|
#include <iterator>
|
||||||
|
#include <numeric>
|
||||||
|
#include <ranges>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<std::random_access_iterator S, std::random_access_iterator T>
|
||||||
|
requires std::equality_comparable_with<
|
||||||
|
std::iter_value_t<S>,
|
||||||
|
std::iter_value_t<T>
|
||||||
|
>
|
||||||
|
constexpr int edit_distance(S s, unsigned m, T t, unsigned n)
|
||||||
|
{
|
||||||
|
std::array<std::vector<int>, 2> memo;
|
||||||
|
auto *v0 = &memo[0];
|
||||||
|
auto *v1 = &memo[1];
|
||||||
|
|
||||||
|
for (auto& v : memo) {
|
||||||
|
v.resize(n+1);
|
||||||
|
}
|
||||||
|
std::iota(v0->begin(), v0->end(), 0);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < m; ++i) {
|
||||||
|
(*v1)[0] = i+1;
|
||||||
|
for (auto j = 0u; j < n; ++j) {
|
||||||
|
auto const deletion_cost = (*v0)[j+1] + 1;
|
||||||
|
auto const insertion_cost = (*v1)[j] + 1;
|
||||||
|
auto const substitution_cost = (*v0)[j] + (s[i] != t[j]);
|
||||||
|
|
||||||
|
(*v1)[j+1] = std::min({ deletion_cost, insertion_cost, substitution_cost });
|
||||||
|
}
|
||||||
|
std::swap(v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*v0)[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
std::ranges::random_access_range Range1,
|
||||||
|
std::ranges::random_access_range Range2
|
||||||
|
>
|
||||||
|
requires std::equality_comparable_with<
|
||||||
|
std::ranges::range_value_t<Range1>,
|
||||||
|
std::ranges::range_value_t<Range2>
|
||||||
|
>
|
||||||
|
constexpr int edit_distance(Range1 const& range1, Range2 const& range2)
|
||||||
|
{
|
||||||
|
return edit_distance(
|
||||||
|
std::begin(range1), std::ranges::size(range1),
|
||||||
|
std::begin(range2), std::ranges::size(range2)
|
||||||
|
);
|
||||||
|
}
|
179
musique/cmd.cc
Normal file
179
musique/cmd.cc
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <edit_distance.hh>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <musique/cmd.hh>
|
||||||
|
#include <musique/common.hh>
|
||||||
|
#include <musique/interpreter/builtin_function_documentation.hh>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
extern "C" {
|
||||||
|
#include <io.h>
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using Empty_Argument = void(*)();
|
||||||
|
using Requires_Argument = void(*)(std::string_view);
|
||||||
|
using Defines_Code = cmd::Run(*)(std::string_view);
|
||||||
|
using Parameter = std::variant<Empty_Argument, Requires_Argument, Defines_Code>;
|
||||||
|
|
||||||
|
using namespace cmd;
|
||||||
|
|
||||||
|
// from musique/main.cc:
|
||||||
|
extern bool enable_repl;
|
||||||
|
extern bool ast_only_mode;
|
||||||
|
extern void usage();
|
||||||
|
|
||||||
|
static constexpr std::array all_parameters = [] {
|
||||||
|
Defines_Code provide_function = [](std::string_view fname) -> cmd::Run {
|
||||||
|
return { .type = Run::Deffered_File, .argument = fname };
|
||||||
|
};
|
||||||
|
|
||||||
|
Defines_Code provide_inline_code = [](std::string_view code) -> cmd::Run {
|
||||||
|
return { .type = Run::Argument, .argument = code };
|
||||||
|
};
|
||||||
|
|
||||||
|
Defines_Code provide_file = [](std::string_view fname) -> cmd::Run {
|
||||||
|
return { .type = Run::File, .argument = fname };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Requires_Argument show_docs = [](std::string_view builtin) {
|
||||||
|
if (auto maybe_docs = find_documentation_for_builtin(builtin); maybe_docs) {
|
||||||
|
std::cout << *maybe_docs << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "musique: error: cannot find documentation for given builtin" << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
Empty_Argument set_interactive_mode = [] { enable_repl = true; };
|
||||||
|
Empty_Argument set_ast_only_mode = [] { ast_only_mode = true; };
|
||||||
|
|
||||||
|
Empty_Argument print_version = [] { std::cout << Musique_Version << std::endl; };
|
||||||
|
Empty_Argument print_help = usage;
|
||||||
|
|
||||||
|
using Entry = std::pair<std::string_view, Parameter>;
|
||||||
|
|
||||||
|
// First entry for given action type should always be it's cannonical name
|
||||||
|
return std::array {
|
||||||
|
Entry { "fun", provide_function },
|
||||||
|
Entry { "def", provide_function },
|
||||||
|
Entry { "f", provide_function },
|
||||||
|
Entry { "func", provide_function },
|
||||||
|
Entry { "function", provide_function },
|
||||||
|
|
||||||
|
Entry { "run", provide_file },
|
||||||
|
Entry { "r", provide_file },
|
||||||
|
Entry { "exec", provide_file },
|
||||||
|
|
||||||
|
Entry { "repl", set_interactive_mode },
|
||||||
|
Entry { "i", set_interactive_mode },
|
||||||
|
Entry { "interactive", set_interactive_mode },
|
||||||
|
|
||||||
|
Entry { "doc", show_docs },
|
||||||
|
Entry { "d", show_docs },
|
||||||
|
Entry { "docs", show_docs },
|
||||||
|
|
||||||
|
Entry { "inline", provide_inline_code },
|
||||||
|
Entry { "c", provide_inline_code },
|
||||||
|
Entry { "code", provide_inline_code },
|
||||||
|
|
||||||
|
Entry { "help", print_help },
|
||||||
|
Entry { "?", print_help },
|
||||||
|
Entry { "/?", print_help },
|
||||||
|
Entry { "h", print_help },
|
||||||
|
|
||||||
|
Entry { "version", print_version },
|
||||||
|
Entry { "v", print_version },
|
||||||
|
|
||||||
|
Entry { "ast", set_ast_only_mode },
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
bool cmd::accept_commandline_argument(std::vector<cmd::Run> &runnables, std::span<char const*> &args)
|
||||||
|
{
|
||||||
|
if (args.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto const& [name, handler] : all_parameters) {
|
||||||
|
// TODO Parameters starting with - or -- should be considered equal
|
||||||
|
if (name != args.front()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
args = args.subspan(1);
|
||||||
|
std::visit(Overloaded {
|
||||||
|
[](Empty_Argument const& h) {
|
||||||
|
h();
|
||||||
|
},
|
||||||
|
[&args, name=name](Requires_Argument const& h) {
|
||||||
|
if (args.empty()) {
|
||||||
|
std::cerr << "musique: error: option " << std::quoted(name) << " requires an argument" << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
h(args.front());
|
||||||
|
args = args.subspan(1);
|
||||||
|
},
|
||||||
|
[&, name=name](Defines_Code const& h) {
|
||||||
|
if (args.empty()) {
|
||||||
|
std::cerr << "musique: error: option " << std::quoted(name) << " requires an argument" << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
runnables.push_back(h(args.front()));
|
||||||
|
args = args.subspan(1);
|
||||||
|
}
|
||||||
|
}, handler);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cmd::print_close_matches(std::string_view arg)
|
||||||
|
{
|
||||||
|
auto minimum_distance = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
std::array<typename decltype(all_parameters)::value_type, 3> closest;
|
||||||
|
|
||||||
|
std::partial_sort_copy(
|
||||||
|
all_parameters.begin(), all_parameters.end(),
|
||||||
|
closest.begin(), closest.end(),
|
||||||
|
[&minimum_distance, arg](auto const& lhs, auto const& rhs) {
|
||||||
|
auto const lhs_score = edit_distance(arg, lhs.first);
|
||||||
|
auto const rhs_score = edit_distance(arg, rhs.first);
|
||||||
|
minimum_distance = std::min({ minimum_distance, lhs_score, rhs_score });
|
||||||
|
return lhs_score < rhs_score;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
std::cout << "The most similar commands are:\n";
|
||||||
|
std::unordered_set<void*> shown;
|
||||||
|
if (minimum_distance <= 3) {
|
||||||
|
for (auto const& [ name, handler ] : closest) {
|
||||||
|
auto const handler_p = std::visit([](auto *v) { return reinterpret_cast<void*>(v); }, handler);
|
||||||
|
if (!shown.contains(handler_p)) {
|
||||||
|
std::cout << " " << name << std::endl;
|
||||||
|
shown.insert(handler_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cmd::is_tty()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return _isatty(STDOUT_FILENO);
|
||||||
|
#else
|
||||||
|
return isatty(fileno(stdout));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
35
musique/cmd.hh
Normal file
35
musique/cmd.hh
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef MUSIQUE_CMD_HH
|
||||||
|
#define MUSIQUE_CMD_HH
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
#include <string_view>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace cmd
|
||||||
|
{
|
||||||
|
/// Describes all arguments that will be run
|
||||||
|
struct Run
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
File,
|
||||||
|
Argument,
|
||||||
|
Deffered_File
|
||||||
|
} type;
|
||||||
|
|
||||||
|
std::string_view argument;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Accept and execute next command line argument with its parameters if it has any
|
||||||
|
bool accept_commandline_argument(std::vector<cmd::Run> &runnables, std::span<char const*> &args);
|
||||||
|
|
||||||
|
/// Print all arguments that are similar to one provided
|
||||||
|
void print_close_matches(std::string_view arg);
|
||||||
|
|
||||||
|
/// Recognize if stdout is connected to terminal
|
||||||
|
bool is_tty();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MUSIQUE_CMD_HH
|
||||||
|
|
145
musique/main.cc
145
musique/main.cc
@ -1,13 +1,13 @@
|
|||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <edit_distance.hh>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <span>
|
#include <musique/cmd.hh>
|
||||||
#include <thread>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include <musique/format.hh>
|
#include <musique/format.hh>
|
||||||
|
#include <musique/interpreter/builtin_function_documentation.hh>
|
||||||
#include <musique/interpreter/env.hh>
|
#include <musique/interpreter/env.hh>
|
||||||
#include <musique/interpreter/interpreter.hh>
|
#include <musique/interpreter/interpreter.hh>
|
||||||
#include <musique/lexer/lines.hh>
|
#include <musique/lexer/lines.hh>
|
||||||
@ -17,14 +17,11 @@
|
|||||||
#include <musique/try.hh>
|
#include <musique/try.hh>
|
||||||
#include <musique/unicode.hh>
|
#include <musique/unicode.hh>
|
||||||
#include <musique/value/block.hh>
|
#include <musique/value/block.hh>
|
||||||
#include <musique/interpreter/builtin_function_documentation.hh>
|
#include <span>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifndef _WIN32
|
||||||
extern "C" {
|
|
||||||
#include <io.h>
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <bestline.h>
|
#include <bestline.h>
|
||||||
}
|
}
|
||||||
@ -32,36 +29,12 @@ extern "C" {
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static bool quiet_mode = false;
|
bool ast_only_mode = false;
|
||||||
static bool ast_only_mode = false;
|
bool enable_repl = false;
|
||||||
static bool enable_repl = false;
|
|
||||||
static unsigned repl_line_number = 1;
|
static unsigned repl_line_number = 1;
|
||||||
|
|
||||||
#define Ignore(Call) do { auto const ignore_ ## __LINE__ = (Call); (void) ignore_ ## __LINE__; } while(0)
|
#define Ignore(Call) do { auto const ignore_ ## __LINE__ = (Call); (void) ignore_ ## __LINE__; } while(0)
|
||||||
|
|
||||||
/// Pop string from front of an array
|
|
||||||
template<typename T = std::string_view>
|
|
||||||
static T pop(std::span<char const*> &span)
|
|
||||||
{
|
|
||||||
auto element = span.front();
|
|
||||||
span = span.subspan(1);
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, std::string_view>) {
|
|
||||||
return element;
|
|
||||||
} else if constexpr (std::is_arithmetic_v<T>) {
|
|
||||||
T result;
|
|
||||||
auto end = element + std::strlen(element);
|
|
||||||
auto [ptr, ec] = std::from_chars(element, end, result);
|
|
||||||
if (ec != decltype(ec){}) {
|
|
||||||
std::cout << "Expected natural number as argument" << std::endl;
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
static_assert(always_false<T>, "Unsupported type for pop operation");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Print usage and exit
|
/// Print usage and exit
|
||||||
[[noreturn]] void usage()
|
[[noreturn]] void usage()
|
||||||
{
|
{
|
||||||
@ -246,15 +219,6 @@ void completion(char const* buf, bestlineCompletions *lc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool is_tty()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
return _isatty(STDOUT_FILENO);
|
|
||||||
#else
|
|
||||||
return isatty(fileno(stdout));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handles commands inside REPL session (those starting with ':')
|
/// Handles commands inside REPL session (those starting with ':')
|
||||||
///
|
///
|
||||||
/// Returns if one of command matched
|
/// Returns if one of command matched
|
||||||
@ -353,98 +317,43 @@ static Result<bool> handle_repl_session_commands(std::string_view input, Runner
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Fancy main that supports Result forwarding on error (Try macro)
|
/// Fancy main that supports Result forwarding on error (Try macro)
|
||||||
static std::optional<Error> Main(std::span<char const*> args)
|
static std::optional<Error> Main(std::span<char const*> args)
|
||||||
{
|
{
|
||||||
if (is_tty() && getenv("NO_COLOR") == nullptr) {
|
if (cmd::is_tty() && getenv("NO_COLOR") == nullptr) {
|
||||||
pretty::terminal_mode();
|
pretty::terminal_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes all arguments that will be run
|
|
||||||
struct Run
|
|
||||||
{
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
File,
|
|
||||||
Argument,
|
|
||||||
Deffered_File
|
|
||||||
} type;
|
|
||||||
std::string_view argument;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Run> runnables;
|
std::vector<cmd::Run> runnables;
|
||||||
|
|
||||||
while (not args.empty()) {
|
|
||||||
std::string_view arg = pop(args);
|
|
||||||
|
|
||||||
if (arg == "-" || !arg.starts_with('-')) {
|
for (;;) if (!cmd::accept_commandline_argument(runnables, args)) {
|
||||||
runnables.push_back({ .type = Run::File, .argument = std::move(arg) });
|
if (args.size()) {
|
||||||
continue;
|
std::cerr << "musique: error: Failed to recognize parameter " << std::quoted(args.front()) << std::endl;
|
||||||
|
cmd::print_close_matches(args.front());
|
||||||
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (arg == "-c" || arg == "--run") {
|
/*
|
||||||
if (args.empty()) {
|
|
||||||
std::cerr << "musique: error: option " << arg << " requires an argument" << std::endl;
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
runnables.push_back({ .type = Run::Argument, .argument = pop(args) });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg == "-f" || arg == "--as-function") {
|
|
||||||
if (args.empty()) {
|
|
||||||
std::cerr << "musique: error: option " << arg << " requires an argument" << std::endl;
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
runnables.push_back({ .type = Run::Deffered_File, .argument = pop(args) });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg == "--quiet" || arg == "-q") {
|
|
||||||
quiet_mode = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg == "--ast") {
|
if (arg == "--ast") {
|
||||||
ast_only_mode = true;
|
ast_only_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg == "--repl" || arg == "-I" || arg == "--interactive") {
|
|
||||||
enable_repl = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg == "--version" || arg == "-v") {
|
if (arg == "--version" || arg == "-v") {
|
||||||
std::cout << Musique_Version << std::endl;
|
std::cout << Musique_Version << std::endl;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (arg == "--doc" || arg == "-d") {
|
|
||||||
if (args.empty()) {
|
|
||||||
std::cerr << "musique: error: option " << arg << " requires an argument" << std::endl;
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
if (auto maybe_docs = find_documentation_for_builtin(pop(args)); maybe_docs) {
|
|
||||||
std::cout << *maybe_docs << std::endl;
|
|
||||||
return {};
|
|
||||||
} else {
|
|
||||||
std::cerr << "musique: error: cannot find documentation for given builtin" << std::endl;
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg == "-h" || arg == "--help") {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cerr << "musique: error: unrecognized command line option: " << arg << std::endl;
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Runner runner;
|
Runner runner;
|
||||||
|
|
||||||
for (auto const& [type, argument] : runnables) {
|
for (auto const& [type, argument] : runnables) {
|
||||||
if (type == Run::Argument) {
|
if (type == cmd::Run::Argument) {
|
||||||
Lines::the.add_line("<arguments>", argument, repl_line_number);
|
Lines::the.add_line("<arguments>", argument, repl_line_number);
|
||||||
Try(runner.run(argument, "<arguments>"));
|
Try(runner.run(argument, "<arguments>"));
|
||||||
repl_line_number++;
|
repl_line_number++;
|
||||||
@ -463,7 +372,7 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Lines::the.add_file(std::string(path), eternal_sources.back());
|
Lines::the.add_file(std::string(path), eternal_sources.back());
|
||||||
if (type == Run::File) {
|
if (type == cmd::Run::File) {
|
||||||
Try(runner.run(eternal_sources.back(), path));
|
Try(runner.run(eternal_sources.back(), path));
|
||||||
} else {
|
} else {
|
||||||
Try(runner.deffered_file(eternal_sources.back(), argument));
|
Try(runner.deffered_file(eternal_sources.back(), argument));
|
||||||
@ -471,8 +380,8 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
enable_repl = enable_repl || std::all_of(runnables.begin(), runnables.end(),
|
enable_repl = enable_repl || std::all_of(runnables.begin(), runnables.end(),
|
||||||
[](Run const& run) {
|
[](cmd::Run const& run) {
|
||||||
return run.type == Run::Deffered_File;
|
return run.type == cmd::Run::Deffered_File;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (runnables.empty() || enable_repl) {
|
if (runnables.empty() || enable_repl) {
|
||||||
|
Loading…
Reference in New Issue
Block a user