#!/usr/bin/env python # Encoding: UTF-8 """This script launches a GUI for testing regular expressions.""" import sys import os import re import sre_constants from textwrap import dedent try: import wx import wx.aui import wx.lib.anchors as anchors except ImportError: print "This script requires wxPython." sys.exit(1) class RegexTesterFrame(wx.Frame): def __init__(self): wx.Frame.__init__( self, None, -1, 'Regex tester', (100, 100), (1024, 768), wx.DEFAULT_FRAME_STYLE ) # wx.Frame.__init__( # self, None, -1, 'Regex tester', wx.DefaultPosition, # wx.DefaultSize, wx.DEFAULT_FRAME_STYLE # ) self.initialize_components() self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP) self.statusbar.SetFieldsCount(2) self.statusbar.SetStatusWidths([-1, -3]) self.statusbar.SetStatusText('Welcome to the RegEx tester!', 0) def initialize_components(self): self._mgr = wx.aui.AuiManager() self._mgr.SetManagedWindow(self) self.SetMinSize(wx.Size(800, 400)) # Create a toolbar for the regex modifiers (flags). self._mgr.AddPane( self.create_flags_panel(), wx.aui.AuiPaneInfo().Name('modifiers').ToolbarPane().Top() ) # Create a toolbar for the regex modifiers (flags). self._mgr.AddPane( self.create_functions_panel(), wx.aui.AuiPaneInfo().Name('functions').ToolbarPane().Top() ) # Create the text input pane. self._mgr.AddPane( self.create_text_input_panel(), wx.aui.AuiPaneInfo().Name('text_input').Caption('Text input'). CloseButton(False).Left().Layer(1).BestSize((600, 100)) ) # Create the regex pane. self._mgr.AddPane( self.create_regex_panel(), wx.aui.AuiPaneInfo().Name('regex').Caption('Regex'). CloseButton(False).Top().BestSize((200, 100)) ) # Create the output pane. self._mgr.AddPane( self.create_output_panel(), wx.aui.AuiPaneInfo().Name('output').CloseButton(False).CenterPane(). BestSize((200, 300)) ) self._mgr.Update() self.Bind(wx.EVT_CLOSE, self.on_close) def create_flags_panel(self): panel = wx.Panel(self, -1) # Create the check boxes. self.flag_dotall_checkbox = wx.CheckBox(panel, -1, 'DOTALL') self.flag_ic_checkbox = wx.CheckBox(panel, -1, 'IGNORECASE') self.flag_ext_checkbox = wx.CheckBox(panel, -1, 'VERBOSE') self.flag_multiline_checkbox = wx.CheckBox(panel, -1, 'MULTILINE') # Check ignore case by default. self.flag_ic_checkbox.SetValue(True) # Bind the change event to run the update function. for checkbox in [self.flag_dotall_checkbox, self.flag_ic_checkbox, self.flag_ext_checkbox, self.flag_multiline_checkbox]: self.Bind( wx.EVT_CHECKBOX, self.update_output_event, checkbox ) # Create the layout sizer. sizer = wx.BoxSizer() sizer.Add(wx.StaticText(panel, -1, 'Flags: ')) sizer.Add(self.flag_dotall_checkbox) sizer.Add(self.flag_ic_checkbox) sizer.Add(self.flag_ext_checkbox) sizer.Add(self.flag_multiline_checkbox) # Create the outer sizer and add the inner sizer to it. outer_sizer = wx.BoxSizer() outer_sizer.Add(sizer, border=5, flag=wx.ALL) # Apply the outer sizer to the panel and return it. panel.SetSizerAndFit(outer_sizer) return panel def create_functions_panel(self): panel = wx.Panel(self, -1) # Create the radio buttons. self.func_search_radio = wx.RadioButton(panel, -1, 'Search') self.func_match_radio = wx.RadioButton(panel, -1, 'Match') self.func_findall_radio = wx.RadioButton(panel, -1, 'Find all') # Check the search function radio button by default. self.func_search_radio.SetValue(True) # Bind the radio buttons' change events to update the output. for radio in [self.func_search_radio, self.func_match_radio, self.func_findall_radio]: self.Bind(wx.EVT_RADIOBUTTON, self.update_output_event, radio) # Add the radio buttons to the sizer. sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(wx.StaticText(panel, -1, 'Function: ')) sizer.AddMany([ self.func_search_radio, self.func_match_radio, self.func_findall_radio ]) # Create the outer sizer and add the inner sizer to it. outer_sizer = wx.BoxSizer() outer_sizer.Add(sizer, border=5, flag=wx.ALL) panel.SetSizerAndFit(outer_sizer) return panel def create_regex_panel(self): panel = wx.Panel(self) self.regex_textbox = wx.TextCtrl( panel, style=wx.NO_BORDER | wx.TE_MULTILINE ) sizer = wx.BoxSizer() sizer.Add(self.regex_textbox, proportion=1, flag=wx.EXPAND) panel.SetSizerAndFit(sizer) # Bind the text change event. self.Bind( wx.EVT_TEXT, self.update_output_event, self.regex_textbox ) return panel def create_text_input_panel(self): panel = wx.Panel(self) self.input_textbox = wx.TextCtrl( panel, style=wx.NO_BORDER | wx.TE_MULTILINE | wx.TE_DONTWRAP | wx.HSCROLL ) sizer = wx.BoxSizer() sizer.Add(self.input_textbox, proportion=1, flag=wx.EXPAND) panel.SetSizerAndFit(sizer) # Bind the text change event. self.Bind( wx.EVT_TEXT, self.update_output_event, self.input_textbox ) return panel def create_output_panel(self): panel = wx.Panel(self) sizer = wx.BoxSizer(wx.VERTICAL) self.output_textbox = wx.TextCtrl( panel, -1, style=wx.TE_MULTILINE | wx.TE_READONLY ) sizer.Add(wx.StaticText(panel, -1, 'Output:'), border=5, flag=wx.ALL | wx.TOP | wx.LEFT | wx.RIGHT) sizer.Add(self.output_textbox, proportion=1, border=10, flag=wx.EXPAND | wx.ALL) panel.SetSizerAndFit(sizer) return panel def update_output_event(self, event): self.update_output() def update_output(self): """Function that checks the values in all controls and updates the output.""" r = self.regex_textbox.GetValue() text = self.input_textbox.GetValue() # Fetch the regex flags. flags = 0 if self.flag_dotall_checkbox.GetValue(): flags |= re.DOTALL if self.flag_ic_checkbox.GetValue(): flags |= re.IGNORECASE if self.flag_ext_checkbox.GetValue(): flags |= re.VERBOSE if self.flag_multiline_checkbox.GetValue(): flags |= re.MULTILINE # Fetch the function choice. if self.func_search_radio.GetValue(): fn = re.search elif self.func_match_radio.GetValue(): fn = re.match elif self.func_findall_radio.GetValue(): fn = re.findall else: wx.MessageBox('None of the functions are chosen... Somehow.') return # Try to perform the regex match. On error, display the error in the # status bar. try: result = fn(r, text, flags) except sre_constants.error as e: msg = 'Regex compilation error: ' + e.message self.SetStatusText(msg, 1) return # Empty the error part of the status bar just in case. self.SetStatusText('', 1) # If there is a result to the match or search function. if result and fn is not re.findall: output = dedent(u""" Match: {} Groups: {} Group dict: {} """) output = output.format( repr(result.group()), repr(result.groups()), repr(result.groupdict()) ) # If there is a findall result. elif result and fn is re.findall: output = u"Matches: " + repr(result) # No result. else: output = u"No matches." # Set the result text. self.output_textbox.SetValue(output) def on_close(self, event): self._mgr.UnInit() del self._mgr self.Destroy() class RegexTesterApp(wx.App): def OnInit(self): mainframe = RegexTesterFrame() mainframe.Show() self.SetTopWindow(mainframe) return True def main(): app = RegexTesterApp(True) app.MainLoop() if __name__ == '__main__': main()