1
0
Эх сурвалжийг харах

cmake-gui: Add regex explorer window

Gregor Jasny 10 жил өмнө
parent
commit
fc656fa4fe

+ 6 - 0
Help/release/dev/regex-explorer.rst

@@ -0,0 +1,6 @@
+regex-explorer
+--------------
+
+* The Qt base CMake GUI got a Regular Expression Explorer which could be used to
+  create and evaluate regular expressions in real-time. The explorer window
+  is available via the ``Tools`` menu.

+ 4 - 0
Source/QtDialog/CMakeLists.txt

@@ -113,12 +113,15 @@ set(SRCS
   QCMakeCacheView.h
   QCMakeWidgets.cxx
   QCMakeWidgets.h
+  RegexExplorer.cxx
+  RegexExplorer.h
   )
 QT4_WRAP_UI(UI_SRCS
   CMakeSetupDialog.ui
   Compilers.ui
   CrossCompiler.ui
   AddCacheEntry.ui
+  RegexExplorer.ui
   )
 QT4_WRAP_CPP(MOC_SRCS
   AddCacheEntry.h
@@ -128,6 +131,7 @@ QT4_WRAP_CPP(MOC_SRCS
   QCMake.h
   QCMakeCacheView.h
   QCMakeWidgets.h
+  RegexExplorer.h
   )
 QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
 

+ 10 - 0
Source/QtDialog/CMakeSetupDialog.cxx

@@ -33,6 +33,7 @@
 #include "QCMakeCacheView.h"
 #include "AddCacheEntry.h"
 #include "FirstConfigure.h"
+#include "RegexExplorer.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
@@ -125,6 +126,9 @@ CMakeSetupDialog::CMakeSetupDialog()
                    this, SLOT(doInstallForCommandLine()));
 #endif
   ToolsMenu->addSeparator();
+  ToolsMenu->addAction(tr("Regular Expression Explorer..."),
+                       this, SLOT(doRegexExplorerDialog()));
+  ToolsMenu->addSeparator();
   ToolsMenu->addAction(tr("&Find in Output..."),
                        this, SLOT(doOutputFindDialog()),
                        QKeySequence::Find);
@@ -1272,6 +1276,12 @@ void CMakeSetupDialog::doOutputFindDialog()
     }
 }
 
+void CMakeSetupDialog::doRegexExplorerDialog()
+{
+  RegexExplorer dialog(this);
+  dialog.exec();
+}
+
 void CMakeSetupDialog::doOutputFindPrev()
 {
   doOutputFindNext(false);

+ 1 - 0
Source/QtDialog/CMakeSetupDialog.h

@@ -82,6 +82,7 @@ protected slots:
   void doOutputFindNext(bool directionForward = true);
   void doOutputFindPrev();
   void doOutputErrorNext();
+  void doRegexExplorerDialog();
 
 protected:
 

+ 166 - 0
Source/QtDialog/RegexExplorer.cxx

@@ -0,0 +1,166 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2015 Kitware, Inc., Gregor Jasny
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#include "RegexExplorer.h"
+
+RegexExplorer::RegexExplorer(QWidget* p) : QDialog(p), m_matched(false)
+{
+  this->setupUi(this);
+
+  for(int i = 1; i < cmsys::RegularExpression::NSUBEXP; ++i)
+    {
+    matchNumber->addItem(
+      QString("Match %1").arg(QString::number(i)),
+      QVariant(i));
+    }
+  matchNumber->setCurrentIndex(0);
+}
+
+void RegexExplorer::setStatusColor(QWidget* widget, bool successful)
+{
+  QColor color = successful ? QColor(0, 127, 0) : Qt::red;
+
+  QPalette palette = widget->palette();
+  palette.setColor(QPalette::Foreground, color);
+  widget->setPalette(palette);
+}
+
+void RegexExplorer::on_regularExpression_textChanged(const QString& text)
+{
+#ifdef QT_NO_STL
+  m_regex = text.toAscii().constData();
+#else
+  m_regex = text.toStdString();
+#endif
+
+  bool validExpression =
+    stripEscapes(m_regex) && m_regexParser.compile(m_regex);
+  if(!validExpression)
+    {
+    m_regexParser.set_invalid();
+    }
+
+  setStatusColor(labelRegexValid, validExpression);
+
+  on_inputText_textChanged();
+}
+
+void RegexExplorer::on_inputText_textChanged()
+{
+  if(m_regexParser.is_valid())
+    {
+    QString plainText = inputText->toPlainText();
+#ifdef QT_NO_STL
+    m_text = plainText.toAscii().constData();
+#else
+    m_text = plainText.toStdString();
+#endif
+    m_matched = m_regexParser.find(m_text);
+    }
+  else
+    {
+    m_matched = false;
+    }
+
+  setStatusColor(labelRegexMatch, m_matched);
+
+  if(!m_matched)
+    {
+    clearMatch();
+    return;
+    }
+
+#ifdef QT_NO_STL
+  QString matchText = m_regexParser.match(0).c_str();
+#else
+  QString matchText = QString::fromStdString(m_regexParser.match(0));
+#endif
+  match0->setPlainText(matchText);
+
+  on_matchNumber_currentIndexChanged(matchNumber->currentIndex());
+}
+
+void RegexExplorer::on_matchNumber_currentIndexChanged(int index)
+{
+  if(!m_matched)
+    {
+    return;
+    }
+
+  QVariant itemData = matchNumber->itemData(index);
+  int idx = itemData.toInt();
+
+  if(idx < 1 || idx >= cmsys::RegularExpression::NSUBEXP)
+    {
+    return;
+    }
+
+#ifdef QT_NO_STL
+  QString match = m_regexParser.match(idx).c_str();
+#else
+  QString match = QString::fromStdString(m_regexParser.match(idx));
+#endif
+  matchN->setPlainText(match);
+}
+
+void RegexExplorer::clearMatch()
+{
+  match0->clear();
+  matchN->clear();
+}
+
+bool RegexExplorer::stripEscapes(std::string& source)
+{
+  const char* in = source.c_str();
+
+  std::string result;
+  result.reserve(source.size());
+
+  for(char inc = *in; inc != '\0'; inc = *++in)
+    {
+    if(inc == '\\')
+      {
+      char nextc = in[1];
+      if(nextc == 't')
+        {
+        result.append(1, '\t');
+        in++;
+        }
+      else if(nextc == 'n')
+        {
+        result.append(1, '\n');
+        in++;
+        }
+      else if(nextc == 't')
+        {
+        result.append(1, '\t');
+        in++;
+        }
+      else if(isalnum(nextc) || nextc == '\0')
+        {
+        return false;
+        }
+      else
+        {
+        result.append(1, nextc);
+        in++;
+        }
+      }
+    else
+      {
+        result.append(1, inc);
+      }
+    }
+
+    source = result;
+    return true;
+}

+ 48 - 0
Source/QtDialog/RegexExplorer.h

@@ -0,0 +1,48 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2015 Kitware, Inc., Gregor Jasny
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#ifndef RegexExplorer_h
+#define RegexExplorer_h
+
+#include <string>
+#include <cmsys/RegularExpression.hxx>
+#include <QDialog>
+
+#include "ui_RegexExplorer.h"
+
+class QString;
+class QWidget;
+
+class RegexExplorer : public QDialog, public Ui::RegexExplorer
+{
+  Q_OBJECT
+public:
+  RegexExplorer(QWidget* p);
+
+private slots:
+  void on_regularExpression_textChanged(const QString& text);
+  void on_inputText_textChanged();
+  void on_matchNumber_currentIndexChanged(int index);
+
+private:
+  static void setStatusColor(QWidget* widget, bool successful);
+  static bool stripEscapes(std::string& regex);
+
+  void clearMatch();
+
+  cmsys::RegularExpression m_regexParser;
+  std::string m_text;
+  std::string m_regex;
+  bool m_matched;
+};
+
+#endif

+ 155 - 0
Source/QtDialog/RegexExplorer.ui

@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RegexExplorer</class>
+ <widget class="QDialog" name="RegexExplorer">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>639</width>
+    <height>555</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Regular Expression Explorer</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Input Text</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPlainTextEdit" name="inputText"/>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Regular Expression</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_3">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Fixed</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QLabel" name="labelRegexValid">
+       <property name="text">
+        <string>Valid</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_4">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Fixed</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QLabel" name="labelRegexMatch">
+       <property name="text">
+        <string>Match</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QLineEdit" name="regularExpression"/>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Complete Match</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPlainTextEdit" name="match0">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QComboBox" name="matchNumber">
+       <property name="editable">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QPlainTextEdit" name="matchN">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>