Browse Source

Formatting cleanup

pipelines/235045657
eidheim 5 years ago
parent
commit
3c726f52da
  1. 17
      src/autocomplete.cpp
  2. 26
      src/directories.cpp
  3. 40
      src/files.hpp
  4. 17
      src/git.cpp
  5. 11
      src/info.cpp
  6. 11
      src/notebook.cpp
  7. 11
      src/selection_dialog.cpp
  8. 92
      src/source.cpp
  9. 87
      src/source_base.cpp
  10. 97
      src/source_clang.cpp
  11. 105
      src/source_diff.cpp
  12. 78
      src/source_generic.cpp
  13. 207
      src/source_language_protocol.cpp
  14. 186
      src/source_spellcheck.cpp
  15. 82
      src/terminal.cpp
  16. 8
      tests/process_test.cpp

17
src/autocomplete.cpp

@ -25,14 +25,15 @@ Autocomplete::Autocomplete(Gsv::View *view, bool &interactive_completion, guint
stop(); stop();
}); });
view->signal_key_release_event().connect([](GdkEventKey *event) { view->signal_key_release_event().connect(
if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) { [](GdkEventKey *event) {
if(CompletionDialog::get()->on_key_release(event)) if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) {
return true; if(CompletionDialog::get()->on_key_release(event))
} return true;
return false; }
}, return false;
false); },
false);
view->signal_focus_out_event().connect([this](GdkEventFocus *event) { view->signal_focus_out_event().connect([this](GdkEventFocus *event) {
stop(); stop();

26
src/directories.cpp

@ -674,12 +674,13 @@ void Directories::add_or_update_path(const boost::filesystem::path &dir_path, co
if(repository) if(repository)
repository->clear_saved_status(); repository->clear_saved_status();
connection->disconnect(); connection->disconnect();
*connection = Glib::signal_timeout().connect([path_and_row, this]() { *connection = Glib::signal_timeout().connect(
if(directories.find(path_and_row->first.string()) != directories.end()) [path_and_row, this]() {
add_or_update_path(path_and_row->first, path_and_row->second, true); if(directories.find(path_and_row->first.string()) != directories.end())
return false; add_or_update_path(path_and_row->first, path_and_row->second, true);
}, return false;
500); },
500);
} }
}); });
@ -695,12 +696,13 @@ void Directories::add_or_update_path(const boost::filesystem::path &dir_path, co
Gio::FileMonitorEvent monitor_event) { Gio::FileMonitorEvent monitor_event) {
if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
connection->disconnect(); connection->disconnect();
*connection = Glib::signal_timeout().connect([this, path_and_row] { *connection = Glib::signal_timeout().connect(
if(directories.find(path_and_row->first.string()) != directories.end()) [this, path_and_row] {
colorize_path(path_and_row->first, false); if(directories.find(path_and_row->first.string()) != directories.end())
return false; colorize_path(path_and_row->first, false);
}, return false;
500); },
500);
} }
}); });
} }

40
src/files.hpp

