正規表現チェッカー

by tepe
♥0 | Line 354 | Modified 2014-11-17 18:08:35 | MIT License
play

ActionScript3 source code

/**
 * Copyright tepe ( http://wonderfl.net/user/tepe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hRmd
 */

package {
    import flash.display.*;
    import flash.text.*;
    import flash.events.*;
    import flash.net.*;
    import flash.ui.*;
    public class FlashTest extends Sprite {
        private var t1:TextEditor;//原文
        private var t2:TextField;
        private var t3:TextField;//正規表現
        private var t4:TextField;
        private var t5:TextField;//パラメータ
        private var so : SharedObject;// = SharedObject.getLocal("my_data");
        //区間開始
        //(['"\{\(\[]|//|/\*)
        //区間終了
        //(['"\}\]\)]|\n|\*/)
        public function FlashTest() {
            // write as3 code here..
            init();
        }

        
 
        private function init():void{
            
            
            
            t1 = new TextEditor();
            t2 = new TextField();
            t3 = new TextField();
            t4 = new TextField();
            t5 = new TextField();
            
            t1.border = true;
            t1.width = 460;
            t1.height = 200;
            t1.wordWrap = true;
            t1.y=40;
            t1.type = "input";
            //t1.multiline = true;
            t1.text = "";
            addChild(t1);
            t1.addEventListener(KeyboardEvent.KEY_UP,onKey);
            t1.addEventListener(Event.CHANGE,onChange);
            
            //リスト
            t2.y = 240;
            t2.width=460;
            t2.height=220;
            t2.selectable=false;
            addChild(t2);
            t2.addEventListener(MouseEvent.MOUSE_MOVE,onMove1);
            t2.addEventListener(MouseEvent.CLICK,onClick2);
              
            
            //正規表現入力ボックス
            t3.border = true;
            t3.type = "input";
            t3.width = 400;
            t3.height =20;
            t3.text = "<[\\S\\?]+[^>]*>";
            addChild(t3);
            t3.addEventListener(Event.CHANGE,onChange);
            t3.addEventListener(KeyboardEvent.KEY_UP,addList);
            
            
            
            
            t4.width = 450;
            t4.height = 20;
            t4.y = 20;
            addChild(t4);
            
            t5 = new TextField();//正規表現パラメータ
            t5.border = true;
            t5.type = "input";
            t5.width = 50;
            t5.height =20;
            t5.x = 400;
            addChild(t5);
            t5.addEventListener(Event.CHANGE,onChange);
            
            addEventListener(MouseEvent.CLICK,onClick);
            t5.text = "gm";
            
            
            so = SharedObject.getLocal("data");
            if(so){
                t1.text = "1";
                var data:Object = so.data;
                t1.text = "2";
                //data["t1"] = "tst";
                if(so.data.hasOwnProperty("t1"))t1.text = data["t1"];
                if(so.data.hasOwnProperty("t2"))t2.text = data["t2"];
                if(so.data.hasOwnProperty("t3"))t3.text = data["t3"];
                //if(so.data.hasOwnProperty("t4"))t4.text = data["t4"];
                if(so.data.hasOwnProperty("t5"))t5.text = data["t5"];
                //t1.text = "3";
            }
            else{
                t1.text = "0";
            }

     
            update();
        }
        private function onKey(e:KeyboardEvent):void{
            update();
            save();
        }


        private function onClick(e:MouseEvent):void{
            update();
        }

        private function onChange(e:Event):void{
            update();
        }
        
        private function save():void{
            var data:Object = so.data;
            data["t1"] = t1.text;
            data["t2"] = t2.text;
            data["t3"] = t3.text;
            //data["t4"] = t4.text;
            data["t5"] = t5.text;
            so.flush();
        }
        
        private function onMove1(e:MouseEvent):void{
            var mx:Number=e.target.mouseX;
            var my:Number=e.target.mouseY;
            
            var n:int = e.target.getLineIndexAtPoint(mx,my);//指定ポイントの行
            font(t2,n);
        }

        private function onClick2(e:MouseEvent):void{
            var mx:Number=e.target.mouseX;
            var my:Number=e.target.mouseY;
            
            var n:int = e.target.getLineIndexAtPoint(mx,my);//指定ポイントの行
            t3.text = e.target.getLineText(n);
            update();
            
        }



        //結果更新
        private var ncnt:int = 0;
        private function update():void{
            
            //save();
            if(t3.length<1)return;
            var reg:RegExp = new RegExp(t3.text,t5.text);                
            reg.lastIndex = t1.caretIndex;
            var result:Object = reg.exec(t1.text);
            var str:String = t1.text;
            
            //t4.text = "RegExp = /"+t3.text+"/"+t5.text + "    start:"+t1.caretIndex +"index:"+result.index+" lastIndex:"+reg.lastIndex;
            
            //検索ヒット
            var newFormat:TextFormat = new TextFormat(); 
            newFormat.size = 12;
            newFormat.font = "Arial";
            newFormat.color = 0xff0000;
            newFormat.italic = true;
            
            //検索ヒット
            var newFormat2:TextFormat = new TextFormat(); 
            newFormat2.size = 12;
            newFormat2.font = "Arial";
            newFormat2.color = 0xcc0000;
            newFormat2.italic = true;
            
            //通常フォーマット
            var Format2:TextFormat = new TextFormat(); 
            Format2.size = 12;
            Format2.font = "Arial";
            Format2.color = 0x000000;
            Format2.italic = false;
            t1.setTextFormat(Format2,0,t1.length);
            
            //テキストフォーマットの設定(フォント設定, 適用開始位置, 適用終了位置)
            //t1.setTextFormat(newFormat, result.index,reg.lastIndex);
            t1.setTextFormat(newFormat, 0, t1.length);
            var cnt:int=0;
            ncnt++;
            t4.text = ncnt.toString();
   
            while (reg.lastIndex!=0) {
                result = reg.exec(t1.text);
                str = t1.text;
                //フォーマット適用範囲を指定
                //if((cnt%2)==1)t1.setTextFormat(newFormat, result.index,reg.lastIndex);
                //else t1.setTextFormat(newFormat2, result.index,reg.lastIndex);
                //t4.text = result.index.toString();
                t4.text = reg.lastIndex.toString(); 
                
                if((cnt%2)==1)newFormat.color = 0xcc0000;
                else newFormat.color = 0xff0000;
                t1.setTextFormat(newFormat, result.index,reg.lastIndex);
                cnt++;
                t4.text = cnt.toString();
                //if(cnt>200)break;
            }
            
           t4.text = "---4 "+ ncnt.toString();;
           t4.text = "RegExp = /"+t3.text+"/"+t5.text + "    start:"+t1.caretIndex +"index:"+result.index+" lastIndex:"+reg.lastIndex;

        }

        //リストに追加
        private function addList(e:KeyboardEvent=null):void{
            if(e.keyCode==13){
                if(t3.text.length==0)return;
                var str:String = t3.text +"\n";
                str += t2.text;
                t2.text = str;
                t3.text="";
            }
        }
        
        //選択行を強調
        private function font(t1:TextField,n:int):void{
            //検索ヒット
            var newFormat2:TextFormat = new TextFormat(); 
            newFormat2.size = 15;
            newFormat2.font = "Arial";
            newFormat2.color = 0x000000;
            newFormat2.italic = true;
            
            
            //通常フォーマット
            var Format2:TextFormat = new TextFormat(); 
            Format2.size = 12;
            Format2.font = "Arial";
            Format2.color = 0x000000; 
            Format2.italic = false;
            t1.setTextFormat(Format2,0,t1.length);//デフォルトフォーマット
            
            var st:int = t1.getLineOffset(n);
            var end:int = st+t1.getLineLength(n);
            
            
            t1.setTextFormat(newFormat2,st,end);//デフォルトフォーマット
            
        }


    }
}

