Browse Source

Callback of Terminal::get().async_process is now run in the main thread

pipelines/280567345
eidheim 5 years ago
parent
commit
92b7cbdb2b
  1. 24
      src/cmake.cpp
  2. 24
      src/meson.cpp
  3. 200
      src/project.cpp
  4. 12
      src/terminal.cpp
  5. 1
      src/terminal.hpp
  6. 2
      src/window.cpp
  7. 48
      tests/terminal_test.cpp

24
src/cmake.cpp

@ -64,24 +64,24 @@ bool CMake::update_default_build(const boost::filesystem::path &default_build_pa
Dialog::Message message("Creating/updating default build", [&canceled] { Dialog::Message message("Creating/updating default build", [&canceled] {
canceled = true; canceled = true;
}); });
std::promise<int> promise; boost::optional<int> exit_status;
auto process = Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", auto process = Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
default_build_path, default_build_path,
[&promise](int exit_status) { [&exit_status](int exit_status_) {
promise.set_value(exit_status); exit_status = exit_status_;
}); });
auto future = promise.get_future();
bool killed = false; bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(!exit_status) {
if(canceled && !killed) { if(canceled && !killed) {
process->kill(); process->kill();
killed = true; killed = true;
} }
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
message.hide(); message.hide();
if(future.get() == 0) { if(exit_status == 0) {
#ifdef _WIN32 //Temporary fix to MSYS2's libclang #ifdef _WIN32 //Temporary fix to MSYS2's libclang
auto compile_commands_file = filesystem::read(compile_commands_path); auto compile_commands_file = filesystem::read(compile_commands_path);
auto replace_drive = [&compile_commands_file](const std::string &param) { auto replace_drive = [&compile_commands_file](const std::string &param) {
@ -124,24 +124,24 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path,
Dialog::Message message("Creating/updating debug build", [&canceled] { Dialog::Message message("Creating/updating debug build", [&canceled] {
canceled = true; canceled = true;
}); });
std::promise<int> promise; boost::optional<int> exit_status;
auto process = Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_BUILD_TYPE=Debug", auto process = Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_BUILD_TYPE=Debug",
debug_build_path, debug_build_path,
[&promise](int exit_status) { [&exit_status](int exit_status_) {
promise.set_value(exit_status); exit_status = exit_status_;
}); });
auto future = promise.get_future();
bool killed = false; bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(!exit_status) {
if(canceled && !killed) { if(canceled && !killed) {
process->kill(); process->kill();
killed = true; killed = true;
} }
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
message.hide(); message.hide();
return future.get() == 0; return exit_status == 0;
} }
boost::filesystem::path CMake::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { boost::filesystem::path CMake::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) {

24
src/meson.cpp

@ -64,24 +64,24 @@ bool Meson::update_default_build(const boost::filesystem::path &default_build_pa
Dialog::Message message("Creating/updating default build", [&canceled] { Dialog::Message message("Creating/updating default build", [&canceled] {
canceled = true; canceled = true;
}); });
std::promise<int> promise; boost::optional<int> exit_status;
auto process = Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype plain " + filesystem::escape_argument(project_path.string()), auto process = Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype plain " + filesystem::escape_argument(project_path.string()),
default_build_path, default_build_path,
[&promise](int exit_status) { [&exit_status](int exit_status_) {
promise.set_value(exit_status); exit_status = exit_status_;
}); });
auto future = promise.get_future();
bool killed = false; bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(!exit_status) {
if(canceled && !killed) { if(canceled && !killed) {
process->kill(); process->kill();
killed = true; killed = true;
} }
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
message.hide(); message.hide();
return future.get() == 0; return exit_status == 0;
} }
bool Meson::update_debug_build(const boost::filesystem::path &debug_build_path, bool force) { bool Meson::update_debug_build(const boost::filesystem::path &debug_build_path, bool force) {
@ -106,24 +106,24 @@ bool Meson::update_debug_build(const boost::filesystem::path &debug_build_path,
Dialog::Message message("Creating/updating debug build", [&canceled] { Dialog::Message message("Creating/updating debug build", [&canceled] {
canceled = true; canceled = true;
}); });
std::promise<int> promise; boost::optional<int> exit_status;
auto process = Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype debug " + filesystem::escape_argument(project_path.string()), auto process = Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype debug " + filesystem::escape_argument(project_path.string()),
debug_build_path, debug_build_path,
[&promise](int exit_status) { [&exit_status](int exit_status_) {
promise.set_value(exit_status); exit_status = exit_status_;
}); });
auto future = promise.get_future();
bool killed = false; bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(!exit_status) {
if(canceled && !killed) { if(canceled && !killed) {
process->kill(); process->kill();
killed = true; killed = true;
} }
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
message.hide(); message.hide();
return future.get() == 0; return exit_status == 0;
} }
boost::filesystem::path Meson::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { boost::filesystem::path Meson::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) {

200
src/project.cpp

@ -386,109 +386,107 @@ void Project::LLDB::debug_start() {
if(exit_status != EXIT_SUCCESS) if(exit_status != EXIT_SUCCESS)
debugging = false; debugging = false;
else { else {
self->dispatcher.post([self, run_arguments, project_path] { std::vector<std::pair<boost::filesystem::path, int>> breakpoints;
std::vector<std::pair<boost::filesystem::path, int>> breakpoints; for(size_t c = 0; c < Notebook::get().size(); c++) {
for(size_t c = 0; c < Notebook::get().size(); c++) { auto view = Notebook::get().get_view(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, *project_path)) { auto iter = view->get_buffer()->begin();
auto iter = view->get_buffer()->begin(); if(view->get_source_buffer()->get_source_marks_at_iter(iter, "debug_breakpoint").size() > 0)
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);
breakpoints.emplace_back(view->file_path, iter.get_line() + 1); while(view->get_source_buffer()->forward_iter_to_source_mark(iter, "debug_breakpoint"))
while(view->get_source_buffer()->forward_iter_to_source_mark(iter, "debug_breakpoint")) breakpoints.emplace_back(view->file_path, iter.get_line() + 1);
breakpoints.emplace_back(view->file_path, iter.get_line() + 1);
}
} }
}
std::string remote_host; std::string remote_host;
auto debug_run_arguments_it = debug_run_arguments.find(project_path->string()); 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) 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; remote_host = debug_run_arguments_it->second.remote_host_port;
static auto on_exit_it = Debug::LLDB::get().on_exit.end(); static auto on_exit_it = Debug::LLDB::get().on_exit.end();
if(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.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, run_arguments](int exit_status) {
debugging = false; 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" + *run_arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
self->dispatcher.post([] { self->dispatcher.post([] {
debug_update_status(""); debug_update_status("");
});
}); });
on_exit_it = std::prev(Debug::LLDB::get().on_exit.end()); });
on_exit_it = std::prev(Debug::LLDB::get().on_exit.end());
static auto on_event_it = Debug::LLDB::get().on_event.end();
if(on_event_it != Debug::LLDB::get().on_event.end()) static auto on_event_it = Debug::LLDB::get().on_event.end();
Debug::LLDB::get().on_event.erase(on_event_it); if(on_event_it != Debug::LLDB::get().on_event.end())
Debug::LLDB::get().on_event.emplace_back([self](const lldb::SBEvent &event) { Debug::LLDB::get().on_event.erase(on_event_it);
std::string status; Debug::LLDB::get().on_event.emplace_back([self](const lldb::SBEvent &event) {
boost::filesystem::path stop_path; std::string status;
unsigned stop_line = 0, stop_column = 0; boost::filesystem::path stop_path;
unsigned stop_line = 0, stop_column = 0;
LockGuard lock(Debug::LLDB::get().mutex);
auto process = lldb::SBProcess::GetProcessFromEvent(event); LockGuard lock(Debug::LLDB::get().mutex);
auto state = lldb::SBProcess::GetStateFromEvent(event); auto process = lldb::SBProcess::GetProcessFromEvent(event);
lldb::SBStream stream; auto state = lldb::SBProcess::GetStateFromEvent(event);
event.GetDescription(stream); lldb::SBStream stream;
std::string event_desc = stream.GetData(); event.GetDescription(stream);
event_desc.pop_back(); std::string event_desc = stream.GetData();
auto pos = event_desc.rfind(" = "); event_desc.pop_back();
if(pos != std::string::npos && pos + 3 < event_desc.size()) auto pos = event_desc.rfind(" = ");
status = event_desc.substr(pos + 3); if(pos != std::string::npos && pos + 3 < event_desc.size())
if(state == lldb::StateType::eStateStopped) { status = event_desc.substr(pos + 3);
char buffer[100]; if(state == lldb::StateType::eStateStopped) {
auto thread = process.GetSelectedThread(); char buffer[100];
auto n = thread.GetStopDescription(buffer, 100); // Returns number of bytes read. Might include null termination... Although maybe on newer versions only. auto thread = process.GetSelectedThread();
if(n > 0) auto n = thread.GetStopDescription(buffer, 100); // Returns number of bytes read. Might include null termination... Although maybe on newer versions only.
status += " (" + std::string(buffer, n <= 100 ? (buffer[n - 1] == '\0' ? n - 1 : n) : 100) + ")"; if(n > 0)
auto line_entry = thread.GetSelectedFrame().GetLineEntry(); status += " (" + std::string(buffer, n <= 100 ? (buffer[n - 1] == '\0' ? n - 1 : n) : 100) + ")";
if(line_entry.IsValid()) { auto line_entry = thread.GetSelectedFrame().GetLineEntry();
lldb::SBStream stream; if(line_entry.IsValid()) {
line_entry.GetFileSpec().GetDescription(stream); lldb::SBStream stream;
auto line = line_entry.GetLine(); line_entry.GetFileSpec().GetDescription(stream);
status += " " + boost::filesystem::path(stream.GetData()).filename().string() + ":" + std::to_string(line); auto line = line_entry.GetLine();
auto column = line_entry.GetColumn(); status += " " + boost::filesystem::path(stream.GetData()).filename().string() + ":" + std::to_string(line);
if(column == 0) auto column = line_entry.GetColumn();
column = 1; if(column == 0)
stop_path = filesystem::get_normal_path(stream.GetData()); column = 1;
stop_line = line - 1; stop_path = filesystem::get_normal_path(stream.GetData());
stop_column = column - 1; stop_line = line - 1;
} stop_column = column - 1;
} }
}
self->dispatcher.post([status = std::move(status), stop_path = std::move(stop_path), stop_line, stop_column] { self->dispatcher.post([status = std::move(status), stop_path = std::move(stop_path), stop_line, stop_column] {
debug_update_status(status); debug_update_status(status);
Project::debug_stop.first = stop_path; Project::debug_stop.first = stop_path;
Project::debug_stop.second.first = stop_line; Project::debug_stop.second.first = stop_line;
Project::debug_stop.second.second = stop_column; Project::debug_stop.second.second = stop_column;
debug_update_stop(); debug_update_stop();
if(Config::get().source.debug_place_cursor_at_stop && !stop_path.empty()) { if(Config::get().source.debug_place_cursor_at_stop && !stop_path.empty()) {
if(Notebook::get().open(stop_path)) { if(Notebook::get().open(stop_path)) {
auto view = Notebook::get().get_current_view(); auto view = Notebook::get().get_current_view();
view->place_cursor_at_line_index(stop_line, stop_column); view->place_cursor_at_line_index(stop_line, stop_column);
view->scroll_to_cursor_delayed(true, false); view->scroll_to_cursor_delayed(true, false);
}
} }
else if(auto view = Notebook::get().get_current_view())
view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter());
});
});
on_event_it = std::prev(Debug::LLDB::get().on_event.end());
std::vector<std::string> startup_commands;
if(dynamic_cast<CargoBuild *>(self->build.get())) {
std::stringstream istream, ostream;
if(Terminal::get().process(istream, ostream, "rustc --print sysroot") == 0) {
auto sysroot = ostream.str();
while(!sysroot.empty() && (sysroot.back() == '\n' || sysroot.back() == '\r'))
sysroot.pop_back();
startup_commands.emplace_back("command script import \"" + sysroot + "/lib/rustlib/etc/lldb_rust_formatters.py\"");
startup_commands.emplace_back("type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust");
startup_commands.emplace_back("type category enable Rust");
} }
} else if(auto view = Notebook::get().get_current_view())
Debug::LLDB::get().start(*run_arguments, *project_path, breakpoints, startup_commands, remote_host); view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter());
});
}); });
on_event_it = std::prev(Debug::LLDB::get().on_event.end());
std::vector<std::string> startup_commands;
if(dynamic_cast<CargoBuild *>(self->build.get())) {
std::stringstream istream, ostream;
if(Terminal::get().process(istream, ostream, "rustc --print sysroot") == 0) {
auto sysroot = ostream.str();
while(!sysroot.empty() && (sysroot.back() == '\n' || sysroot.back() == '\r'))
sysroot.pop_back();
startup_commands.emplace_back("command script import \"" + sysroot + "/lib/rustlib/etc/lldb_rust_formatters.py\"");
startup_commands.emplace_back("type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust");
startup_commands.emplace_back("type category enable Rust");
}
}
Debug::LLDB::get().start(*run_arguments, *project_path, breakpoints, startup_commands, remote_host);
} }
}); });
} }
@ -893,7 +891,7 @@ void Project::Clang::compile_and_run() {
compiling = false; compiling = false;
if(exit_status == 0) { if(exit_status == 0) {
Terminal::get().async_process(arguments, project_path, [arguments](int exit_status) { Terminal::get().async_process(arguments, project_path, [arguments](int exit_status) {
Terminal::get().async_print("\e[2m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); Terminal::get().print("\e[2m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
}); });
} }
}); });
@ -973,7 +971,7 @@ void Project::Markdown::compile_and_run() {
Terminal::get().async_process( Terminal::get().async_process(
command, "", [command](int exit_status) { command, "", [command](int exit_status) {
if(exit_status == 127) if(exit_status == 127)
Terminal::get().async_print("\e[31mError\e[m: executable not found: " + command + "\n", true); Terminal::get().print("\e[31mError\e[m: executable not found: " + command + "\n", true);
}, },
true); true);
} }
@ -1001,7 +999,7 @@ void Project::Python::compile_and_run() {
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().async_process(command, path, [command](int exit_status) {
Terminal::get().async_print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
}); });
} }
@ -1027,7 +1025,7 @@ void Project::JavaScript::compile_and_run() {
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().async_process(command, path, [command](int exit_status) {
Terminal::get().async_print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
}); });
} }
@ -1040,7 +1038,7 @@ void Project::HTML::compile_and_run() {
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().async_process(command, build->project_path, [command](int exit_status) {
Terminal::get().async_print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
}); });
} }
else if(auto view = Notebook::get().get_current_view()) else if(auto view = Notebook::get().get_current_view())
@ -1088,7 +1086,7 @@ void Project::Rust::compile_and_run() {
compiling = false; compiling = false;
if(exit_status == 0) { if(exit_status == 0) {
Terminal::get().async_process(arguments, self->build->project_path, [arguments](int exit_status) { Terminal::get().async_process(arguments, self->build->project_path, [arguments](int exit_status) {
Terminal::get().async_print("\e[2m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); Terminal::get().print("\e[2m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
}); });
} }
}); });

12
src/terminal.cpp

@ -337,7 +337,7 @@ std::shared_ptr<TinyProcessLib::Process> Terminal::async_process(const std::stri
processes.emplace_back(process); processes.emplace_back(process);
} }
std::thread exit_status_thread([this, process, pid, callback = std::move(callback)]() { std::thread([this, process, pid, callback = std::move(callback)]() mutable {
auto exit_status = process->get_exit_status(); auto exit_status = process->get_exit_status();
{ {
LockGuard lock(processes_mutex); LockGuard lock(processes_mutex);
@ -348,10 +348,12 @@ std::shared_ptr<TinyProcessLib::Process> Terminal::async_process(const std::stri
} }
} }
} }
if(callback) if(callback) {
callback(exit_status); dispatcher.post([callback = std::move(callback), exit_status] {
}); callback(exit_status);
exit_status_thread.detach(); });
}
}).detach();
return process; return process;
} }

1
src/terminal.hpp

@ -21,6 +21,7 @@ public:
int process(const std::string &command, const boost::filesystem::path &path = "", bool use_pipes = true); int process(const std::string &command, const boost::filesystem::path &path = "", bool use_pipes = true);
int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path = "", std::ostream *stderr_stream = nullptr); int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path = "", std::ostream *stderr_stream = nullptr);
/// The callback is run in the main thread.
std::shared_ptr<TinyProcessLib::Process> async_process(const std::string &command, const boost::filesystem::path &path = "", std::function<void(int exit_status)> callback = nullptr, bool quiet = false); std::shared_ptr<TinyProcessLib::Process> async_process(const std::string &command, const boost::filesystem::path &path = "", std::function<void(int exit_status)> callback = nullptr, bool quiet = false);
void kill_last_async_process(bool force = false); void kill_last_async_process(bool force = false);
void kill_async_processes(bool force = false); void kill_async_processes(bool force = false);