@ -4,9 +4,11 @@
/// If you add or remove nodes from the default_config_file, increase the juci /// If you add or remove nodes from the default_config_file, increase the juci
/// version number (JUCI_VERSION) in ../CMakeLists.txt to automatically apply /// version number (JUCI_VERSION) in ../CMakeLists.txt to automatically apply
/// the changes to user's ~/.juci/config/config.json files /// the changes to user's ~/.juci/config/config.json files
const std::string default_config_file = R"RAW({ const std::string default_config_file =
"version": ")RAW" + std::string(JUCI_VERSION) + R"RAW({
R"RAW(", "version": ")RAW" +
std::string(JUCI_VERSION) +
R"RAW(",
"gtk_theme": { "gtk_theme": {
"name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh", "name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh",
"name": "", "name": "",
@ -20,18 +22,18 @@ const std::string default_config_file = R"RAW({
"style": "juci-light", "style": "juci-light",
"font_comment": "Use \"\" for default font, and for instance \"Monospace 12\" to also set size",)RAW" "font_comment": "Use \"\" for default font, and for instance \"Monospace 12\" to also set size",)RAW"
#ifdef __APPLE__ #ifdef __APPLE__
R"RAW( R"RAW(
"font": "Menlo",)RAW" "font": "Menlo",)RAW"
#else #else
#ifdef _WIN32 #ifdef _WIN32
R"RAW( R"RAW(
"font": "Consolas",)RAW" "font": "Consolas",)RAW"
#else #else
R"RAW( R"RAW(
"font": "Monospace",)RAW" "font": "Monospace",)RAW"
#endif #endif
#endif #endif
R"RAW( R"RAW(
"cleanup_whitespace_characters_comment": "Remove trailing whitespace characters on save, and add trailing newline if missing", "cleanup_whitespace_characters_comment": "Remove trailing whitespace characters on save, and add trailing newline if missing",
"cleanup_whitespace_characters": false, "cleanup_whitespace_characters": false,
"show_whitespace_characters_comment": "Determines what kind of whitespaces should be drawn. Use comma-separated list of: space, tab, newline, nbsp, leading, text, trailing or all", "show_whitespace_characters_comment": "Determines what kind of whitespaces should be drawn. Use comma-separated list of: space, tab, newline, nbsp, leading, text, trailing or all",
@ -91,13 +93,13 @@ const std::string default_config_file = R"RAW({
"debug_build_path": "<default_build_path>/debug", "debug_build_path": "<default_build_path>/debug",
"cmake": {)RAW" "cmake": {)RAW"
#ifdef _WIN32 #ifdef _WIN32
R"RAW( R"RAW(
"command": "cmake -G\"MSYS Makefiles\"",)RAW" "command": "cmake -G\"MSYS Makefiles\"",)RAW"
#else #else
R"RAW( R"RAW(
"command": "cmake",)RAW" "command": "cmake",)RAW"
#endif #endif
R"RAW( R"RAW(
"compile_command": "cmake --build ." "compile_command": "cmake --build ."
}, },
"meson": { "meson": {
@ -108,13 +110,13 @@ const std::string default_config_file = R"RAW({
"default_build_management_system": "cmake", "default_build_management_system": "cmake",
"save_on_compile_or_run": true,)RAW" "save_on_compile_or_run": true,)RAW"
#ifdef JUCI_USE_UCTAGS #ifdef JUCI_USE_UCTAGS
R"RAW( R"RAW(
"ctags_command": "uctags",)RAW" "ctags_command": "uctags",)RAW"
#else #else
R"RAW( R"RAW(
"ctags_command": "ctags",)RAW" "ctags_command": "ctags",)RAW"
#endif #endif
R"RAW( R"RAW(
"grep_command": "grep", "grep_command": "grep",
"cargo_command": "cargo", "cargo_command": "cargo",
"python_command": "python -u", "python_command": "python -u",
@ -194,26 +196,26 @@ const std::string default_config_file = R"RAW({
"debug_show_breakpoints": "<primary><shift><alt>b", "debug_show_breakpoints": "<primary><shift><alt>b",
"debug_goto_stop": "<primary><shift>l",)RAW" "debug_goto_stop": "<primary><shift>l",)RAW"
#ifdef __linux #ifdef __linux
R"RAW( R"RAW(
"window_next_tab": "<primary>Tab", "window_next_tab": "<primary>Tab",
"window_previous_tab": "<primary><shift>Tab",)RAW" "window_previous_tab": "<primary><shift>Tab",)RAW"
#else #else
R"RAW( R"RAW(
"window_next_tab": "<primary><alt>Right", "window_next_tab": "<primary><alt>Right",
"window_previous_tab": "<primary><alt>Left",)RAW" "window_previous_tab": "<primary><alt>Left",)RAW"
#endif #endif
R"RAW( R"RAW(
"window_goto_tab": "", "window_goto_tab": "",
"window_toggle_split": "", "window_toggle_split": "",
"window_split_source_buffer": "",)RAW" "window_split_source_buffer": "",)RAW"
#ifdef __APPLE__ #ifdef __APPLE__
R"RAW( R"RAW(
"window_toggle_full_screen": "<primary><control>f",)RAW" "window_toggle_full_screen": "<primary><control>f",)RAW"
#else #else
R"RAW( R"RAW(
"window_toggle_full_screen": "F11",)RAW" "window_toggle_full_screen": "F11",)RAW"
#endif #endif
R"RAW( R"RAW(
"window_toggle_tabs": "", "window_toggle_tabs": "",
"window_toggle_zen_mode": "", "window_toggle_zen_mode": "",
"window_clear_terminal": "" "window_clear_terminal": ""

17
src/git.cpp

@ -116,14 +116,15 @@ Git::Repository::Repository(const boost::filesystem::path &path) {
auto git_directory = Gio::File::create_for_path(get_path().string()); auto git_directory = Gio::File::create_for_path(get_path().string());
monitor = git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); monitor = git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES);
monitor_changed_connection = monitor->signal_changed().connect([this](const Glib::RefPtr<Gio::File> &file, monitor_changed_connection = monitor->signal_changed().connect(
const Glib::RefPtr<Gio::File> &, [this](const Glib::RefPtr<Gio::File> &file,
Gio::FileMonitorEvent monitor_event) { const Glib::RefPtr<Gio::File> &,
if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { Gio::FileMonitorEvent monitor_event) {
this->clear_saved_status(); if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
} this->clear_saved_status();
}, }
false); },
false);
} }
Git::Repository::~Repository() { Git::Repository::~Repository() {

11
src/info.cpp

@ -26,11 +26,12 @@ void Info::print(const std::string &text) {
//Timeout based on https://en.wikipedia.org/wiki/Words_per_minute //Timeout based on https://en.wikipedia.org/wiki/Words_per_minute
//(average_words_per_minute*average_letters_per_word)/60 => (228*4.5)/60 = 17.1 //(average_words_per_minute*average_letters_per_word)/60 => (228*4.5)/60 = 17.1
double timeout = 1000.0 * std::max(3.0, 1.0 + text.size() / 17.1); double timeout = 1000.0 * std::max(3.0, 1.0 + text.size() / 17.1);
timeout_connection = Glib::signal_timeout().connect([this]() { timeout_connection = Glib::signal_timeout().connect(
hide(); [this]() {
return false; hide();
}, return false;
timeout); },
timeout);
label.set_text(text); label.set_text(text);
show(); show();

11
src/notebook.cpp

@ -618,11 +618,12 @@ void Notebook::toggle_split() {
show_all(); show_all();
//Make sure the position is correct //Make sure the position is correct
//TODO: report bug to gtk if it is not fixed in gtk3.22 //TODO: report bug to gtk if it is not fixed in gtk3.22
Glib::signal_timeout().connect([this] { Glib::signal_timeout().connect(
set_position(get_width() / 2); [this] {
return false; set_position(get_width() / 2);
}, return false;
200); },
200);
} }
else { else {
for(size_t c = size() - 1; c != static_cast<size_t>(-1); --c) { for(size_t c = size() - 1; c != static_cast<size_t>(-1); --c) {

11
src/selection_dialog.cpp

@ -44,11 +44,12 @@ SelectionDialogBase::SelectionDialogBase(Gtk::TextView *text_view, const boost::
window.set_type_hint(Gdk::WindowTypeHint::WINDOW_TYPE_HINT_COMBO); window.set_type_hint(Gdk::WindowTypeHint::WINDOW_TYPE_HINT_COMBO);
search_entry.signal_changed().connect([this] { search_entry.signal_changed().connect(
if(on_search_entry_changed) [this] {
on_search_entry_changed(search_entry.get_text()); if(on_search_entry_changed)
}, on_search_entry_changed(search_entry.get_text());
false); },
false);
list_view_text.set_search_entry(search_entry); list_view_text.set_search_entry(search_entry);

92
src/source.cpp

@ -588,18 +588,19 @@ void Source::View::setup_signals() {
if(on_motion_last_x != event->x || on_motion_last_y != event->y) { if(on_motion_last_x != event->x || on_motion_last_y != event->y) {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
if((event->state & GDK_BUTTON1_MASK) == 0) { if((event->state & GDK_BUTTON1_MASK) == 0) {
delayed_tooltips_connection = Glib::signal_timeout().connect([this, x = event->x, y = event->y]() { delayed_tooltips_connection = Glib::signal_timeout().connect(
type_tooltips.hide(); [this, x = event->x, y = event->y]() {
diagnostic_tooltips.hide(); type_tooltips.hide();
Tooltips::init(); diagnostic_tooltips.hide();
Gdk::Rectangle rectangle(x, y, 1, 1); Tooltips::init();
if(parsed) { Gdk::Rectangle rectangle(x, y, 1, 1);
show_type_tooltips(rectangle); if(parsed) {
show_diagnostic_tooltips(rectangle); show_type_tooltips(rectangle);
} show_diagnostic_tooltips(rectangle);
return false; }
}, return false;
100); },
100);
} }
if(clickable_tag_applied) { if(clickable_tag_applied) {
@ -608,16 +609,17 @@ void Source::View::setup_signals() {
} }
if((event->state & primary_modifier_mask) && !(event->state & GDK_SHIFT_MASK) && !(event->state & GDK_BUTTON1_MASK)) { if((event->state & primary_modifier_mask) && !(event->state & GDK_SHIFT_MASK) && !(event->state & GDK_BUTTON1_MASK)) {
delayed_tag_clickable_connection.disconnect(); delayed_tag_clickable_connection.disconnect();
delayed_tag_clickable_connection = Glib::signal_timeout().connect([this, x = event->x, y = event->y]() { delayed_tag_clickable_connection = Glib::signal_timeout().connect(
int buffer_x, buffer_y; [this, x = event->x, y = event->y]() {
window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, x, y, buffer_x, buffer_y); int buffer_x, buffer_y;
Gtk::TextIter iter; window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, x, y, buffer_x, buffer_y);
get_iter_at_location(iter, buffer_x, buffer_y); Gtk::TextIter iter;
apply_clickable_tag(iter); get_iter_at_location(iter, buffer_x, buffer_y);
clickable_tag_applied = true; apply_clickable_tag(iter);
return false; clickable_tag_applied = true;
}, return false;
100); },
100);
} }
auto last_mouse_pos = std::make_pair<int, int>(on_motion_last_x, on_motion_last_y); auto last_mouse_pos = std::make_pair<int, int>(on_motion_last_x, on_motion_last_y);
@ -646,30 +648,32 @@ void Source::View::setup_signals() {
hide_tooltips(); hide_tooltips();
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
delayed_tooltips_connection = Glib::signal_timeout().connect([this]() { delayed_tooltips_connection = Glib::signal_timeout().connect(
Tooltips::init(); [this]() {
Gdk::Rectangle rectangle; Tooltips::init();
get_iter_location(get_buffer()->get_insert()->get_iter(), rectangle); Gdk::Rectangle rectangle;
int location_window_x, location_window_y; get_iter_location(get_buffer()->get_insert()->get_iter(), rectangle);
buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, rectangle.get_x(), rectangle.get_y(), location_window_x, location_window_y); int location_window_x, location_window_y;
rectangle.set_x(location_window_x - 2); buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, rectangle.get_x(), rectangle.get_y(), location_window_x, location_window_y);
rectangle.set_y(location_window_y); rectangle.set_x(location_window_x - 2);
rectangle.set_width(5); rectangle.set_y(location_window_y);
if(parsed) { rectangle.set_width(5);
show_type_tooltips(rectangle); if(parsed) {
show_diagnostic_tooltips(rectangle); show_type_tooltips(rectangle);
} show_diagnostic_tooltips(rectangle);
return false; }
}, return false;
500); },
500);
delayed_tag_similar_symbols_connection.disconnect(); delayed_tag_similar_symbols_connection.disconnect();
delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect([this] { delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect(
apply_similar_symbol_tag(); [this] {
similar_symbol_tag_applied = true; apply_similar_symbol_tag();
return false; similar_symbol_tag_applied = true;
}, return false;
100); },
100);
if(SelectionDialog::get()) if(SelectionDialog::get())
SelectionDialog::get()->hide(); SelectionDialog::get()->hide();

87
src/source_base.cpp

@ -343,23 +343,24 @@ void Source::BaseView::monitor_file() {
public: public:
static void f(BaseView *view, boost::optional<std::time_t> previous_last_write_time = {}, bool check_called = false) { static void f(BaseView *view, boost::optional<std::time_t> previous_last_write_time = {}, bool check_called = false) {
view->delayed_monitor_changed_connection.disconnect(); view->delayed_monitor_changed_connection.disconnect();
view->delayed_monitor_changed_connection = Glib::signal_timeout().connect([view, previous_last_write_time, check_called]() { view->delayed_monitor_changed_connection = Glib::signal_timeout().connect(
boost::system::error_code ec; [view, previous_last_write_time, check_called]() {
auto last_write_time = boost::filesystem::last_write_time(view->file_path, ec); boost::system::error_code ec;
if(!ec && last_write_time != view->last_write_time) { auto last_write_time = boost::filesystem::last_write_time(view->file_path, ec);
if(last_write_time == previous_last_write_time) { // If no change has happened in the last second (std::time_t is in seconds). if(!ec && last_write_time != view->last_write_time) {
if(!check_called) // To avoid several info messages when file is changed but not reloaded. if(last_write_time == previous_last_write_time) { // If no change has happened in the last second (std::time_t is in seconds).
view->check_last_write_time(last_write_time); if(!check_called) // To avoid several info messages when file is changed but not reloaded.
Recursive::f(view, last_write_time, true); view->check_last_write_time(last_write_time);
Recursive::f(view, last_write_time, true);
return false;
}
Recursive::f(view, last_write_time);
return false;
}
Recursive::f(view);
return false; return false;
} },
Recursive::f(view, last_write_time); 1000);
return false;
}
Recursive::f(view);
return false;
},
1000);
} }
}; };
delayed_monitor_changed_connection.disconnect(); delayed_monitor_changed_connection.disconnect();
@ -374,11 +375,12 @@ void Source::BaseView::monitor_file() {
Gio::FileMonitorEvent monitor_event) { Gio::FileMonitorEvent monitor_event) {
if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
delayed_monitor_changed_connection.disconnect(); delayed_monitor_changed_connection.disconnect();
delayed_monitor_changed_connection = Glib::signal_timeout().connect([this]() { delayed_monitor_changed_connection = Glib::signal_timeout().connect(
check_last_write_time(); [this]() {
return false; check_last_write_time();
}, return false;
1000); // Has to wait 1 second (std::time_t is in seconds) },
1000); // Has to wait 1 second (std::time_t is in seconds)
} }
}); });
} }
@ -1322,27 +1324,28 @@ void Source::BaseView::setup_extra_cursor_signals() {
auto erase_backward_length = std::make_shared<int>(0); auto erase_backward_length = std::make_shared<int>(0);
auto erase_forward_length = std::make_shared<int>(0); auto erase_forward_length = std::make_shared<int>(0);
auto erase_selection = std::make_shared<bool>(false); auto erase_selection = std::make_shared<bool>(false);
get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length, erase_selection](const Gtk::TextIter &iter_start, const Gtk::TextIter &iter_end) { get_buffer()->signal_erase().connect(
if(enable_multiple_cursors && (!extra_cursors.empty())) { [this, erase_backward_length, erase_forward_length, erase_selection](const Gtk::TextIter &iter_start, const Gtk::TextIter &iter_end) {
auto insert_offset = get_buffer()->get_insert()->get_iter().get_offset(); if(enable_multiple_cursors && (!extra_cursors.empty())) {
*erase_backward_length = insert_offset - iter_start.get_offset(); auto insert_offset = get_buffer()->get_insert()->get_iter().get_offset();
*erase_forward_length = iter_end.get_offset() - insert_offset; *erase_backward_length = insert_offset - iter_start.get_offset();
*erase_forward_length = iter_end.get_offset() - insert_offset;
if(*erase_backward_length == 0) {
auto iter = get_buffer()->get_insert()->get_iter(); if(*erase_backward_length == 0) {
iter.forward_chars(*erase_forward_length); auto iter = get_buffer()->get_insert()->get_iter();
if(iter == get_buffer()->get_selection_bound()->get_iter()) iter.forward_chars(*erase_forward_length);
*erase_selection = true; if(iter == get_buffer()->get_selection_bound()->get_iter())
} *erase_selection = true;
else if(*erase_forward_length == 0) { }
auto iter = get_buffer()->get_insert()->get_iter(); else if(*erase_forward_length == 0) {
iter.backward_chars(*erase_backward_length); auto iter = get_buffer()->get_insert()->get_iter();
if(iter == get_buffer()->get_selection_bound()->get_iter()) iter.backward_chars(*erase_backward_length);
*erase_selection = true; if(iter == get_buffer()->get_selection_bound()->get_iter())
} *erase_selection = true;
} }
}, }
false); },
false);
get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length, erase_selection](const Gtk::TextIter & /*iter_start*/, const Gtk::TextIter & /*iter_end*/) { get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length, erase_selection](const Gtk::TextIter & /*iter_start*/, const Gtk::TextIter & /*iter_end*/) {
if(enable_multiple_cursors && (*erase_backward_length != 0 || *erase_forward_length != 0)) { if(enable_multiple_cursors && (*erase_backward_length != 0 || *erase_forward_length != 0)) {
enable_multiple_cursors = false; enable_multiple_cursors = false;

97
src/source_clang.cpp

@ -643,8 +643,9 @@ void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle)
}; };
VisitorData visitor_data{cursor.get_source_range().get_offsets(), cursor.get_spelling(), {}}; VisitorData visitor_data{cursor.get_source_range().get_offsets(), cursor.get_spelling(), {}};
auto start_cursor = cursor; auto start_cursor = cursor;
for(auto parent = cursor.get_semantic_parent(); parent.get_kind() != clangmm::Cursor::Kind::TranslationUnit && for(auto parent = cursor.get_semantic_parent();
parent.get_kind() != clangmm::Cursor::Kind::ClassDecl; parent.get_kind() != clangmm::Cursor::Kind::TranslationUnit &&
parent.get_kind() != clangmm::Cursor::Kind::ClassDecl;
parent = parent.get_semantic_parent()) parent = parent.get_semantic_parent())
start_cursor = parent; start_cursor = parent;
clang_visitChildren( clang_visitChildren(
@ -801,47 +802,50 @@ Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::pa
}; };
// Activate argument completions // Activate argument completions
get_buffer()->signal_changed().connect([this] { get_buffer()->signal_changed().connect(
if(!interactive_completion) [this] {
return; if(!interactive_completion)
if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) return;
return; if(CompletionDialog::get() && CompletionDialog::get()->is_visible())
if(!has_focus()) return;
return; if(!has_focus())
if(show_parameters) return;
autocomplete.stop(); if(show_parameters)
show_parameters = false; autocomplete.stop();
delayed_show_arguments_connection.disconnect(); show_parameters = false;
delayed_show_arguments_connection = Glib::signal_timeout().connect([this]() { delayed_show_arguments_connection.disconnect();
if(get_buffer()->get_has_selection()) delayed_show_arguments_connection = Glib::signal_timeout().connect(
return false; [this]() {
if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) if(get_buffer()->get_has_selection())
return false; return false;
if(!has_focus()) if(CompletionDialog::get() && CompletionDialog::get()->is_visible())
return false; return false;
if(is_possible_argument()) { if(!has_focus())
autocomplete.stop(); return false;
autocomplete.run(); if(is_possible_argument()) {
} autocomplete.stop();
return false; autocomplete.run();
}, }
500); return false;
}, },
false); 500);
},
false);
// Remove argument completions // Remove argument completions
signal_key_press_event().connect([this](GdkEventKey *event) { signal_key_press_event().connect(
if(show_parameters && CompletionDialog::get() && CompletionDialog::get()->is_visible() && [this](GdkEventKey *event) {
event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && if(show_parameters && CompletionDialog::get() && CompletionDialog::get()->is_visible() &&
event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter && event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up &&
event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab && event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter &&
(event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) { event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab &&
get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); (event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) {
CompletionDialog::get()->hide(); get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter());
} CompletionDialog::get()->hide();
return false; }
}, return false;
false); },
false);
autocomplete.is_restart_key = [this](guint keyval) { autocomplete.is_restart_key = [this](guint keyval) {
auto iter = get_buffer()->get_insert()->get_iter(); auto iter = get_buffer()->get_insert()->get_iter();
@ -2060,11 +2064,12 @@ void Source::ClangView::full_reparse() {
return; return;
if(full_reparse_running) { if(full_reparse_running) {
delayed_full_reparse_connection = Glib::signal_timeout().connect([this] { delayed_full_reparse_connection = Glib::signal_timeout().connect(
full_reparse(); [this] {
return false; full_reparse();
}, return false;
100); },
100);
return; return;
} }

105
src/source_diff.cpp

@ -118,65 +118,70 @@ void Source::DiffView::configure() {
parse_stop = false; parse_stop = false;
monitor_changed = false; monitor_changed = false;
buffer_insert_connection = get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter, const Glib::ustring &text, int) { buffer_insert_connection = get_buffer()->signal_insert().connect(
//Do not perform git diff if no newline is added and line is already marked as added [this](const Gtk::TextIter &iter, const Glib::ustring &text, int) {
if(!iter.starts_line() && iter.has_tag(renderer->tag_added)) { //Do not perform git diff if no newline is added and line is already marked as added
bool newline = false; if(!iter.starts_line() && iter.has_tag(renderer->tag_added)) {
for(auto &c : text.raw()) { bool newline = false;
if(c == '\n') { for(auto &c : text.raw()) {
newline = true; if(c == '\n') {
break; newline = true;
break;
}
}
if(!newline)
return;
} }
} //Remove tag_removed_above/below if newline is inserted
if(!newline) else if(!text.empty() && text[0] == '\n' && iter.has_tag(renderer->tag_removed)) {
return; auto start_iter = get_buffer()->get_iter_at_line(iter.get_line());
} auto end_iter = get_iter_at_line_end(iter.get_line());
//Remove tag_removed_above/below if newline is inserted end_iter.forward_char();
else if(!text.empty() && text[0] == '\n' && iter.has_tag(renderer->tag_removed)) { get_buffer()->remove_tag(renderer->tag_removed_above, start_iter, end_iter);
auto start_iter = get_buffer()->get_iter_at_line(iter.get_line()); get_buffer()->remove_tag(renderer->tag_removed_below, start_iter, end_iter);
auto end_iter = get_iter_at_line_end(iter.get_line()); }
end_iter.forward_char(); parse_state = ParseState::idle;
get_buffer()->remove_tag(renderer->tag_removed_above, start_iter, end_iter); delayed_buffer_changed_connection.disconnect();
get_buffer()->remove_tag(renderer->tag_removed_below, start_iter, end_iter); delayed_buffer_changed_connection = Glib::signal_timeout().connect(
} [this]() {
parse_state = ParseState::idle; parse_state = ParseState::starting;
delayed_buffer_changed_connection.disconnect(); return false;
delayed_buffer_changed_connection = Glib::signal_timeout().connect([this]() { },
parse_state = ParseState::starting; 250);
return false; },
}, false);
250);
},
false);
buffer_erase_connection = get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_iter, const Gtk::TextIter &end_iter) { buffer_erase_connection = get_buffer()->signal_erase().connect(
//Do not perform git diff if start_iter and end_iter is at the same line in addition to the line is tagged added [this](const Gtk::TextIter &start_iter, const Gtk::TextIter &end_iter) {
if(start_iter.get_line() == end_iter.get_line() && start_iter.has_tag(renderer->tag_added)) //Do not perform git diff if start_iter and end_iter is at the same line in addition to the line is tagged added
return; if(start_iter.get_line() == end_iter.get_line() && start_iter.has_tag(renderer->tag_added))
return;
parse_state = ParseState::idle; parse_state = ParseState::idle;
delayed_buffer_changed_connection.disconnect(); delayed_buffer_changed_connection.disconnect();
delayed_buffer_changed_connection = Glib::signal_timeout().connect([this]() { delayed_buffer_changed_connection = Glib::signal_timeout().connect(
parse_state = ParseState::starting; [this]() {
return false; parse_state = ParseState::starting;
}, return false;
250); },
}, 250);
false); },
false);
monitor_changed_connection = repository->monitor->signal_changed().connect([this](const Glib::RefPtr<Gio::File> &file, monitor_changed_connection = repository->monitor->signal_changed().connect([this](const Glib::RefPtr<Gio::File> &file,
const Glib::RefPtr<Gio::File> &, const Glib::RefPtr<Gio::File> &,
Gio::FileMonitorEvent monitor_event) { Gio::FileMonitorEvent monitor_event) {
if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
delayed_monitor_changed_connection.disconnect(); delayed_monitor_changed_connection.disconnect();
delayed_monitor_changed_connection = Glib::signal_timeout().connect([this]() { delayed_monitor_changed_connection = Glib::signal_timeout().connect(
monitor_changed = true; [this]() {
parse_state = ParseState::starting; monitor_changed = true;
LockGuard lock(parse_mutex); parse_state = ParseState::starting;
diff = nullptr; LockGuard lock(parse_mutex);
return false; diff = nullptr;
}, return false;
500); },
500);
} }
}); });

