Browse Source

Fixes #434 : added possibility to add custom commands in menu item juCi++, Commands

merge-requests/404/merge
eidheim 5 years ago
parent
commit
c2eff0a40c
  1. 2
      CMakeLists.txt
  2. 8
      README.md
  3. 1
      src/CMakeLists.txt
  4. 53
      src/commands.cpp
  5. 29
      src/commands.hpp
  6. 3
      src/compile_commands.cpp
  7. 1
      src/debug_lldb.cpp
  8. 2
      src/directories.cpp
  9. 1
      src/files.hpp
  10. 10
      src/filesystem.cpp
  11. 2
      src/filesystem.hpp
  12. 4
      src/menu.cpp
  13. 82
      src/project.cpp
  14. 6
      src/project.hpp
  15. 4
      src/source.cpp
  16. 97
      src/window.cpp
  17. 8
      tests/filesystem_test.cpp
  18. 4
      tests/stubs/project.cpp

2
CMakeLists.txt

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(juci)
set(JUCI_VERSION "1.6.3")
set(JUCI_VERSION "1.6.3.1")
set(CPACK_PACKAGE_NAME "jucipp")
set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim <eidheim@gmail.com>")

8
README.md

@ -11,6 +11,10 @@ IDE is instead integrated directly into juCi++.
For effective development, juCi++ is primarily written for Unix/Linux systems. However, Windows
users can use juCi++ through POSIX compatibility layers such as MSYS2.
## Installation
See [installation guide](docs/install.md).
## Features
- Platform independent
@ -76,10 +80,6 @@ for planned features.
</tr>
</table>
## Installation
See [installation guide](docs/install.md).
## Custom styling
See [custom styling](docs/custom_styling.md).

1
src/CMakeLists.txt

@ -2,6 +2,7 @@
set(JUCI_SHARED_FILES
autocomplete.cpp
cmake.cpp
commands.cpp
compile_commands.cpp
ctags.cpp
dispatcher.cpp

53
src/commands.cpp

@ -0,0 +1,53 @@
#include "commands.hpp"
#include "config.hpp"
#include "filesystem.hpp"
#include "terminal.hpp"
#include <boost/property_tree/json_parser.hpp>
void Commands::load() {
auto commands_file = Config::get().home_juci_path / "commands.json";
boost::system::error_code ec;
if(!boost::filesystem::exists(commands_file, ec))
filesystem::write(commands_file, R"([
{
"key": "<primary><shift>1",
"path_comment": "Regular expression for which paths this command should apply",
"path": "^.*\\.json$",
"compile_comment": "Add compile command if a compilation step is needed prior to the run command. <path_match> is set to the matching file or directory, and <working_directory> is set to the project directory if found or the matching file's directory.",
"compile": "",
"run_comment": "<path_match> is set to the matching file or directory, and <working_directory> is set to the project directory if found or the matching file's directory",
"run": "echo <path_match> && echo <working_directory>",
"debug_comment": "Whether or not this command should run through debugger",
"debug": false,
"debug_remote_host": ""
}
]
)");
commands.clear();
try {
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(commands_file.string(), pt);
for(auto command_it = pt.begin(); command_it != pt.end(); ++command_it) {
auto key_string = command_it->second.get<std::string>("key");
guint key = 0;
GdkModifierType modifier = static_cast<GdkModifierType>(0);
if(!key_string.empty()) {
gtk_accelerator_parse(key_string.c_str(), &key, &modifier);
if(key == 0 && modifier == 0)
Terminal::get().async_print("\e[31mError\e[m: could not parse key string: " + key_string + "\n", true);
}
auto path = command_it->second.get<std::string>("path", "");
boost::optional<std::regex> regex;
if(!path.empty())
regex = std::regex(path, std::regex::optimize);
commands.emplace_back(Command{key, modifier, std::move(regex),
command_it->second.get<std::string>("compile", ""), command_it->second.get<std::string>("run"),
command_it->second.get<bool>("debug", false), command_it->second.get<std::string>("debug_remote_host", "")});
}
}
catch(const std::exception &e) {
Terminal::get().async_print(std::string("\e[31mError\e[m: ") + e.what() + "\n", true);
}
}

29
src/commands.hpp

@ -0,0 +1,29 @@
#pragma once
#include <boost/optional.hpp>
#include <gdk/gdk.h>
#include <regex>
#include <string>
#include <vector>
class Commands {
public:
class Command {
public:
guint key;
GdkModifierType modifier;
boost::optional<std::regex> path;
std::string compile;
std::string run;
bool debug;
std::string debug_remote_host;
};
static Commands &get() {
static Commands instance;
return instance;
}
std::vector<Command> commands;
void load();
};

