ide: Find now support PCRE regexes

git-svn-id: svn://ultimatepp.org/upp/trunk@7504 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-07-11 14:27:08 +00:00
parent c87f090229
commit 32ea2628dd
9 changed files with 179 additions and 115 deletions

View file

@ -3,7 +3,7 @@
//#include <ide/Common/Common.h>
#include <CtrlLib/CtrlLib.h>
#include <plugin/pcre/Pcre.h>
NAMESPACE_UPP
@ -15,7 +15,7 @@ NAMESPACE_UPP
#define IMAGEFILE <CodeEditor/CodeEditor.iml>
#include <Draw/iml_header.h>
void FindWildcardMenu(Callback1<int> cb, Point p, bool tablf, Ctrl *owner = NULL);
void FindWildcardMenu(Callback1<const char *> cb, Point p, bool tablf, Ctrl *owner, bool regexp);
struct LineInfoRecord {
int lineno;
@ -254,7 +254,7 @@ protected:
WString selword;
int iwc;
String iwc;
String highlight;
@ -281,7 +281,7 @@ protected:
void FindReplaceAddHistory();
void FindWildcard();
void ReplaceWildcard();
void InsertWildcard(int c);
void InsertWildcard(const char *s);
void IncrementalFind();
void NoFindError();
void CheckSyntaxRefresh(int pos, const WString& text);
@ -346,6 +346,7 @@ public:
void CloseFindReplace();
void FindReplace(bool pick_selection, bool pick_text, bool replace);
bool FindFrom(int pos, bool back, const wchar *text, bool wholeword, bool ignorecase, bool wildcards, bool block);
bool RegExpFind(int pos, const wchar *text, bool block);
bool Find(bool back, const wchar *text, bool wholeword, bool ignorecase, bool wildcards,
bool block, bool incremental);
bool Find(bool back = false, bool blockreplace = false, bool replace = false, bool incremental = false);
@ -460,7 +461,7 @@ public:
struct FindReplaceData {
String find, replace;
bool wholeword, wildcards, ignorecase, samecase;
bool wholeword, wildcards, ignorecase, samecase, regexp;
};
FindReplaceData GetFindReplaceData() const;

View file

@ -1,4 +1,4 @@
LAYOUT(IDEFindReplaceLayout, 632, 52)
LAYOUT(IDEFindReplaceLayout, 696, 52)
ITEM(Label, info, SetLabel(t_("&Find")).LeftPosZ(4, 60).TopPosZ(4, 19))
ITEM(WithDropChoice<EditString>, find, LeftPosZ(68, 152).TopPosZ(4, 19))
ITEM(Label, dv___2, SetLabel(t_("&Replace")).LeftPosZ(4, 60).TopPosZ(28, 21))
@ -8,8 +8,9 @@ LAYOUT(IDEFindReplaceLayout, 632, 52)
ITEM(Option, wildcards, SetLabel(t_("Wild&cards")).LeftPosZ(268, 72).TopPosZ(4, 19))
ITEM(Option, wholeword, SetLabel(t_("&Whole word")).LeftPosZ(344, 88).TopPosZ(4, 19))
ITEM(Option, ignorecase, SetLabel(t_("&Ignore case")).LeftPosZ(436, 80).TopPosZ(4, 19))
ITEM(Option, incremental, SetLabel(t_("&Incremental")).LeftPosZ(520, 92).TopPosZ(4, 19))
ITEM(Button, close, RightPosZ(4, 20).TopPosZ(4, 19))
ITEM(Option, regexp, SetLabel(t_("RegExp")).LeftPosZ(520, 80).TopPosZ(4, 19))
ITEM(Option, incremental, SetLabel(t_("&Incremental")).LeftPosZ(580, 92).TopPosZ(4, 19))
ITEM(Button, close, RightPosZ(8, 20).TopPosZ(4, 19))
ITEM(Button, amend, LeftPosZ(224, 20).TopPosZ(28, 19))
ITEM(Option, samecase, SetLabel(t_("Mimic case")).LeftPosZ(268, 108).TopPosZ(28, 19))
END_LAYOUT
@ -20,10 +21,10 @@ LAYOUT(BlockReplaceLayout, 400, 116)
ITEM(Label, dv___2, SetLabel(t_("Replace")).LeftPosZ(8, 46).TopPosZ(28, 19))
ITEM(WithDropChoice<EditString>, replace, HSizePosZ(54, 8).TopPosZ(28, 19))
ITEM(Option, wholeword, SetLabel(t_("&Whole word")).LeftPosZ(8, 100).BottomPosZ(40, 20))
ITEM(Option, wildcards, SetLabel(t_("Wild&cards")).LeftPosZ(108, 88).BottomPosZ(40, 20))
ITEM(Option, ignorecase, SetLabel(t_("&Ignore case")).LeftPosZ(208, 92).BottomPosZ(40, 20))
ITEM(Option, samecase, SetLabel(t_("Mimic case")).LeftPosZ(308, 108).BottomPosZ(40, 20))
ITEM(Option, wildcards, SetLabel(t_("Wild&cards")).LeftPosZ(96, 88).BottomPosZ(40, 20))
ITEM(Option, ignorecase, SetLabel(t_("&Ignore case")).LeftPosZ(172, 92).BottomPosZ(40, 20))
ITEM(Option, samecase, SetLabel(t_("Mimic case")).LeftPosZ(260, 108).BottomPosZ(40, 20))
ITEM(Option, regexp, SetLabel(t_("RegEx")).LeftPosZ(344, 108).BottomPosZ(40, 20))
ITEM(Button, next, SetLabel(t_("Replace")).RightPosZ(80, 76).BottomPosZ(8, 24))
ITEM(Button, close, SetLabel(t_("Cancel")).RightPosZ(8, 64).BottomPosZ(8, 24))
END_LAYOUT

View file

@ -3,7 +3,8 @@ description "The source files edit, derived from CtrlLib's LineEdit\377";
optimize_speed;
uses
CtrlLib;
CtrlLib,
plugin/pcre;
file
CodeEditor.h,

View file

@ -16,6 +16,7 @@ void CodeEditor::InitFindReplace()
found = notfoundfw = notfoundbk = foundsel = false;
persistent_find_replace = false;
findreplace.find <<= findreplace.wholeword <<= findreplace.wildcards
<<= findreplace.incremental <<= findreplace.regexp
<<= findreplace.ignorecase <<= THISBACK(IncrementalFind);
}
@ -33,6 +34,11 @@ FindReplaceDlg::FindReplaceDlg()
void FindReplaceDlg::Sync()
{
samecase.Enable(ignorecase);
bool b = !regexp;
wildcards.Enable(b);
prev.Enable(b);
ignorecase.Enable(b);
wholeword.Enable(b);
}
dword CodeEditor::find_next_key = K_F3;
@ -183,8 +189,43 @@ bool CodeEditor::Find(bool back, const wchar *text, bool wholeword, bool ignorec
return FindFrom(pos, back, text, wholeword, ignorecase, wildcards, block);
}
bool CodeEditor::RegExpFind(int pos, const wchar *text, bool block)
{
RegExp regex(ToUtf8(text));
int line = GetLinePos(pos);
int linecount = GetLineCount();
String ln = ToUtf8(GetWLine(line).Mid(pos));
for(;;) {
if(regex.Match(ln)) {
for(int i = 0; i < regex.GetCount(); i++)
SetFound(i, WILDANY, regex.GetString(i).ToWString());
int off = regex.GetOffset();
int len = utf8len(~ln + off, regex.GetLength());
pos = GetPos(line, utf8len(~ln, off) + pos);
foundtext = GetW(pos, len);
if(!block) {
foundsel = true;
SetSelection(pos, pos + len);
foundsel = false;
CenterCursor();
}
foundpos = pos;
foundsize = len;
found = true;
return true;
}
if(++line >= linecount)
return false;
ln = GetUtf8Line(line);
pos = 0;
}
}
bool CodeEditor::FindFrom(int pos, bool back, const wchar *text, bool wholeword, bool ignorecase,
bool wildcards, bool block) {
if(findreplace.regexp)
return RegExpFind(pos, text, block);
WString ft;
const wchar *s = text;
while(*s) {
@ -536,23 +577,36 @@ void CodeEditor::FindReplace(bool pick_selection, bool pick_text, bool replace)
}
}
void CodeEditor::InsertWildcard(int c)
void CodeEditor::InsertWildcard(const char *s)
{
iwc = c;
iwc = s;
}
void FindWildcardMenu(Callback1<int> cb, Point p, bool tablf, Ctrl *owner)
void FindWildcardMenu(Callback1<const char *> cb, Point p, bool tablf, Ctrl *owner, bool regexp)
{
MenuBar menu;
menu.Add("One or more spaces", callback1(cb, '%'));
menu.Add("One or more any characters", callback1(cb, '*'));
menu.Add("C++ identifier", callback1(cb, '$'));
menu.Add("Number", callback1(cb, '#'));
menu.Add("Any character", callback1(cb, '?'));
if(tablf) {
menu.Separator();
menu.Add("Tab", callback1(cb, '\t'));
menu.Add("Line feed", callback1(cb, '\n'));
if(regexp) {
menu.Add("One or more spaces", callback1(cb, " +"));
menu.Add("One or more any characters", callback1(cb, ".+"));
menu.Add("Word", callback1(cb, "\\w+"));
menu.Add("Number", callback1(cb, "\\d+"));
menu.Add("Any character", callback1(cb, "."));
if(tablf) {
menu.Separator();
menu.Add("Tab", callback1(cb, "\\t"));
}
}
else {
menu.Add("One or more spaces", callback1(cb, "%"));
menu.Add("One or more any characters", callback1(cb, "*"));
menu.Add("C++ identifier", callback1(cb, "$"));
menu.Add("Number", callback1(cb, "#"));
menu.Add("Any character", callback1(cb, "?"));
if(tablf) {
menu.Separator();
menu.Add("Tab", callback1(cb, "\\t"));
menu.Add("Line feed", callback1(cb, "\\n"));
}
}
menu.Execute(owner, p);
}
@ -561,83 +615,56 @@ void CodeEditor::FindWildcard()
{
int l, h;
findreplace.find.GetSelection(l, h);
iwc = 0;
iwc.Clear();
FindWildcardMenu(THISBACK(InsertWildcard), findreplace.find.GetPushScreenRect().TopRight(), true,
&findreplace);
if(iwc) {
findreplace.wildcards = true;
&findreplace, findreplace.regexp);
if(iwc.GetCount()) {
if(!findreplace.regexp)
findreplace.wildcards = true;
findreplace.find.SetFocus();
findreplace.find.SetSelection(l, h);
findreplace.find.RemoveSelection();
if(iwc == '\t') {
findreplace.find.Insert('\\');
findreplace.find.Insert('t');
}
else
if(iwc == '\n') {
findreplace.find.Insert('\\');
findreplace.find.Insert('n');
}
else
findreplace.find.Insert(iwc);
findreplace.find.Insert(iwc);
}
}
void CodeEditor::ReplaceWildcard()
{
MenuBar menu;
menu.Add("Matched spaces", THISBACK1(InsertWildcard, '%'));
menu.Add("Matched one or more any characters", THISBACK1(InsertWildcard, '*'));
menu.Add("Matched C++ identifier", THISBACK1(InsertWildcard, '$'));
menu.Add("Matched number", THISBACK1(InsertWildcard, '#'));
menu.Add("Matched any character", THISBACK1(InsertWildcard, '?'));
menu.Add("0-based replace index", THISBACK1(InsertWildcard, '0'));
menu.Add("1-based replace index", THISBACK1(InsertWildcard, '1'));
String ptxt;
if(findreplace.regexp) {
ptxt = "Matched subpattern %d";
}
else {
menu.Add("Matched spaces", THISBACK1(InsertWildcard, "%"));
menu.Add("Matched one or more any characters", THISBACK1(InsertWildcard, "*"));
menu.Add("Matched C++ identifier", THISBACK1(InsertWildcard, "$"));
menu.Add("Matched number", THISBACK1(InsertWildcard, "#"));
menu.Add("Matched any character", THISBACK1(InsertWildcard, "?"));
}
menu.Add("0-based replace index", THISBACK1(InsertWildcard, "0"));
menu.Add("1-based replace index", THISBACK1(InsertWildcard, "1"));
menu.Separator();
for(int i = 1; i <= 9; i++)
menu.Add(Format("Matched wildcard %d", i), THISBACK1(InsertWildcard, i));
menu.Add(Format(ptxt, i), THISBACK1(InsertWildcard, "@"+AsString(i)));
menu.Separator();
menu.Add("To upper", THISBACK1(InsertWildcard, '+'));
menu.Add("To lower", THISBACK1(InsertWildcard, '-'));
menu.Add("InitCaps", THISBACK1(InsertWildcard, '!'));
menu.Add("To upper", THISBACK1(InsertWildcard, "+"));
menu.Add("To lower", THISBACK1(InsertWildcard, "-"));
menu.Add("InitCaps", THISBACK1(InsertWildcard, "!"));
menu.Separator();
menu.Add("Tab", THISBACK1(InsertWildcard, 20));
menu.Add("Line feed", THISBACK1(InsertWildcard, 21));
menu.Add("Tab", THISBACK1(InsertWildcard, "\\t"));
menu.Add("Line feed", THISBACK1(InsertWildcard, "\\n"));
int l, h;
findreplace.replace.GetSelection(l, h);
iwc = 0;
iwc.Clear();
menu.Execute(&findreplace, findreplace.replace.GetPushScreenRect().TopRight());
if(iwc) {
findreplace.wildcards = true;
if(iwc.GetCount()) {
if(!findreplace.regexp)
findreplace.wildcards = true;
findreplace.replace.SetFocus();
findreplace.replace.SetSelection(l, h);
findreplace.replace.RemoveSelection();
if(iwc == 20) {
findreplace.replace.Insert('\\');
findreplace.replace.Insert('t');
}
else
if(iwc == 21) {
findreplace.replace.Insert('\\');
findreplace.replace.Insert('n');
}
else
if(iwc == '0') {
findreplace.replace.Insert('@');
findreplace.replace.Insert('@');
}
else
if(iwc == '1') {
findreplace.replace.Insert('@');
findreplace.replace.Insert('#');
}
else
if(iwc >= 1 && iwc <= 9) {
findreplace.replace.Insert('@');
findreplace.replace.Insert(iwc + '0');
}
else
findreplace.replace.Insert(iwc);
findreplace.replace.Insert(iwc);
}
}
@ -670,7 +697,7 @@ void CodeEditor::DoFindBack()
void CodeEditor::SerializeFind(Stream& s)
{
int version = 1;
int version = 2;
s / version;
s % findreplace.find;
findreplace.find.SerializeList(s);
@ -680,6 +707,8 @@ void CodeEditor::SerializeFind(Stream& s)
s % findreplace.replace;
if(version >= 1)
s % findreplace.incremental;
if(version >= 2)
s % findreplace.regexp;
findreplace.replace.SerializeList(s);
}
@ -692,6 +721,7 @@ CodeEditor::FindReplaceData CodeEditor::GetFindReplaceData() const
r.ignorecase = ~findreplace.ignorecase;
r.wildcards = ~findreplace.wildcards;
r.samecase = ~findreplace.samecase;
r.regexp = ~findreplace.regexp;
return r;
}
@ -703,6 +733,7 @@ void CodeEditor::SetFindReplaceData(const FindReplaceData& r)
findreplace.ignorecase <<= r.ignorecase;
findreplace.wildcards <<= r.wildcards;
findreplace.samecase <<= r.samecase;
findreplace.regexp <<= r.regexp;
}
END_UPP_NAMESPACE

