Browse Source

Added Edit.Show/Hide that can be used to hide text in a buffer by making it smaller

merge-requests/393/head
eidheim 7 years ago
parent
commit
7a456b8ddb
  1. 2
      CMakeLists.txt
  2. 1
      src/files.h
  3. 6
      src/menu.cc
  4. 2
      src/notebook.cc
  5. 151
      src/source.cc
  6. 6
      src/source.h
  7. 10
      src/source_base.cc
  8. 1
      src/source_base.h
  9. 5
      src/window.cc

2
CMakeLists.txt

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

1
src/files.h

@ -89,6 +89,7 @@ const std::string default_config_file = R"RAW({
"edit_cut": "<primary>x", "edit_cut": "<primary>x",
"edit_copy": "<primary>c", "edit_copy": "<primary>c",
"edit_paste": "<primary>v", "edit_paste": "<primary>v",
"edit_show_or_hide": "",
"edit_find": "<primary>f", "edit_find": "<primary>f",
"source_spellcheck": "", "source_spellcheck": "",
"source_spellcheck_clear": "", "source_spellcheck_clear": "",

6
src/menu.cc

@ -197,6 +197,12 @@ const Glib::ustring menu_xml = R"RAW(<interface>
<attribute name='action'>app.edit_paste</attribute> <attribute name='action'>app.edit_paste</attribute>
</item> </item>
</section> </section>
<section>
<item>
<attribute name='label' translatable='yes'>_Show/_Hide</attribute>
<attribute name='action'>app.edit_show_or_hide</attribute>
</item>
</section>
<section> <section>
<item> <item>
<attribute name='label' translatable='yes'>_Find</attribute> <attribute name='label' translatable='yes'>_Find</attribute>

2
src/notebook.cc