////////////////////////////////////////////////////////////////////////
//  TextEditor class
////////////////////////////////////////////////////////////////////////

/*
    --TextFieldへの追加機能--
        ・改行入力
        ・タブ入力
        ・オートインデント
        ・アンドゥ/リドゥ
*/

    import flash.text.TextField;
    import flash.events.*;
    class TextEditor extends TextField {
        private var prevText:String = "";//text変更前の状態
        private var indentStr:String;
        private var sc:StringComparator = new StringComparator();
        private var historyManager:HistoryManager = new HistoryManager();
        private var comparator:StringComparator = new StringComparator();
        
        public function TextEditor():void {
            this.type = "input";//入力可能
            //this.multiline = true;//マルチライン
            this.addEventListener(KeyboardEvent.KEY_DOWN, onKey); 
            this.addEventListener(FocusEvent.KEY_FOCUS_CHANGE,focusChangeListener);//タブキーによるフォーカス変更をキャンセル
            this.addEventListener(Event.CHANGE,onChange);//textの変更

        }
        
        private var sw:Boolean;
        private function onChange(e:Event):void{  
    
            if(sw==false)addHistory();
            if(sw2==true){
                this.multiline = false;
                sw2=false;
            }

            prevText = this.text;
            sw=false;      
        }
      
        private function focusChangeListener(e:FocusEvent):void{
            e.preventDefault();
        }
        
        //入力履歴更新
        private function addHistory():void{
            comparator.compare(prevText, this.text);   
            var entry:HistoryEntry = new HistoryEntry(comparator.commonPrefixLength);      
                entry.removeText = prevText.substring(comparator.commonPrefixLength, prevText.length - comparator.commonSuffixLength);
                entry.addText = this.text.substring(comparator.commonPrefixLength, this.text.length - comparator.commonSuffixLength);
                historyManager.appendEntry(entry); 
                prevText = this.text;
        }

        
        //キー入力
        private var sw2:Boolean;
        private function onKey(e:KeyboardEvent):void {        
            // Ctrl+Z : UNDO
            if (e.keyCode == 90 && e.ctrlKey) {
                sw=true;
                undo();
                return;
            }
        
            // Ctrl+Y : REDO
            if (e.keyCode == 89 && e.ctrlKey) {
                sw=true;
                redo();
                return;
            }
            //ペースト
            if(e.keyCode == 86 && e.ctrlKey){
                this.multiline = true;//改行を含むコピーに対応
                sw2=true;
            }

            
            //キャレット位置に改行文字を挿入
            if(e.keyCode == 13 || e.keyCode == 108){
                lineFeed();
                return;
            }
            //tab
            if (e.keyCode == 9) {
                tab();
                return;
            }
        }
        

        
        //改行
        
        public function lineFeed():void{
            //sw2=true;
            var str1:String;
            var str2:String;
            var scrV:int = this.scrollV;
            str1 = this.text.substring(0, this.caretIndex);
            str2 = this.text.substring(this.caretIndex, this.length);
            this.text = str1;
            this.appendText("\n");//キャレット位置で改行
                
            //インデント構造(タブ&スペースの構成)を調べる
            var indent:int=0;
            var prevReturn:int = this.text.lastIndexOf('\r', this.caretIndex-1);//前回の改行位置
            //一つ前の改行直後に続くタブコードの数=インデント深度
            for (var j:int = prevReturn+1; j < this.caretIndex; j++) {
                if (this.text.charAt(j) == '\t' || this.text.charAt(j) == ' ' ) indent++;
                else break;
            }
            //上の行のインデントに従う
            var iStr:String = this.text.slice(prevReturn + 1, prevReturn + 1 + indent);
            indentStr = iStr;
            this.appendText(iStr);//インデント
            this.text += str2;//結合 
             
            //キャレット位置をインクリメント
            this.scrollV = scrV;
            this.setSelection(this.caretIndex +indent + 1, this.caretIndex +indent + 1);
            
            this.dispatchEvent(new Event(Event.CHANGE));
            
        }

        //タブ
        public function tab():void{
            var str1:String;
            var str2:String;
            str1 = this.text.substring(0, this.caretIndex);
            str2 = this.text.substring(this.caretIndex, this.length);
            this.text = str1 + '\t' + str2;
            //キャレット位置をインクリメント
            this.setSelection(this.caretIndex + 1, this.caretIndex + 1);        
            this.dispatchEvent(new Event(Event.CHANGE));
        }

        //アンドゥ
        public function undo():void {
            if (historyManager.canBack) {
                var entry:HistoryEntry = historyManager.back();
                //テキストセット
                this.replaceText(entry.index, entry.index + entry.addText.length, entry.removeText);
                //キャレット位置セット
                this.setSelection(entry.index + entry.removeText.length, entry.index + entry.removeText.length);               
            }
            this.dispatchEvent(new Event(Event.CHANGE));           
        }
    
        //リドゥ
        public function redo():void {
            if (historyManager.canForward) {
                var entry:HistoryEntry = historyManager.forward();
                //テキストセット
                this.replaceText(entry.index, entry.index + entry.removeText.length, entry.addText);
                //キャレット位置セット
                this.setSelection(entry.index + entry.addText.length, entry.index + entry.addText.length);            
            }
            this.dispatchEvent(new Event(Event.CHANGE));         
        }
        
    }