3
src/compile_commands.cpp

@ -1,6 +1,7 @@
#include "compile_commands.hpp"
#include "clangmm.hpp"
#include "config.hpp"
#include "filesystem.hpp"
#include "terminal.hpp"
#include "utility.hpp"
#include <algorithm>
@ -107,7 +108,7 @@ CompileCommands::CompileCommands(const boost::filesystem::path &build_path) {
if(parameter_start_pos != std::string::npos)
add_parameter();
commands.emplace_back(Command{directory, parameters, boost::filesystem::absolute(file, build_path)});
commands.emplace_back(Command{directory, parameters, filesystem::get_absolute_path(file, build_path)});
}
}
catch(...) {

1
src/debug_lldb.cpp

@ -129,6 +129,7 @@ void Debug::LLDB::start(const std::string &command, const boost::filesystem::pat
argv.emplace_back(argument.c_str());
argv.emplace_back(nullptr);
executable = filesystem::get_absolute_path(executable, path).string();
auto target = debugger->CreateTarget(executable.c_str());
if(!target.IsValid()) {
Terminal::get().async_print("\e[31mError (debug)\e[m: Could not create debug target to: " + executable + '\n', true);

2
src/directories.cpp

@ -438,7 +438,7 @@ Directories::Directories() : Gtk::ListViewText(1) {
return;
Gtk::MessageDialog dialog(*static_cast<Gtk::Window *>(get_toplevel()), "Delete!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
dialog.set_default_response(Gtk::RESPONSE_NO);
dialog.set_secondary_text("Are you sure you want to delete " + menu_popup_row_path.string() + "?");
dialog.set_secondary_text("Are you sure you want to delete " + filesystem::get_short_path(menu_popup_row_path).string() + "?");
int result = dialog.run();
if(result == Gtk::RESPONSE_YES) {
boost::system::error_code ec;

1
src/files.hpp

@ -126,6 +126,7 @@ const std::string default_config_file =
"keybindings": {
"preferences": "<primary>comma",
"snippets": "",
"commands": "",
"quit": "<primary>q",
"file_new_file": "<primary>n",
"file_new_folder": "<primary><shift>n",

10
src/filesystem.cpp

@ -233,6 +233,16 @@ boost::filesystem::path filesystem::get_relative_path(const boost::filesystem::p
return relative_path;
}
boost::filesystem::path filesystem::get_absolute_path(const boost::filesystem::path &path, const boost::filesystem::path &base) noexcept {
boost::filesystem::path absolute_path;
for(auto path_it = path.begin(); path_it != path.end(); ++path_it) {
if(path_it == path.begin() && (!path.has_root_path() && *path_it != "~"))
absolute_path /= base;
absolute_path /= *path_it;
}
return absolute_path;
}
boost::filesystem::path filesystem::get_executable(const boost::filesystem::path &executable_name) noexcept {
#if defined(__APPLE__) || defined(_WIN32)
return executable_name;

2
src/filesystem.hpp

@ -35,6 +35,8 @@ public:
static boost::filesystem::path get_relative_path(const boost::filesystem::path &path, const boost::filesystem::path &base) noexcept;
static boost::filesystem::path get_absolute_path(const boost::filesystem::path &path, const boost::filesystem::path &base) noexcept;
/// Return executable with latest version in filename on systems that is lacking executable_name symbolic link
static boost::filesystem::path get_executable(const boost::filesystem::path &executable_name) noexcept;

4
src/menu.cpp

@ -104,6 +104,10 @@ const Glib::ustring menu_xml = R"RAW(<interface>
<attribute name='label' translatable='yes'>_Snippets</attribute>
<attribute name='action'>app.snippets</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Commands</attribute>
<attribute name='action'>app.commands</attribute>
</item>
</section>
<section>
<item>

82
src/project.cpp

@ -1,4 +1,5 @@
#include "project.hpp"
#include "commands.hpp"
#include "config.hpp"
#include "directories.hpp"
#include "filesystem.hpp"
@ -72,6 +73,9 @@ void Project::on_save(size_t index) {
view->set_snippets();
}
if(view->file_path == Config::get().home_juci_path / "commands.json")
Commands::get().load();
boost::filesystem::path build_path;
if(view->language && view->language->get_id() == "cmake") {
if(view->file_path.filename() == "CMakeLists.txt")
@ -259,8 +263,13 @@ std::pair<std::string, std::string> Project::Base::debug_get_run_arguments() {
return {"", ""};
}
void Project::Base::debug_start() {
void Project::Base::debug_compile_and_start() {
Info::get().print("Could not find a supported project");
}
void Project::Base::debug_start(const std::string &command, const boost::filesystem::path &path, const std::string &remote_host) {
Info::get().print("Could not find a supported project");
Project::debugging = false;
}
#ifdef JUCI_ENABLE_DEBUG
@ -336,7 +345,7 @@ Project::DebugOptions *Project::LLDB::debug_get_options() {
return debug_options.get();
}
void Project::LLDB::debug_start() {
void Project::LLDB::debug_compile_and_start() {
auto default_build_path = build->get_default_path();
if(default_build_path.empty() || !build->update_default())
return;
@ -344,17 +353,19 @@ void Project::LLDB::debug_start() {
if(debug_build_path.empty() || !build->update_debug())
return;
auto project_path = std::make_shared<boost::filesystem::path>(build->project_path);
auto run_arguments_it = debug_run_arguments.find(project_path->string());
auto run_arguments = std::make_shared<std::string>();
if(run_arguments_it != debug_run_arguments.end())
*run_arguments = run_arguments_it->second.arguments;
auto run_arguments_it = debug_run_arguments.find(build->project_path.string());
std::string run_arguments;
std::string remote_host;
if(run_arguments_it != debug_run_arguments.end()) {
run_arguments = run_arguments_it->second.arguments;
if(run_arguments_it->second.remote_enabled)
remote_host = run_arguments_it->second.remote_host_port;
}
if(run_arguments->empty()) {
if(run_arguments.empty()) {
auto view = Notebook::get().get_current_view();
*run_arguments = build->get_executable(view ? view->file_path : Directories::get().path).string();
if(run_arguments->empty()) {
run_arguments = build->get_executable(view ? view->file_path : Directories::get().path).string();
if(run_arguments.empty()) {
if(!build->is_valid())
Terminal::get().print("\e[31mError\e[m: build folder no longer valid, please rebuild project.\n", true);
else {
@ -363,10 +374,10 @@ void Project::LLDB::debug_start() {
}
return;
}
size_t pos = run_arguments->find(default_build_path.string());
size_t pos = run_arguments.find(default_build_path.string());
if(pos != std::string::npos)
run_arguments->replace(pos, default_build_path.string().size(), debug_build_path.string());
*run_arguments = filesystem::escape_argument(filesystem::get_short_path(*run_arguments).string());
run_arguments.replace(pos, default_build_path.string().size(), debug_build_path.string());
run_arguments = filesystem::escape_argument(filesystem::get_short_path(run_arguments).string());
}
debugging = true;
@ -374,15 +385,21 @@ void Project::LLDB::debug_start() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mCompiling and debugging " + *run_arguments + "\e[m\n");
Terminal::get().async_process(build->get_compile_command(), debug_build_path, [self = this->shared_from_this(), run_arguments, project_path](int exit_status) {
Terminal::get().print("\e[2mCompiling and debugging: " + run_arguments + "\e[m\n");
Terminal::get().async_process(build->get_compile_command(), debug_build_path, [self = this->shared_from_this(), run_arguments, project_path = build->project_path, remote_host](int exit_status) {
if(exit_status != EXIT_SUCCESS)
debugging = false;
else {
self->debug_start(run_arguments, project_path, remote_host);
}
});
}
void Project::LLDB::debug_start(const std::string &command, const boost::filesystem::path &path, const std::string &remote_host) {
std::vector<std::pair<boost::filesystem::path, int>> breakpoints;
for(size_t c = 0; c < Notebook::get().size(); c++) {
auto view = Notebook::get().get_view(c);
if(filesystem::file_in_path(view->file_path, *project_path)) {
if(filesystem::file_in_path(view->file_path, path)) {
auto iter = view->get_buffer()->begin();
if(view->get_source_buffer()->get_source_marks_at_iter(iter, "debug_breakpoint").size() > 0)
breakpoints.emplace_back(view->file_path, iter.get_line() + 1);
@ -391,17 +408,12 @@ void Project::LLDB::debug_start() {
}
}
std::string remote_host;
auto debug_run_arguments_it = debug_run_arguments.find(project_path->string());
if(debug_run_arguments_it != debug_run_arguments.end() && debug_run_arguments_it->second.remote_enabled)
remote_host = debug_run_arguments_it->second.remote_host_port;
static auto on_exit_it = Debug::LLDB::get().on_exit.end();
if(on_exit_it != Debug::LLDB::get().on_exit.end())
Debug::LLDB::get().on_exit.erase(on_exit_it);
Debug::LLDB::get().on_exit.emplace_back([self, run_arguments](int exit_status) {
Debug::LLDB::get().on_exit.emplace_back([self = shared_from_this(), command](int exit_status) {
debugging = false;
Terminal::get().async_print("\e[2m" + *run_arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
Terminal::get().async_print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
self->dispatcher.post([] {
debug_update_status("");
});
@ -411,7 +423,7 @@ void Project::LLDB::debug_start() {
static auto on_event_it = Debug::LLDB::get().on_event.end();
if(on_event_it != Debug::LLDB::get().on_event.end())
Debug::LLDB::get().on_event.erase(on_event_it);
Debug::LLDB::get().on_event.emplace_back([self](const lldb::SBEvent &event) {
Debug::LLDB::get().on_event.emplace_back([self = shared_from_this()](const lldb::SBEvent &event) {
std::string status;
boost::filesystem::path stop_path;
unsigned stop_line = 0, stop_column = 0;
@ -468,7 +480,7 @@ void Project::LLDB::debug_start() {
on_event_it = std::prev(Debug::LLDB::get().on_event.end());
std::vector<std::string> startup_commands;
if(dynamic_cast<CargoBuild *>(self->build.get())) {
if(dynamic_cast<CargoBuild *>(build.get())) {
auto sysroot = filesystem::get_rust_sysroot_path().string();
if(!sysroot.empty()) {
std::string line;
@ -480,9 +492,7 @@ void Project::LLDB::debug_start() {
}
}
}
Debug::LLDB::get().start(*run_arguments, *project_path, breakpoints, startup_commands, remote_host);
}
});
Debug::LLDB::get().start(command, path, breakpoints, startup_commands, remote_host);
}
void Project::LLDB::debug_continue() {
@ -703,7 +713,7 @@ void Project::Clang::compile() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mCompiling project " + filesystem::get_short_path(build->project_path).string() + "\e[m\n");
Terminal::get().print("\e[2mCompiling project: " + filesystem::get_short_path(build->project_path).string() + "\e[m\n");
Terminal::get().async_process(build->get_compile_command(), default_build_path, [](int exit_status) {
compiling = false;
});
@ -741,7 +751,7 @@ void Project::Clang::compile_and_run() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mCompiling and running " + arguments + "\e[m\n");
Terminal::get().print("\e[2mCompiling and running: " + arguments + "\e[m\n");
Terminal::get().async_process(build->get_compile_command(), default_build_path, [arguments, project_path](int exit_status) {
compiling = false;
if(exit_status == 0) {
@ -852,7 +862,7 @@ void Project::Python::compile_and_run() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mRunning " + command + "\e[m\n");
Terminal::get().print("\e[2mRunning: " + command + "\e[m\n");
Terminal::get().async_process(command, path, [command](int exit_status) {
Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
});
@ -878,7 +888,7 @@ void Project::JavaScript::compile_and_run() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mRunning " + command + "\e[m\n");
Terminal::get().print("\e[2mRunning: " + command + "\e[m\n");
Terminal::get().async_process(command, path, [command](int exit_status) {
Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
});
@ -891,7 +901,7 @@ void Project::HTML::compile_and_run() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mRunning " + command + "\e[m\n");
Terminal::get().print("\e[2mRunning: " + command + "\e[m\n");
Terminal::get().async_process(command, build->project_path, [command](int exit_status) {
Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
});
@ -919,7 +929,7 @@ void Project::Rust::compile() {
if(Config::get().terminal.clear_on_compile)
Terminal::get().clear();
Terminal::get().print("\e[2mCompiling project " + filesystem::get_short_path(build->project_path).string() + "\e[m\n");
Terminal::get().print("\e[2mCompiling project: " + filesystem::get_short_path(build->project_path).string() + "\e[m\n");
Terminal::get().async_process(build->get_compile_command(), build->project_path, [](int exit_status) {
compiling = false;
@ -933,7 +943,7 @@ void Project::Rust::compile_and_run() {
Terminal::get().clear();
auto arguments = get_run_arguments().second;
Terminal::get().print("\e[2mCompiling and running " + arguments + "\e[m\n");
Terminal::get().print("\e[2mCompiling and running: " + arguments + "\e[m\n");
auto self = this->shared_from_this();
Terminal::get().async_process(build->get_compile_command(), build->project_path, [self, arguments = std::move(arguments)](int exit_status) {

6
src/project.hpp

@ -64,7 +64,8 @@ namespace Project {
virtual std::pair<std::string, std::string> debug_get_run_arguments();
virtual Project::DebugOptions *debug_get_options() { return nullptr; }
Tooltips debug_variable_tooltips;
virtual void debug_start();
virtual void debug_compile_and_start();
virtual void debug_start(const std::string &command, const boost::filesystem::path &path, const std::string &remote_host);
virtual void debug_continue() {}
virtual void debug_stop() {}
virtual void debug_kill() {}
@ -85,7 +86,8 @@ namespace Project {
#ifdef JUCI_ENABLE_DEBUG
std::pair<std::string, std::string> debug_get_run_arguments() override;
Project::DebugOptions *debug_get_options() override;
void debug_start() override;
void debug_compile_and_start() override;
void debug_start(const std::string &command, const boost::filesystem::path &path, const std::string &remote_host) override;
void debug_continue() override;
void debug_stop() override;
void debug_kill() override;

4
src/source.cpp

@ -2104,8 +2104,10 @@ bool Source::View::on_key_press_event(GdkEventKey *event) {
{
LockGuard lock(snippets_mutex);
if(snippets) {
guint keyval_without_state;
gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, (GdkModifierType)0, 0, &keyval_without_state, nullptr, nullptr, nullptr);
for(auto &snippet : *snippets) {
if(snippet.key == event->keyval && (snippet.modifier & event->state) == snippet.modifier) {
if((snippet.key == event->keyval || snippet.key == keyval_without_state) && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) == snippet.modifier) {
insert_snippet(get_buffer()->get_insert()->get_iter(), snippet.body);
return true;
}

97
src/window.cpp

@ -3,6 +3,7 @@
#ifdef JUCI_ENABLE_DEBUG
#include "debug_lldb.hpp"
#endif
#include "commands.hpp"
#include "compile_commands.hpp"
#include "dialog.hpp"
#include "directories.hpp"
@ -15,6 +16,7 @@
#include "project.hpp"
#include "selection_dialog.hpp"
#include "terminal.hpp"
#include <boost/algorithm/string.hpp>
Window::Window() {
Gsv::init();
@ -166,6 +168,7 @@ Window::Window() {
void Window::configure() {
Config::get().load();
Snippets::get().load();
Commands::get().load();
auto screen = get_screen();
static Glib::RefPtr<Gtk::CssProvider> css_provider_theme;
@ -284,6 +287,9 @@ void Window::set_menu_actions() {
menu.add_action("snippets", []() {
Notebook::get().open(Config::get().home_juci_path / "snippets.json");
});
menu.add_action("commands", []() {
Notebook::get().open(Config::get().home_juci_path / "commands.json");
});
menu.add_action("quit", [this]() {
close();
});
@ -1386,7 +1392,7 @@ void Window::set_menu_actions() {
Project::current = Project::create();
if(Config::get().project.save_on_compile_or_run)
Project::save_files(Project::current->build->project_path);
Project::save_files(!Project::current->build->project_path.empty() ? Project::current->build->project_path : Project::get_preferably_view_folder());
Project::current->compile_and_run();
});
@ -1399,7 +1405,7 @@ void Window::set_menu_actions() {
Project::current = Project::create();
if(Config::get().project.save_on_compile_or_run)
Project::save_files(Project::current->build->project_path);
Project::save_files(!Project::current->build->project_path.empty() ? Project::current->build->project_path : Project::get_preferably_view_folder());
Project::current->compile();
});
@ -1507,9 +1513,9 @@ void Window::set_menu_actions() {
Project::current = Project::create();
if(Config::get().project.save_on_compile_or_run)
Project::save_files(Project::current->build->project_path);
Project::save_files(!Project::current->build->project_path.empty() ? Project::current->build->project_path : Project::get_preferably_view_folder());
Project::current->debug_start();
Project::current->debug_compile_and_start();
});
menu.add_action("debug_stop", []() {
if(Project::current)
@ -1893,6 +1899,89 @@ void Window::add_widgets() {
}
bool Window::on_key_press_event(GdkEventKey *event) {
guint keyval_without_state;
gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, (GdkModifierType)0, 0, &keyval_without_state, nullptr, nullptr, nullptr);
for(auto &command : Commands::get().commands) {
if((command.key == event->keyval || command.key == keyval_without_state) && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) == command.modifier) {
auto view = Notebook::get().get_current_view();
auto view_folder = Project::get_preferably_view_folder();
auto path = view ? view->file_path : view_folder;
if(command.path) {
std::smatch sm;
if(!std::regex_match(path.string(), sm, *command.path) && !std::regex_match(filesystem::get_short_path(path).string(), sm, *command.path))
continue;
}
auto project = Project::create();
auto run_path = !project->build->project_path.empty() ? project->build->project_path : view_folder;
auto compile = command.compile;
boost::replace_all(compile, "<path_match>", filesystem::escape_argument(path.string()));
boost::replace_all(compile, "<working_directory>", filesystem::escape_argument(run_path.string()));
auto run = command.run;
boost::replace_all(run, "<path_match>", filesystem::escape_argument(path.string()));
boost::replace_all(run, "<working_directory>", filesystem::escape_argument(run_path.string()));
if(!compile.empty() || command.debug) {
if(Project::debugging && command.debug) // Possibly continue current debugging
break;
if(Project::compiling || Project::debugging) {
Info::get().print("Compile or debug in progress");
break;
}
Project::current = project;
}
if(Config::get().project.save_on_compile_or_run)
Project::save_files(run_path);
if(Config::get().terminal.clear_on_run_command || (!compile.empty() && Config::get().terminal.clear_on_compile))
Terminal::get().clear();
if(!compile.empty()) {
if(!project->build->get_default_path().empty())
project->build->update_default();
if(command.debug && !project->build->get_debug_path().empty())
project->build->update_debug();
if(!command.debug) {
Project::compiling = true;
Terminal::get().print("\e[2mCompiling and running: " + run + "\e[m\n");
Terminal::get().async_process(compile, run_path, [run, run_path](int exit_status) {
Project::compiling = false;
if(exit_status == 0) {
Terminal::get().async_process(run, run_path, [run](int exit_status) {
Terminal::get().print("\e[2m" + run + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
});
}
});
}
else { // Debug
Project::debugging = true;
Terminal::get().print("\e[2mCompiling and debugging: " + run + "\e[m\n");
Terminal::get().async_process(compile, run_path, [project = project->shared_from_this(), run, run_path, debug_remote_host = command.debug_remote_host](int exit_status) {
if(exit_status != EXIT_SUCCESS)
Project::debugging = false;
else
project->debug_start(run, run_path, debug_remote_host);
});
}
}
else if(!command.debug) {
Terminal::get().async_print("\e[2mRunning: " + run + "\e[m\n");
Terminal::get().async_process(run, run_path, [run](int exit_status) {
Terminal::get().print("\e[2m" + run + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
});
}
else { // Debug
Project::debugging = true;
Terminal::get().async_print("\e[2mDebugging: " + run + "\e[m\n");
project->debug_start(run, run_path, command.debug_remote_host);
}
return true;
}
}
if(event->keyval == GDK_KEY_Escape) {
EntryBox::get().hide();
}

8
tests/filesystem_test.cpp

@ -105,6 +105,14 @@ int main() {
g_assert(filesystem::get_relative_path("/test2/test.cc", "/test/base") == boost::filesystem::path("..") / ".." / "test2" / "test.cc");
}
{
g_assert(filesystem::get_absolute_path("./test1/test2", "/home") == boost::filesystem::path("/") / "home" / "." / "test1" / "test2");
g_assert(filesystem::get_absolute_path("../test1/test2", "/home") == boost::filesystem::path("/") / "home" / ".." / "test1" / "test2");
g_assert(filesystem::get_absolute_path("test1/test2", "/home") == boost::filesystem::path("/") / "home" / "test1" / "test2");
g_assert(filesystem::get_absolute_path("/test1/test2", "/home") == boost::filesystem::path("/") / "test1" / "test2");
g_assert(filesystem::get_absolute_path("~/test1/test2", "/home") == boost::filesystem::path("~") / "test1" / "test2");
}
{
boost::filesystem::path path = "/ro ot/te stæøå.txt";
auto uri = filesystem::get_uri_from_path(path);

4
tests/stubs/project.cpp

@ -18,4 +18,6 @@ std::pair<std::string, std::string> Project::Base::debug_get_run_arguments() {
return std::make_pair<std::string, std::string>("", "");
}
void Project::Base::debug_start() {}
void Project::Base::debug_compile_and_start() {}
void Project::Base::debug_start(const std::string &command, const boost::filesystem::path &path, const std::string &remote_host) {}

Loading…
Cancel
Save