Compare commits

..

3 Commits

Author SHA1 Message Date
Robert Bendun
d351b49148 cleared mess in platform.hh 2023-03-04 18:35:46 +01:00
Robert Bendun
4dccde7830 Save history between command invocations 2023-03-04 17:59:33 +01:00
Robert Bendun
ff58e6506d Fix CTRL-C one time use on Windows 2023-03-04 16:39:16 +01:00
9 changed files with 177 additions and 17 deletions

View File

@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- `CTRL-C` handler that turns notes that are playing off
### Changed
- Moved from `bestline` to `replxx` Readline implementation due to lack of Windows support from bestline
## [0.4.0] ## [0.4.0]
### Added ### Added

View File

@ -13,7 +13,7 @@ VERSION := $(MAJOR).$(MINOR).$(PATCH)-dev+$(COMMIT)
CXXFLAGS:=$(CXXFLAGS) -std=c++20 -Wall -Wextra -Werror=switch -Werror=return-type -Werror=unused-result -ggdb CXXFLAGS:=$(CXXFLAGS) -std=c++20 -Wall -Wextra -Werror=switch -Werror=return-type -Werror=unused-result -ggdb
CPPFLAGS:=$(CPPFLAGS) -DMusique_Version='"$(VERSION)"' \ CPPFLAGS:=$(CPPFLAGS) -DMusique_Version='"$(VERSION)"' \
-Ilib/expected/ -I. -Ilib/bestline/ -Ilib/rtmidi/ -Ilib/link/include -Ilib/asio/include/ -Ilib/replxx/include -Ilib/expected/ -I. -Ilib/bestline/ -Ilib/rtmidi/ -Ilib/link/include -Ilib/asio/include/ -Ilib/replxx/include -DREPLXX_STATIC
LDFLAGS=-flto LDFLAGS=-flto
LDLIBS= -lpthread LDLIBS= -lpthread

View File

@ -62,4 +62,11 @@ concept Three_Way_Comparable = requires (T const& lhs, T const& rhs) {
{ lhs <=> rhs }; { lhs <=> rhs };
}; };
template<typename Needle, typename ...Heystack>
requires (std::equality_comparable_with<Needle const&, Heystack const&> && ...)
constexpr bool one_of(Needle const& needle, Heystack const& ...heystack)
{
return ((needle == heystack) || ...);
}
#endif #endif

View File