2
src/window.cpp

@ -1391,7 +1391,7 @@ void Window::set_menu_actions() {
Terminal::get().async_print("\e[2mRunning: " + content + "\e[m\n"); Terminal::get().async_print("\e[2mRunning: " + content + "\e[m\n");
Terminal::get().async_process(content, directory_folder, [content](int exit_status) { Terminal::get().async_process(content, directory_folder, [content](int exit_status) {
Terminal::get().async_print("\e[2m" + content + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); Terminal::get().print("\e[2m" + content + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n");
}); });
} }
if(Config::get().terminal.hide_entry_on_run_command) if(Config::get().terminal.hide_entry_on_run_command)

48
tests/terminal_test.cpp

@ -281,68 +281,68 @@ int main() {
// async_process tests // async_process tests
{ {
terminal.clear(); terminal.clear();
std::promise<int> done; boost::optional<int> exit_status;
terminal.async_process("echo test", "", [&done](int exit_status) { terminal.async_process("echo test", "", [&exit_status](int exit_status_) {
done.set_value(exit_status); exit_status = exit_status_;
}); });
auto future = done.get_future(); while(!exit_status) {
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
assert(future.get() == 0); assert(exit_status == 0);
assert(buffer->get_text() == "test\n"); assert(buffer->get_text() == "test\n");
assert(!buffer->begin().starts_tag(terminal.bold_tag)); assert(!buffer->begin().starts_tag(terminal.bold_tag));
assert(!buffer->end().ends_tag(terminal.bold_tag)); assert(!buffer->end().ends_tag(terminal.bold_tag));
} }
{ {
terminal.clear(); terminal.clear();
std::promise<int> done; boost::optional<int> exit_status;
terminal.async_process( terminal.async_process(
"echo test", "", [&done](int exit_status) { "echo test", "", [&exit_status](int exit_status_) {
done.set_value(exit_status); exit_status = exit_status_;
}, },
true); true);
auto future = done.get_future(); while(!exit_status) {
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
assert(future.get() == 0); assert(exit_status == 0);
assert(buffer->get_text() == ""); assert(buffer->get_text() == "");
} }
{ {
terminal.clear(); terminal.clear();
std::promise<int> done; boost::optional<int> exit_status;
terminal.async_process("testing_invalid_command", "", [&done](int exit_status) { terminal.async_process("testing_invalid_command", "", [&exit_status](int exit_status_) {
done.set_value(exit_status); exit_status = exit_status_;
}); });
auto future = done.get_future(); while(!exit_status) {
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
assert(future.get() != 0); assert(exit_status != 0);
assert(buffer->begin().starts_tag(terminal.bold_tag)); assert(buffer->begin().starts_tag(terminal.bold_tag));
assert(buffer->end().ends_tag(terminal.bold_tag)); assert(buffer->end().ends_tag(terminal.bold_tag));
assert(buffer->get_text() != ""); assert(buffer->get_text() != "");
} }
{ {
terminal.clear(); terminal.clear();
std::promise<int> done; boost::optional<int> exit_status;
terminal.async_process( terminal.async_process(
"testing_invalid_command", "", [&done](int exit_status) { "testing_invalid_command", "", [&exit_status](int exit_status_) {
done.set_value(exit_status); exit_status = exit_status_;
}, },
true); true);
auto future = done.get_future(); while(!exit_status) {
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
assert(future.get() != 0); assert(exit_status != 0);
assert(buffer->get_text() == ""); assert(buffer->get_text() == "");
} }

Loading…
Cancel
Save