import __AS3__.vec.Vector;

class HistoryManager {
    public var currentIndex:int = 0;
    public var length:int=0;
    private var entries:Vector.<HistoryEntry>;
    
    public function HistoryManager() {
        entries = new Vector.<HistoryEntry>();
    }
    //履歴追記
    public function appendEntry(entry:HistoryEntry):void {
        entries.length = currentIndex;
        length = entries.length;
        entries.push(entry);
        currentIndex++;// = entries.length;
    }
    //履歴削除
    public function clear():void {
        currentIndex = 0;
        entries.length = 0;
    }
    //リドゥ可能
    public function get canForward():Boolean {
        return currentIndex < entries.length;
    }
    //アンドゥ可能
    public function get canBack():Boolean {
        return currentIndex > 0;
    }
    //リドゥ
    public function forward():HistoryEntry {
        return entries[currentIndex++];
    }
    //アンドゥ
    public function back():HistoryEntry {
        return entries[--currentIndex];
    }

}


class HistoryEntry {
    public var index:int;
    public var removeText:String;
    public var addText:String;
    
    public function HistoryEntry(index:int=0, remove:String="", add:String="") {
        this.index   = index;//文字列先頭位置
        this.removeText = remove;//消した文字列
        this.addText = add;//追加した文字列
    }
}
    

 // 文字列の左右一致を数える