@ -14,9 +14,11 @@
#include <musique/lexer/lines.hh> #include <musique/lexer/lines.hh>
#include <musique/midi/midi.hh> #include <musique/midi/midi.hh>
#include <musique/parser/parser.hh> #include <musique/parser/parser.hh>
#include <musique/platform.hh>
#include <musique/pretty.hh> #include <musique/pretty.hh>
#include <musique/try.hh> #include <musique/try.hh>
#include <musique/unicode.hh> #include <musique/unicode.hh>
#include <musique/user_directory.hh>
#include <musique/value/block.hh> #include <musique/value/block.hh>
#include <replxx.hxx> #include <replxx.hxx>
@ -225,6 +227,7 @@ struct Runner
} }
} catch (KeyboardInterrupt const&) { } catch (KeyboardInterrupt const&) {
interpreter.turn_off_all_active_notes(); interpreter.turn_off_all_active_notes();
interpreter.starter.stop();
std::cout << std::endl; std::cout << std::endl;
} }
return {}; return {};
@ -250,8 +253,9 @@ void completion(char const* buf, bestlineCompletions *lc)
} }
#endif #endif
bool is_tty() static bool is_tty()
{ {
// Can't use if constexpr since _isatty is not defined on non-windows platforms
#ifdef _WIN32 #ifdef _WIN32
return _isatty(STDOUT_FILENO); return _isatty(STDOUT_FILENO);
#else #else
@ -357,6 +361,16 @@ static Result<bool> handle_repl_session_commands(std::string_view input, Runner
return false; return false;
} }
static Runner *runner;
void sigint_handler(int sig)
{
if (sig == SIGINT) {
runner->interpreter.issue_interrupt();
}
std::signal(SIGINT, sigint_handler);
}
/// 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)
{ {
@ -431,8 +445,9 @@ static std::optional<Error> Main(std::span<char const*> args)
std::exit(1); std::exit(1);
} }
static Runner runner; Runner runner;
std::signal(SIGINT, [](int sig) { if (sig == SIGINT) runner.interpreter.issue_interrupt(); }); ::runner = &runner;
std::signal(SIGINT, sigint_handler);
for (auto const& [type, argument] : runnables) { for (auto const& [type, argument] : runnables) {
if (type == Run::Argument) { if (type == Run::Argument) {
@ -473,13 +488,11 @@ static std::optional<Error> Main(std::span<char const*> args)
replxx::Replxx repl; replxx::Replxx repl;
{ auto const history_path = (user_directory::data_home() / "history").string();
std::ifstream history(".musique_history");
repl.history_load(history);
}
repl.set_max_history_size(2048); repl.set_max_history_size(2048);
repl.set_max_hint_rows(3); repl.set_max_hint_rows(3);
repl.history_load(history_path);
for (;;) { for (;;) {
char const* input = nullptr; char const* input = nullptr;
@ -501,6 +514,7 @@ static std::optional<Error> Main(std::span<char const*> args)
} }
repl.history_add(std::string(command)); repl.history_add(std::string(command));
repl.history_save(history_path);
if (command.starts_with(':')) { if (command.starts_with(':')) {
command.remove_prefix(1); command.remove_prefix(1);

24
musique/platform.hh Normal file
View File

@ -0,0 +1,24 @@
#ifndef MUSIQUE_PLATFORM_HH
#define MUSIQUE_PLATFORM_HH
namespace platform
{
enum class Operating_System
{
MacOS,
Unix,
Windows,
};
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
static constexpr Operating_System os = Operating_System::Windows;
#elif defined(__APPLE__)
static constexpr Operating_System os = Operating_System::MacOS;
#elif defined(__linux__) || defined(__unix__)
static constexpr Operating_System os = Operating_System::Unix;
#else
#error "Unknown platform"
#endif
}
#endif // MUSIQUE_PLATFORM_HH

92
musique/user_directory.cc Normal file
View File

@ -0,0 +1,92 @@
#include <musique/user_directory.hh>
#include <musique/errors.hh>
#include <musique/platform.hh>
static std::filesystem::path home()
{
if constexpr (platform::os == platform::Operating_System::Windows) {
if (auto home = std::getenv("USERPROFILE")) return home;
if (auto drive = std::getenv("HOMEDRIVE")) {
if (auto path = std::getenv("HOMEPATH")) {
return std::string(drive) + path;
}
}
} else {
if (auto home = std::getenv("HOME")) {
return home;
}
}
unreachable();
}
std::filesystem::path user_directory::data_home()
{
std::filesystem::path path;
static_assert(one_of(platform::os,
platform::Operating_System::Unix,
platform::Operating_System::Windows,
platform::Operating_System::MacOS
));
if constexpr (platform::os == platform::Operating_System::Unix) {
if (auto data = std::getenv("XDG_DATA_HOME")) {
path = data;
} else {
path = home() / ".local" / "share";
}
}
if constexpr (platform::os == platform::Operating_System::Windows) {
if (auto data = std::getenv("LOCALAPPDATA")) {
path = data;
} else {
path = home() / "AppData" / "Local";
}
}
if constexpr (platform::os == platform::Operating_System::MacOS) {
path = home() / "Library";
}
path /= "musique";
std::filesystem::create_directories(path);
return path;
}
std::filesystem::path user_directory::config_home()
{
std::filesystem::path path;
static_assert(one_of(platform::os,
platform::Operating_System::Unix,
platform::Operating_System::Windows,
platform::Operating_System::MacOS
));
if constexpr (platform::os == platform::Operating_System::Unix) {
if (auto data = std::getenv("XDG_CONFIG_HOME")) {
path = data;
} else {
path = home() / ".config";
}
}
if constexpr (platform::os == platform::Operating_System::Windows) {
if (auto data = std::getenv("LOCALAPPDATA")) {
path = data;
} else {
path = home() / "AppData" / "Local";
}
}
if constexpr (platform::os == platform::Operating_System::MacOS) {
path = home() / "Library" / "Preferences";
}
path /= "musique";
std::filesystem::create_directories(path);
return path;
}

15
musique/user_directory.hh Normal file
View File

@ -0,0 +1,15 @@
#ifndef MUSIQUE_USER_DIRECTORY_HH
#define MUSIQUE_USER_DIRECTORY_HH
#include <filesystem>
namespace user_directory
{
/// Returns system-specific user directory for data; same as XDG_DATA_HOME
std::filesystem::path data_home();
/// Returns system-specific user directory for config; same as XDG_CONFIG_HOME
std::filesystem::path config_home();
}
#endif // MUSIQUE_USER_DIRECTORY_HH

View File

@ -1,15 +1,15 @@
Release_Obj=$(addprefix bin/$(os)/,$(Obj)) Release_Obj=$(addprefix bin/$(os)/,$(Obj))
bin/$(os)/libreplxx.a: # bin/$(os)/libreplxx.a:
@CXX=$(CXX) os=$(os) scripts/build_replxx.sh # @CXX=$(CXX) os=$(os) scripts/build_replxx.sh
bin/$(os)/%.o: musique/%.cc bin/$(os)/%.o: musique/%.cc
@echo "CXX $@" @echo "CXX $@"
@$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $< -c @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $< -c
bin/$(os)/$(Target): $(Release_Obj) bin/$(os)/main.o bin/$(os)/rtmidi.o bin/$(os)/libreplxx.a bin/$(os)/$(Target): $(Release_Obj) bin/$(os)/main.o bin/$(os)/rtmidi.o
@echo "CXX $@" @echo "CXX $@"
@$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $(Release_Obj) bin/$(os)/rtmidi.o -Lbin/$(os)/ $(LDFLAGS) $(LDLIBS) -lreplxx @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $(shell CXX=$(CXX) os=$(os) scripts/build_replxx.sh) $(Release_Obj) bin/$(os)/rtmidi.o $(LDFLAGS) $(LDLIBS)
Debug_Obj=$(addprefix bin/$(os)/debug/,$(Obj)) Debug_Obj=$(addprefix bin/$(os)/debug/,$(Obj))

View File

@ -8,13 +8,13 @@ mkdir -p "bin/${os}/replxx"
objects="" objects=""
echo "Building libreplxx library archive" find lib/replxx/src/ -name '*.cxx' -o -name '*.cpp' | while read -r src
ar rcs "bin/${os}/libreplxx.a" $(find lib/replxx/src/ -name '*.cxx' -o -name '*.cpp' | while read -r src
do do
dst="${src##"$prefix"}" dst="${src##"$prefix"}"
dst="bin/${os}/replxx/${dst%%.*}.o" dst="bin/${os}/replxx/${dst%%.*}.o"
"${CXX}" -Ilib/replxx/src/ -Ilib/replxx/include/ -c -o "$dst" "$src" -std=c++20 -O3 -DREPLXX_STATIC if [ ! -f "$dst" ]; then
"${CXX}" -Ilib/replxx/src/ -Ilib/replxx/include/ -c -o "$dst" "$src" -std=c++20 -O3 -DREPLXX_STATIC
fi
echo "${dst}" echo "${dst}"
done) done