Seven Yu @ 03/26/2008 (6:14 am)

RegexTester v2.0.1(源码)

Tags: , , , ::

本篇日志只有源码, 下载及开发历史见上篇日志.

PLAIN TEXT >> ACTIONSCRIPT:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--
  3. Regex Tester v2.0.1
  4. Author: Seven Yu (Dofy)
  5. E-Mail/gtalk: dofyyu at gmail dot com
  6. URL: http://dofy.net/ http://phpz.org/
  7. -->
  8. <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
  9.     layout="vertical" horizontalAlign="left" width="400" height="500"
  10.     creationComplete="initApp();"
  11.     showStatusBar="false"
  12.     backgroundColor="0xeeeeee"
  13.     xmlns:ctrler="org.phpz.controls.*">
  14. <mx:Style>
  15.     Application {
  16.         padding-top: 10px;
  17.         padding-right: 10px;
  18.         padding-bottom: 10px;
  19.         padding-left: 10px;
  20.     }
  21.     Application, ToolTip {
  22.         font-size: 12px;
  23.     }
  24.     Label {
  25.         font-weight: bold;
  26.     }
  27. </mx:Style>
  28. <mx:Script>
  29.     <![CDATA[
  30.         import mx.events.DragEvent;
  31.         import mx.controls.Alert;
  32.         import mx.controls.CheckBox;
  33.         import mx.events.ItemClickEvent;
  34.        
  35.         private const FILE_MAX_SIZE:uint = 1024;
  36.        
  37.         private const TITLE_WARNING:String = "Warning!";
  38.         private const TITLE_OK:String      = "Ok!";
  39.        
  40.         private const MSG_ONE_FILE:String      = "Accept one file only.";
  41.         private const MSG_NOT_TEXT_FILE:String = "Accept Text file only.";
  42.         private const MSG_EXCEED_SIZE:String   = "File size could not exceed " + FILE_MAX_SIZE + " bytes.";
  43.         private const MSG_REGEX_PASTED:String  = "Regex pasted.";
  44.        
  45.         private var reg:RegExp = new RegExp();
  46.         private var objArray:Array = new Array();
  47.         private var curIndex:int;
  48.        
  49.         private var _curLastIndex:int;
  50.         private var _curFlags:Array = new Array();
  51.         private var flags:Array = new Array(
  52.                                     ["g", "global"],
  53.                                     ["i", "ignore case"],
  54.                                     ["m", "multiline"],
  55.                                     ["s", "dotall"],
  56.                                     ["x", "extended"]);
  57.        
  58.         /**
  59.          * 初始化
  60.          * */
  61.         private function initApp():void
  62.         {
  63.             // 添加修饰符 checkbox
  64.             var curFlag:CheckBox;
  65.             for (var i:uint = 0; i <flags.length; i++)
  66.             {
  67.                 curFlag = frmFlags.addChild(new CheckBox()) as CheckBox;
  68.                 curFlag.label = flags[i][0];
  69.                 curFlag.toolTip = flags[i][1];
  70.                 curFlag.addEventListener(Event.CHANGE, flagChangeHandler);
  71.             }
  72.             pattern.setFocus();
  73.             // 绑定事件
  74.             nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
  75.             pattern.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, dragEnterHandler);
  76.             pattern.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, dragDropHandler);
  77.             testText.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, dragEnterHandler);
  78.             testText.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, dragDropHandler);
  79.         }
  80.        
  81.         override protected function keyDownHandler(event:KeyboardEvent):void
  82.         {
  83.             if (event.controlKey)
  84.             {
  85.                 switch (event.keyCode)
  86.                 {
  87.                     case Keyboard.NUMBER_1:
  88.                     {
  89.                         pattern.setFocus();
  90.                         break;
  91.                     }
  92.                     case Keyboard.NUMBER_2:
  93.                     {
  94.                         testText.setFocus();
  95.                         break;
  96.                     }
  97.                     case Keyboard.BACKQUOTE:
  98.                     {
  99.                         (frmFlags.getChildAt(0) as CheckBox).setFocus();
  100.                         break;
  101.                     }
  102.                 }
  103.             }
  104.         }
  105.        
  106.         /**
  107.          * 设置修饰符
  108.          * */
  109.         private function flagChangeHandler(evt:Event):void
  110.         {
  111.             var obj:Object = evt.target;
  112.             obj.selected
  113.                 ? _curFlags.push(obj.label)
  114.                 : _curFlags.splice(_curFlags.indexOf(obj.label), 1);
  115.             setRegContent();
  116.         }
  117.        
  118.         /**
  119.          * 执行测试
  120.          * */
  121.         private function test():void
  122.         {
  123.             var execObj:Object;
  124.             // 重置结果数组和索引变量
  125.             objArray = new Array();
  126.             curIndex = 0;
  127.            
  128.             do
  129.             {
  130.                 _curLastIndex = reg.lastIndex;
  131.                 (execObj = reg.exec(testText.text)) != null && objArray.push(execObj);
  132.             }
  133.             while (_curLastIndex != reg.lastIndex && reg.lastIndex> 0)
  134.            
  135.             displayObj(0); // 显示结果
  136.         }
  137.        
  138.         /**
  139.          * 显示结果
  140.          * */
  141.         private function displayObj(offset:int):void
  142.         {
  143.             // 设置结果索引导航
  144.             if (objArray.length> 0)
  145.             {
  146.                 curIndex += offset;
  147.                 if (curIndex <0)
  148.                 {
  149.                     curIndex = objArray.length - 1;
  150.                 }
  151.                 else if (curIndex>= objArray.length)
  152.                 {
  153.                     curIndex = 0;
  154.                 }
  155.             }
  156.            
  157.             // 显示结果信息
  158.             var obj:Object = objArray[curIndex];
  159.             frmResult.label = obj
  160.                                 ? "Result: " + (curIndex+1) + " of " + objArray.length + " match."
  161.                                 : "Result: no match.";
  162.             result.text = "";
  163.             for ( var k:String in obj)
  164.             {
  165.                 result.text += k + ": \"" + obj[k] + "\"\n";
  166.             }
  167.         }
  168.        
  169.         /**
  170.          * 检测正则
  171.          * */
  172.         private function checkRegexp(data:String):void
  173.         {
  174.             var re:RegExp = /^\/(.*?)\/([gimsx]*)$/is;
  175.             var reObj:Object = re.exec(data);
  176.             if (reObj == null)
  177.             {
  178.                 pattern.text = data;
  179.             }
  180.             else
  181.             {
  182.                 pattern.text = reObj[1];
  183.                 var chks:Array = frmFlags.getChildren();
  184.                 for (var i:uint = 0; i <chks.length; i++)
  185.                 {
  186.                     chks[i].selected = (reObj[2].indexOf(chks[i].label) !== -1);
  187.                 }
  188.                 _curFlags = (reObj[2] as String).split('');
  189.             }
  190.         }
  191.        
  192.         /**
  193.          * 替换换行符
  194.          * */
  195.         private function cleanText(txt:String):String
  196.         {
  197.             return txt.replace(/\r\n/g, "\n");
  198.         }
  199.        
  200.         /**
  201.          * 结果导航
  202.          * */
  203.         private function displayObjHandler(evt:ItemClickEvent):void
  204.         {
  205.             displayObj(evt.index * 2 - 1);
  206.         }
  207.        
  208.         /**
  209.          * 拖拽实现
  210.          * */
  211.         private function dragEnterHandler(evt:NativeDragEvent):void
  212.         {
  213.             stage.nativeWindow.activate();
  214.             (evt.currentTarget as TextArea).setFocus();
  215.             var clip:Clipboard = evt.clipboard;
  216.             if (clip.hasFormat(ClipboardFormats.FILE_LIST_FORMAT))
  217.             {
  218.                 NativeDragManager.acceptDragDrop(evt.currentTarget as InteractiveObject);
  219.             }
  220.         }
  221.        
  222.         /**
  223.          * 放置事件
  224.          * */
  225.         private function dragDropHandler(evt:NativeDragEvent):void
  226.         {
  227.             var loader:URLLoader = new URLLoader();
  228.             var txtBox:TextArea = evt.currentTarget as TextArea;
  229.             var file:File = checkFile(evt.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array);
  230.             loader.addEventListener(Event.COMPLETE,
  231.                                         function(ievt:Event):void
  232.                                         {
  233.                                             txtBox.id == "pattern"
  234.                                                 ? checkRegexp(cleanText(ievt.target.data))
  235.                                                 : txtBox.text = cleanText(ievt.target.data);
  236.                                             setRegContent();
  237.                                         }
  238.                                     );
  239.             file != null && loader.load(new URLRequest(file.nativePath));
  240.         }
  241.        
  242.         private function checkFile(files:Array):File
  243.         {
  244.             if (files == null)
  245.             {
  246.                 return null;
  247.             }
  248.             if (files.length> 1)
  249.             {
  250.                 Alert.show(MSG_ONE_FILE, TITLE_WARNING);
  251.                 return null;
  252.             }
  253.             var file:File = files[0];
  254.             if (file.isDirectory || file.extension.toLowerCase() != 'txt')
  255.             {
  256.                 Alert.show(MSG_NOT_TEXT_FILE, TITLE_WARNING);
  257.                 return null;
  258.             }
  259.             if (file.size> FILE_MAX_SIZE)
  260.             {
  261.                 Alert.show(MSG_EXCEED_SIZE, TITLE_WARNING);
  262.                 return null;
  263.             }
  264.             return file;
  265.         }
  266.        
  267.         /**
  268.          * 设置表达式
  269.          * */
  270.         private function setRegContent():void
  271.         {
  272.             reg = new RegExp(pattern.text, _curFlags.join(''));
  273.             test();
  274.         }
  275.                
  276.         /**
  277.          * 显示关于对话框
  278.          * */
  279.         private function showAboutInfo():void
  280.         {
  281.             result.htmlText  = "<p align=\"center\">";
  282.             result.htmlText += "<b><font size=\"17\">Regex Tester</font></b> ";
  283.             result.htmlText += "<font color=\"#999999\">version 2.0.1</font><br />";
  284.             result.htmlText += "<b>Author:</b> Seven Yu (Dofy)<br />";
  285.             result.htmlText += "<b>E-Mail/gtalk:</b> dofyyu" + "@gmail.com<br />";
  286.             result.htmlText += "<b>URL:</b> <a href=\"http://dofy.net/\"><u>dofy.net</u></a> &amp; ";
  287.             result.htmlText += "<a href=\"http://phpz.org/\"><u>phpz.org</u></a><br />";
  288.             result.htmlText += "<br />Copyright (C) 2008 dofy's den all rights reserved.";
  289.             result.htmlText += "</p>";
  290.         }
  291.     ]]>
  292. </mx:Script>
  293. <mx:VDividedBox width="100%" height="100%">
  294.     <mx:VBox width="100%" height="100%">
  295.         <mx:FormItem label="Regex:" width="100%" direction="horizontal" horizontalAlign="right">
  296.             <mx:Button label="Copy">
  297.                 <mx:click>
  298.                     <![CDATA[
  299.                         Clipboard.generalClipboard.setData(ClipboardFormats.TEXT_FORMAT, reg)
  300.                         && Alert.show(MSG_REGEX_PASTED, TITLE_OK);
  301.                     ]]>
  302.                 </mx:click>
  303.             </mx:Button>
  304.             <mx:Button label="About" click="showAboutInfo();" />
  305.         </mx:FormItem>
  306.         <ctrler:TabTextArea id="pattern" width="100%" height="100%" keyUp="setRegContent();" />
  307.         <mx:FormItem id="frmFlags" label="Flag:" direction="horizontal" />
  308.     </mx:VBox>
  309.    
  310.     <mx:VBox width="100%" height="100%">
  311.         <mx:Label text="Test Text:" />
  312.         <ctrler:TabTextArea id="testText" width="100%" height="100%" keyUp="test();" />
  313.     </mx:VBox>
  314.    
  315.     <mx:VBox width="100%" height="100%">
  316.         <mx:FormItem id="frmResult" label="Result:" width="100%" horizontalAlign="right">
  317.             <mx:ButtonBar id="btnBar" itemClick="displayObjHandler(event);">
  318.                 <mx:Array>
  319.                     <mx:String><![CDATA[<]]></mx:String>
  320.                     <mx:String><![CDATA[>]]></mx:String>
  321.                 </mx:Array>
  322.             </mx:ButtonBar>
  323.         </mx:FormItem>
  324.         <mx:TextArea id="result" editable="false" tabEnabled="false" width="100%" height="100%" />
  325.     </mx:VBox>
  326.    
  327. </mx:VDividedBox>
  328. </mx:WindowedApplication>

Seven Yu @ 03/26/2008 (6:14 am)

RegexTester v2.0.1

Tags: , , , ::

RegexTester 是用 Adobe Flex Builder 开发的 Air 应用程序, 可以进行 ActionScript 3.0 的正则式的测试, 是正则测试和学习的有力助手.

欢迎大家下载试用, bug 报告邮箱: dofyyu at gmail dot com.

下载 / 源码

开发历史:

  • 2008.03.04 v 1.0 基本功能实现;
  • 2008.03.05 v 1.1/1.15 优化/移除冗余代码, 修复了一个全局模式造成死循环的 bug.
  • 2008.03.05 v1.17 修正结果包含 html 代码 bug(暂时取消用 htmlText 显示结果)
  • 2008.03.06 v2.0 更名为 RegexTester 支持文件拖拽, 自动分析正则式
  • 2008.03.06 v2.0.1 正则输入框和测试文本输入框支持输入 tab, 但不能用 tab 键切换焦点(可以用 ctrl + tab)

快捷键:

  • Ctrl+` 焦点定位到修饰符(flags)
  • Ctrl+1 焦点定位到正则输入框
  • Ctrl+2 焦点定位到测试文本框