View file

@ -1,7 +1,8 @@
#ifndef _CodeEditor_icpp_init_stub
#define _CodeEditor_icpp_init_stub
#include "CtrlLib/init"
#define BLITZ_INDEX__ Fd579c6629af5990c016d4bd1dc2b4c20
#include "plugin/pcre/init"
#define BLITZ_INDEX__ F8defc3b59944b6f49a28a98ad6148c81
#include "CRegister.icpp"
#undef BLITZ_INDEX__
#endif

View file

@ -29,7 +29,7 @@ FileSel& sSD()
}
void Ide::SerializeFindInFiles(Stream& s) {
int version = 4;
int version = 5;
s / version;
s % ff.files;
ff.files.SerializeList(s);
@ -47,6 +47,8 @@ void Ide::SerializeFindInFiles(Stream& s) {
s % ff.readonly;
if(version >= 4)
s % ff.samecase;
if(version >= 5)
s % ff.regexp;
}
void SearchForFiles(Vector<String>& files, String dir, String mask, int readonly, Progress& pi) {
@ -121,8 +123,21 @@ bool Match(const char *f, const char *s, bool we, bool ignorecase, int& count) {
return we && iscid(*s) ? false : true;
}
void Ide::AddFoundFile(const String& fn, int ln, const String& line, int pos, int count)
{
ErrorInfo f;
f.file = fn;
f.lineno = ln;
f.linepos = 0;
f.kind = 0;
f.message = "\1" + EditorSyntax::GetSyntaxForFilename(fn) + "\1" +
AsString(pos) + "\1" + AsString(count) + "\1" + line;
ffound.Add(GetFileName(fn), ln, f.message, RawToValue(f));
ffound.Sync();
}
bool Ide::SearchInFile(const String& fn, const String& pattern, bool wholeword, bool ignorecase,
int& n) {
int& n, RegExp *regexp) {
FileIn in(fn);
if(!in) return true;
int ln = 1;
@ -133,23 +148,20 @@ bool Ide::SearchInFile(const String& fn, const String& pattern, bool wholeword,
String line = in.GetLine();
bool bw = true;
int count;
for(const char *s = line; *s; s++) {
if(bw && Match(pattern, s, we, ignorecase, count)) {
ErrorInfo f;
f.file = fn;
f.lineno = ln;
f.linepos = 0;
f.kind = 0;
f.message = "\1" + EditorSyntax::GetSyntaxForFilename(fn) + "\1" +
AsString(s - line) + "\1" + AsString(count) + "\1" + line;
ffound.Add(GetFileName(fn), ln, f.message, RawToValue(f));
ffound.Sync();
infile++;
n++;
break;
}
if(wb) bw = !iscid(*s);
if(regexp) {
if(regexp->Match(line))
AddFoundFile(fn, ln, line, regexp->GetOffset(), regexp->GetLength());
}
else
for(const char *s = line; *s; s++) {
if(bw && Match(pattern, s, we, ignorecase, count)) {
AddFoundFile(fn, ln, line, s - line, count);
infile++;
n++;
break;
}
if(wb) bw = !iscid(*s);
}
ln++;
}
@ -241,7 +253,9 @@ void Ide::FindInFiles(bool replace) {
(ff.samecase, d.samecase)
(ff.wholeword, d.wholeword)
(ff.wildcards, d.wildcards)
(ff.regexp, d.regexp)
;
ff.Sync();
if(String(ff.folder).IsEmpty())
ff.folder <<= GetUppDir();
ff.style <<= STYLE_NO_REPLACE;
@ -253,6 +267,7 @@ void Ide::FindInFiles(bool replace) {
rf.Retrieve();
editor.SetFindReplaceData(d);
if(c == IDOK) {
Renumber();
@ -266,6 +281,13 @@ void Ide::FindInFiles(bool replace) {
~ff.files, ~ff.readonly, pi);
if(!pi.Canceled()) {
String pattern;
RegExp rx, *regexp = NULL;
if(ff.regexp) {
rx.SetPattern(~ff.find);
regexp = &rx;
pattern = "dummy";
}
else
if(ff.wildcards) {
String q = ~ff.find;
for(const char *s = q; *s; s++)
@ -295,7 +317,7 @@ void Ide::FindInFiles(bool replace) {
pi.SetText(files[i]);
if(pi.StepCanceled()) break;
if(!IsNull(pattern)) {
if(!SearchInFile(files[i], pattern, ff.wholeword, ff.ignorecase, n))
if(!SearchInFile(files[i], pattern, ff.wholeword, ff.ignorecase, n, regexp))
break;
}
else {
@ -335,16 +357,16 @@ void Ide::TranslateString()
}
}
void Ide::InsertWildcard(int c) {
iwc = c;
void Ide::InsertWildcard(const char *s) {
iwc = s;
}
void Ide::FindWildcard() {
int l, h;
ff.find.GetSelection(l, h);
iwc = 0;
FindWildcardMenu(THISBACK(InsertWildcard), ff.find.GetPushScreenRect().TopRight(), false);
if(iwc) {
FindWildcardMenu(THISBACK(InsertWildcard), ff.find.GetPushScreenRect().TopRight(), false, NULL, ff.regexp);
if(iwc.GetCount()) {
ff.wildcards = true;
ff.find.SetFocus();
ff.find.SetSelection(l, h);
@ -401,11 +423,15 @@ void Ide::ConstructFindInFiles() {
void FindInFilesDlg::Sync()
{
replace.Enable((int)~style);
bool b = !regexp;
wildcards.Enable(b);
ignorecase.Enable(b);
wholeword.Enable(b);
}
FindInFilesDlg::FindInFilesDlg()
{
style <<= THISBACK(Sync);
regexp <<= style <<= THISBACK(Sync);
readonly <<= Null;
}

View file

@ -732,7 +732,7 @@ public:
String find_file_search_string;
FindInFilesDlg ff;
int iwc;
String iwc;
int doc_serial;
TopicCtrl doc;
@ -1062,9 +1062,10 @@ public:
void FindFolder();
void FindSetStdDir(String n);
void FindStdDir();
void InsertWildcard(int c);
void InsertWildcard(const char *s);
void AddFoundFile(const String& fn, int ln, const String& line, int pos, int count);
bool SearchInFile(const String& fn, const String& pattern,
bool wholeword, bool ignorecase, int& n);
bool wholeword, bool ignorecase, int& n, RegExp *regexp);
void SyncFindInFiles();
void ConstructFindInFiles();
void SerializeFindInFiles(Stream& s);

View file

@ -81,9 +81,10 @@ LAYOUT(FindInFilesLayout, 420, 152)
ITEM(Switch, style, SetLabel(t_("&None\nCo&nfirm\n&Auto")).LeftPosZ(52, 164).TopPosZ(78, 15))
ITEM(Label, replace_lbl2, SetLabel(t_("with:")).LeftPosZ(220, 28).TopPosZ(76, 19))
ITEM(Option, wholeword, SetLabel(t_("&Whole word")).LeftPosZ(54, 80).BottomPosZ(34, 18))
ITEM(Option, wildcards, SetLabel(t_("Wild&cards")).LeftPosZ(140, 72).BottomPosZ(34, 18))
ITEM(Option, ignorecase, SetLabel(t_("&Ignore case")).LeftPosZ(216, 84).BottomPosZ(34, 18))
ITEM(Option, samecase, SetLabel(t_("Mimic case")).LeftPosZ(304, 112).BottomPosZ(34, 18))
ITEM(Option, wildcards, SetLabel(t_("Wild&cards")).LeftPosZ(136, 72).BottomPosZ(34, 18))
ITEM(Option, ignorecase, SetLabel(t_("&Ignore case")).LeftPosZ(208, 84).BottomPosZ(34, 18))
ITEM(Option, samecase, SetLabel(t_("Mimic case")).LeftPosZ(288, 100).BottomPosZ(34, 18))
ITEM(Option, regexp, SetLabel(t_("RegEx")).LeftPosZ(368, 112).BottomPosZ(34, 18))
ITEM(Option, readonly, ThreeState(true).SetLabel(t_("Read-only files")).LeftPosZ(54, 142).BottomPosZ(14, 16))
ITEM(Button, ok, SetLabel(t_("OK")).RightPosZ(72, 64).BottomPosZ(6, 22))
ITEM(Button, cancel, SetLabel(t_("Cancel")).RightPosZ(4, 64).BottomPosZ(6, 22))

View file

@ -1,9 +1,10 @@
description "PCRE regular expressions library\377";
description "PCRE regular expressions library\3770,128,128";
file
Pcre.h,
RegExp.h,
RegExp.cpp,
lib/config.h,
lib.cpp,
COPYING;