[hull] Add start on command interpreter
This commit is contained in:
@ -19,6 +19,9 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(applib)
|
add_subdirectory(applib)
|
||||||
|
if(NOT APPLE)
|
||||||
|
add_subdirectory(hull)
|
||||||
|
endif()
|
||||||
add_subdirectory(keel)
|
add_subdirectory(keel)
|
||||||
add_subdirectory(turbine)
|
add_subdirectory(turbine)
|
||||||
if(${OLYMPIC_BUILD_STUDIO})
|
if(${OLYMPIC_BUILD_STUDIO})
|
||||||
|
12
src/olympic/hull/CMakeLists.txt
Normal file
12
src/olympic/hull/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
add_library(Hull)
|
||||||
|
target_sources(
|
||||||
|
Hull PUBLIC
|
||||||
|
FILE_SET CXX_MODULES FILES
|
||||||
|
hull.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
Hull PUBLIC
|
||||||
|
OxStd
|
||||||
|
)
|
98
src/olympic/hull/hull.cpp
Normal file
98
src/olympic/hull/hull.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module;
|
||||||
|
|
||||||
|
#include <ox/std/string.hpp>
|
||||||
|
|
||||||
|
export module hull;
|
||||||
|
|
||||||
|
namespace hull {
|
||||||
|
|
||||||
|
export
|
||||||
|
template<typename Str = ox::String, size_t SmallVecSz = 0>
|
||||||
|
constexpr ox::Result<ox::Vector<Str, SmallVecSz>> parseCmd(ox::StringViewCR cmd) noexcept
|
||||||
|
requires(ox::is_same_v<Str, ox::String> || ox::is_same_v<Str, ox::StringView>) {
|
||||||
|
auto const tokens = split(cmd, ' ');
|
||||||
|
ox::Vector<Str, SmallVecSz> args;
|
||||||
|
char waitingFor{};
|
||||||
|
auto const handleString = [&waitingFor, &args](
|
||||||
|
ox::StringViewCR token,
|
||||||
|
char const delimiter) {
|
||||||
|
if (endsWith(token, delimiter)) {
|
||||||
|
args.emplace_back(substr(token, 1, token.size() - 1));
|
||||||
|
} else {
|
||||||
|
waitingFor = delimiter;
|
||||||
|
args.emplace_back(substr(token, 1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (auto const &token : tokens) {
|
||||||
|
if (waitingFor) {
|
||||||
|
if (endsWith(token, waitingFor)) {
|
||||||
|
waitingFor = 0;
|
||||||
|
}
|
||||||
|
auto &tgt = *args.back().value;
|
||||||
|
if constexpr (ox::is_same_v<Str, ox::String>) {
|
||||||
|
tgt += substr(token, 0, token.size() - 1);
|
||||||
|
} else {
|
||||||
|
tgt = {tgt.data(), tgt.size() + token.size() - 1};
|
||||||
|
}
|
||||||
|
} else if (beginsWith(token, '"')) {
|
||||||
|
handleString(token, '"');
|
||||||
|
} else if (beginsWith(token, '\'')) {
|
||||||
|
handleString(token, '\'');
|
||||||
|
} else {
|
||||||
|
args.emplace_back(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (waitingFor) {
|
||||||
|
return ox::Error{1, "unterminated string"};
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Str = ox::String>
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr bool testParse(ox::StringViewCR cmd, std::initializer_list<ox::StringView> const &expected) noexcept {
|
||||||
|
auto const [args, err] = parseCmd<Str>(cmd);
|
||||||
|
static constexpr auto equals = [](auto const &a, auto const &b) {
|
||||||
|
if (a.size() != b.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto i = 0u; i < a.size(); ++i) {
|
||||||
|
if (a[i] != b[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
return !err && equals(args, ox::Vector(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(testParse("echo asdf", {"echo", "asdf"}));
|
||||||
|
static_assert(testParse<ox::String>("echo asdf", {"echo", "asdf"}));
|
||||||
|
|
||||||
|
static_assert(testParse("echo \"asdf\"", {"echo", "asdf"}));
|
||||||
|
static_assert(testParse<ox::String>("echo \"asdf\"", {"echo", "asdf"}));
|
||||||
|
|
||||||
|
static_assert(testParse("echo 'asdf'", {"echo", "asdf"}));
|
||||||
|
static_assert(testParse<ox::String>("echo 'asdf'", {"echo", "asdf"}));
|
||||||
|
|
||||||
|
static_assert(testParse("echo 'asdf' aoue", {"echo", "asdf", "aoue"}));
|
||||||
|
static_assert(testParse<ox::String>("echo 'asdf' aoue", {"echo", "asdf", "aoue"}));
|
||||||
|
|
||||||
|
export class Prompt {
|
||||||
|
|
||||||
|
private:
|
||||||
|
ox::String m_cmd;
|
||||||
|
ox::String m_workingDir{"/"};
|
||||||
|
ox::Vector<ox::String> m_prevCmds;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user