diff --git a/src/autocomplete.cpp b/src/autocomplete.cpp index 0787039..0c50990 100644 --- a/src/autocomplete.cpp +++ b/src/autocomplete.cpp @@ -25,14 +25,15 @@ Autocomplete::Autocomplete(Gsv::View *view, bool &interactive_completion, guint stop(); }); - view->signal_key_release_event().connect([](GdkEventKey *event) { - if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) { - if(CompletionDialog::get()->on_key_release(event)) - return true; - } - return false; - }, - false); + view->signal_key_release_event().connect( + [](GdkEventKey *event) { + if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) { + if(CompletionDialog::get()->on_key_release(event)) + return true; + } + return false; + }, + false); view->signal_focus_out_event().connect([this](GdkEventFocus *event) { stop(); diff --git a/src/directories.cpp b/src/directories.cpp index d6cd6dd..5508dc4 100644 --- a/src/directories.cpp +++ b/src/directories.cpp @@ -674,12 +674,13 @@ void Directories::add_or_update_path(const boost::filesystem::path &dir_path, co if(repository) repository->clear_saved_status(); connection->disconnect(); - *connection = Glib::signal_timeout().connect([path_and_row, this]() { - if(directories.find(path_and_row->first.string()) != directories.end()) - add_or_update_path(path_and_row->first, path_and_row->second, true); - return false; - }, - 500); + *connection = Glib::signal_timeout().connect( + [path_and_row, this]() { + if(directories.find(path_and_row->first.string()) != directories.end()) + add_or_update_path(path_and_row->first, path_and_row->second, true); + return false; + }, + 500); } }); @@ -695,12 +696,13 @@ void Directories::add_or_update_path(const boost::filesystem::path &dir_path, co Gio::FileMonitorEvent monitor_event) { if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { connection->disconnect(); - *connection = Glib::signal_timeout().connect([this, path_and_row] { - if(directories.find(path_and_row->first.string()) != directories.end()) - colorize_path(path_and_row->first, false); - return false; - }, - 500); + *connection = Glib::signal_timeout().connect( + [this, path_and_row] { + if(directories.find(path_and_row->first.string()) != directories.end()) + colorize_path(path_and_row->first, false); + return false; + }, + 500); } }); } diff --git a/src/files.hpp b/src/files.hpp index 410d04d..058103c 100644 --- a/src/files.hpp +++ b/src/files.hpp @@ -4,9 +4,11 @@ /// If you add or remove nodes from the default_config_file, increase the juci /// version number (JUCI_VERSION) in ../CMakeLists.txt to automatically apply /// the changes to user's ~/.juci/config/config.json files -const std::string default_config_file = R"RAW({ - "version": ")RAW" + std::string(JUCI_VERSION) + - R"RAW(", +const std::string default_config_file = + R"RAW({ + "version": ")RAW" + + std::string(JUCI_VERSION) + + R"RAW(", "gtk_theme": { "name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh", "name": "", @@ -20,18 +22,18 @@ const std::string default_config_file = R"RAW({ "style": "juci-light", "font_comment": "Use \"\" for default font, and for instance \"Monospace 12\" to also set size",)RAW" #ifdef __APPLE__ - R"RAW( + R"RAW( "font": "Menlo",)RAW" #else #ifdef _WIN32 - R"RAW( + R"RAW( "font": "Consolas",)RAW" #else - R"RAW( + R"RAW( "font": "Monospace",)RAW" #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": 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", @@ -91,13 +93,13 @@ const std::string default_config_file = R"RAW({ "debug_build_path": "/debug", "cmake": {)RAW" #ifdef _WIN32 - R"RAW( + R"RAW( "command": "cmake -G\"MSYS Makefiles\"",)RAW" #else - R"RAW( + R"RAW( "command": "cmake",)RAW" #endif - R"RAW( + R"RAW( "compile_command": "cmake --build ." }, "meson": { @@ -108,13 +110,13 @@ const std::string default_config_file = R"RAW({ "default_build_management_system": "cmake", "save_on_compile_or_run": true,)RAW" #ifdef JUCI_USE_UCTAGS - R"RAW( + R"RAW( "ctags_command": "uctags",)RAW" #else - R"RAW( + R"RAW( "ctags_command": "ctags",)RAW" #endif - R"RAW( + R"RAW( "grep_command": "grep", "cargo_command": "cargo", "python_command": "python -u", @@ -194,26 +196,26 @@ const std::string default_config_file = R"RAW({ "debug_show_breakpoints": "b", "debug_goto_stop": "l",)RAW" #ifdef __linux - R"RAW( + R"RAW( "window_next_tab": "Tab", "window_previous_tab": "Tab",)RAW" #else - R"RAW( + R"RAW( "window_next_tab": "Right", "window_previous_tab": "Left",)RAW" #endif - R"RAW( + R"RAW( "window_goto_tab": "", "window_toggle_split": "", "window_split_source_buffer": "",)RAW" #ifdef __APPLE__ - R"RAW( + R"RAW( "window_toggle_full_screen": "f",)RAW" #else - R"RAW( + R"RAW( "window_toggle_full_screen": "F11",)RAW" #endif - R"RAW( + R"RAW( "window_toggle_tabs": "", "window_toggle_zen_mode": "", "window_clear_terminal": "" diff --git a/src/git.cpp b/src/git.cpp index 9000403..a912252 100644 --- a/src/git.cpp +++ b/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()); monitor = git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); - monitor_changed_connection = monitor->signal_changed().connect([this](const Glib::RefPtr &file, - const Glib::RefPtr &, - Gio::FileMonitorEvent monitor_event) { - if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { - this->clear_saved_status(); - } - }, - false); + monitor_changed_connection = monitor->signal_changed().connect( + [this](const Glib::RefPtr &file, + const Glib::RefPtr &, + Gio::FileMonitorEvent monitor_event) { + if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { + this->clear_saved_status(); + } + }, + false); } Git::Repository::~Repository() { diff --git a/src/info.cpp b/src/info.cpp index bd8220a..75602f9 100644 --- a/src/info.cpp +++ b/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 //(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); - timeout_connection = Glib::signal_timeout().connect([this]() { - hide(); - return false; - }, - timeout); + timeout_connection = Glib::signal_timeout().connect( + [this]() { + hide(); + return false; + }, + timeout); label.set_text(text); show(); diff --git a/src/notebook.cpp b/src/notebook.cpp index 3eaab1c..28ded3a 100644 --- a/src/notebook.cpp +++ b/src/notebook.cpp @@ -618,11 +618,12 @@ void Notebook::toggle_split() { show_all(); //Make sure the position is correct //TODO: report bug to gtk if it is not fixed in gtk3.22 - Glib::signal_timeout().connect([this] { - set_position(get_width() / 2); - return false; - }, - 200); + Glib::signal_timeout().connect( + [this] { + set_position(get_width() / 2); + return false; + }, + 200); } else { for(size_t c = size() - 1; c != static_cast(-1); --c) { diff --git a/src/selection_dialog.cpp b/src/selection_dialog.cpp index 7ac3c24..06bc213 100644 --- a/src/selection_dialog.cpp +++ b/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); - search_entry.signal_changed().connect([this] { - if(on_search_entry_changed) - on_search_entry_changed(search_entry.get_text()); - }, - false); + search_entry.signal_changed().connect( + [this] { + if(on_search_entry_changed) + on_search_entry_changed(search_entry.get_text()); + }, + false); list_view_text.set_search_entry(search_entry); diff --git a/src/source.cpp b/src/source.cpp index 59877dc..74dd2ae 100644 --- a/src/source.cpp +++ b/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) { delayed_tooltips_connection.disconnect(); if((event->state & GDK_BUTTON1_MASK) == 0) { - delayed_tooltips_connection = Glib::signal_timeout().connect([this, x = event->x, y = event->y]() { - type_tooltips.hide(); - diagnostic_tooltips.hide(); - Tooltips::init(); - Gdk::Rectangle rectangle(x, y, 1, 1); - if(parsed) { - show_type_tooltips(rectangle); - show_diagnostic_tooltips(rectangle); - } - return false; - }, - 100); + delayed_tooltips_connection = Glib::signal_timeout().connect( + [this, x = event->x, y = event->y]() { + type_tooltips.hide(); + diagnostic_tooltips.hide(); + Tooltips::init(); + Gdk::Rectangle rectangle(x, y, 1, 1); + if(parsed) { + show_type_tooltips(rectangle); + show_diagnostic_tooltips(rectangle); + } + return false; + }, + 100); } 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)) { delayed_tag_clickable_connection.disconnect(); - delayed_tag_clickable_connection = Glib::signal_timeout().connect([this, x = event->x, y = event->y]() { - int buffer_x, buffer_y; - window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, x, y, buffer_x, buffer_y); - Gtk::TextIter iter; - get_iter_at_location(iter, buffer_x, buffer_y); - apply_clickable_tag(iter); - clickable_tag_applied = true; - return false; - }, - 100); + delayed_tag_clickable_connection = Glib::signal_timeout().connect( + [this, x = event->x, y = event->y]() { + int buffer_x, buffer_y; + window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, x, y, buffer_x, buffer_y); + Gtk::TextIter iter; + get_iter_at_location(iter, buffer_x, buffer_y); + apply_clickable_tag(iter); + clickable_tag_applied = true; + return false; + }, + 100); } auto last_mouse_pos = std::make_pair(on_motion_last_x, on_motion_last_y); @@ -646,30 +648,32 @@ void Source::View::setup_signals() { hide_tooltips(); delayed_tooltips_connection.disconnect(); - delayed_tooltips_connection = Glib::signal_timeout().connect([this]() { - Tooltips::init(); - Gdk::Rectangle rectangle; - get_iter_location(get_buffer()->get_insert()->get_iter(), rectangle); - int location_window_x, location_window_y; - buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, rectangle.get_x(), rectangle.get_y(), location_window_x, location_window_y); - rectangle.set_x(location_window_x - 2); - rectangle.set_y(location_window_y); - rectangle.set_width(5); - if(parsed) { - show_type_tooltips(rectangle); - show_diagnostic_tooltips(rectangle); - } - return false; - }, - 500); + delayed_tooltips_connection = Glib::signal_timeout().connect( + [this]() { + Tooltips::init(); + Gdk::Rectangle rectangle; + get_iter_location(get_buffer()->get_insert()->get_iter(), rectangle); + int location_window_x, location_window_y; + buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, rectangle.get_x(), rectangle.get_y(), location_window_x, location_window_y); + rectangle.set_x(location_window_x - 2); + rectangle.set_y(location_window_y); + rectangle.set_width(5); + if(parsed) { + show_type_tooltips(rectangle); + show_diagnostic_tooltips(rectangle); + } + return false; + }, + 500); delayed_tag_similar_symbols_connection.disconnect(); - delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect([this] { - apply_similar_symbol_tag(); - similar_symbol_tag_applied = true; - return false; - }, - 100); + delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect( + [this] { + apply_similar_symbol_tag(); + similar_symbol_tag_applied = true; + return false; + }, + 100); if(SelectionDialog::get()) SelectionDialog::get()->hide(); diff --git a/src/source_base.cpp b/src/source_base.cpp index 72b1ffc..367fc1f 100644 --- a/src/source_base.cpp +++ b/src/source_base.cpp @@ -343,23 +343,24 @@ void Source::BaseView::monitor_file() { public: static void f(BaseView *view, boost::optional previous_last_write_time = {}, bool check_called = false) { view->delayed_monitor_changed_connection.disconnect(); - view->delayed_monitor_changed_connection = Glib::signal_timeout().connect([view, previous_last_write_time, check_called]() { - boost::system::error_code ec; - auto last_write_time = boost::filesystem::last_write_time(view->file_path, ec); - if(!ec && last_write_time != view->last_write_time) { - if(last_write_time == previous_last_write_time) { // If no change has happened in the last second (std::time_t is in seconds). - if(!check_called) // To avoid several info messages when file is changed but not reloaded. - view->check_last_write_time(last_write_time); - Recursive::f(view, last_write_time, true); + view->delayed_monitor_changed_connection = Glib::signal_timeout().connect( + [view, previous_last_write_time, check_called]() { + boost::system::error_code ec; + auto last_write_time = boost::filesystem::last_write_time(view->file_path, ec); + if(!ec && last_write_time != view->last_write_time) { + if(last_write_time == previous_last_write_time) { // If no change has happened in the last second (std::time_t is in seconds). + if(!check_called) // To avoid several info messages when file is changed but not reloaded. + 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; - } - Recursive::f(view, last_write_time); - return false; - } - Recursive::f(view); - return false; - }, - 1000); + }, + 1000); } }; delayed_monitor_changed_connection.disconnect(); @@ -374,11 +375,12 @@ void Source::BaseView::monitor_file() { Gio::FileMonitorEvent monitor_event) { if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { delayed_monitor_changed_connection.disconnect(); - delayed_monitor_changed_connection = Glib::signal_timeout().connect([this]() { - check_last_write_time(); - return false; - }, - 1000); // Has to wait 1 second (std::time_t is in seconds) + delayed_monitor_changed_connection = Glib::signal_timeout().connect( + [this]() { + check_last_write_time(); + return false; + }, + 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(0); auto erase_forward_length = std::make_shared(0); auto erase_selection = std::make_shared(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) { - if(enable_multiple_cursors && (!extra_cursors.empty())) { - auto insert_offset = get_buffer()->get_insert()->get_iter().get_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(); - iter.forward_chars(*erase_forward_length); - 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(); - iter.backward_chars(*erase_backward_length); - if(iter == get_buffer()->get_selection_bound()->get_iter()) - *erase_selection = true; - } - } - }, - 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) { + if(enable_multiple_cursors && (!extra_cursors.empty())) { + auto insert_offset = get_buffer()->get_insert()->get_iter().get_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(); + iter.forward_chars(*erase_forward_length); + 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(); + iter.backward_chars(*erase_backward_length); + if(iter == get_buffer()->get_selection_bound()->get_iter()) + *erase_selection = true; + } + } + }, + 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*/) { if(enable_multiple_cursors && (*erase_backward_length != 0 || *erase_forward_length != 0)) { enable_multiple_cursors = false; diff --git a/src/source_clang.cpp b/src/source_clang.cpp index 87c935b..d7596ec 100644 --- a/src/source_clang.cpp +++ b/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(), {}}; auto start_cursor = cursor; - for(auto parent = cursor.get_semantic_parent(); parent.get_kind() != clangmm::Cursor::Kind::TranslationUnit && - parent.get_kind() != clangmm::Cursor::Kind::ClassDecl; + for(auto parent = cursor.get_semantic_parent(); + parent.get_kind() != clangmm::Cursor::Kind::TranslationUnit && + parent.get_kind() != clangmm::Cursor::Kind::ClassDecl; parent = parent.get_semantic_parent()) start_cursor = parent; clang_visitChildren( @@ -801,47 +802,50 @@ Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::pa }; // Activate argument completions - get_buffer()->signal_changed().connect([this] { - if(!interactive_completion) - return; - if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) - return; - if(!has_focus()) - return; - if(show_parameters) - autocomplete.stop(); - show_parameters = false; - delayed_show_arguments_connection.disconnect(); - delayed_show_arguments_connection = Glib::signal_timeout().connect([this]() { - if(get_buffer()->get_has_selection()) - return false; - if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) - return false; - if(!has_focus()) - return false; - if(is_possible_argument()) { - autocomplete.stop(); - autocomplete.run(); - } - return false; - }, - 500); - }, - false); + get_buffer()->signal_changed().connect( + [this] { + if(!interactive_completion) + return; + if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) + return; + if(!has_focus()) + return; + if(show_parameters) + autocomplete.stop(); + show_parameters = false; + delayed_show_arguments_connection.disconnect(); + delayed_show_arguments_connection = Glib::signal_timeout().connect( + [this]() { + if(get_buffer()->get_has_selection()) + return false; + if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) + return false; + if(!has_focus()) + return false; + if(is_possible_argument()) { + autocomplete.stop(); + autocomplete.run(); + } + return false; + }, + 500); + }, + false); // Remove argument completions - signal_key_press_event().connect([this](GdkEventKey *event) { - if(show_parameters && CompletionDialog::get() && CompletionDialog::get()->is_visible() && - event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && - event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter && - event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab && - (event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) { - get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); - CompletionDialog::get()->hide(); - } - return false; - }, - false); + signal_key_press_event().connect( + [this](GdkEventKey *event) { + if(show_parameters && CompletionDialog::get() && CompletionDialog::get()->is_visible() && + event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && + event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter && + event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab && + (event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) { + get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); + CompletionDialog::get()->hide(); + } + return false; + }, + false); autocomplete.is_restart_key = [this](guint keyval) { auto iter = get_buffer()->get_insert()->get_iter(); @@ -2060,11 +2064,12 @@ void Source::ClangView::full_reparse() { return; if(full_reparse_running) { - delayed_full_reparse_connection = Glib::signal_timeout().connect([this] { - full_reparse(); - return false; - }, - 100); + delayed_full_reparse_connection = Glib::signal_timeout().connect( + [this] { + full_reparse(); + return false; + }, + 100); return; } diff --git a/src/source_diff.cpp b/src/source_diff.cpp index 8044b1e..c54f89b 100644 --- a/src/source_diff.cpp +++ b/src/source_diff.cpp @@ -118,65 +118,70 @@ void Source::DiffView::configure() { parse_stop = false; monitor_changed = false; - buffer_insert_connection = get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter, const Glib::ustring &text, int) { - //Do not perform git diff if no newline is added and line is already marked as added - if(!iter.starts_line() && iter.has_tag(renderer->tag_added)) { - bool newline = false; - for(auto &c : text.raw()) { - if(c == '\n') { - newline = true; - break; + buffer_insert_connection = get_buffer()->signal_insert().connect( + [this](const Gtk::TextIter &iter, const Glib::ustring &text, int) { + //Do not perform git diff if no newline is added and line is already marked as added + if(!iter.starts_line() && iter.has_tag(renderer->tag_added)) { + bool newline = false; + for(auto &c : text.raw()) { + if(c == '\n') { + newline = true; + break; + } + } + if(!newline) + return; } - } - if(!newline) - return; - } - //Remove tag_removed_above/below if newline is inserted - else if(!text.empty() && text[0] == '\n' && iter.has_tag(renderer->tag_removed)) { - auto start_iter = get_buffer()->get_iter_at_line(iter.get_line()); - auto end_iter = get_iter_at_line_end(iter.get_line()); - end_iter.forward_char(); - get_buffer()->remove_tag(renderer->tag_removed_above, start_iter, end_iter); - get_buffer()->remove_tag(renderer->tag_removed_below, start_iter, end_iter); - } - parse_state = ParseState::idle; - delayed_buffer_changed_connection.disconnect(); - delayed_buffer_changed_connection = Glib::signal_timeout().connect([this]() { - parse_state = ParseState::starting; - return false; - }, - 250); - }, - false); + //Remove tag_removed_above/below if newline is inserted + else if(!text.empty() && text[0] == '\n' && iter.has_tag(renderer->tag_removed)) { + auto start_iter = get_buffer()->get_iter_at_line(iter.get_line()); + auto end_iter = get_iter_at_line_end(iter.get_line()); + end_iter.forward_char(); + get_buffer()->remove_tag(renderer->tag_removed_above, start_iter, end_iter); + get_buffer()->remove_tag(renderer->tag_removed_below, start_iter, end_iter); + } + parse_state = ParseState::idle; + delayed_buffer_changed_connection.disconnect(); + delayed_buffer_changed_connection = Glib::signal_timeout().connect( + [this]() { + parse_state = ParseState::starting; + return false; + }, + 250); + }, + false); - buffer_erase_connection = get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_iter, const Gtk::TextIter &end_iter) { - //Do not perform git diff if start_iter and end_iter is at the same line in addition to the line is tagged added - if(start_iter.get_line() == end_iter.get_line() && start_iter.has_tag(renderer->tag_added)) - return; + buffer_erase_connection = get_buffer()->signal_erase().connect( + [this](const Gtk::TextIter &start_iter, const Gtk::TextIter &end_iter) { + //Do not perform git diff if start_iter and end_iter is at the same line in addition to the line is tagged added + if(start_iter.get_line() == end_iter.get_line() && start_iter.has_tag(renderer->tag_added)) + return; - parse_state = ParseState::idle; - delayed_buffer_changed_connection.disconnect(); - delayed_buffer_changed_connection = Glib::signal_timeout().connect([this]() { - parse_state = ParseState::starting; - return false; - }, - 250); - }, - false); + parse_state = ParseState::idle; + delayed_buffer_changed_connection.disconnect(); + delayed_buffer_changed_connection = Glib::signal_timeout().connect( + [this]() { + parse_state = ParseState::starting; + return false; + }, + 250); + }, + false); monitor_changed_connection = repository->monitor->signal_changed().connect([this](const Glib::RefPtr &file, const Glib::RefPtr &, Gio::FileMonitorEvent monitor_event) { if(monitor_event != Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { delayed_monitor_changed_connection.disconnect(); - delayed_monitor_changed_connection = Glib::signal_timeout().connect([this]() { - monitor_changed = true; - parse_state = ParseState::starting; - LockGuard lock(parse_mutex); - diff = nullptr; - return false; - }, - 500); + delayed_monitor_changed_connection = Glib::signal_timeout().connect( + [this]() { + monitor_changed = true; + parse_state = ParseState::starting; + LockGuard lock(parse_mutex); + diff = nullptr; + return false; + }, + 500); } }); diff --git a/src/source_generic.cpp b/src/source_generic.cpp index e18d1d1..9fa4759 100644 --- a/src/source_generic.cpp +++ b/src/source_generic.cpp @@ -112,26 +112,27 @@ void Source::GenericView::setup_buffer_words() { } // Remove changed word at insert - get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter_, const Glib::ustring &text, int bytes) { - auto iter = iter_; - if(!is_token_char(*iter)) - iter.backward_char(); - - if(is_token_char(*iter)) { - auto word = get_token_iters(iter); - if(word.second.get_offset() - word.first.get_offset() >= 3) { - LockGuard lock(buffer_words_mutex); - auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second)); - if(it != buffer_words.end()) { - if(it->second > 1) - --(it->second); - else - buffer_words.erase(it); + get_buffer()->signal_insert().connect( + [this](const Gtk::TextIter &iter_, const Glib::ustring &text, int bytes) { + auto iter = iter_; + if(!is_token_char(*iter)) + iter.backward_char(); + + if(is_token_char(*iter)) { + auto word = get_token_iters(iter); + if(word.second.get_offset() - word.first.get_offset() >= 3) { + LockGuard lock(buffer_words_mutex); + auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second)); + if(it != buffer_words.end()) { + if(it->second > 1) + --(it->second); + else + buffer_words.erase(it); + } + } } - } - } - }, - false); + }, + false); // 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) { @@ -152,25 +153,26 @@ void Source::GenericView::setup_buffer_words() { }); // Remove words within text that was removed - get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_, const Gtk::TextIter &end_) { - auto start = start_; - auto end = end_; - if(!is_token_char(*start)) - start.backward_char(); - end.forward_char(); - auto words = get_words(start, end); - LockGuard lock(buffer_words_mutex); - for(auto &word : words) { - auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second)); - if(it != buffer_words.end()) { - if(it->second > 1) - --(it->second); - else - buffer_words.erase(it); - } - } - }, - false); + get_buffer()->signal_erase().connect( + [this](const Gtk::TextIter &start_, const Gtk::TextIter &end_) { + auto start = start_; + auto end = end_; + if(!is_token_char(*start)) + start.backward_char(); + end.forward_char(); + auto words = get_words(start, end); + LockGuard lock(buffer_words_mutex); + for(auto &word : words) { + auto it = buffer_words.find(get_buffer()->get_text(word.first, word.second)); + if(it != buffer_words.end()) { + if(it->second > 1) + --(it->second); + else + buffer_words.erase(it); + } + } + }, + false); // Add new word resulting from erased text get_buffer()->signal_erase().connect([this](const Gtk::TextIter &start_, const Gtk::TextIter & /*end*/) { diff --git a/src/source_language_protocol.cpp b/src/source_language_protocol.cpp index 092e3c2..254c6c2 100644 --- a/src/source_language_protocol.cpp +++ b/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_)) { process = std::make_unique( - filesystem::escape_argument(language_id + "-language-server"), root_path.string(), [this](const char *bytes, size_t n) { - server_message_stream.write(bytes, n); - parse_server_message(); }, [](const char *bytes, size_t n) { std::cerr.write(bytes, n); }, true, TinyProcessLib::Config{1048576}); + filesystem::escape_argument(language_id + "-language-server"), root_path.string(), + [this](const char *bytes, size_t n) { + 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::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); 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 } }, "textDocument": { "synchronization": { "dynamicRegistration": true, "didSave": true }, @@ -168,38 +175,38 @@ LanguageProtocol::Capabilities LanguageProtocol::Client::initialize(Source::Lang "checkOnSave": { "enable": true } }, "trace": "off")", - [this, &result_processed](const boost::property_tree::ptree &result, bool error) { - if(!error) { - if(auto capabilities_pt = result.get_child_optional("capabilities")) { - try { - capabilities.text_document_sync = static_cast(capabilities_pt->get("textDocumentSync")); - } - catch(...) { - capabilities.text_document_sync = static_cast(capabilities_pt->get("textDocumentSync.change", 0)); - } - capabilities.hover = capabilities_pt->get("hoverProvider", false); - capabilities.completion = static_cast(capabilities_pt->get_child_optional("completionProvider")); - capabilities.signature_help = static_cast(capabilities_pt->get_child_optional("signatureHelpProvider")); - capabilities.definition = capabilities_pt->get("definitionProvider", false); - capabilities.references = capabilities_pt->get("referencesProvider", false); - capabilities.document_highlight = capabilities_pt->get("documentHighlightProvider", false); - capabilities.workspace_symbol = capabilities_pt->get("workspaceSymbolProvider", false); - capabilities.document_symbol = capabilities_pt->get("documentSymbolProvider", false); - capabilities.document_formatting = capabilities_pt->get("documentFormattingProvider", false); - capabilities.document_range_formatting = capabilities_pt->get("documentRangeFormattingProvider", false); - capabilities.rename = capabilities_pt->get("renameProvider", false); - if(!capabilities.rename) - capabilities.rename = capabilities_pt->get("renameProvider.prepareProvider", false); - capabilities.code_action = capabilities_pt->get("codeActionProvider", false); - if(!capabilities.code_action) - capabilities.code_action = static_cast(capabilities_pt->get_child_optional("codeActionProvider.codeActionKinds")); - capabilities.type_coverage = capabilities_pt->get("typeCoverageProvider", false); - } + [this, &result_processed](const boost::property_tree::ptree &result, bool error) { + if(!error) { + if(auto capabilities_pt = result.get_child_optional("capabilities")) { + try { + capabilities.text_document_sync = static_cast(capabilities_pt->get("textDocumentSync")); + } + catch(...) { + capabilities.text_document_sync = static_cast(capabilities_pt->get("textDocumentSync.change", 0)); + } + capabilities.hover = capabilities_pt->get("hoverProvider", false); + capabilities.completion = static_cast(capabilities_pt->get_child_optional("completionProvider")); + capabilities.signature_help = static_cast(capabilities_pt->get_child_optional("signatureHelpProvider")); + capabilities.definition = capabilities_pt->get("definitionProvider", false); + capabilities.references = capabilities_pt->get("referencesProvider", false); + capabilities.document_highlight = capabilities_pt->get("documentHighlightProvider", false); + capabilities.workspace_symbol = capabilities_pt->get("workspaceSymbolProvider", false); + capabilities.document_symbol = capabilities_pt->get("documentSymbolProvider", false); + capabilities.document_formatting = capabilities_pt->get("documentFormattingProvider", false); + capabilities.document_range_formatting = capabilities_pt->get("documentRangeFormattingProvider", false); + capabilities.rename = capabilities_pt->get("renameProvider", false); + if(!capabilities.rename) + capabilities.rename = capabilities_pt->get("renameProvider.prepareProvider", false); + capabilities.code_action = capabilities_pt->get("codeActionProvider", false); + if(!capabilities.code_action) + capabilities.code_action = static_cast(capabilities_pt->get_child_optional("codeActionProvider.codeActionKinds")); + capabilities.type_coverage = capabilities_pt->get("typeCoverageProvider", false); + } - write_notification("initialized", ""); - } - result_processed.set_value(); - }); + write_notification("initialized", ""); + } + result_processed.set_value(); + }); result_processed.get_future().get(); initialized = true; @@ -1024,7 +1031,11 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector{}); - pair.first->second.emplace_back(edit.new_text, filesystem::get_path_from_uri(file_it->first).string(), std::make_pair(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(edit.range.start.line, edit.range.start.character), + Offset(edit.range.end.line, edit.range.end.character))); break; } } @@ -1034,7 +1045,11 @@ void Source::LanguageProtocolView::update_diagnostics_async(std::vector{}); - pair.first->second.emplace_back(edit.new_text, filesystem::get_path_from_uri(file_it->first).string(), std::make_pair(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(edit.range.start.line, edit.range.start.character), + Offset(edit.range.end.line, edit.range.end.character))); break; } } @@ -1400,17 +1415,19 @@ Source::Offset Source::LanguageProtocolView::get_declaration(const Gtk::TextIter void Source::LanguageProtocolView::setup_signals() { 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) { - std::string 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); - - 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":""})" + "]"); - }, - false); + get_buffer()->signal_insert().connect( + [this](const Gtk::TextIter &start, const Glib::ustring &text_, int bytes) { + std::string 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); + + 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":""})" + "]"); + }, + false); } else if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::full) { get_buffer()->signal_changed().connect([this]() { @@ -1439,47 +1456,50 @@ void Source::LanguageProtocolView::setup_autocomplete() { if(capabilities.signature_help) { // Activate argument completions - get_buffer()->signal_changed().connect([this] { - if(!interactive_completion) - return; - if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) - return; - if(!has_focus()) - return; - if(autocomplete_show_arguments) - autocomplete->stop(); - autocomplete_show_arguments = false; - autocomplete_delayed_show_arguments_connection.disconnect(); - autocomplete_delayed_show_arguments_connection = Glib::signal_timeout().connect([this]() { - if(get_buffer()->get_has_selection()) - return false; - if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) - return false; - if(!has_focus()) - return false; - if(is_possible_argument()) { - autocomplete->stop(); - autocomplete->run(); - } - return false; - }, - 500); - }, - false); + get_buffer()->signal_changed().connect( + [this] { + if(!interactive_completion) + return; + if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) + return; + if(!has_focus()) + return; + if(autocomplete_show_arguments) + autocomplete->stop(); + autocomplete_show_arguments = false; + autocomplete_delayed_show_arguments_connection.disconnect(); + autocomplete_delayed_show_arguments_connection = Glib::signal_timeout().connect( + [this]() { + if(get_buffer()->get_has_selection()) + return false; + if(CompletionDialog::get() && CompletionDialog::get()->is_visible()) + return false; + if(!has_focus()) + return false; + if(is_possible_argument()) { + autocomplete->stop(); + autocomplete->run(); + } + return false; + }, + 500); + }, + false); // Remove argument completions - signal_key_press_event().connect([this](GdkEventKey *event) { - if(autocomplete_show_arguments && CompletionDialog::get() && CompletionDialog::get()->is_visible() && - event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && - event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter && - event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab && - (event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) { - get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); - CompletionDialog::get()->hide(); - } - return false; - }, - false); + signal_key_press_event().connect( + [this](GdkEventKey *event) { + if(autocomplete_show_arguments && CompletionDialog::get() && CompletionDialog::get()->is_visible() && + event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && + event->keyval != GDK_KEY_Return && event->keyval != GDK_KEY_KP_Enter && + event->keyval != GDK_KEY_ISO_Left_Tab && event->keyval != GDK_KEY_Tab && + (event->keyval < GDK_KEY_Shift_L || event->keyval > GDK_KEY_Hyper_R)) { + get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); + CompletionDialog::get()->hide(); + } + return false; + }, + false); } 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 dispatcher.post([this] { update_type_coverage_connection.disconnect(); - update_type_coverage_connection = Glib::signal_timeout().connect([this]() { - --update_type_coverage_retries; - update_type_coverage(); - return false; - }, - 1000); + update_type_coverage_connection = Glib::signal_timeout().connect( + [this]() { + --update_type_coverage_retries; + update_type_coverage(); + return false; + }, + 1000); }); } return; diff --git a/src/source_spellcheck.cpp b/src/source_spellcheck.cpp index 649c4ee..787c709 100644 --- a/src/source_spellcheck.cpp +++ b/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->property_underline() = Pango::Underline::UNDERLINE_ERROR; - signal_key_press_event().connect([](GdkEventKey *event) { - if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) { - if(SelectionDialog::get()->on_key_press(event)) - return true; - } + signal_key_press_event().connect( + [](GdkEventKey *event) { + if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) { + if(SelectionDialog::get()->on_key_press(event)) + return true; + } - return false; - }, - false); + return false; + }, + false); //The following signal is added in case SpellCheckView is not subclassed 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 = Glib::signal_timeout().connect([this]() { - auto iter = get_buffer()->begin(); - Gtk::TextIter begin_no_spellcheck_iter; - if(spellcheck_all) { - bool spell_check = !get_source_buffer()->iter_has_context_class(iter, "no-spell-check"); - if(!spell_check) - begin_no_spellcheck_iter = iter; - while(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; + delayed_spellcheck_error_clear = Glib::signal_timeout().connect( + [this]() { + auto iter = get_buffer()->begin(); + Gtk::TextIter begin_no_spellcheck_iter; + if(spellcheck_all) { + bool spell_check = !get_source_buffer()->iter_has_context_class(iter, "no-spell-check"); + if(!spell_check) + begin_no_spellcheck_iter = iter; + while(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; + 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) 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) - begin_no_spellcheck_iter = iter; - while(iter != get_buffer()->end()) { - auto iter1 = iter; - auto iter2 = iter; - 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")) - iter2 = get_buffer()->end(); - - if(iter2 < iter1) - iter = iter2; - else - iter = iter1; - 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); + while(iter != get_buffer()->end()) { + auto iter1 = iter; + auto iter2 = iter; + 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")) + iter2 = get_buffer()->end(); + + if(iter2 < iter1) + iter = iter2; + else + iter = iter1; + 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 - get_buffer()->signal_insert().connect([this](const Gtk::TextIter &start_iter, const Glib::ustring &inserted_string, int) { - if(!spellcheck_checker) - return; - - if(disable_spellcheck) { - auto iter = start_iter; - if(!is_word_iter(iter) && !iter.starts_line()) - iter.backward_char(); - if(is_word_iter(iter)) { - auto word = get_word(iter); - get_buffer()->remove_tag(spellcheck_error_tag, word.first, word.second); - } - } - }, - false); + get_buffer()->signal_insert().connect( + [this](const Gtk::TextIter &start_iter, const Glib::ustring &inserted_string, int) { + if(!spellcheck_checker) + return; + + if(disable_spellcheck) { + auto iter = start_iter; + if(!is_word_iter(iter) && !iter.starts_line()) + iter.backward_char(); + if(is_word_iter(iter)) { + auto word = get_word(iter); + get_buffer()->remove_tag(spellcheck_error_tag, word.first, word.second); + } + } + }, + false); get_buffer()->signal_mark_set().connect([this](const Gtk::TextIter &iter, const Glib::RefPtr &mark) { if(mark->get_name() == "insert") { @@ -155,34 +158,35 @@ Source::SpellCheckView::SpellCheckView(const boost::filesystem::path &file_path, delayed_spellcheck_suggestions_connection.disconnect(); if(get_buffer()->get_has_selection()) return; - delayed_spellcheck_suggestions_connection = Glib::signal_timeout().connect([this]() { - if(get_buffer()->get_insert()->get_iter().has_tag(spellcheck_error_tag)) { - SelectionDialog::create(this, false); - auto word = get_word(get_buffer()->get_insert()->get_iter()); - if(*word.first == '\'' && word.second.get_offset() - word.first.get_offset() >= 3) { - auto before_end = word.second; - if(before_end.backward_char() && *before_end == '\'') { - word.first.forward_char(); - word.second.backward_char(); + delayed_spellcheck_suggestions_connection = Glib::signal_timeout().connect( + [this]() { + if(get_buffer()->get_insert()->get_iter().has_tag(spellcheck_error_tag)) { + SelectionDialog::create(this, false); + auto word = get_word(get_buffer()->get_insert()->get_iter()); + if(*word.first == '\'' && word.second.get_offset() - word.first.get_offset() >= 3) { + auto before_end = word.second; + if(before_end.backward_char() && *before_end == '\'') { + 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; - 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(); - } - return false; - }, - 500); + }, + 500); } }); diff --git a/src/terminal.cpp b/src/terminal.cpp index fe5d913..cfe1490 100644 --- a/src/terminal.cpp +++ b/src/terminal.cpp @@ -211,7 +211,13 @@ int Terminal::process(const std::string &command, const boost::filesystem::path std::unique_ptr process; if(use_pipes) process = std::make_unique( - 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 process = std::make_unique(command, path.string()); @@ -228,19 +234,24 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c scroll_to_bottom(); TinyProcessLib::Process process( - command, path.string(), [&stdout_stream](const char *bytes, size_t n) { - Glib::ustring umessage(std::string(bytes, n)); - Glib::ustring::iterator iter; - while(!umessage.validate(iter)) { - auto next_char_iter = 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) - stderr_stream->write(bytes, n); - else - async_print(std::string(bytes, n), true); }, true); + command, path.string(), + [&stdout_stream](const char *bytes, size_t n) { + Glib::ustring umessage(std::string(bytes, n)); + Glib::ustring::iterator iter; + while(!umessage.validate(iter)) { + auto next_char_iter = 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) + stderr_stream->write(bytes, n); + else + async_print(std::string(bytes, n), true); + }, + true); if(process.get_id() <= 0) { async_print("\e[31mError\e[m: failed to run command: " + command + "\n", true); @@ -268,25 +279,30 @@ std::shared_ptr Terminal::async_process(const std::stri stdin_buffer.clear(); auto process = std::make_shared( - command, path.string(), [this, quiet](const char *bytes, size_t n) { - if(!quiet) { - // Print stdout message sequentially to avoid the GUI becoming unresponsive - std::promise message_printed; - dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { - Terminal::get().print(std::move(message)); - message_printed.set_value(); - }); - message_printed.get_future().get(); - } }, [this, quiet](const char *bytes, size_t n) { - if(!quiet) { - // Print stderr message sequentially to avoid the GUI becoming unresponsive - std::promise message_printed; - dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { - Terminal::get().print(std::move(message), true); - message_printed.set_value(); - }); - message_printed.get_future().get(); - } }, true); + command, path.string(), + [this, quiet](const char *bytes, size_t n) { + if(!quiet) { + // Print stdout message sequentially to avoid the GUI becoming unresponsive + std::promise message_printed; + dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { + Terminal::get().print(std::move(message)); + message_printed.set_value(); + }); + message_printed.get_future().get(); + } + }, + [this, quiet](const char *bytes, size_t n) { + if(!quiet) { + // Print stderr message sequentially to avoid the GUI becoming unresponsive + std::promise message_printed; + dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { + Terminal::get().print(std::move(message), true); + message_printed.set_value(); + }); + message_printed.get_future().get(); + } + }, + true); auto pid = process->get_id(); if(pid <= 0) { diff --git a/tests/process_test.cpp b/tests/process_test.cpp index 7acca6e..fd0664e 100644 --- a/tests/process_test.cpp +++ b/tests/process_test.cpp @@ -15,7 +15,13 @@ int main() { { 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(output->substr(0, 4) == "Test"); g_assert(!error->empty());