Commit 1e61b5ac authored by Fabien Parent's avatar Fabien Parent
Browse files

Completion of all entries (files, regex, substitution) with the last 10 used.

parent cfb3728c
......@@ -31,6 +31,8 @@ SUBDIRS = po
bin_PROGRAMS = src/regexxer
src_regexxer_SOURCES = \
src/completionstack.cc \
src/completionstack.h \
src/controller.cc \
src/controller.h \
src/filebuffer.cc \
......
/*
* Copyright (c) 2009 Fabien Parent <parent.f@gmail.com>
*
* This file is part of regexxer.
*
* regexxer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* regexxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with regexxer; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "completionstack.h"
#include <gtkmm/liststore.h>
namespace Regexxer
{
CompletionStack::CompletionStack(const std::list<Glib::ustring>& stack) :
infinite_stack_(true),
stack_size_(0),
completion_column_model_(),
completion_model_(Gtk::ListStore::create(completion_column_model_))
{
push(stack);
}
CompletionStack::CompletionStack(unsigned int stack_size, const std::list<Glib::ustring>& stack) :
infinite_stack_(false),
stack_size_(stack_size),
completion_column_model_(),
completion_model_(Gtk::ListStore::create(completion_column_model_))
{
push(stack);
}
void CompletionStack::push(const std::list<Glib::ustring> values)
{
for (std::list<Glib::ustring>::const_reverse_iterator item = values.rbegin();
item != values.rend(); item++)
{
push(*item);
}
}
void CompletionStack::push(const Glib::ustring value)
{
if (value.empty())
return;
Gtk::ListStore::Children children = completion_model_->children();
for (Gtk::ListStore::Children::iterator i = children.begin(); i != children.end(); i++)
{
if (i->get_value(completion_column_model_.value_) == value)
{
completion_model_->move(i, children.begin());
return;
}
}
Gtk::TreeModel::Row row = *(completion_model_->prepend());
row[completion_column_model_.value_] = value;
if (!infinite_stack_ && children.size() > stack_size_)
{
Gtk::ListStore::Children::iterator last_element = --(children.end());
completion_model_->erase(last_element);
}
}
std::list<Glib::ustring> CompletionStack::get_stack()
{
std::list<Glib::ustring> return_stack;
Gtk::ListStore::Children children = completion_model_->children();
for (Gtk::ListStore::Children::iterator i = children.begin(); i != children.end(); i++)
{
return_stack.push_back(i->get_value(completion_column_model_.value_));
}
return return_stack;
}
Glib::RefPtr<Gtk::ListStore> CompletionStack::get_completion_model()
{
return completion_model_;
}
Gtk::TreeModelColumn<Glib::ustring> CompletionStack::get_completion_column()
{
return completion_column_model_.value_;
}
CompletionStack::~CompletionStack()
{
}
} // namespace Regexxer
/*
* Copyright (c) 2009 Fabien Parent <parent.f@gmail.com>
*
* This file is part of regexxer.
*
* regexxer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* regexxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with regexxer; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef REGEXXER_COMPLETIONSTACK_H_INCLUDED
#define REGEXXER_COMPLETIONSTACK_H_INCLUDED
#include <gtkmm/treemodel.h>
#include <list>
namespace Gtk
{
class ListStore;
}
namespace Regexxer
{
class CompletionStack
{
public:
CompletionStack(const std::list<Glib::ustring>& stack = std::list<Glib::ustring>());
CompletionStack(unsigned int stack_size, const std::list<Glib::ustring>& stack = std::list<Glib::ustring>());
virtual ~CompletionStack();
void push(const Glib::ustring value);
void push(const std::list<Glib::ustring> values);
Glib::RefPtr<Gtk::ListStore> get_completion_model();
Gtk::TreeModelColumn<Glib::ustring> get_completion_column();
std::list<Glib::ustring> get_stack();
protected:
CompletionStack(const CompletionStack&);
CompletionStack operator=(const CompletionStack&);
private:
class CompletionColumnModel : public Gtk::TreeModel::ColumnRecord
{
public:
CompletionColumnModel()
{
add(value_);
}
Gtk::TreeModelColumn<Glib::ustring> value_;
};
bool infinite_stack_;
unsigned int stack_size_;
CompletionColumnModel completion_column_model_;
Glib::RefPtr<Gtk::ListStore> completion_model_;
};
} // namespace Regexxer
#endif /* REGEXXER_COMPLETIONSTACK_H_INCLUDED */
......@@ -38,6 +38,9 @@ const char *const conf_key_match_color = "/apps/regexxer/match_color";
const char *const conf_key_current_match_color = "/apps/regexxer/current_match_color";
const char *const conf_key_toolbar_style = "/apps/regexxer/toolbar_style";
const char *const conf_key_fallback_encoding = "/apps/regexxer/fallback_encoding";
const char *const conf_key_substitution_patterns = "/apps/regexxer/substitution_patterns";
const char *const conf_key_regex_patterns = "/apps/regexxer/regex_patterns";
const char *const conf_key_files_patterns = "/apps/regexxer/files_patterns";
const char *const ui_mainwindow_filename = REGEXXER_PKGDATADIR G_DIR_SEPARATOR_S
"mainwindow.ui";
......
......@@ -183,10 +183,16 @@ MainWindow::MainWindow()
table_file_ (0),
button_folder_ (0),
combo_entry_pattern_ (Gtk::manage(new Gtk::ComboBoxEntryText())),
combo_entry_pattern_completion_stack_(10, Gnome::Conf::Client::get_default_client()->get_string_list(conf_key_files_patterns)),
combo_entry_pattern_completion_ (Gtk::EntryCompletion::create()),
button_recursive_ (0),
button_hidden_ (0),
entry_regex_ (0),
entry_regex_completion_stack_(10, Gnome::Conf::Client::get_default_client()->get_string_list(conf_key_regex_patterns)),
entry_regex_completion_ (Gtk::EntryCompletion::create()),
entry_substitution_ (0),
entry_substitution_completion_stack_(10, Gnome::Conf::Client::get_default_client()->get_string_list(conf_key_substitution_patterns)),
entry_substitution_completion_ (Gtk::EntryCompletion::create()),
button_multiple_ (0),
button_caseless_ (0),
filetree_ (Gtk::manage(new FileTree())),
......@@ -201,7 +207,10 @@ MainWindow::MainWindow()
undo_stack_ (new UndoStack())
{
load_xml();
entry_regex_ = comboboxentry_regex_->get_entry();
entry_substitution_ = comboboxentry_substitution_->get_entry();
textview_->set_buffer(FileBuffer::create());
window_->set_title(PACKAGE_NAME);
......@@ -234,19 +243,35 @@ void MainWindow::initialize(const InitState& init)
const bool folder_exists = button_folder_->set_current_folder(folder);
combo_entry_pattern_->get_entry()->set_text((init.pattern.empty()) ? Glib::ustring(1, '*') : init.pattern);
entry_regex_ ->set_text(init.regex);
combo_entry_pattern_->set_model(combo_entry_pattern_completion_stack_.get_completion_model());
combo_entry_pattern_->set_text_column(combo_entry_pattern_completion_stack_.get_completion_column());
combo_entry_pattern_->get_entry()->set_completion(combo_entry_pattern_completion_);
entry_regex_->set_text(init.regex);
entry_regex_->set_completion(entry_regex_completion_);
entry_substitution_->set_text(init.substitution);
entry_substitution_->set_completion(entry_substitution_completion_);
comboboxentry_regex_->set_model(entry_regex_completion_stack_.get_completion_model());
comboboxentry_regex_->set_text_column(entry_regex_completion_stack_.get_completion_column());
comboboxentry_substitution_->set_model(entry_substitution_completion_stack_.get_completion_model());
comboboxentry_substitution_->set_text_column(entry_substitution_completion_stack_.get_completion_column());
combo_entry_pattern_completion_->set_model(combo_entry_pattern_completion_stack_.get_completion_model());
combo_entry_pattern_completion_->set_text_column(combo_entry_pattern_completion_stack_.get_completion_column());
combo_entry_pattern_completion_->set_inline_completion(true);
combo_entry_pattern_completion_->set_popup_completion(false);
entry_regex_completion_->set_model(entry_regex_completion_stack_.get_completion_model());
entry_regex_completion_->set_text_column(entry_regex_completion_stack_.get_completion_column());
entry_regex_completion_->set_inline_completion(true);
entry_regex_completion_->set_popup_completion(false);
combo_entry_pattern_->append_text("*.[ch]");
combo_entry_pattern_->append_text("*.{c,cc,cpp,cxx,c++,C,h,hh,hpp,hxx,h++}");
combo_entry_pattern_->append_text("*.{ccg,hg}");
combo_entry_pattern_->append_text("*.idl");
combo_entry_pattern_->append_text("*.{java,jsp}");
combo_entry_pattern_->append_text("*.{pl,pm,cgi}");
combo_entry_pattern_->append_text("*.py");
combo_entry_pattern_->append_text("*.php[0-9]?");
combo_entry_pattern_->append_text("*.{html,htm,shtml,js,wml}");
combo_entry_pattern_->append_text("*.{xml,xsl,css,dtd,xsd}");
entry_substitution_completion_->set_model(entry_substitution_completion_stack_.get_completion_model());
entry_substitution_completion_->set_text_column(entry_substitution_completion_stack_.get_completion_column());
entry_substitution_completion_->set_inline_completion(true);
entry_substitution_completion_->set_popup_completion(false);
button_recursive_->set_active(!init.no_recursive);
button_hidden_ ->set_active(init.hidden);
......@@ -282,8 +307,8 @@ void MainWindow::load_xml()
xml->get_widget("button_folder", button_folder_);
xml->get_widget("button_recursive", button_recursive_);
xml->get_widget("button_hidden", button_hidden_);
xml->get_widget("entry_regex", entry_regex_);
xml->get_widget("entry_substitution", entry_substitution_);
xml->get_widget("comboboxentry_regex", comboboxentry_regex_);
xml->get_widget("comboboxentry_substitution", comboboxentry_substitution_);
xml->get_widget("button_multiple", button_multiple_);
xml->get_widget("button_caseless", button_caseless_);
xml->get_widget("scrollwin_textview", scrollwin_textview_);
......@@ -505,6 +530,10 @@ void MainWindow::on_find_files()
if (dialog.run() != Gtk::RESPONSE_OK)
return;
}
const Glib::ustring files_regex = combo_entry_pattern_->get_entry()->get_text();
combo_entry_pattern_completion_stack_.push(files_regex);
Gnome::Conf::Client::get_default_client()->set_string_list(conf_key_files_patterns, combo_entry_pattern_completion_stack_.get_stack());
std::string folder = button_folder_->get_filename();
......@@ -519,7 +548,7 @@ void MainWindow::on_find_files()
try
{
Pcre::Pattern pattern (Util::shell_pattern_to_regex(combo_entry_pattern_->get_entry()->get_text()), Pcre::DOTALL);
Pcre::Pattern pattern (Util::shell_pattern_to_regex(files_regex), Pcre::DOTALL);
filetree_->find_files(folder, pattern,
button_recursive_->get_active(),
......@@ -548,7 +577,10 @@ void MainWindow::on_exec_search()
const Glib::ustring regex = entry_regex_->get_text();
const bool caseless = button_caseless_->get_active();
const bool multiple = button_multiple_->get_active();
entry_regex_completion_stack_.push(regex);
Gnome::Conf::Client::get_default_client()->set_string_list(conf_key_regex_patterns, entry_regex_completion_stack_.get_stack());
try
{
Pcre::Pattern pattern (regex, (caseless) ? Pcre::CASELESS : Pcre::CompileOptions(0));
......@@ -733,7 +765,10 @@ void MainWindow::on_replace()
{
if (const FileBufferPtr buffer = FileBufferPtr::cast_static(textview_->get_buffer()))
{
buffer->replace_current_match(entry_substitution_->get_text());
const Glib::ustring substitution = entry_substitution_->get_text();
entry_substitution_completion_stack_.push(substitution);
Gnome::Conf::Client::get_default_client()->set_string_list(conf_key_substitution_patterns, entry_substitution_completion_stack_.get_stack());
buffer->replace_current_match(substitution);
on_go_next(true);
}
}
......@@ -742,7 +777,10 @@ void MainWindow::on_replace_file()
{
if (const FileBufferPtr buffer = FileBufferPtr::cast_static(textview_->get_buffer()))
{
buffer->replace_all_matches(entry_substitution_->get_text());
const Glib::ustring substitution = entry_substitution_->get_text();
entry_substitution_completion_stack_.push(substitution);
Gnome::Conf::Client::get_default_client()->set_string_list(conf_key_substitution_patterns, entry_substitution_completion_stack_.get_stack());
buffer->replace_all_matches(substitution);
statusline_->set_match_index(0);
}
}
......@@ -751,7 +789,10 @@ void MainWindow::on_replace_all()
{
BusyAction busy (*this);
filetree_->replace_all_matches(entry_substitution_->get_text());
const Glib::ustring substitution = entry_substitution_->get_text();
entry_substitution_completion_stack_.push(substitution);
Gnome::Conf::Client::get_default_client()->set_string_list(conf_key_substitution_patterns, entry_substitution_completion_stack_.get_stack());
filetree_->replace_all_matches(substitution);
statusline_->set_match_index(0);
}
......
......@@ -24,6 +24,7 @@
#include "controller.h"
#include "filebuffer.h"
#include "sharedptr.h"
#include "completionstack.h"
#include <sigc++/sigc++.h>
#include <glibmm/refptr.h>
......@@ -41,10 +42,11 @@ class Entry;
class FileChooser;
class Toolbar;
class Window;
class ComboBoxEntryText;
class ComboBoxEntry;
class VBox;
class ScrolledWindow;
class Table;
class EntryCompletion;
}
namespace gtksourceview
......@@ -100,12 +102,24 @@ private:
Gtk::Table* table_file_;
Gtk::FileChooser* button_folder_;
Gtk::ComboBoxEntryText* combo_entry_pattern_;
Gtk::ComboBoxEntry* combo_entry_pattern_;
CompletionStack combo_entry_pattern_completion_stack_;
Glib::RefPtr<Gtk::EntryCompletion> combo_entry_pattern_completion_;
Gtk::CheckButton* button_recursive_;
Gtk::CheckButton* button_hidden_;
Gtk::ComboBoxEntry* comboboxentry_regex_;
Gtk::Entry* entry_regex_;
CompletionStack entry_regex_completion_stack_;
Glib::RefPtr<Gtk::EntryCompletion> entry_regex_completion_;
Gtk::ComboBoxEntry* comboboxentry_substitution_;
Gtk::Entry* entry_substitution_;
CompletionStack entry_substitution_completion_stack_;
Glib::RefPtr<Gtk::EntryCompletion> entry_substitution_completion_;
Gtk::CheckButton* button_multiple_;
Gtk::CheckButton* button_caseless_;
......
......@@ -551,7 +551,6 @@
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Search:</property>
<property name="mnemonic_widget">entry_regex</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
......@@ -563,7 +562,6 @@
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Replace:</property>
<property name="mnemonic_widget">entry_substitution</property>
</object>
<packing>
<property name="top_attach">1</property>
......@@ -572,32 +570,6 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_regex">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">A regular expression in Perl syntax</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_substitution">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The new string to substitute. As in Perl, you can refer to parts of the match using $1, $2, etc. or even $+, $&amp;, $` and $'. The operators \l, \u, \L, \U and \E are supported as well.</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox_options">
<property name="visible">True</property>
......@@ -659,6 +631,29 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkComboBoxEntry" id="comboboxentry_regex">
<property name="visible">True</property>
<property name="tooltip_text" translatable="yes">A regular expression in Perl syntax</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkComboBoxEntry" id="comboboxentry_substitution">
<property name="visible">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
......
<?xml version="1.0"?>
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/apps/regexxer/files_patterns</key>
<applyto>/apps/regexxer/files_patterns</applyto>
<owner>regexxer</owner>
<type>list</type>
<list_type>string</list_type>
<default_value>
<value>
<list type="string">
</list>
</value>
</default_value>
<locale name="C">
<short>Regex Patterns</short>
<long>List of last pattern used for the file's regex entry.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/regexxer/regex_patterns</key>
<applyto>/apps/regexxer/regex_patterns</applyto>
<owner>regexxer</owner>
<type>list</type>
<list_type>string</list_type>
<default_value>
<value>
<list type="string">
</list>
</value>
</default_value>
<locale name="C">
<short>Regex Patterns</short>
<long>List of last pattern used for the regex entry.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/regexxer/substitution_patterns</key>
<applyto>/apps/regexxer/substitution_patterns</applyto>
<owner>regexxer</owner>
<type>list</type>
<list_type>string</list_type>
<default_value>
<value>
<list type="string">
</list>
</value>
</default_value>
<locale name="C">
<short>Regex Patterns</short>
<long>List of last pattern used for the substitution entry.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/regexxer/textview_font</key>
<applyto>/apps/regexxer/textview_font</applyto>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment