Browse Source

Fixes #420: added Find Pattern to Source menu

merge-requests/399/head
eidheim 6 years ago
parent
commit
994306e26c
  1. 2
      CMakeLists.txt
  2. 1
      src/config.cc
  3. 1
      src/config.h
  4. 4
      src/directories.cc
  5. 2
      src/files.h
  6. 4
      src/menu.cc
  7. 169
      src/window.cc
  8. 3
      src/window.h

2
CMakeLists.txt

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

1
src/config.cc

@ -202,6 +202,7 @@ void Config::read(const boost::property_tree::ptree &cfg) {
project.save_on_compile_or_run = cfg.get<bool>("project.save_on_compile_or_run");
project.clear_terminal_on_compile = cfg.get<bool>("project.clear_terminal_on_compile");
project.ctags_command = cfg.get<std::string>("project.ctags_command");
project.grep_command = cfg.get<std::string>("project.grep_command");
project.python_command = cfg.get<std::string>("project.python_command");
project.markdown_command = cfg.get<std::string>("project.markdown_command");

1
src/config.h

@ -48,6 +48,7 @@ public:
bool save_on_compile_or_run;
bool clear_terminal_on_compile;
std::string ctags_command;
std::string grep_command;
std::string python_command;
std::string markdown_command;
};

4
src/directories.cc

@ -341,7 +341,7 @@ Directories::Directories() : Gtk::ListViewText(1) {
EntryBox::get().hide();
});
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Folder name");
entry_it->set_placeholder_text("Folder Name");
EntryBox::get().buttons.emplace_back("Create New Folder", [entry_it]() {
entry_it->activate();
});
@ -420,7 +420,7 @@ Directories::Directories() : Gtk::ListViewText(1) {
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Filename");
EntryBox::get().buttons.emplace_back("Rename file", [entry_it]() {
EntryBox::get().buttons.emplace_back("Rename File", [entry_it]() {
entry_it->activate();
});

2
src/files.h

@ -112,6 +112,7 @@ const std::string default_config_file = R"RAW({
"source_show_completion" : "",
"source_find_file": "<primary>p",
"source_find_symbol": "<primary><shift>f",
"source_find_pattern": "<alt><shift>f",
"source_comments_toggle": "<primary>slash",
"source_comments_add_documentation": "<primary><alt>slash",
"source_find_documentation": "<primary><shift>d",
@ -192,6 +193,7 @@ const std::string default_config_file = R"RAW({
"save_on_compile_or_run": true,
"clear_terminal_on_compile": true,
"ctags_command": "ctags",
"grep_command": "grep",
"python_command": "PYTHONUNBUFFERED=1 python",
"markdown_command": "grip -b"
},

4
src/menu.cc

@ -304,6 +304,10 @@ const Glib::ustring menu_xml = R"RAW(<interface>
<attribute name='label' translatable='yes'>_Find _Symbol</attribute>
<attribute name='action'>app.source_find_symbol</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Find _Pattern</attribute>
<attribute name='action'>app.source_find_pattern</attribute>
</item>
</section>
<section>
<submenu>

169
src/window.cc

@ -784,6 +784,151 @@ void Window::set_menu_actions() {
project->show_symbols();
});
menu.add_action("source_find_pattern", [this]() {
auto view = Notebook::get().get_current_view();
std::string excludes = "--exclude-dir=node_modules";
boost::filesystem::path search_path;
if(view)
search_path = view->file_path.parent_path();
else if(!Directories::get().path.empty())
search_path = Directories::get().path;
else {
boost::system::error_code ec;
search_path = boost::filesystem::current_path(ec);
if(ec) {
Terminal::get().print("Error: could not find current path\n", true);
return;
}
}
auto build = Project::Build::create(search_path);
auto project_path = build->project_path;
boost::filesystem::path default_path, debug_path;
if(!project_path.empty()) {
search_path = project_path;
excludes += " --exclude-dir=" + filesystem::escape_argument(filesystem::get_relative_path(build->get_default_path(), project_path).string());
excludes += " --exclude-dir=" + filesystem::escape_argument(filesystem::get_relative_path(build->get_debug_path(), project_path).string());
}
EntryBox::get().clear();
EntryBox::get().entries.emplace_back(last_find_pattern, [this, search_path = std::move(search_path), excludes = std::move(excludes)](const std::string &pattern) {
if(!pattern.empty()) {
std::stringstream stdin_stream;
std::string flags;
if(!find_pattern_case_sensitive)
flags += " -i";
if(find_pattern_extended_regex)
flags += " -E";
auto escaped_pattern = '\'' + pattern + '\'';
for(size_t i = 1; i < escaped_pattern.size() - 1; ++i) {
if(escaped_pattern[i] == '\'') {
escaped_pattern.insert(i, "\\");
++i;
}
}
std::string command = Config::get().project.grep_command + " -R " + flags + " --color=always --binary-files=without-match " + excludes + " -n " + escaped_pattern + " *";
//TODO: when debian stable gets newer g++ version that supports move on streams, remove unique_ptr below
auto stdout_stream = std::make_unique<std::stringstream>();
Terminal::get().process(stdin_stream, *stdout_stream, command, search_path);
stdout_stream->seekg(0, std::ios::end);
if(stdout_stream->tellg() == 0) {
Info::get().print("Pattern not found");
EntryBox::get().hide();
return;
}
stdout_stream->seekg(0, std::ios::beg);
if(auto view = Notebook::get().get_current_view())
SelectionDialog::create(view, true, true);
else
SelectionDialog::create(true, true);
std::string line;
while(std::getline(*stdout_stream, line)) {
auto line_markup = Glib::Markup::escape_text(line);
size_t start = 0;
while((start = line_markup.find("&#x1b;[", start)) != std::string::npos) {
auto start_end = line_markup.find("&#x1b;[K", start + 7);
if(start_end == std::string::npos)
break;
auto start_size = start_end - start + 8;
auto end = line_markup.find("&#x1b;[m&#x1b;[K", start + start_size);
if(end == std::string::npos)
break;
line_markup.replace(end, 16, "</b>");
line_markup.replace(start, start_size, "<b>");
start = end - start_size + 3 + 4;
}
SelectionDialog::get()->add_row(line_markup);
}
SelectionDialog::get()->on_select = [search_path = std::move(search_path)](unsigned int index, const std::string &text, bool hide_window) {
auto remove_markup = [](std::string &markup) {
auto start = markup.end();
for(auto it = markup.begin(); it != markup.end();) {
if(*it == '<') {
start = it;
it++;
}
else if(*it == '>' && start != markup.end()) {
it = markup.erase(start, ++it);
start = markup.end();
}
else
it++;
}
};
auto file_end = text.find(':');
if(file_end != std::string::npos) {
auto file = text.substr(0, file_end);
remove_markup(file);
auto line_end = text.find(':', file_end + 1);
if(line_end != std::string::npos) {
try {
auto line_str = text.substr(file_end + 1, line_end - file_end);
remove_markup(line_str);
auto line = std::stoi(line_str);
Notebook::get().open(search_path / file);
auto view = Notebook::get().get_current_view();
view->place_cursor_at_line_pos(line - 1, 0);
view->scroll_to_cursor_delayed(true, false);
}
catch(...) {
}
}
}
};
SelectionDialog::get()->show();
}
EntryBox::get().hide();
});
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Pattern");
entry_it->signal_changed().connect([this, entry_it]() {
last_find_pattern = entry_it->get_text();
});
EntryBox::get().buttons.emplace_back("Find Pattern", [entry_it]() {
entry_it->activate();
});
EntryBox::get().toggle_buttons.emplace_back("Aa");
EntryBox::get().toggle_buttons.back().set_tooltip_text("Match Case");
EntryBox::get().toggle_buttons.back().set_active(find_pattern_case_sensitive);
EntryBox::get().toggle_buttons.back().on_activate = [this]() {
find_pattern_case_sensitive = !find_pattern_case_sensitive;
};
EntryBox::get().toggle_buttons.emplace_back(".*");
EntryBox::get().toggle_buttons.back().set_tooltip_text("Use Extended Regex");
EntryBox::get().toggle_buttons.back().set_active(find_pattern_extended_regex);
EntryBox::get().toggle_buttons.back().on_activate = [this]() {
find_pattern_extended_regex = !find_pattern_extended_regex;
};
EntryBox::get().show();
});
menu.add_action("source_find_file", []() {
auto view = Notebook::get().get_current_view();
@ -1182,8 +1327,8 @@ void Window::set_menu_actions() {
EntryBox::get().hide();
}, 50);
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Project: Set Run Arguments");
EntryBox::get().buttons.emplace_back("Project: set run arguments", [entry_it]() {
entry_it->set_placeholder_text("Run Arguments");
EntryBox::get().buttons.emplace_back("Set Run Arguments", [entry_it]() {
entry_it->activate();
});
EntryBox::get().show();
@ -1247,7 +1392,7 @@ void Window::set_menu_actions() {
}, 30);
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Command");
EntryBox::get().buttons.emplace_back("Run command", [entry_it]() {
EntryBox::get().buttons.emplace_back("Run Command", [entry_it]() {
entry_it->activate();
});
EntryBox::get().show();
@ -1279,7 +1424,7 @@ void Window::set_menu_actions() {
EntryBox::get().hide();
}, 50);
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Debug: Set Run Arguments");
entry_it->set_placeholder_text("Debug Run Arguments");
if(auto options = project->debug_get_options()) {
EntryBox::get().buttons.emplace_back("", [options]() {
@ -1291,7 +1436,7 @@ void Window::set_menu_actions() {
options->set_relative_to(EntryBox::get().buttons.back());
}
EntryBox::get().buttons.emplace_back("Debug: set run arguments", [entry_it]() {
EntryBox::get().buttons.emplace_back("Set Debug Run Arguments", [entry_it]() {
entry_it->activate();
});
EntryBox::get().show();
@ -1353,7 +1498,7 @@ void Window::set_menu_actions() {
}, 30);
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Debug Command");
EntryBox::get().buttons.emplace_back("Run debug command", [entry_it]() {
EntryBox::get().buttons.emplace_back("Run Debug Command", [entry_it]() {
entry_it->activate();
});
EntryBox::get().show();
@ -1789,7 +1934,7 @@ void Window::set_tab_entry() {
EntryBox::get().entries.emplace_back(std::to_string(tab_char_and_size.second));
auto entry_tab_size_it = EntryBox::get().entries.begin();
entry_tab_size_it->set_placeholder_text("Tab size");
entry_tab_size_it->set_placeholder_text("Tab Size");
char tab_char = tab_char_and_size.first;
std::string tab_char_string;
@ -1800,7 +1945,7 @@ void Window::set_tab_entry() {
EntryBox::get().entries.emplace_back(tab_char_string);
auto entry_tab_char_it = EntryBox::get().entries.rbegin();
entry_tab_char_it->set_placeholder_text("Tab char");
entry_tab_char_it->set_placeholder_text("Tab Char");
const auto activate_function = [entry_tab_char_it, entry_tab_size_it, label_it](const std::string &content) {
if(auto view = Notebook::get().get_current_view()) {
@ -1831,7 +1976,7 @@ void Window::set_tab_entry() {
entry_tab_char_it->on_activate = activate_function;
entry_tab_size_it->on_activate = activate_function;
EntryBox::get().buttons.emplace_back("Set tab in current buffer", [entry_tab_char_it]() {
EntryBox::get().buttons.emplace_back("Set Tab", [entry_tab_char_it]() {
entry_tab_char_it->activate();
});
@ -1854,8 +1999,8 @@ void Window::goto_line_entry() {
}
});
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Line number");
EntryBox::get().buttons.emplace_back("Go to line", [entry_it]() {
entry_it->set_placeholder_text("Line Number");
EntryBox::get().buttons.emplace_back("Go to Line", [entry_it]() {
entry_it->activate();
});
EntryBox::get().show();
@ -1878,7 +2023,7 @@ void Window::rename_token_entry() {
EntryBox::get().hide();
});
auto entry_it = EntryBox::get().entries.begin();
entry_it->set_placeholder_text("New name");
entry_it->set_placeholder_text("New Name");
EntryBox::get().buttons.emplace_back("Rename", [entry_it]() {
entry_it->activate();
});

3
src/window.h

@ -30,9 +30,12 @@ private:
void rename_token_entry();
std::string last_search;
std::string last_replace;
std::string last_find_pattern;
std::string last_run_command;
std::string last_run_debug_command;
bool case_sensitive_search = true;
bool regex_search = false;
bool search_entry_shown = false;
bool find_pattern_case_sensitive = true;
bool find_pattern_extended_regex = false;
};

Loading…
Cancel
Save