@ -435,7 +435,7 @@ void Notebook::open_uri(const std::string &uri) {
void Notebook::configure(size_t index) { void Notebook::configure(size_t index) {
auto source_font_description = Pango::FontDescription(Config::get().source.font); auto source_font_description = Pango::FontDescription(Config::get().source.font);
auto source_map_font_desc = Pango::FontDescription(static_cast<std::string>(source_font_description.get_family()) + " " + Config::get().source.map_font_size); auto source_map_font_desc = Pango::FontDescription(source_font_description.get_family() + " " + Config::get().source.map_font_size);
source_maps.at(index)->override_font(source_map_font_desc); source_maps.at(index)->override_font(source_map_font_desc);
if(Config::get().source.show_map) { if(Config::get().source.show_map) {
if(hboxes.at(index)->get_children().size() == 1) if(hboxes.at(index)->get_children().size() == 1)

151
src/source.cc

@ -8,6 +8,7 @@
#include "selection_dialog.h" #include "selection_dialog.h"
#include "terminal.h" #include "terminal.h"
#include "utility.h" #include "utility.h"
#include <algorithm>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <boost/spirit/home/qi/char.hpp> #include <boost/spirit/home/qi/char.hpp>
#include <boost/spirit/home/qi/operator.hpp> #include <boost/spirit/home/qi/operator.hpp>
@ -152,6 +153,9 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
link_tag = get_buffer()->create_tag("link"); link_tag = get_buffer()->create_tag("link");
hide_tag = get_buffer()->create_tag();
hide_tag->property_scale() = 0.25;
if(language) { if(language) {
auto language_id = language->get_id(); auto language_id = language->get_id();
if(language_id == "chdr" || language_id == "cpphdr" || language_id == "c" || language_id == "cpp") { if(language_id == "chdr" || language_id == "cpphdr" || language_id == "c" || language_id == "cpp") {
@ -373,7 +377,7 @@ void Source::View::configure() {
else else
set_wrap_mode(Gtk::WrapMode::WRAP_NONE); set_wrap_mode(Gtk::WrapMode::WRAP_NONE);
property_highlight_current_line() = Config::get().source.highlight_current_line; property_highlight_current_line() = Config::get().source.highlight_current_line;
property_show_line_numbers() = Config::get().source.show_line_numbers; line_renderer->set_visible(Config::get().source.show_line_numbers);
if(Config::get().source.font.size() > 0) if(Config::get().source.font.size() > 0)
override_font(Pango::FontDescription(Config::get().source.font)); override_font(Pango::FontDescription(Config::get().source.font));
@ -459,17 +463,43 @@ void Source::View::setup_signals() {
} }
}); });
signal_realize().connect([this] {
auto gutter = get_gutter(Gtk::TextWindowType::TEXT_WINDOW_LEFT); // Line numbers
auto renderer = gutter->get_renderer_at_pos(15, 0); line_renderer = Gtk::manage(new Gsv::GutterRendererText());
if(renderer) { auto gutter = get_gutter(Gtk::TextWindowType::TEXT_WINDOW_LEFT);
renderer_activate_connection.disconnect();
renderer_activate_connection = renderer->signal_activate().connect([this](const Gtk::TextIter &iter, const Gdk::Rectangle &, GdkEvent *) { line_renderer->set_alignment_mode(Gsv::GutterRendererAlignmentMode::GUTTER_RENDERER_ALIGNMENT_MODE_FIRST);
if(toggle_breakpoint) line_renderer->set_alignment(1.0, -1);
toggle_breakpoint(iter.get_line()); line_renderer->set_padding(3, -1);
}); gutter->insert(line_renderer, GTK_SOURCE_VIEW_GUTTER_POSITION_LINES);
auto set_line_renderer_width = [this] {
int width, height;
line_renderer->measure(std::to_string(get_buffer()->get_line_count()), width, height);
line_renderer->set_size(width);
};
set_line_renderer_width();
get_buffer()->signal_changed().connect([set_line_renderer_width] {
set_line_renderer_width();
});
signal_style_updated().connect([set_line_renderer_width] {
set_line_renderer_width();
});
line_renderer->signal_query_data().connect([this](const Gtk::TextIter &start, const Gtk::TextIter &end, Gsv::GutterRendererState state) {
if(!start.begins_tag(hide_tag) && !start.has_tag(hide_tag)) {
if(start.get_line() == get_buffer()->get_insert()->get_iter().get_line())
line_renderer->set_text(Gsv::Markup("<b>" + std::to_string(start.get_line() + 1) + "</b>"));
else
line_renderer->set_text(Gsv::Markup(std::to_string(start.get_line() + 1)));
} }
}); });
line_renderer->signal_query_activatable().connect([](const Gtk::TextIter &, const Gdk::Rectangle &, GdkEvent *) {
return true;
});
line_renderer->signal_activate().connect([this](const Gtk::TextIter &iter, const Gdk::Rectangle &, GdkEvent *) {
if(toggle_breakpoint)
toggle_breakpoint(iter.get_line());
});
type_tooltips.on_motion = [this] { type_tooltips.on_motion = [this] {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
@ -478,6 +508,7 @@ void Source::View::setup_signals() {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
}; };
signal_motion_notify_event().connect([this](GdkEventMotion *event) { signal_motion_notify_event().connect([this](GdkEventMotion *event) {
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();
@ -957,7 +988,6 @@ Source::View::~View() {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
delayed_tag_similar_symbols_connection.disconnect(); delayed_tag_similar_symbols_connection.disconnect();
delayed_tag_clickable_connection.disconnect(); delayed_tag_clickable_connection.disconnect();
renderer_activate_connection.disconnect();
non_deleted_views.erase(this); non_deleted_views.erase(this);
views.erase(this); views.erase(this);
@ -977,6 +1007,105 @@ void Source::View::hide_dialogs() {
CompletionDialog::get()->hide(); CompletionDialog::get()->hide();
} }
void Source::View::show_or_hide() {
Gtk::TextIter start, end;
get_buffer()->get_selection_bounds(start, end);
if(start == end && !(start.starts_line() && start.ends_line())) { // Select code block instead if no current selection
start = get_buffer()->get_iter_at_line(start.get_line());
auto tabs_end = get_tabs_end_iter(start);
auto start_tabs = tabs_end.get_line_offset() - start.get_line_offset();
if(!end.ends_line())
end.forward_to_line_end();
auto last_empty = get_buffer()->end();
auto last_tabs_end = get_buffer()->end();
while(true) {
if(end.ends_line()) {
auto line_start = get_buffer()->get_iter_at_line(end.get_line());
auto tabs_end = get_tabs_end_iter(line_start);
if(end.starts_line() || tabs_end.ends_line()) { // Empty line
if(!last_empty)
last_empty = end;
}
else {
auto tabs = tabs_end.get_line_offset() - line_start.get_line_offset();
if(is_cpp && tabs == 0 && *line_start == '#') { // C/C++ defines can be at the first line
if(end.get_line() == start.get_line()) // Do not try to find define blocks since these rarely are indented
break;
}
else if(tabs < start_tabs) {
end = get_buffer()->get_iter_at_line(end.get_line());
break;
}
else if(tabs == start_tabs) {
// Check for block continuation keywords
std::string text = get_buffer()->get_text(tabs_end, end);
if(end.get_line() != start.get_line()) {
if(text.empty()) {
end = get_buffer()->get_iter_at_line(end.get_line());
break;
}
static std::vector<std::string> exact = {"}", ")", "]", ">", "</", "else", "endif"};
static std::vector<std::string> followed_by_non_token_char = {"elseif", "elif", "case", "default", "private", "public", "protected"};
if(text == "{") { // C/C++ sometimes starts a block with a standalone {
if(!is_token_char(*last_tabs_end)) {
end = get_buffer()->get_iter_at_line(end.get_line());
break;
}
else { // Check for ; at the end of last line
auto iter = tabs_end;
while(iter.backward_char() && iter > last_tabs_end && (*iter == ' ' || *iter == '\t' || iter.ends_line() || !is_code_iter(iter))) {
}
if(*iter == ';') {
end = get_buffer()->get_iter_at_line(end.get_line());
break;
}
}
}
else if(std::none_of(exact.begin(), exact.end(), [&text](const std::string &e) {
return text.compare(0, e.size(), e) == 0;
}) &&
std::none_of(followed_by_non_token_char.begin(), followed_by_non_token_char.end(), [this, &text](const std::string &e) {
return text.compare(0, e.size(), e) == 0 && text.size() > e.size() && !is_token_char(text[e.size()]);
})) {
end = get_buffer()->get_iter_at_line(end.get_line());
break;
}
}
last_tabs_end = tabs_end;
}
last_empty = get_buffer()->end();
}
}
if(end.is_end())
break;
end.forward_char();
}
if(last_empty)
end = get_buffer()->get_iter_at_line(last_empty.get_line());
}
if(start == end)
end.forward_char(); // Select empty line
if(!start.starts_line())
start = get_buffer()->get_iter_at_line(start.get_line());
if(!end.ends_line() && !end.starts_line())
end.forward_to_line_end();
if((start.begins_tag(hide_tag) || start.has_tag(hide_tag)) && (end.ends_tag(hide_tag) || end.has_tag(hide_tag))) {
get_buffer()->remove_tag(hide_tag, start, end);
return;
}
auto iter = start;
if(iter.forward_to_tag_toggle(hide_tag) && iter < end) {
get_buffer()->remove_tag(hide_tag, start, end);
return;
}
get_buffer()->apply_tag(hide_tag, start, end);
}
void Source::View::insert_with_links_tagged(const Glib::RefPtr<Gtk::TextBuffer> &buffer, const std::string &text) { void Source::View::insert_with_links_tagged(const Glib::RefPtr<Gtk::TextBuffer> &buffer, const std::string &text) {
static std::regex http_regex("(https?://[a-zA-Z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=]+[a-zA-Z0-9\\-_~/@$*+;=])"); static std::regex http_regex("(https?://[a-zA-Z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=]+[a-zA-Z0-9\\-_~/@$*+;=])");
std::smatch sm; std::smatch sm;

6
src/source.h

@ -81,6 +81,8 @@ namespace Source {
void hide_tooltips() override; void hide_tooltips() override;
void hide_dialogs() override; void hide_dialogs() override;
void show_or_hide(); /// Show or hide text selection
bool soft_reparse_needed = false; bool soft_reparse_needed = false;
bool full_reparse_needed = false; bool full_reparse_needed = false;
virtual void soft_reparse(bool delayed = false) { soft_reparse_needed = false; } virtual void soft_reparse(bool delayed = false) { soft_reparse_needed = false; }
@ -104,6 +106,8 @@ namespace Source {
Glib::RefPtr<Gtk::TextTag> link_tag; /// Used in tooltips Glib::RefPtr<Gtk::TextTag> link_tag; /// Used in tooltips
void insert_with_links_tagged(const Glib::RefPtr<Gtk::TextBuffer> &buffer, const std::string &text); void insert_with_links_tagged(const Glib::RefPtr<Gtk::TextBuffer> &buffer, const std::string &text);
Glib::RefPtr<Gtk::TextTag> hide_tag;
virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { diagnostic_tooltips.show(rectangle); } virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { diagnostic_tooltips.show(rectangle); }
void add_diagnostic_tooltip(const Gtk::TextIter &start, const Gtk::TextIter &end, bool error, std::function<void(const Glib::RefPtr<Gtk::TextBuffer> &)> &&set_buffer); void add_diagnostic_tooltip(const Gtk::TextIter &start, const Gtk::TextIter &end, bool error, std::function<void(const Glib::RefPtr<Gtk::TextBuffer> &)> &&set_buffer);
void clear_diagnostic_tooltips(); void clear_diagnostic_tooltips();
@ -141,7 +145,7 @@ namespace Source {
Gsv::DrawSpacesFlags parse_show_whitespace_characters(const std::string &text); Gsv::DrawSpacesFlags parse_show_whitespace_characters(const std::string &text);
sigc::connection renderer_activate_connection; Gsv::GutterRendererText *line_renderer;
bool use_fixed_continuation_indenting = true; bool use_fixed_continuation_indenting = true;
bool is_cpp = false; bool is_cpp = false;

10
src/source_base.cc

@ -605,16 +605,22 @@ Gtk::TextIter Source::BaseView::get_tabs_end_iter() {
return get_tabs_end_iter(get_buffer()->get_insert()); return get_tabs_end_iter(get_buffer()->get_insert());
} }
bool Source::BaseView::is_token_char(gunichar chr) {
if((chr >= 'A' && chr <= 'Z') || (chr >= 'a' && chr <= 'z') || (chr >= '0' && chr <= '9') || chr == '_')
return true;
return false;
}
std::pair<Gtk::TextIter, Gtk::TextIter> Source::BaseView::get_token_iters(Gtk::TextIter iter) { std::pair<Gtk::TextIter, Gtk::TextIter> Source::BaseView::get_token_iters(Gtk::TextIter iter) {
auto start = iter; auto start = iter;
auto end = iter; auto end = iter;
while((*iter >= 'A' && *iter <= 'Z') || (*iter >= 'a' && *iter <= 'z') || (*iter >= '0' && *iter <= '9') || *iter == '_') { while(is_token_char(*iter)) {
start = iter; start = iter;
if(!iter.backward_char()) if(!iter.backward_char())
break; break;
} }
while((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') { while(is_token_char(*end)) {
if(!end.forward_char()) if(!end.forward_char())
break; break;
} }

1
src/source_base.h

@ -121,6 +121,7 @@ namespace Source {
Gtk::TextIter get_tabs_end_iter(int line_nr); Gtk::TextIter get_tabs_end_iter(int line_nr);
Gtk::TextIter get_tabs_end_iter(); Gtk::TextIter get_tabs_end_iter();
bool is_token_char(gunichar chr);
std::pair<Gtk::TextIter, Gtk::TextIter> get_token_iters(Gtk::TextIter iter); std::pair<Gtk::TextIter, Gtk::TextIter> get_token_iters(Gtk::TextIter iter);
std::string get_token(const Gtk::TextIter &iter); std::string get_token(const Gtk::TextIter &iter);
void cleanup_whitespace_characters(); void cleanup_whitespace_characters();

5
src/window.cc

@ -522,6 +522,11 @@ void Window::set_menu_actions() {
} }
}); });
menu.add_action("edit_show_or_hide", []() {
if(auto view = Notebook::get().get_current_view())
view->show_or_hide();
});
menu.add_action("edit_find", [this]() { menu.add_action("edit_find", [this]() {
search_and_replace_entry(); search_and_replace_entry();
}); });

Loading…
Cancel
Save