mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 14:15:49 -06:00
New features TransformText.
В строке замены дабавлены следующие возможности:
1. Добавлена подсветка групп.
Только цвета заданные в настройке "colorGroup" . 13 цветов по умолчанию.
Если использовано больше групп, добавьте цвета в pgadmin3opt.json
2. Добавлены пользовательские группы вида [ ].
Группы (вида \g{n} и []) указанные в квадратных скобках проверяются на пустые значения и
Если они ВСЕ пустые то всё выражение в [] считается пустой строкой.
Скобки могут быть вложенными.
Применяются для того что бы не выводить разделитель для пустой группы.
Например: [\t \g{2}[\t \g{3}]]
3. Добавлена возможность не выводить содержимое группы.
Для этого группу указывают так: \G{n}
Применяется для замены текста на пользовательский.
Например: [and not null\G{2}]
Этот фрагмент выведет "and not null" если группа 2 не пустая иначе ""
4. Разносить текст замены можно на несколько строк.
Переводы строк при замене игнорируются.
Если нужно добавить перевод строк в текст замены нужно явно указать \n\r.
This commit is contained in:
parent
fbc741af9c
commit
feaaf49bc6
2 changed files with 147 additions and 29 deletions
|
|
@ -2,6 +2,17 @@
|
|||
#include "pgAdmin3.h"
|
||||
#include <wx/clipbrd.h>
|
||||
#include "ctl/ctlStyledText.h"
|
||||
enum class eTypeGroup {
|
||||
SIMPLE_TEXT = -1,
|
||||
USER_GROUP_START = -2,
|
||||
USER_GROUP_END = -3
|
||||
};
|
||||
struct interval {
|
||||
size_t start = -1;
|
||||
size_t len = 0;
|
||||
int style = 0;
|
||||
};
|
||||
|
||||
class dlgTransformText :
|
||||
public pgDialog
|
||||
{
|
||||
|
|
@ -29,6 +40,9 @@ private:
|
|||
bool isGroup = false;
|
||||
int nGroup = -1;
|
||||
wxString text;
|
||||
int flags = 0;
|
||||
int start = -1;
|
||||
int len = 0;
|
||||
};
|
||||
wxJSONValue LoadConfig(const wxString confname);
|
||||
void CheckLimits();
|
||||
|
|
@ -38,7 +52,27 @@ private:
|
|||
void SetStyled(ctlStyledText* s);
|
||||
void showNumber(ctlStyledText* text, bool visible);
|
||||
void AppendTextControl(ctlStyledText* ctrl, const wxString appendtext, bool isnewline = false);
|
||||
/// <summary>
|
||||
/// Обработка строки замены и подготовка специальной струкутуры.
|
||||
/// Допустимые спец. комбинации \t \r\ \n
|
||||
/// \g{n} Ссылка на группы wxRegExp n=0..N
|
||||
/// \G{n} Не выводить содержимое группы. Имеет смысл использовать для замены текста группы на свой
|
||||
/// [ ] Пользовальская группа обладающая следующим свойством:
|
||||
/// Если в этой группе присутствуют \g{n} и они все пустые то вся группа [ ] считается пустой
|
||||
/// Пользовательские группы могут быть вложенными.
|
||||
/// </summary>
|
||||
/// <param name="repstr"></param>
|
||||
/// <returns></returns>
|
||||
std::vector<replace_opt> BuildString(const wxString repstr);
|
||||
wxString ReplaceFormatting(
|
||||
const wxString& src,
|
||||
const wxRegEx& r,
|
||||
const std::vector<dlgTransformText::replace_opt> st,
|
||||
int &position,
|
||||
interval m2[],
|
||||
int maxsizeintervalarray,
|
||||
int &currindex,
|
||||
size_t &start_frame);
|
||||
|
||||
wxString src;
|
||||
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ std::vector<dlgTransformText::replace_opt> dlgTransformText::BuildString(const w
|
|||
wxString e;
|
||||
for (int i = 0; i < repstr.length(); i++) {
|
||||
wxChar c = repstr[i];
|
||||
if (c == '\n'|| c=='\r') continue;
|
||||
if (!isback && c == '\\') {
|
||||
isback = true;
|
||||
continue;
|
||||
|
|
@ -318,18 +319,20 @@ std::vector<dlgTransformText::replace_opt> dlgTransformText::BuildString(const w
|
|||
if (c == 'r') c = '\r';
|
||||
else if (c == 'n') c = '\n';
|
||||
else if (c == 't') c = '\t';
|
||||
else if (c == 'g') {
|
||||
else if (c == 'g'|| c=='G') {
|
||||
int l = repstr.length();
|
||||
if (l - i > 2) {
|
||||
int pos = repstr.find_first_of('}', i);
|
||||
int flags = 0;
|
||||
if (pos >= 0) {
|
||||
wxString ngrp = repstr.substr(i + 2, pos - i - 2);
|
||||
int ngroup = -1;
|
||||
int scanned = wxSscanf(ngrp, "%d", &ngroup);
|
||||
if (scanned == 1) {
|
||||
if (a.length() > 0) rez.push_back({ false,-1,a });
|
||||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||||
a.clear();
|
||||
rez.push_back({ true,ngroup,wxEmptyString });
|
||||
if (c == 'G') flags |= 1;
|
||||
rez.push_back({ true,ngroup,wxEmptyString,flags,i-1,pos-i+2 });
|
||||
i = pos;
|
||||
isback = false;
|
||||
continue;
|
||||
|
|
@ -340,10 +343,22 @@ std::vector<dlgTransformText::replace_opt> dlgTransformText::BuildString(const w
|
|||
}
|
||||
isback = false;
|
||||
}
|
||||
else if (c == '[') {
|
||||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||||
a.clear();
|
||||
rez.push_back({ true,(int)eTypeGroup::USER_GROUP_START,wxEmptyString });
|
||||
continue;
|
||||
}
|
||||
else if (c == ']') {
|
||||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||||
a.clear();
|
||||
rez.push_back({ true,(int)eTypeGroup::USER_GROUP_END,wxEmptyString });
|
||||
continue;
|
||||
}
|
||||
a.Append(c);
|
||||
if (e.length() > 0) break;
|
||||
}
|
||||
if (a.length() > 0) rez.push_back({ false,-1,a });
|
||||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||||
return rez;
|
||||
}
|
||||
void dlgTransformText::AppendTextControl(ctlStyledText* ctrl, const wxString appendtext, bool isnewline) {
|
||||
|
|
@ -568,6 +583,7 @@ void dlgTransformText::OnOk(wxCommandEvent& ev) {
|
|||
void dlgTransformText::SetStyled(ctlStyledText* s) {
|
||||
int regstyle = wxSTC_STYLE_LASTPREDEFINED + 1;
|
||||
s->StyleClearAll();
|
||||
s->ClearDocumentStyle();
|
||||
countGroupColor = opt["colorGroup"].Size();
|
||||
for (int i = regstyle; i < regstyle + countGroupColor; i++) {
|
||||
wxString strcl = opt["colorGroup"][i - regstyle].AsString();
|
||||
|
|
@ -582,16 +598,73 @@ void dlgTransformText::SetStyled(ctlStyledText* s) {
|
|||
s->StyleSetForeground(i, *wxBLACK);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wxString dlgTransformText::ReplaceFormatting(
|
||||
const wxString &src,
|
||||
const wxRegEx &r,
|
||||
const std::vector<dlgTransformText::replace_opt> st,
|
||||
int &position,
|
||||
interval m2[],
|
||||
int maxsizeintervalarray,
|
||||
int &currindex,
|
||||
size_t &start_frame)
|
||||
{
|
||||
bool isEmptyGroup = true;
|
||||
int maxgroup = r.GetMatchCount();
|
||||
wxString replstr;
|
||||
int ci=currindex;
|
||||
size_t sf = start_frame;
|
||||
while (position<st.size()) {
|
||||
auto& j = st[position++];
|
||||
wxString s;
|
||||
if (j.isGroup && j.nGroup >= 0 && j.nGroup < maxgroup) {
|
||||
s = r.GetMatch(src, j.nGroup);
|
||||
if (ci >= maxsizeintervalarray) break;
|
||||
if (s.length() > 0) isEmptyGroup = false;
|
||||
// verify flags
|
||||
if (j.flags && 1) {
|
||||
// no print group
|
||||
s = wxEmptyString;
|
||||
}
|
||||
m2[ci++] = { sf ,s.length(),j.nGroup };
|
||||
replstr.Append(s);
|
||||
}
|
||||
else if (j.nGroup == (int)eTypeGroup::SIMPLE_TEXT) {
|
||||
s = j.text;
|
||||
replstr.Append(s);
|
||||
}
|
||||
else if (j.nGroup == (int)eTypeGroup::USER_GROUP_START) {
|
||||
s = ReplaceFormatting(src, r, st, position, m2, 100, ci, sf);
|
||||
if (s.length() > 0) {
|
||||
isEmptyGroup = false;
|
||||
}
|
||||
replstr.Append(s);
|
||||
continue;
|
||||
}
|
||||
else if (j.nGroup == (int)eTypeGroup::USER_GROUP_END) {
|
||||
break;
|
||||
}
|
||||
sf += s.length();
|
||||
}
|
||||
if (isEmptyGroup) {
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
else {
|
||||
// OK. save current posintion
|
||||
currindex = ci;
|
||||
start_frame = sf;
|
||||
return replstr;
|
||||
}
|
||||
|
||||
}
|
||||
void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
||||
// Check params
|
||||
struct interval {
|
||||
size_t start = -1;
|
||||
size_t len = 0;
|
||||
int style = 0;
|
||||
};
|
||||
interval m[100];
|
||||
wxRegEx RegNewLine(srcRowSep, wxRE_NEWLINE);
|
||||
int toplineSrc = srcText->GetFirstVisibleLine();
|
||||
int toplineTrg = trgText->GetFirstVisibleLine();
|
||||
srcText->StyleClearAll();
|
||||
//srcText->SetText(src);
|
||||
srcText->ClearAll();
|
||||
|
|
@ -606,6 +679,7 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
int regstyle = wxSTC_STYLE_LASTPREDEFINED + 1;
|
||||
SetStyled(srcText);
|
||||
SetStyled(trgText);
|
||||
SetStyled(trgField);
|
||||
//bool fieldexp = regfld.Compile(v, wxRE_NEWLINE);
|
||||
if (regfld.IsValid()) {
|
||||
int sstart = 0;
|
||||
|
|
@ -620,6 +694,7 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
// wxString sepField = txtSepField->GetValue();
|
||||
wxString trgFieldReg = trgField->GetText();
|
||||
std::vector<replace_opt> repArray;
|
||||
std::vector<int> colorizetrgField(countGroupColor,-1);
|
||||
repArray = BuildString(trgFieldReg);
|
||||
if (repArray.size() == 0) {
|
||||
trgField->SetBackgroundColour(red);
|
||||
|
|
@ -645,7 +720,7 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
bool isSepRowEndConst = true;
|
||||
wxString SepRowEndConst;
|
||||
for (auto& j : sepRowEndArray) {
|
||||
if (j.isGroup) {
|
||||
if (j.isGroup && j.nGroup>=0) {
|
||||
isSepRowEndConst = false;
|
||||
break;
|
||||
}
|
||||
|
|
@ -676,7 +751,7 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
}
|
||||
else
|
||||
for (auto& j : sepRowEndArray) {
|
||||
if (j.isGroup) {
|
||||
if (j.isGroup && j.nGroup >= 0) {
|
||||
if (j.nGroup >= 0 && j.nGroup < maxgroup) {
|
||||
wxString s = regfld.GetMatch(tmp, j.nGroup);
|
||||
sepRend.Append(s);
|
||||
|
|
@ -794,26 +869,13 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
int CharPosEnd = srcText->PositionRelative(CharPos, ii.len);
|
||||
srcText->SetStyling(CharPosEnd - CharPos, ii.style);
|
||||
}
|
||||
|
||||
// build replace string
|
||||
wxString replstr;
|
||||
interval m2[100];
|
||||
currentIdx = 0;
|
||||
start_frame = 0;
|
||||
for (auto& j : repArray) {
|
||||
wxString s;
|
||||
if (j.isGroup) {
|
||||
if (j.nGroup >= 0 && j.nGroup < maxgroup) {
|
||||
s = regfld.GetMatch(tmp, j.nGroup);
|
||||
replstr.Append(s);
|
||||
m2[currentIdx++] = { start_frame ,s.length(),j.nGroup };
|
||||
}
|
||||
}
|
||||
else {
|
||||
s = j.text;
|
||||
replstr.Append(s);
|
||||
}
|
||||
start_frame += s.length();
|
||||
}
|
||||
int pos = 0;
|
||||
wxString replstr = ReplaceFormatting(tmp, regfld,repArray, pos, m2, 100, currentIdx, start_frame);
|
||||
//trgText->AddText(replstr);
|
||||
//AppendTextControl(trgText, );
|
||||
int start2 = trgText->GetTextLength();
|
||||
|
|
@ -828,9 +890,13 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
continue;
|
||||
}
|
||||
trgText->StartStyling(CharPos);
|
||||
if (ii.style > countGroupColor) ii.style = countGroupColor + regstyle - 1;
|
||||
if (ii.style >= countGroupColor) ii.style = countGroupColor - 1;
|
||||
int CharPosEnd = trgText->PositionRelative(CharPos, ii.len);
|
||||
trgText->SetStyling(CharPosEnd - CharPos, ii.style + regstyle);
|
||||
// colorize wxString trgFieldReg = trgField->GetText();
|
||||
if (ii.style < colorizetrgField.size() && colorizetrgField[ii.style]==-1) {
|
||||
colorizetrgField[ii.style] = ii.style;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -854,6 +920,22 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
limitLine = tmp_limitLine;
|
||||
int srcl = src.length();
|
||||
m_msg->SetLabelText(wxString::Format("Lines %d Char %d Matches %d", cntLines, srcl, cntMathes));
|
||||
// colorize wxString trgFieldReg = trgField->GetText();
|
||||
int pp = -1;
|
||||
for (auto &stl: colorizetrgField) {
|
||||
if (stl == -1) continue;
|
||||
for (auto& j : repArray) {
|
||||
|
||||
if (j.isGroup && j.nGroup >= 0 && stl== j.nGroup) {
|
||||
int CharPos = trgField->PositionRelative(0, j.start);
|
||||
trgField->StartStyling(CharPos);
|
||||
|
||||
int CharPosEnd = trgField->PositionRelative(CharPos, j.len);
|
||||
trgField->SetStyling(CharPosEnd - CharPos, stl + regstyle);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -861,7 +943,9 @@ void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
|||
srcText->SetText(src.Mid(0, limitChar));
|
||||
}
|
||||
if (srcText->GetTextLength()>= limitChar) srcText->AppendText("\n...");
|
||||
srcText->SetFirstVisibleLine(toplineSrc);
|
||||
trgText->SetFirstVisibleLine(toplineTrg);
|
||||
srcText->Update();
|
||||
txtField->Refresh();
|
||||
|
||||
trgField->Update();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue