Editor: added extended regular expression support (C++11) as of QScintilla 2.11.0.

Tue, 05 Mar 2019 19:00:06 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 05 Mar 2019 19:00:06 +0100
changeset 6841
43af1e698c9d
parent 6840
98bb329e39ce
child 6842
c83dcb7c6147

Editor: added extended regular expression support (C++11) as of QScintilla 2.11.0.

Preferences/ConfigurationPages/EditorSearchPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/EditorSearchPage.ui file | annotate | diff | comparison | revisions
Preferences/__init__.py file | annotate | diff | comparison | revisions
QScintilla/QsciScintillaCompat.py file | annotate | diff | comparison | revisions
QScintilla/SearchReplaceWidget.py file | annotate | diff | comparison | revisions
QScintilla/Shell.py file | annotate | diff | comparison | revisions
changelog file | annotate | diff | comparison | revisions
--- a/Preferences/ConfigurationPages/EditorSearchPage.py	Tue Mar 05 18:59:19 2019 +0100
+++ b/Preferences/ConfigurationPages/EditorSearchPage.py	Tue Mar 05 19:00:06 2019 +0100
@@ -9,6 +9,8 @@
 
 from __future__ import unicode_literals
 
+from QScintilla.QsciScintillaCompat import QSCINTILLA_VERSION
+
 from .ConfigurationPageBase import ConfigurationPageBase
 from .Ui_EditorSearchPage import Ui_EditorSearchPage
 
@@ -40,6 +42,14 @@
         self.markOccurrencesTimeoutSpinBox.setValue(
             Preferences.getEditor("MarkOccurrencesTimeout"))
         
+        if QSCINTILLA_VERSION() < 0x020B00:
+            self.regexpModeBox.setEnabled(False)
+        else:
+            if Preferences.getEditor("SearchRegexpMode") == 0:
+                self.regexpPosixButton.setChecked(True)
+            else:
+                self.regexpCxx11Button.setChecked(True)
+        
         self.initColour(
             "SearchMarkers", self.searchMarkerButton,
             Preferences.getEditorColour, hasAlpha=True)
@@ -62,6 +72,13 @@
             "MarkOccurrencesTimeout",
             self.markOccurrencesTimeoutSpinBox.value())
         
+        if self.regexpPosixButton.isChecked():
+            mode = 0
+        else:
+            mode = 1
+        Preferences.setEditor(
+            "SearchRegexpMode", mode)
+        
         self.saveColours(Preferences.setEditorColour)
 
 
--- a/Preferences/ConfigurationPages/EditorSearchPage.ui	Tue Mar 05 18:59:19 2019 +0100
+++ b/Preferences/ConfigurationPages/EditorSearchPage.ui	Tue Mar 05 19:00:06 2019 +0100
@@ -1,7 +1,8 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>EditorSearchPage</class>
- <widget class="QWidget" name="EditorSearchPage" >
-  <property name="geometry" >
+ <widget class="QWidget" name="EditorSearchPage">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
@@ -9,106 +10,106 @@
     <height>596</height>
    </rect>
   </property>
-  <layout class="QVBoxLayout" >
+  <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
-    <widget class="QLabel" name="headerLabel" >
-     <property name="text" >
-      <string>&lt;b>Configure editor search options&lt;/b></string>
+    <widget class="QLabel" name="headerLabel">
+     <property name="text">
+      <string>&lt;b&gt;Configure editor search options&lt;/b&gt;</string>
      </property>
     </widget>
    </item>
    <item>
-    <widget class="Line" name="line3" >
-     <property name="frameShape" >
+    <widget class="Line" name="line3">
+     <property name="frameShape">
       <enum>QFrame::HLine</enum>
      </property>
-     <property name="frameShadow" >
+     <property name="frameShadow">
       <enum>QFrame::Sunken</enum>
      </property>
-     <property name="orientation" >
+     <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
     </widget>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox_4" >
-     <property name="title" >
+    <widget class="QGroupBox" name="groupBox_4">
+     <property name="title">
       <string>Search Markers</string>
      </property>
-     <layout class="QVBoxLayout" >
+     <layout class="QVBoxLayout">
       <item>
-       <widget class="QCheckBox" name="occurrencesMarkersEnabledCheckBox" >
-        <property name="toolTip" >
+       <widget class="QCheckBox" name="occurrencesMarkersEnabledCheckBox">
+        <property name="toolTip">
          <string>Select, whether markers for all occurrences of the current word shall be shown</string>
         </property>
-        <property name="text" >
+        <property name="text">
          <string>Highlight all occurrences of current word</string>
         </property>
        </widget>
       </item>
       <item>
-       <widget class="QCheckBox" name="searchMarkersEnabledCheckBox" >
-        <property name="toolTip" >
+       <widget class="QCheckBox" name="searchMarkersEnabledCheckBox">
+        <property name="toolTip">
          <string>Select, whether search markers shall be shown for a standard search</string>
         </property>
-        <property name="text" >
+        <property name="text">
          <string>Highlight all occurrences of search text</string>
         </property>
        </widget>
       </item>
       <item>
-       <widget class="QCheckBox" name="quicksearchMarkersEnabledCheckBox" >
-        <property name="toolTip" >
+       <widget class="QCheckBox" name="quicksearchMarkersEnabledCheckBox">
+        <property name="toolTip">
          <string>Select, whether search markers shall be shown for a quicksearch</string>
         </property>
-        <property name="text" >
+        <property name="text">
          <string>Highlight all occurrences of quicksearch text</string>
         </property>
        </widget>
       </item>
       <item>
-       <layout class="QHBoxLayout" >
+       <layout class="QHBoxLayout">
         <item>
-         <widget class="QLabel" name="label" >
-          <property name="text" >
+         <widget class="QLabel" name="label">
+          <property name="text">
            <string>Timeout for current word highlighting:</string>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QSpinBox" name="markOccurrencesTimeoutSpinBox" >
-          <property name="toolTip" >
+         <widget class="QSpinBox" name="markOccurrencesTimeoutSpinBox">
+          <property name="toolTip">
            <string>Enter the time in milliseconds after which occurrences of the current word shall be highlighted</string>
           </property>
-          <property name="alignment" >
+          <property name="alignment">
            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
           </property>
-          <property name="buttonSymbols" >
+          <property name="buttonSymbols">
            <enum>QAbstractSpinBox::PlusMinus</enum>
           </property>
-          <property name="correctionMode" >
+          <property name="correctionMode">
            <enum>QAbstractSpinBox::CorrectToNearestValue</enum>
           </property>
-          <property name="suffix" >
+          <property name="suffix">
            <string> ms</string>
           </property>
-          <property name="minimum" >
+          <property name="minimum">
            <number>100</number>
           </property>
-          <property name="maximum" >
+          <property name="maximum">
            <number>5000</number>
           </property>
-          <property name="singleStep" >
+          <property name="singleStep">
            <number>100</number>
           </property>
          </widget>
         </item>
         <item>
          <spacer>
-          <property name="orientation" >
+          <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
-          <property name="sizeHint" stdset="0" >
+          <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
@@ -119,36 +120,36 @@
        </layout>
       </item>
       <item>
-       <layout class="QHBoxLayout" >
+       <layout class="QHBoxLayout">
         <item>
-         <widget class="QLabel" name="TextLabel2_2_2_2_2_2" >
-          <property name="text" >
+         <widget class="QLabel" name="TextLabel2_2_2_2_2_2">
+          <property name="text">
            <string>Marker Colour:</string>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QPushButton" name="searchMarkerButton" >
-          <property name="minimumSize" >
+         <widget class="QPushButton" name="searchMarkerButton">
+          <property name="minimumSize">
            <size>
             <width>100</width>
             <height>0</height>
            </size>
           </property>
-          <property name="toolTip" >
+          <property name="toolTip">
            <string>Select the colour for the search markers.</string>
           </property>
-          <property name="text" >
+          <property name="text">
            <string/>
           </property>
          </widget>
         </item>
         <item>
          <spacer>
-          <property name="orientation" >
+          <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
-          <property name="sizeHint" stdset="0" >
+          <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
@@ -162,11 +163,43 @@
     </widget>
    </item>
    <item>
+    <widget class="QGroupBox" name="regexpModeBox">
+     <property name="title">
+      <string>Regular Expression Type</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QRadioButton" name="regexpPosixButton">
+        <property name="toolTip">
+         <string>Select to used the QScintilla POSIX alike regular expression mode.</string>
+        </property>
+        <property name="text">
+         <string>QScintilla Regular Mode (POSIX)</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="regexpCxx11Button">
+        <property name="toolTip">
+         <string>Select to used the QScintilla extended (C++11) regular expression mode.</string>
+        </property>
+        <property name="text">
+         <string>QScintilla Extended  Mode (C++11)</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
     <spacer>
-     <property name="orientation" >
+     <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
-     <property name="sizeHint" stdset="0" >
+     <property name="sizeHint" stdset="0">
       <size>
        <width>558</width>
        <height>231</height>
--- a/Preferences/__init__.py	Tue Mar 05 18:59:19 2019 +0100
+++ b/Preferences/__init__.py	Tue Mar 05 19:00:06 2019 +0100
@@ -467,6 +467,7 @@
         "QuickSearchMarkersEnabled": True,
         "MarkOccurrencesEnabled": True,
         "MarkOccurrencesTimeout": 500,     # 500 milliseconds
+        "SearchRegexpMode": 0,             # 0: POSIX mode, 1: CXX11 mode
         "AdvancedEncodingDetection": True,
         
         "SpellCheckingEnabled": True,
@@ -2170,7 +2171,7 @@
                  "AutoCompletionCacheSize", "AutoCompletionCacheTime",
                  "AutoCompletionWatchdogTime", "AutoCompletionMaxLines",
                  "AutoCompletionMaxChars", "CallTipsVisible",
-                 "CallTipsStyle", "MarkOccurrencesTimeout",
+                 "CallTipsStyle", "MarkOccurrencesTimeout", "SearchRegexpMode",
                  "AutoSpellCheckChunkSize", "SpellCheckingMinWordSize",
                  "PostScriptLevel", "EOLMode", "ZoomFactor", "WhitespaceSize",
                  "OnlineSyntaxCheckInterval", "OnlineChangeTraceInterval",
--- a/QScintilla/QsciScintillaCompat.py	Tue Mar 05 18:59:19 2019 +0100
+++ b/QScintilla/QsciScintillaCompat.py	Tue Mar 05 19:00:06 2019 +0100
@@ -852,25 +852,37 @@
     
     def findFirstTarget(self, expr_, re_, cs_, wo_,
                         begline=-1, begindex=-1, endline=-1, endindex=-1,
-                        ws_=False):
+                        ws_=False, posix=False, cxx11=False):
         """
         Public method to search in a specified range of text without
         setting the selection.
         
-        @param expr_ search expression (string)
-        @param re_ flag indicating a regular expression (boolean)
-        @param cs_ flag indicating a case sensitive search (boolean)
-        @param wo_ flag indicating a word only search (boolean)
-        @keyparam begline line number to start from (-1 to indicate current
-            position) (integer)
-        @keyparam begindex index to start from (-1 to indicate current
-            position) (integer)
-        @keyparam endline line number to stop at (-1 to indicate end of
-            document) (integer)
-        @keyparam endindex index number to stop at (-1 to indicate end of
-            document) (integer)
-        @keyparam ws_ flag indicating a word start search (boolean)
-        @return flag indicating a successful search (boolean)
+        @param expr_ search expression
+        @type str
+        @param re_ flag indicating a regular expression
+        @type bool
+        @param cs_ flag indicating a case sensitive search
+        @type bool
+        @param wo_ flag indicating a word only search
+        @type bool
+        @param begline line number to start from (-1 to indicate current
+            position)
+        @type int
+        @param begindex index to start from (-1 to indicate current position)
+        @type int
+        @param endline line number to stop at (-1 to indicate end of document)
+        @type int
+        @param endindex index number to stop at (-1 to indicate end of
+            document)
+        @type int
+        @param ws_ flag indicating a word start search (boolean)
+        @type bool
+        @param posix
+        @type bool
+        @param cxx11
+        @type bool
+        @return flag indicating a successful search
+        @rtype bool
         """
         self.__targetSearchFlags = 0
         if re_:
@@ -881,6 +893,14 @@
             self.__targetSearchFlags |= QsciScintilla.SCFIND_WHOLEWORD
         if ws_:
             self.__targetSearchFlags |= QsciScintilla.SCFIND_WORDSTART
+        if posix:
+            self.__targetSearchFlags |= QsciScintilla.SCFIND_POSIX
+        try:
+            if cxx11:
+                self.__targetSearchFlags |= QsciScintilla.SCFIND_CXX11REGEX
+        except AttributeError:
+            # defined for PyQt >= 2.11.0
+            pass
         
         if begline < 0 or begindex < 0:
             self.__targetSearchStart = self.SendScintilla(
@@ -1736,6 +1756,54 @@
             for line in folds:
                 self.foldLine(line)
     
+    #########################################################################
+    # method below implement a compatibility variant for the findFirst()
+    # extended with version 2.11
+    #########################################################################
+
+    def findFirst(self, expression, regexp, caseSensitive, word, wrap,
+                  forward=True, line=-1, index=-1, show=True, posix=False,
+                  cxx11=False):
+        """
+        Public method to search in the current editor text.
+        
+        @param expression search expression
+        @type str
+        @param regexp flag indicating a regular expression
+        @type bool
+        @param caseSensitive flag indicating a case sensitive search
+        @type bool
+        @param word flag indicating a word only search
+        @type bool
+        @param wrap flag indicating to warp around
+        @type bool
+        @param forward flag indicating the search direction
+        @type bool
+        @param line line to start the search on
+        @type int
+        @param index index to start the search on
+        @type int
+        @param show flag indicating to set the selection to the found
+            expression
+        @type bool
+        @param posix flag indicating the POSIX regular expression search mode
+        @type bool
+        @param cxx11 flag indicating the CXX11 regular expression search mode
+        @type bool
+        @return flag indicating a successful search
+        @rtype bool
+        """
+        if QSCINTILLA_VERSION() >= 0x020B00:
+            return super(QsciScintillaCompat, self).findFirst(
+                expression, regexp, caseSensitive, word, wrap,
+                forward=forward, line=line, index=index, show=show,
+                posix=posix, cxx11=cxx11)
+        else:
+            return super(QsciScintillaCompat, self).findFirst(
+                expression, regexp, caseSensitive, word, wrap,
+                forward=forward, line=line, index=index, show=show,
+                posix=posix)
+    
 ##    #########################################################################
 ##    # methods below have been added to QScintilla starting with version 2.x
 ##    #########################################################################
--- a/QScintilla/SearchReplaceWidget.py	Tue Mar 05 18:59:19 2019 +0100
+++ b/QScintilla/SearchReplaceWidget.py	Tue Mar 05 19:00:06 2019 +0100
@@ -119,6 +119,9 @@
 <td>This matches 1 or more times. For example, <code>Sa+m</code> matches
 <code>Sam</code>, <code>Saam</code>, <code>Saaam</code> and so on.</td></tr>
 </table>
+<p>When using the Extended (C++11) regular expression mode more features are
+available, generally similar to regular expression support in JavaScript. See
+the documentation of your C++ runtime for details on what is supported.<p>
 """
         )
         self.setWhatsThis(whatsThis)
@@ -439,6 +442,10 @@
         indexTo = -1
         if self.ui.selectionCheckBox.isChecked():
             lineFrom, indexFrom, lineTo, indexTo = self.__selectionBoundary()
+        posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and
+                     self.ui.regexpCheckBox.isChecked())
+        cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and
+                     self.ui.regexpCheckBox.isChecked())
         
         aw.clearSearchIndicators()
         ok = aw.findFirstTarget(
@@ -446,7 +453,8 @@
             self.ui.regexpCheckBox.isChecked(),
             self.ui.caseCheckBox.isChecked(),
             self.ui.wordCheckBox.isChecked(),
-            lineFrom, indexFrom, lineTo, indexTo)
+            lineFrom, indexFrom, lineTo, indexTo,
+            posix=posixMode, cxx11=cxx11Mode)
         while ok:
             tgtPos, tgtLen = aw.getFoundTarget()
             if tgtLen == 0:
@@ -541,6 +549,10 @@
                 index = indexTo
         
         if ok:
+            posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and
+                         self.ui.regexpCheckBox.isChecked())
+            cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and
+                         self.ui.regexpCheckBox.isChecked())
             ok = aw.findFirst(
                 txt,
                 self.ui.regexpCheckBox.isChecked(),
@@ -549,7 +561,8 @@
                 self.ui.wrapCheckBox.isChecked(),
                 not backwards,
                 line, index,
-                posix=self.ui.regexpCheckBox.isChecked())
+                posix=posixMode,
+                cxx11=cxx11Mode)
         
         if ok and self.ui.selectionCheckBox.isChecked():
             lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
@@ -601,7 +614,8 @@
                         self.ui.wrapCheckBox.isChecked(),
                         not backwards,
                         line, index,
-                        posix=self.ui.regexpCheckBox.isChecked())
+                        posix=posixMode,
+                        cxx11=cxx11Mode)
                     if ok:
                         lineFrom, indexFrom, lineTo, indexTo = \
                             aw.getSelection()
@@ -628,7 +642,8 @@
                         self.ui.wrapCheckBox.isChecked(),
                         not backwards,
                         line, index,
-                        posix=self.ui.regexpCheckBox.isChecked())
+                        posix=posixMode,
+                        cxx11=cxx11Mode)
                     if ok:
                         lineFrom, indexFrom, lineTo, indexTo = \
                             aw.getSelection()
@@ -840,13 +855,18 @@
         else:
             line = 0
             index = 0
+        posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and
+                     self.ui.regexpCheckBox.isChecked())
+        cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and
+                     self.ui.regexpCheckBox.isChecked())
         ok = aw.findFirst(
             ftxt,
             self.ui.regexpCheckBox.isChecked(),
             self.ui.caseCheckBox.isChecked(),
             self.ui.wordCheckBox.isChecked(),
             False, True, line, index,
-            posix=self.ui.regexpCheckBox.isChecked())
+            posix=posixMode,
+            cxx11=cxx11Mode)
         
         if ok and self.ui.selectionCheckBox.isChecked():
             lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
@@ -886,7 +906,8 @@
                         self.ui.caseCheckBox.isChecked(),
                         self.ui.wordCheckBox.isChecked(),
                         False, True, line, index,
-                        posix=self.ui.regexpCheckBox.isChecked())
+                        posix=posixMode,
+                        cxx11=cxx11Mode)
                     if ok:
                         lineFrom, indexFrom, lineTo, indexTo = \
                             aw.getSelection()
--- a/QScintilla/Shell.py	Tue Mar 05 18:59:19 2019 +0100
+++ b/QScintilla/Shell.py	Tue Mar 05 19:00:06 2019 +0100
@@ -2239,9 +2239,11 @@
         @type bool
         """
         self.__lastSearch = (txt, caseSensitive, wholeWord, regexp)
+        posixMode = Preferences.getEditor("SearchRegexpMode") == 0 and regexp
+        cxx11Mode = Preferences.getEditor("SearchRegexpMode") == 1 and regexp
         ok = self.findFirst(
             txt, regexp, caseSensitive, wholeWord, True, forward=True,
-            posix=regexp)
+            posix=posixMode, cxx11=cxx11Mode)
         self.searchStringFound.emit(ok)
     
     def __searchPrev(self):
@@ -2271,9 +2273,12 @@
             line, index = self.getSelection()[:2]
         else:
             line, index = -1, -1
+        posixMode = Preferences.getEditor("SearchRegexpMode") == 0 and regexp
+        cxx11Mode = Preferences.getEditor("SearchRegexpMode") == 1 and regexp
         ok = self.findFirst(
             txt, regexp, caseSensitive, wholeWord, True,
-            forward=False, line=line, index=index, posix=regexp)
+            forward=False, line=line, index=index, posix=posixMode,
+            cxx11=cxx11Mode)
         self.searchStringFound.emit(ok)
     
     def historyStyle(self):
--- a/changelog	Tue Mar 05 18:59:19 2019 +0100
+++ b/changelog	Tue Mar 05 19:00:06 2019 +0100
@@ -2,6 +2,8 @@
 ----------
 Version 19.04:
 - bug fixes
+- Editor
+  -- added extended regular expression support (C++11) as of QScintilla 2.11.0
 - Email
   -- changed the Google Mail interface to not use obsoleted packages anymore
 - Multi Project

eric ide

mercurial