78
src/source_generic.cpp

@ -112,26 +112,27 @@ void Source::GenericView::setup_buffer_words() {
} }
// Remove changed word at insert // Remove changed word at insert
get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter_, const Glib::ustring &text, int bytes) { get_buffer()->signal_insert().connect(
auto iter = iter_; [this](const Gtk::TextIter &iter_, const Glib::ustring &text, int bytes) {
if(!is_token_char(*iter)) auto iter = iter_;
iter.backward_char(); if(!is_token_char(*iter))
iter.backward_char();
if(is_token_char(*iter)) {
auto word = get_token_iters(iter); if(is_token_char(*iter)) {
if(word.second.get_offset() - word.first.get_offset() >= 3) { auto word = get_token_iters(iter);
LockGuard lock(buffer_words_mutex); if(word.second.get_offset() - word.first.get_offset() >= 3) {
auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second)); LockGuard lock(buffer_words_mutex);
if(it != buffer_words.end()) { auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second));
if(it->second > 1) if(it != buffer_words.end()) {
--(it->second); if(it->second > 1)
else --(it->second);
buffer_words.erase(it); else
buffer_words.erase(it);
}
}
} }
} },
} false);
},
false);
// Add all words between start and end of insert // Add all words between start and end of insert
get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter, const Glib::ustring &text, int bytes) { get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter, const Glib::ustring &text, int bytes) {
@ -152,25 +153,26 @@ void Source::GenericView::setup_buffer_words() {
}); });
// Remove words within text that was removed // Remove words within text that was removed
get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_, const Gtk::TextIter &end_) { get_buffer()->signal_erase().connect(
auto start = start_; [this](const Gtk::TextIter &start_, const Gtk::TextIter &end_) {
auto end = end_; auto start = start_;
if(!is_token_char(*start)) auto end = end_;
start.backward_char(); if(!is_token_char(*start))
end.forward_char(); start.backward_char();
auto words = get_words(start, end); end.forward_char();
LockGuard lock(buffer_words_mutex); auto words = get_words(start, end);
for(auto &word : words) { LockGuard lock(buffer_words_mutex);
auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second)); for(auto &word : words) {
if(it != buffer_words.end()) { auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second));
if(it->second > 1) if(it != buffer_words.end()) {
--(it->second); if(it->second > 1)
else --(it->second);
buffer_words.erase(it); else
} buffer_words.erase(it);
} }
}, }
false); },
false);
// Add new word resulting from erased text // Add new word resulting from erased text
get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_, const Gtk::TextIter & /*end*/) { get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_, const Gtk::TextIter & /*end*/) {

207
src/source_language_protocol.cpp

@ -51,9 +51,15 @@ LanguageProtocol::TextEdit::TextEdit(const boost::property_tree::ptree &pt, std:
LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string language_id_) : root_path(std::move(root_path_)), language_id(std::move(language_id_)) { LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string language_id_) : root_path(std::move(root_path_)), language_id(std::move(language_id_)) {
process = std::make_unique<TinyProcessLib::Process>( process = std::make_unique<TinyProcessLib::Process>(
filesystem::escape_argument(language_id + "-language-server"), root_path.string(), [this](const char *bytes, size_t n) { filesystem::escape_argument(language_id + "-language-server"), root_path.string(),
server_message_stream.write(bytes, n); [this](const char *bytes, size_t n) {
parse_server_message(); }, [](const char *bytes, size_t n) { std::cerr.write(bytes, n); }, true, TinyProcessLib::Config{1048576}); server_message_stream.write(bytes, n);
parse_server_message();
},
[](const char *bytes, size_t n) {
std::cerr.write(bytes, n);
},
true, TinyProcessLib::Config{1048576});
} }
std::shared_ptr<LanguageProtocol::Client> LanguageProtocol::Client::get(const boost::filesystem::path &file_path, const std::string &language_id) { std::shared_ptr<LanguageProtocol::Client> LanguageProtocol::Client::get(const boost::filesystem::path &file_path, const std::string &language_id) {
@ -126,7 +132,8 @@ LanguageProtocol::Capabilities LanguageProtocol::Client::initialize(Source::Lang
LockGuard lock(read_write_mutex); LockGuard lock(read_write_mutex);
process_id = process->get_id(); process_id = process->get_id();
} }
write_request(nullptr, "initialize", "\"processId\":" + std::to_string(process_id) + R"(,"rootUri":")" + filesystem::get_uri_from_path(root_path) + R"(","capabilities": { write_request(
nullptr, "initialize", "\"processId\":" + std::to_string(process_id) + R"(,"rootUri":")" + filesystem::get_uri_from_path(root_path) + R"(","capabilities": {
"workspace": { "symbol": { "dynamicRegistration": true } }, "workspace": { "symbol": { "dynamicRegistration": true } },
"textDocument": { "textDocument": {
"synchronization": { "dynamicRegistration": true, "didSave": true }, "synchronization": { "dynamicRegistration": true, "didSave": true },
@ -168,38 +175,38 @@ LanguageProtocol::Capabilities LanguageProtocol::Client::initialize(Source::Lang
"checkOnSave": { "enable": true } "checkOnSave": { "enable": true }
}, },
"trace": "off")", "trace": "off")",
[this, &result_processed](const boost::property_tree::ptree &result, bool error) { [this, &result_processed](const boost::property_tree::ptree &result, bool error) {
if(!error) { if(!error) {
if(auto capabilities_pt = result.get_child_optional("capabilities")) { if(auto capabilities_pt = result.get_child_optional("capabilities")) {
try { try {
capabilities.text_document_sync = static_cast<LanguageProtocol::Capabilities::TextDocumentSync>(capabilities_pt->get<int>("textDocumentSync")); capabilities.text_document_sync = static_cast<LanguageProtocol::Capabilities::TextDocumentSync>(capabilities_pt->get<int>("textDocumentSync"));
} }
catch(...) { catch(...) {
capabilities.text_document_sync = static_cast<LanguageProtocol::Capabilities::TextDocumentSync>(capabilities_pt->get<int>("textDocumentSync.change", 0)); capabilities.text_document_sync = static_cast<LanguageProtocol::Capabilities::TextDocumentSync>(capabilities_pt->get<int>("textDocumentSync.change", 0));
} }
capabilities.hover = capabilities_pt->get<bool>("hoverProvider", false); capabilities.hover = capabilities_pt->get<bool>("hoverProvider", false);
capabilities.completion = static_cast<bool>(capabilities_pt->get_child_optional("completionProvider")); capabilities.completion = static_cast<bool>(capabilities_pt->get_child_optional("completionProvider"));
capabilities.signature_help = static_cast<bool>(capabilities_pt->get_child_optional("signatureHelpProvider")); capabilities.signature_help = static_cast<bool>(capabilities_pt->get_child_optional("signatureHelpProvider"));
capabilities.definition = capabilities_pt->get<bool>("definitionProvider", false); capabilities.definition = capabilities_pt->get<bool>("definitionProvider", false);
capabilities.references = capabilities_pt->get<bool>("referencesProvider", false); capabilities.references = capabilities_pt->get<bool>("referencesProvider", false);
capabilities.document_highlight = capabilities_pt->get<bool>("documentHighlightProvider", false); capabilities.document_highlight = capabilities_pt->get<bool>("documentHighlightProvider", false);
capabilities.workspace_symbol = capabilities_pt->get<bool>("workspaceSymbolProvider", false); capabilities.workspace_symbol = capabilities_pt->get<bool>("workspaceSymbolProvider", false);
capabilities.document_symbol = capabilities_pt->get<bool>("documentSymbolProvider", false); capabilities.document_symbol = capabilities_pt->get<bool>("documentSymbolProvider", false);
capabilities.document_formatting = capabilities_pt->get<bool>("documentFormattingProvider", false); capabilities.document_formatting = capabilities_pt->get<bool>("documentFormattingProvider", false);
capabilities.document_range_formatting = capabilities_pt->get<bool>("documentRangeFormattingProvider", false); capabilities.document_range_formatting = capabilities_pt->get<bool>("documentRangeFormattingProvider", false);
capabilities.rename = capabilities_pt->get<bool>("renameProvider", false); capabilities.rename = capabilities_pt->get<bool>("renameProvider", false);
if(!capabilities.rename) if(!capabilities.rename)
capabilities.rename = capabilities_pt->get<bool>("renameProvider.prepareProvider", false); capabilities.rename = capabilities_pt->get<bool>("renameProvider.prepareProvider", false);
capabilities.code_action = capabilities_pt->get<bool>("codeActionProvider", false); capabilities.code_action = capabilities_pt->get<bool>("codeActionProvider", false);
if(!capabilities.code_action) if(!capabilities.code_action)
capabilities.code_action = static_cast<bool>(capabilities_pt->get_child_optional("codeActionProvider.codeActionKinds")); capabilities.code_action = static_cast<bool>(capabilities_pt->get_child_optional("codeActionProvider.codeActionKinds"));
capabilities.type_coverage = capabilities_pt->get<bool>("typeCoverageProvider", false); capabilities.type_coverage = capabilities_pt->get<bool>("typeCoverageProvider", false);
} }
write_notification("initialized", ""); write_notification("initialized", "");
} }
result_processed.set_value(); result_processed.set_value();
}); });
result_processed.get_future().get(); result_processed.get_future().get();
initialized = true; initialized = true;
@ -1024,7 +1031,11 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector<Language
for(auto &quickfix_diagnostic : quickfix_diagnostics) { for(auto &quickfix_diagnostic : quickfix_diagnostics) {
if(diagnostic.message == quickfix_diagnostic.message && diagnostic.range == quickfix_diagnostic.range) { if(diagnostic.message == quickfix_diagnostic.message && diagnostic.range == quickfix_diagnostic.range) {
auto pair = diagnostic.quickfixes.emplace(title, std::vector<Source::FixIt>{}); auto pair = diagnostic.quickfixes.emplace(title, std::vector<Source::FixIt>{});
pair.first->second.emplace_back(edit.new_text, filesystem::get_path_from_uri(file_it->first).string(), std::make_pair<Offset, Offset>(Offset(edit.range.start.line, edit.range.start.character), Offset(edit.range.end.line, edit.range.end.character))); pair.first->second.emplace_back(
edit.new_text,
filesystem::get_path_from_uri(file_it->first).string(),
std::make_pair<Offset, Offset>(Offset(edit.range.start.line, edit.range.start.character),
Offset(edit.range.end.line, edit.range.end.character)));
break; break;
} }
} }
@ -1034,7 +1045,11 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector<Language
for(auto &diagnostic : diagnostics) { for(auto &diagnostic : diagnostics) {
if(edit.range.start.line == diagnostic.range.start.line) { if(edit.range.start.line == diagnostic.range.start.line) {
auto pair = diagnostic.quickfixes.emplace(title, std::vector<Source::FixIt>{}); auto pair = diagnostic.quickfixes.emplace(title, std::vector<Source::FixIt>{});
pair.first->second.emplace_back(edit.new_text, filesystem::get_path_from_uri(file_it->first).string(), std::make_pair<Offset, Offset>(Offset(edit.range.start.line, edit.range.start.character), Offset(edit.range.end.line, edit.range.end.character))); pair.first->second.emplace_back(
edit.new_text,
filesystem::get_path_from_uri(file_it->first).string(),
std::make_pair<Offset, Offset>(Offset(edit.range.start.line, edit.range.start.character),
Offset(edit.range.end.line, edit.range.end.character)));
break; break;
} }
} }
@ -1400,17 +1415,19 @@ Source::Offset Source::LanguageProtocolView::get_declaration(const Gtk::TextIter
void Source::LanguageProtocolView::setup_signals() { void Source::LanguageProtocolView::setup_signals() {
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::incremental) { if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::incremental) {
get_buffer()->signal_insert().connect([this](const Gtk::TextIter &start, const Glib::ustring &text_, int bytes) { get_buffer()->signal_insert().connect(
std::string text = text_; [this](const Gtk::TextIter &start, const Glib::ustring &text_, int bytes) {
escape_text(text); std::string text = text_;
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(}},"text":")" + text + "\"}" + "]"); escape_text(text);
}, client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(}},"text":")" + text + "\"}" + "]");
false); },
false);
get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start, const Gtk::TextIter &end) {
client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(end.get_line()) + ",\"character\":" + std::to_string(end.get_line_offset()) + R"(}},"text":""})" + "]"); get_buffer()->signal_erase().connect(
}, [this](const Gtk::TextIter &start, const Gtk::TextIter &end) {
false); client->write_notification("textDocument/didChange", R"("textDocument":{"uri":")" + this->uri + R"(","version":)" + std::to_string(document_version++) + "},\"contentChanges\":[" + R"({"range":{"start":{"line": )" + std::to_string(start.get_line()) + ",\"character\":" + std::to_string(start.get_line_offset()) + R"(},"end":{"line":)" + std::to_string(end.get_line()) + ",\"character\":" + std::to_string(end.get_line_offset()) + R"(}},"text":""})" + "]");
},
false);
} }
else if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::full) { else if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::full) {
get_buffer()->signal_changed().connect([this]() { get_buffer()->signal_changed().connect([this]() {
@ -1439,47 +1456,50 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(capabilities.signature_help) { if(capabilities.signature_help) {
// Activate argument completions // Activate argument completions
get_buffer()->signal_changed().connect([this] { get_buffer()->signal_changed().connect(
if(!interactive_completion) [this] {
return; if(!interactive_completion)
if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) return;
return; if(CompletionDialog::get() && CompletionDialog::get()->is_visible())
if(!has_focus()) return;
return; if(!has_focus())
if(autocomplete_show_arguments) return;
autocomplete->stop(); if(autocomplete_show_arguments)
autocomplete_show_arguments = false; autocomplete->stop();
autocomplete_delayed_show_arguments_connection.disconnect(); autocomplete_show_arguments = false;
autocomplete_delayed_show_arguments_connection = Glib::signal_timeout().connect([this]() { autocomplete_delayed_show_arguments_connection.disconnect();
if(get_buffer()->get_has_selection()) autocomplete_delayed_show_arguments_connection = Glib::signal_timeout().connect(
return false; [this]() {
if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) if(get_buffer()->get_has_selection())
return false; return false;
if(!has_focus()) if(CompletionDialog::get() && CompletionDialog::get()->is_visible())
return false; return false;
if(is_possible_argument()) { if(!has_focus())
autocomplete->stop(); return false;
autocomplete->run(); if(is_possible_argument()) {
} autocomplete->stop();
return false; autocomplete->run();
}, }
500); return false;
}, },
false); 500);
},
false);
// Remove argument completions // Remove argument completions
signal_key_press_event().connect([this](GdkEventKey *event) { signal_key_press_event().connect(
if(autocomplete_show_arguments && CompletionDialog::get() && CompletionDialog::get()->is_visible() && [this](GdkEventKey *event) {
event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && if(autocomplete_show_arguments && CompletionDialog::get() && CompletionDialog::get()->is_visible() &&
event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter && event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up &&
event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab && event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter &&
(event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) { event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab &&
get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); (event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) {
CompletionDialog::get()->hide(); get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter());
} CompletionDialog::get()->hide();
return false; }
}, return false;
false); },
false);
} }
autocomplete->is_restart_key = [this](guint keyval) { autocomplete->is_restart_key = [this](guint keyval) {
@ -1826,12 +1846,13 @@ void Source::LanguageProtocolView::update_type_coverage() {
if(update_type_coverage_retries > 0) { // Retry typeCoverage request, since these requests can fail while waiting for language server to start if(update_type_coverage_retries > 0) { // Retry typeCoverage request, since these requests can fail while waiting for language server to start
dispatcher.post([this] { dispatcher.post([this] {
update_type_coverage_connection.disconnect(); update_type_coverage_connection.disconnect();
update_type_coverage_connection = Glib::signal_timeout().connect([this]() { update_type_coverage_connection = Glib::signal_timeout().connect(
--update_type_coverage_retries; [this]() {
update_type_coverage(); --update_type_coverage_retries;
return false; update_type_coverage();
}, return false;
1000); },
1000);
}); });
} }
return; return;

186
src/source_spellcheck.cpp

@ -13,15 +13,16 @@ Source::SpellCheckView::SpellCheckView(const boost::filesystem::path &file_path,
spellcheck_error_tag = get_buffer()->create_tag("spellcheck_error"); spellcheck_error_tag = get_buffer()->create_tag("spellcheck_error");
spellcheck_error_tag->property_underline() = Pango::Underline::UNDERLINE_ERROR; spellcheck_error_tag->property_underline() = Pango::Underline::UNDERLINE_ERROR;
signal_key_press_event().connect([](GdkEventKey *event) { signal_key_press_event().connect(
if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) { [](GdkEventKey *event) {
if(SelectionDialog::get()->on_key_press(event)) if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) {
return true; if(SelectionDialog::get()->on_key_press(event))
} return true;
}
return false; return false;
}, },
false); false);
//The following signal is added in case SpellCheckView is not subclassed //The following signal is added in case SpellCheckView is not subclassed
signal_key_press_event().connect([this](GdkEventKey *event) { signal_key_press_event().connect([this](GdkEventKey *event) {
@ -83,68 +84,70 @@ Source::SpellCheckView::SpellCheckView(const boost::filesystem::path &file_path,
} }
} }
delayed_spellcheck_error_clear.disconnect(); delayed_spellcheck_error_clear.disconnect();
delayed_spellcheck_error_clear = Glib::signal_timeout().connect([this]() { delayed_spellcheck_error_clear = Glib::signal_timeout().connect(
auto iter = get_buffer()->begin(); [this]() {
Gtk::TextIter begin_no_spellcheck_iter; auto iter = get_buffer()->begin();
if(spellcheck_all) { Gtk::TextIter begin_no_spellcheck_iter;
bool spell_check = !get_source_buffer()->iter_has_context_class(iter, "no-spell-check"); if(spellcheck_all) {
if(!spell_check) bool spell_check = !get_source_buffer()->iter_has_context_class(iter, "no-spell-check");
begin_no_spellcheck_iter = iter; if(!spell_check)
while(iter != get_buffer()->end()) { begin_no_spellcheck_iter = iter;
if(!get_source_buffer()->iter_forward_to_context_class_toggle(iter, "no-spell-check")) while(iter != get_buffer()->end()) {
iter = get_buffer()->end(); if(!get_source_buffer()->iter_forward_to_context_class_toggle(iter, "no-spell-check"))
iter = get_buffer()->end();
spell_check = !spell_check;
spell_check = !spell_check;
if(!spell_check)
begin_no_spellcheck_iter = iter;
else
get_buffer()->remove_tag(spellcheck_error_tag, begin_no_spellcheck_iter, iter);
}
return false;
}
bool spell_check = get_source_buffer()->iter_has_context_class(iter, "string") || get_source_buffer()->iter_has_context_class(iter, "comment");
if(!spell_check) if(!spell_check)
begin_no_spellcheck_iter = iter; begin_no_spellcheck_iter = iter;
else while(iter != get_buffer()->end()) {
get_buffer()->remove_tag(spellcheck_error_tag, begin_no_spellcheck_iter, iter); auto iter1 = iter;
} auto iter2 = iter;
return false; if(!get_source_buffer()->iter_forward_to_context_class_toggle(iter1, "string"))
} iter1 = get_buffer()->end();
if(!get_source_buffer()->iter_forward_to_context_class_toggle(iter2, "comment"))
bool spell_check = get_source_buffer()->iter_has_context_class(iter, "string") || get_source_buffer()->iter_has_context_class(iter, "comment"); iter2 = get_buffer()->end();
if(!spell_check)
begin_no_spellcheck_iter = iter; if(iter2 < iter1)
while(iter != get_buffer()->end()) { iter = iter2;
auto iter1 = iter; else
auto iter2 = iter; iter = iter1;
if(!get_source_buffer()->iter_forward_to_context_class_toggle(iter1, "string")) spell_check = !spell_check;
iter1 = get_buffer()->end(); if(!spell_check)
if(!get_source_buffer()->iter_forward_to_context_class_toggle(iter2, "comment")) begin_no_spellcheck_iter = iter;
iter2 = get_buffer()->end(); else
get_buffer()->remove_tag(spellcheck_error_tag, begin_no_spellcheck_iter, iter);
if(iter2 < iter1) }
iter = iter2; return false;
else },
iter = iter1; 1000);
spell_check = !spell_check;
if(!spell_check)
begin_no_spellcheck_iter = iter;
else
get_buffer()->remove_tag(spellcheck_error_tag, begin_no_spellcheck_iter, iter);
}
return false;
},
1000);
}); });
// In case of for instance text paste or undo/redo // In case of for instance text paste or undo/redo
get_buffer()->signal_insert().connect([this](const Gtk::TextIter &start_iter, const Glib::ustring &inserted_string, int) { get_buffer()->signal_insert().connect(
if(!spellcheck_checker) [this](const Gtk::TextIter &start_iter, const Glib::ustring &inserted_string, int) {
return; if(!spellcheck_checker)
return;
if(disable_spellcheck) {
auto iter = start_iter; if(disable_spellcheck) {
if(!is_word_iter(iter) && !iter.starts_line()) auto iter = start_iter;
iter.backward_char(); if(!is_word_iter(iter) && !iter.starts_line())
if(is_word_iter(iter)) { iter.backward_char();
auto word = get_word(iter); if(is_word_iter(iter)) {
get_buffer()->remove_tag(spellcheck_error_tag, word.first, word.second); auto word = get_word(iter);
} get_buffer()->remove_tag(spellcheck_error_tag, word.first, word.second);
} }
}, }
false); },
false);
get_buffer()->signal_mark_set().connect([this](const Gtk::TextIter &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) { get_buffer()->signal_mark_set().connect([this](const Gtk::TextIter &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) {
if(mark->get_name() == "insert") { if(mark->get_name() == "insert") {
@ -155,34 +158,35 @@ Source::SpellCheckView::SpellCheckView(const boost::filesystem::path &file_path,
delayed_spellcheck_suggestions_connection.disconnect(); delayed_spellcheck_suggestions_connection.disconnect();
if(get_buffer()->get_has_selection()) if(get_buffer()->get_has_selection())
return; return;
delayed_spellcheck_suggestions_connection = Glib::signal_timeout().connect([this]() { delayed_spellcheck_suggestions_connection = Glib::signal_timeout().connect(
if(get_buffer()->get_insert()->get_iter().has_tag(spellcheck_error_tag)) { [this]() {
SelectionDialog::create(this, false); if(get_buffer()->get_insert()->get_iter().has_tag(spellcheck_error_tag)) {
auto word = get_word(get_buffer()->get_insert()->get_iter()); SelectionDialog::create(this, false);
if(*word.first == '\'' && word.second.get_offset() - word.first.get_offset() >= 3) { auto word = get_word(get_buffer()->get_insert()->get_iter());
auto before_end = word.second; if(*word.first == '\'' && word.second.get_offset() - word.first.get_offset() >= 3) {
if(before_end.backward_char() && *before_end == '\'') { auto before_end = word.second;
word.first.forward_char(); if(before_end.backward_char() && *before_end == '\'') {
word.second.backward_char(); word.first.forward_char();
word.second.backward_char();
}
}
auto suggestions = get_spellcheck_suggestions(word.first, word.second);
if(suggestions.size() == 0)
return false;
for(auto &suggestion : suggestions)
SelectionDialog::get()->add_row(suggestion);
SelectionDialog::get()->on_select = [this, word](unsigned int index, const std::string &text, bool hide_window) {
get_buffer()->begin_user_action();
get_buffer()->erase(word.first, word.second);
get_buffer()->insert(get_buffer()->get_insert()->get_iter(), text);
get_buffer()->end_user_action();
};
hide_tooltips();
SelectionDialog::get()->show();
} }
}
auto suggestions = get_spellcheck_suggestions(word.first, word.second);
if(suggestions.size() == 0)
return false; return false;
for(auto &suggestion : suggestions) },
SelectionDialog::get()->add_row(suggestion); 500);
SelectionDialog::get()->on_select = [this, word](unsigned int index, const std::string &text, bool hide_window) {
get_buffer()->begin_user_action();
get_buffer()->erase(word.first, word.second);
get_buffer()->insert(get_buffer()->get_insert()->get_iter(), text);
get_buffer()->end_user_action();
};
hide_tooltips();
SelectionDialog::get()->show();
}
return false;
},
500);
} }
}); });

82
src/terminal.cpp

@ -211,7 +211,13 @@ int Terminal::process(const std::string &command, const boost::filesystem::path
std::unique_ptr<TinyProcessLib::Process> process; std::unique_ptr<TinyProcessLib::Process> process;
if(use_pipes) if(use_pipes)
process = std::make_unique<TinyProcessLib::Process>( process = std::make_unique<TinyProcessLib::Process>(
command, path.string(), [this](const char *bytes, size_t n) { async_print(std::string(bytes, n)); }, [this](const char *bytes, size_t n) { async_print(std::string(bytes, n), true); }); command, path.string(),
[this](const char *bytes, size_t n) {
async_print(std::string(bytes, n));
},
[this](const char *bytes, size_t n) {
async_print(std::string(bytes, n), true);
});
else else
process = std::make_unique<TinyProcessLib::Process>(command, path.string()); process = std::make_unique<TinyProcessLib::Process>(command, path.string());
@ -228,19 +234,24 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c
scroll_to_bottom(); scroll_to_bottom();
TinyProcessLib::Process process( TinyProcessLib::Process process(
command, path.string(), [&stdout_stream](const char *bytes, size_t n) { command, path.string(),
Glib::ustring umessage(std::string(bytes, n)); [&stdout_stream](const char *bytes, size_t n) {
Glib::ustring::iterator iter; Glib::ustring umessage(std::string(bytes, n));
while(!umessage.validate(iter)) { Glib::ustring::iterator iter;
auto next_char_iter = iter; while(!umessage.validate(iter)) {
next_char_iter++; auto next_char_iter = iter;
umessage.replace(iter, next_char_iter, "?"); next_char_iter++;
} umessage.replace(iter, next_char_iter, "?");
stdout_stream.write(umessage.data(), n); }, [this, stderr_stream](const char *bytes, size_t n) { }
if(stderr_stream) stdout_stream.write(umessage.data(), n);
stderr_stream->write(bytes, n); },
else [this, stderr_stream](const char *bytes, size_t n) {
async_print(std::string(bytes, n), true); }, true); if(stderr_stream)
stderr_stream->write(bytes, n);
else
async_print(std::string(bytes, n), true);
},
true);
if(process.get_id() <= 0) { if(process.get_id() <= 0) {
async_print("\e[31mError\e[m: failed to run command: " + command + "\n", true); async_print("\e[31mError\e[m: failed to run command: " + command + "\n", true);
@ -268,25 +279,30 @@ std::shared_ptr<TinyProcessLib::Process> Terminal::async_process(const std::stri
stdin_buffer.clear(); stdin_buffer.clear();
auto process = std::make_shared<TinyProcessLib::Process>( auto process = std::make_shared<TinyProcessLib::Process>(
command, path.string(), [this, quiet](const char *bytes, size_t n) { command, path.string(),
if(!quiet) { [this, quiet](const char *bytes, size_t n) {
// Print stdout message sequentially to avoid the GUI becoming unresponsive if(!quiet) {
std::promise<void> message_printed; // Print stdout message sequentially to avoid the GUI becoming unresponsive
dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { std::promise<void> message_printed;
Terminal::get().print(std::move(message)); dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable {
message_printed.set_value(); Terminal::get().print(std::move(message));
}); message_printed.set_value();
message_printed.get_future().get(); });
} }, [this, quiet](const char *bytes, size_t n) { message_printed.get_future().get();
if(!quiet) { }
// Print stderr message sequentially to avoid the GUI becoming unresponsive },
std::promise<void> message_printed; [this, quiet](const char *bytes, size_t n) {
dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { if(!quiet) {
Terminal::get().print(std::move(message), true); // Print stderr message sequentially to avoid the GUI becoming unresponsive
message_printed.set_value(); std::promise<void> message_printed;
}); dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable {
message_printed.get_future().get(); Terminal::get().print(std::move(message), true);
} }, true); message_printed.set_value();
});
message_printed.get_future().get();
}
},
true);
auto pid = process->get_id(); auto pid = process->get_id();
if(pid <= 0) { if(pid <= 0) {

8
tests/process_test.cpp

@ -15,7 +15,13 @@ int main() {
{ {
TinyProcessLib::Process process( TinyProcessLib::Process process(
"echo Test && ls an_incorrect_path", "", [output](const char *bytes, size_t n) { *output += std::string(bytes, n); }, [error](const char *bytes, size_t n) { *error += std::string(bytes, n); }); "echo Test && ls an_incorrect_path", "",
[output](const char *bytes, size_t n) {
*output += std::string(bytes, n);
},
[error](const char *bytes, size_t n) {
*error += std::string(bytes, n);
});
g_assert(process.get_exit_status() > 0); g_assert(process.get_exit_status() > 0);
g_assert(output->substr(0, 4) == "Test"); g_assert(output->substr(0, 4) == "Test");
g_assert(!error->empty()); g_assert(!error->empty());

Loading…
Cancel
Save