class StringComparator {
    // 左側の共通文字列長
    public var commonPrefixLength:int;    
    // 右側の共通文字列長
    public var commonSuffixLength:int;
    /**
     * 2つの文字列を比較し、commonPrefixLengthとcommonSuffixLengthをセットする
     * 
     * @param str1 比較する文字列の一方
     * @param str2 比較する文字列の他方
     */
    public function compare(str1:String, str2:String):void {
        var minLength:int = Math.min(str1.length, str2.length);
        var step:int, l:int, r:int;
        
        step = Math.pow(2, Math.floor(Math.log(minLength) / Math.log(2)));
        for (l=0; l<minLength; ) {
            if (str1.substr(0, l + step) != str2.substr(0, l + step)) {
                if (step == 1) { break; }
                step >>= 1;
            } else {
                l += step;
            }
        }
        l = Math.min(l, minLength);
        
        minLength -= l;
        
        step = Math.pow(2, Math.floor(Math.log(minLength) / Math.log(2)));
        for (r=0; r<minLength; ) {
            if (str1.substr(-r - step) != str2.substr(-r - step)) {
                if (step == 1) { break; }
                step >>= 1;
            } else {
                r += step;
            }
        }
        r = Math.min(r, minLength);
        
        commonPrefixLength = l;
        commonSuffixLength = r;
    }    
}  

Forked