[Rt-commit] r6017 - in people/jesse: . refactoring refactoring/extract_method

jesse at bestpractical.com jesse at bestpractical.com
Thu Sep 21 08:17:55 EDT 2006


Author: jesse
Date: Thu Sep 21 08:17:54 2006
New Revision: 6017

Added:
   people/jesse/refactoring/
   people/jesse/refactoring/extract_method/
   people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/
   people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/oscon-europe.2006.xul
   people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/takahashi.css
   people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/takahashi.js
   people/jesse/refactoring/extract_method/extract   (contents, props changed)
Modified:
   people/jesse/   (props changed)

Log:
 r27709 at pinglin:  jesse | 2006-09-21 14:17:49 +0200
  * An example of an extract_method tool for perl


Added: people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/oscon-europe.2006.xul
==============================================================================
--- (empty file)
+++ people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/oscon-europe.2006.xul	Thu Sep 21 08:17:54 2006
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="chrome://global/skin/" type="text/css"?><?xml-stylesheet href="takahashi.css" type="text/css"?><page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);">
+<html:textarea id="builtinCode" style="visibility: collapse">
+Refactoring Perl
+----
+One refactoring
+----
+extract_method
+----
+Please put on your 
+Perl Sensitive
+Sunglasses now.
+----
+How do you go from:
+----
+ sub do_thing {
+    my $self = shift;
+    my $thingy = shift;
+     
+    my %args = ( foo => 'bar'); 
+    print "We'll do some stuff";
+
+    # Pretend this an interesting bit of code
+    system ($thingy, $args{'foo'});
+    $self->log("Ran the user's rm -rf");
+
+ }
+----
+To this:
+----
+ sub do_thing {
+   my $self = shift;
+   my $thingy = shift;
+     
+   my %args = ( foo => 'bar'); 
+   print "We'll do some stuff";
+
+   $self->run_command($thingy,\%args);
+ }
+
+ sub run_command { 
+   my $self = shift;
+   my $thingy = shift;
+   my %args = %{(shift)};
+
+   # Pretend this an interesting bit of code
+   system ($thingy, $args{'foo'});
+   $self->log("Ran the user's rm -rf");
+ }
+----
+The hard bit
+----
+Writing the signature
+----
+(The real hard bit is the polish 
+to make this generally useful)
+----
+Our extracted code
+----
+ system ($thingy, $args{'foo'});
+ $self->log("Ran the user's rm -rf");
+----
+PPI?
+----
+Scares me
+----
+Regexps?
+----
+Too broken
+----
+So how do we
+get the signature?
+----
+I blame Damian
+----
+And James Duncan
+----
+And Piers Cawley
+----
+Piers did this
+5 years ago.
+----
+He didn't publish.
+----
+At least he told me
+about on Tuesday.
+----
+So. Generating 
+that signature.
+----
+Without PPI and Regexps,
+we're kinda screwed, no?
+----
+What can
+parse Perl5?
+----
+Only one thing...
+----
+perl
+----
+We can use B::!
+----
+Only MAD_PROPS
+gives you enough
+B::Rope
+----
+That's 5.9+ only.
+----
+So. How to get
+that data out
+of perl?
+----
+{{#tag|Hint:}} Ruby 
+can not
+do this.
+----
+{{#i|at least not this way}}
+----
+So. let's get our 
+code compiling.
+----
+
+ # cat > /tmp/xxx
+ system ($thingy, $args{'foo'});
+ $self->log("Ran the user's rm -rf");
+----
+ # perl -Mstrict -C /tmp/xxx
+ Global symbol "$thingy" requires explicit package name at /tmp/xxx line 1.
+ Global symbol "%args" requires explicit package name at /tmp/xxx line 1.
+ Global symbol "$self" requires explicit package name at /tmp/xxx line 2.
+ Execution of /tmp/xxx aborted due to compilation errors.
+----
+{{#i|Now}} you can 
+use the regexps.
+----
+Yes, it's a hack.
+----
+But it works.
+----
+http://fsck.com/~jesse/extract
+----
+The code {{#warn|sucks}}.
+----
+A bit less than it did.
+----
+I've used it to
+refactor itself.
+----
+Twice
+----
+Thanks!
+http://fsck.com/~jesse/extract
+</html:textarea>
+<deck flex="1" id="deck">
+<vbox flex="1" onmousemove="Presentation.onMouseMoveOnCanvas(event);">
+<toolbox id="canvasToolbar">
+<toolbar>
+<toolbarbutton oncommand="Presentation.home()" label="|&lt;&lt;" observes="canBack"/>
+<toolbarbutton oncommand="Presentation.back()" label="&lt;" observes="canBack"/>
+<toolbarbutton oncommand="Presentation.forward()" label="&gt;" observes="canForward"/>
+<toolbarbutton oncommand="Presentation.end()" label="&gt;&gt;|" observes="canForward"/>
+<toolbarseparator/>
+<hbox align="center">
+<textbox id="current_page" size="4" oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/>
+<description value="/"/>
+<description id="max_page"/>
+</hbox>
+<toolbarseparator/>
+<vbox flex="2">
+<spacer flex="1"/>
+<scrollbar id="scroller" align="center" orient="horizontal" oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" onmousedown="Presentation.onScrollerDragStart();" onmousemove="Presentation.onScrollerDragMove();" onmouseup="Presentation.onScrollerDragDrop();"/>
+<spacer flex="1"/>
+</vbox>
+<toolbarseparator/>
+<spacer flex="1"/>
+<toolbarseparator/>
+<toolbarbutton id="toggleEva" label="Eva" type="checkbox" autoCheck="false" oncommand="Presentation.toggleEvaMode();"/>
+<toolbarseparator/>
+<toolbarbutton label="Edit" oncommand="Presentation.toggleEditMode();"/>
+<toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
+</toolbar>
+</toolbox>
+<vbox flex="1" id="canvas" onclick="Presentation.onPresentationClick(event);">
+<spacer flex="1"/>
+<hbox flex="1">
+<spacer flex="1"/>
+<vbox id="content">
+</vbox>
+<spacer flex="1"/>
+</hbox>
+<spacer flex="1"/>
+</vbox>
+</vbox>
+<vbox flex="1" id="edit">
+<toolbox>
+<toolbar>
+<toolbarbutton label="New Page" oncommand="Presentation.addPage()"/>
+<spacer flex="1"/>
+<toolbarseparator/>
+<toolbarbutton label="View" oncommand="Presentation.toggleEditMode();"/>
+<toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
+</toolbar>
+</toolbox>
+<textbox id="textField" flex="1" multiline="true" oninput="Presentation.onEdit()"/>
+<hbox collapsed="true">
+<iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/>
+</hbox>
+</vbox>
+</deck>
+<broadcasterset>
+<broadcaster id="canBack"/>
+<broadcaster id="canForward"/>
+</broadcasterset>
+<commandset>
+<command id="cmd_forward" oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/>
+<command id="cmd_back" oncommand="if (Presentation.isPresentationMode) Presentation.back();"/>
+<command id="cmd_home" oncommand="if (Presentation.isPresentationMode) Presentation.home();"/>
+<command id="cmd_end" oncommand="if (Presentation.isPresentationMode) Presentation.end();"/>
+</commandset>
+<keyset>
+<key key=" "      command="cmd_forward"/>
+<key keycode="VK_ENTER"      command="cmd_forward"/>
+<key keycode="VK_RETURN"     command="cmd_forward"/>
+<key keycode="VK_PAGE_DOWN"  command="cmd_forward"/>
+<key keycode="VK_RIGHT"      command="cmd_forward"/>
+<key keycode="VK_DOWN"       command="cmd_forward"/>
+<!--key keycode="VK_BACK_SPACE" command="cmd_back"/-->
+<key keycode="VK_UP"    command="cmd_back"/>
+<key keycode="VK_PAGE_UP"    command="cmd_back"/>
+<!--
+<key keycode="VK_BACK_UP"    command="cmd_back"/>-->
+<!--
+<key keycode="VK_BACK_LEFT"  command="cmd_back"/>-->
+<key keycode="VK_HOME"       command="cmd_home"/>
+<!--
+<key keycode="VK_END"        command="cmd_end"/>-->
+<key key="n" modifiers="accel" oncommand="Presentation.addPage();"/>
+<key key="r" modifiers="accel" oncommand="window.location.reload();"/>
+<key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/>
+<key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/>
+</keyset>
+<script src="takahashi.js" type="application/x-javascript" />
+</page>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+   -
+   - The Initial Developer of the Original Code is SHIMODA Hiroshi.
+   - Portions created by the Initial Developer are Copyright (C) 2005
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+

Added: people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/takahashi.css
==============================================================================
--- (empty file)
+++ people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/takahashi.css	Thu Sep 21 08:17:54 2006
@@ -0,0 +1,184 @@
+ at charset "UTF-8";
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#canvas {
+    /*
+	background: black !important;
+	color: white !important;
+        */
+        font-weight: bold;
+	font-family:
+                "Candara"
+                "Georgia"
+                "DejaVu Serif Condensed"
+                "Arial"
+		"Bitstream Vera Sans"
+		"Verdana"
+		"Apple LiGothic"
+		"Arial Black"
+                "Bitstream Vera Sans"
+		sans-serif !important;
+}
+#canvas * {
+	cursor: pointer !important;
+}
+#canvas image {
+	width: auto;
+	height: auto;
+}
+.link-text {
+	color: #99CCFF !important;
+	text-decoration: none !important;
+}
+.link-text:hover {
+	color: #CCEEFF !important;
+/*        border-bottom: dotted 1px; */
+}
+.link-text:active {
+	color: white !important;
+}
+.s {
+        text-decoration: line-through;
+}
+.iu {
+        text-decoration: underline;
+        font-style: italic;
+}
+.ui {
+/*      text-decoration: underline; */
+        font-style: italic;
+}
+.u {
+        text-decoration: underline;
+}
+.i {
+        font-style: italic;
+        font-family: "Times New Roman"
+                     "Bitstream Vera Serif"
+                     serif;
+}
+.c {
+        font-family: "Anonymous"
+		     "Lucida Console"
+		     "Andale Mono"
+                     "Bitstream Vera Sans Mono"
+                     monospace;
+}
+.t {
+        font-style: italic;
+}
+
+.h {
+        color: #ff0000;
+}
+
+.tag {
+        color: #33f;
+}
+.warn {
+        color: #f00;
+}
+.att {
+        color: #9999cc;
+}
+.key {
+        color: #00ffff;
+}
+.hid {
+        color: #999999;
+}
+.hidt {
+        color: #999999;
+        font-style: italic;
+}
+.pre {
+        font-family: "Anonymous"
+		     "Lucida Console"
+		     "Andale Mono"
+                     "Bitstream Vera Sans Mono"
+                     monospace;
+        padding-bottom: 8px;
+}
+#canvas[rendering="true"] image {
+	display: none;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+	color: white !important;
+}
+
+
+tabbox, tabpanels, tabpanel {
+	margin: 0;
+	padding: 0;
+}
+
+
+
+
+#canvas[eva="true"] {
+	background: white !important;
+	color: black !important;
+	font-family:
+                "Georgia"
+                "DejaVu Serif Condensed"
+		"Apple LiGothic"
+		"Arial Black"
+		serif !important;
+}
+#canvas[eva="true"] .link-text {
+	color: red !important;
+	text-decoration: none !important;
+}
+#canvas[eva="true"] .link-text:hover {
+	color: pink !important;
+}
+#canvas[eva="true"] .link-text:active {
+	color: orange !important;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+	color: black !important;
+}
+
+
+
+
+#canvasToolbar {
+	position: relative;
+}
+
+.subtitle {
+	display: none;
+    font-family: "Kochi Gothic";
+    color: yellow;
+    text-align: center;
+    font-size: 40px;
+    background: black;
+    bottom: 10;
+    padding-bottom: 10px;
+    padding-top: 10px;
+    spacing: 10px;
+}

Added: people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/takahashi.js
==============================================================================
--- (empty file)
+++ people/jesse/refactoring/extract_method/2006-eurooscon-lightining-talk/takahashi.js	Thu Sep 21 08:17:54 2006
@@ -0,0 +1,518 @@
+var Presentation = {
+    init : function(option){
+        this.size = 9;
+
+        this._offset  = 0;
+        this.canvas   = document.getElementById('canvas');
+        this.content  = document.getElementById('content');
+        this.textbox  = document.getElementById('textField');
+        this.deck     = document.getElementById('deck');
+        this.scroller = document.getElementById('scroller');
+
+               this.canvas.appendChild(document.createElement('description'));
+               this.canvas.lastChild.setAttribute('id', "caption");
+               this.canvas.lastChild.setAttribute('class', 'subtitle');
+        this.toolbar         = document.getElementById('canvasToolbar');
+        this.toolbarHeight   = this.toolbar.boxObject.height;
+        this.isToolbarHidden = true;
+        this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;');
+
+        if(option){
+            for(var i in option){this[i] = option[i]}
+        }
+
+        if (this.readParameter()) {
+            this.takahashi();
+        }
+
+        document.documentElement.focus();
+    },
+
+    takahashi : function(){
+        if (!document.title)
+            document.title = this.data[0].replace(/[\r\n]/g, ' ');
+
+        if(!this.data[this.offset]){
+            this.offset = this.data.length-1;
+        }
+        document.getElementById("current_page").value = this.offset+1;
+        document.getElementById("max_page").value     = this.data.length;
+
+        this.scroller.setAttribute('maxpos', this.data.length-1);
+        this.scroller.setAttribute('curpos', this.offset);
+
+        var broadcaster = document.getElementById('canBack');
+        if (!this.offset)
+            broadcaster.setAttribute('disabled', true);
+        else
+            broadcaster.removeAttribute('disabled');
+
+        var broadcaster = document.getElementById('canForward');
+        if (this.offset == this.data.length-1)
+            broadcaster.setAttribute('disabled', true);
+        else
+            broadcaster.removeAttribute('disabled');
+
+        this.canvas.setAttribute('rendering', true);
+
+        var text = this.data[this.offset].
+                replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n")
+                .split('\n');
+        var range = document.createRange();
+        range.selectNodeContents(this.content);
+        range.deleteContents();
+        range.detach();
+
+        var line;
+        var newLine;
+        var uri;
+        var image_width;
+        var image_total_width  = 0;
+        var image_height;
+        var image_total_height = 0;
+        var image_src;
+        var code_listing = 0;
+
+
+        var labelId = 0;
+
+        for (var i = 0; i < text.length; i++)
+        {
+            this.content.appendChild(document.createElement('hbox'));
+            this.content.lastChild.setAttribute('align', 'center');
+            this.content.lastChild.setAttribute('pack', 'center');
+
+            line = text[i];
+            image_width  = 0;
+            image_height = 0;
+            var subtitle = '';
+
+            if (line.match(/^~/)) {
+              subtitle = line.substring(1);
+              line = '';
+            }
+
+
+            if (line.match(/^ /)) {
+              code_listing = 1; 
+              this.content.lastChild.setAttribute('align', 'left');
+              this.content.lastChild.setAttribute('class', 'pre');
+              line = line.substring(1)
+            } 
+            while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)([^\}]+)\}\})(.+)?/))
+            {
+                if (RegExp.$1) {
+                    this.content.lastChild.appendChild(document.createElement('description'));
+                    this.content.lastChild.lastChild.setAttribute('value', RegExp.$1);
+                }
+                newLine = line.substring((RegExp.$1+RegExp.$2).length);
+
+                // Images
+                if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) {
+                    this.content.lastChild.appendChild(document.createElement('image'));
+                    image_src = RegExp.$2;
+                    if (image_src.indexOf('http://') < 0 &&
+                        image_src.indexOf('https://') < 0)
+                        image_src = this.dataFolder+image_src;
+                    this.content.lastChild.lastChild.setAttribute('src', image_src);
+                    this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
+                    this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
+                    image_width  += parseInt(RegExp.$3 || '0');
+                    image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
+                }
+
+                // Styles
+                // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) {
+                else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)([^\}]+)\}\}/.test(line)) {
+                    uri = RegExp.$4;
+                    this.content.lastChild.appendChild(document.createElement('description'));
+                    this.content.lastChild.lastChild.setAttribute('value', uri);
+                    this.content.lastChild.lastChild.setAttribute('class', RegExp.$3);
+                }
+
+                // Links
+                else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) {
+                    uri = RegExp.$4;
+                    if (uri.indexOf('://') < 0)
+                        uri = this.dataFolder+uri;
+                    this.content.lastChild.appendChild(document.createElement('description'));
+                    this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
+                    this.content.lastChild.lastChild.setAttribute('href', uri);
+                    this.content.lastChild.lastChild.setAttribute('tooltiptext', uri);
+                    this.content.lastChild.lastChild.setAttribute('statustext', uri);
+                    this.content.lastChild.lastChild.setAttribute('class', 'link-text');
+                }
+
+                line = newLine;
+            }
+
+            if (line) {
+                this.content.lastChild.appendChild(document.createElement('description'));
+                this.content.lastChild.lastChild.setAttribute('value', line);
+            }
+
+            image_total_width = Math.max(image_total_width, image_width);
+            image_total_height += image_height;
+        }
+
+        this.content.setAttribute('style', 'font-size:10px;');
+          caption =  document.getElementById('caption');
+        if (subtitle) {
+               caption.setAttribute('value', subtitle);
+        } else {
+               caption.setAttribute('value', '');
+
+        }
+
+        if (this.content.boxObject.width) {
+            var canvas_w  = this.canvas.boxObject.width;
+            var canvas_h  = this.canvas.boxObject.height-image_total_height;
+
+            var content_w = this.content.boxObject.width;
+            var new_fs = Math.round((canvas_w/content_w) * this.size);
+
+            if (new_fs > 32) {
+                new_fs = new_fs - (new_fs % 32) 
+            }
+            //if (code_listing) { new_fs = 48;}
+
+            this.content.setAttribute('style', 'top: 0');
+            this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+
+            if (this.content.boxObject.width < image_total_width) {
+                content_w = image_total_width;
+                new_fs = Math.round((canvas_w/content_w) * this.size);
+                this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+            }
+
+            var content_h = this.content.boxObject.height;
+            if(content_h >= (canvas_h - 70)){ // That 50 is space for subtitles
+                new_fs = Math.round(((canvas_h-70)/content_h) * new_fs);
+                this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+                content_h = this.content.boxObject.height;
+            }
+        }
+        this.canvas.removeAttribute('rendering');
+    },
+
+    reload : function() {
+        if (this.dataPath != location.href) {
+            var path = this.dataPath;
+            if (location.href.match(/^https?:/)) {
+                var request = new XMLHttpRequest();
+                request.open('GET', path);
+                request.onload = function() {
+                    Presentation.textbox.value = request.responseText;
+                    Presentation.data = Presentation.textbox.value.split('----');
+
+                    Presentation.takahashi();
+
+                    path = null;
+                    request = null;
+                };
+                request.send(null);
+            }
+            else {
+                document.getElementById('dataLoader').setAttribute('src', 'about:blank');
+                window.setTimeout(function() {
+                    document.getElementById('dataLoader').setAttribute('src', path);
+                    path = null;
+                }, 10);
+            }
+        }
+        else
+            window.location.reload();
+    },
+
+    forward : function(){
+        this.offset++;
+        this.takahashi();
+    },
+    back : function(){
+        this.offset--;
+        if(this.offset < 0){this.offset = 0}
+        this.takahashi();
+    },
+    home : function(){
+        this.offset = 0;
+        this.takahashi();
+    },
+    end : function(){
+        this.offset = this.data.length-1;
+        this.takahashi();
+    },
+    showPage : function(aPageOffset){
+        this.offset = aPageOffset ? aPageOffset : 0 ;
+        this.takahashi();
+    },
+
+    addPage : function() {
+        if (this.textbox.value &&
+            !this.textbox.value.match(/(\r\n|[\r\n])$/))
+            this.textbox.value += '\n';
+        this.textbox.value += '----\n';
+        this.onEdit();
+    },
+
+    toggleEditMode : function(){
+        this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ;
+    },
+    toggleEvaMode : function(){
+        var check = document.getElementById('toggleEva');
+        if (this.canvas.getAttribute('eva') == 'true') {
+            this.canvas.removeAttribute('eva');
+            check.checked = false;
+        }
+        else {
+            this.canvas.setAttribute('eva', true);
+            check.checked = true;
+        }
+    },
+
+    onPresentationClick : function(aEvent){
+        if (!this.isToolbarHidden)
+            this.showHideToolbar();
+
+        switch(aEvent.button)
+        {
+            case 0:
+                var uri = aEvent.target.getAttribute('href');
+                if (uri)
+                    window.open(uri);
+                else {
+                    this.forward();
+                    document.documentElement.focus();
+                }
+                break;
+            case 2:
+                this.back();
+                document.documentElement.focus();
+                break;
+            default:
+                break;
+        }
+    },
+    onScrollerDragStart : function(){
+        this.scroller.dragging = true;
+    },
+    onScrollerDragMove : function(){
+        if (this.scroller.dragging)
+            this.showPage(parseInt(this.scroller.getAttribute('curpos')));
+    },
+    onScrollerDragDrop : function(){
+        if (this.scroller.dragging) {
+            this.showPage(parseInt(this.scroller.getAttribute('curpos')));
+        }
+         this.scroller.dragging = false;
+    },
+    onEdit : function() {
+        this.data = this.textbox.value.split('----');
+        this.takahashi();
+    },
+
+    onKeyPress : function(aEvent) {
+        switch(aEvent.keyCode)
+        {
+            case aEvent.DOM_VK_BACK_SPACE:
+                if (this.isPresentationMode) {
+                    aEvent.preventBubble();
+                    aEvent.preventDefault();
+                    Presentation.back();
+                }
+                break;
+            default:
+                break;
+        }
+    },
+
+
+    onToolbarArea   : false,
+    toolbarHeight   : 0,
+    toolbarDelay    : 300,
+    toolbarTimer    : null,
+    isToolbarHidden : false,
+    onMouseMoveOnCanvas : function(aEvent) {
+        if (this.scroller.dragging) return;
+
+        this.onToolbarArea = (aEvent.clientY < this.toolbarHeight);
+
+        if (this.isToolbarHidden == this.onToolbarArea) {
+            if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer);
+            this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay);
+        }
+    },
+    onMouseMoveOnCanvasCallback : function() {
+        if (this.isToolbarHidden == this.onToolbarArea)
+            this.showHideToolbar();
+    },
+
+    toolbarAnimationDelay : 100,
+    toolbarAnimationSteps : 5,
+    toolbarAnimationInfo  : null,
+    toolbarAnimationTimer : null,
+    showHideToolbar : function()
+    {
+        if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer);
+
+        this.toolbarAnimationInfo = { count : 0 };
+        if (this.isToolbarHidden) {
+            this.toolbarAnimationInfo.start = 0;
+            this.toolbarAnimationInfo.end   = this.toolbarHeight;
+        }
+        else {
+            this.toolbarAnimationInfo.start = this.toolbarHeight;
+            this.toolbarAnimationInfo.end   = 0;
+        }
+        this.toolbarAnimationInfo.current = 0;
+
+        this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;');
+
+        this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
+    },
+    animateToolbar : function()
+    {
+        this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps);
+
+        var top, bottom;
+        if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) {
+            top    = this.toolbarHeight-this.toolbarAnimationInfo.current;
+            bottom = this.toolbarAnimationInfo.current;
+        }
+        else {
+            top    = this.toolbarAnimationInfo.current;
+            bottom = this.toolbarHeight-this.toolbarAnimationInfo.current;
+        }
+
+        top    = Math.min(Math.max(top, 0), this.toolbarHeight);
+        bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight);
+
+        this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px');
+
+        if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) {
+            this.toolbarAnimationInfo.count++;
+            this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
+        }
+        else
+            this.isToolbarHidden = !this.isToolbarHidden;
+    },
+
+
+
+    get offset(){
+        return this._offset;
+    },
+    set offset(aValue){
+        this._offset = parseInt(aValue || 0);
+        document.documentElement.setAttribute('lastoffset', this.offset);
+        return this.offset;
+    },
+
+    get data(){
+        if (!this._data) {
+             // Make sure you break the text into parts smaller than 4096
+             // characters, and name them as indicated. Tweak as required.
+             // (What a hack. A JS programmer should find a better way.)
+             // Luc St-Louis, and email is lucs at pobox.com.
+
+                 nodes = document.getElementById('builtinCode').childNodes;
+                 content = '';
+                for (i in nodes) {
+                    if (nodes[i].nodeValue) {
+                    content = content + nodes[i].nodeValue;
+                    }
+                }
+    
+               this._data = content.split("----");
+        }
+
+        return this._data;
+    },
+    set data(aValue){
+        this._data = aValue;
+        return aValue;
+    },
+
+
+    get isPresentationMode(){
+        return (this.deck.selectedIndex == 0);
+    },
+
+
+    get dataPath(){
+        if (!this._dataPath)
+            this.dataPath = location.href;
+        return this._dataPath;
+    },
+    set dataPath(aValue){
+        var oldDataPath = this._dataPath;
+        this._dataPath = aValue;
+        if (oldDataPath != aValue) {
+            this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, '');
+        }
+        return this._dataPath;
+    },
+
+    get dataFolder(){
+        if (!this._dataFolder)
+            this.dataPath = this.dataPath;
+        return this._dataFolder;
+    },
+    set dataFolder(aValue){
+        this._dataFolder = aValue;
+        return this._dataFolder;
+    },
+
+    readParameter : function() {
+        if (location.search) {
+            var param = location.search.replace(/^\?/, '');
+
+            if (param.match(/page=([0-9]+)/i))
+                this.offset = parseInt(RegExp.$1)-1;
+
+            if (param.match(/edit=(1|true|yes)/i))
+                this.toggleEditMode();
+
+            if (param.match(/eva=(1|true|yes)/i))
+                this.toggleEvaMode();
+
+            if (param.match(/data=([^&;]+)/i)) {
+                var path = unescape(RegExp.$1);
+                this.dataPath = path;
+                if (location.href.match(/^https?:/)) {
+                    var request = new XMLHttpRequest();
+                    request.open('GET', path);
+                    request.onload = function() {
+                        Presentation.textbox.value = request.responseText;
+                        Presentation.data = Presentation.textbox.value.split('----');
+
+                        Presentation.takahashi();
+                    };
+                    request.send(null);
+                }
+                else {
+                    document.getElementById('dataLoader').setAttribute('src', path);
+                }
+                return false;
+            }
+        }
+        return true;
+    },
+    onDataLoad : function() {
+        if (!window.frames[0].document.body.hasChildNodes()) return;
+        var data = window.frames[0].document.body.firstChild.innerHTML;
+        if (!data) return;
+
+        this.textbox.value = data;
+        this.data = this.textbox.value.split('----');
+
+        this.takahashi();
+    }
+};
+
+function init()
+{
+    window.removeEventListener('load', init, false);
+
+    Presentation.init();
+}
+window.addEventListener('load', init, false);

Added: people/jesse/refactoring/extract_method/extract
==============================================================================
--- (empty file)
+++ people/jesse/refactoring/extract_method/extract	Thu Sep 21 08:17:54 2006
@@ -0,0 +1,87 @@
+perl;
+
+use warnings;
+use strict;
+use IO::All;
+
+my $code =join('',<STDIN>);
+
+print extract_method($code);
+
+sub extract_method {
+    my $code = shift;
+    write_file($code);
+    my $err  = 1;
+    my @args = ();
+    while ($err) {
+        $err = 0;
+        open( my $perl, "-|", 'perl -C /tmp/code.txt 2>&1' )
+            || die $@;
+        while ( my $item = <$perl> ) {
+            if ( $item
+                =~ /Global symbol "(.*)" requires explicit package name/ )
+            {
+                $err = 1;
+                push @args, $1 unless (grep {$1 eq $_} @args);
+            }
+        }
+        write_file($code, @args);
+    }
+    return codegen($code,'final', at args);
+}
+
+sub write_file {
+    my $code = shift;
+    my @args = (@_);
+    codegen($code, 'test', @args) > io('/tmp/code.txt');
+
+}
+
+sub codegen {
+    my $code = shift;
+    my $mode = shift;
+    my @args = (@_);
+
+    my $selforthis_signature = qr/^(\$self|\$this)$/;
+    my ($class_obj) = grep { $_ =~ /$selforthis_signature/ } @args;
+    my @params = grep { $_ !~ /$selforthis_signature/ } @args;
+    my $method_body = generate_signature( $class_obj, \@params, $code );
+    my $subname = 'mysub_' . int( rand(1000) );
+    my $invocation;
+    if ($class_obj) {
+        $invocation = $class_obj . "->" . $subname;
+    } else {
+        $invocation = $subname;
+    }
+    my $ret = "$invocation("
+        . join( ',', map { $_ =~ /^(\%|\@)/ ? '\\' . $_ : $_ } @params )
+        . ");\n";
+    $ret .= "sub $subname { \n"
+        . ( $mode eq 'test' ? "use strict;\n" : '' )
+        . $method_body . "\n}";
+    return $ret;
+}
+
+sub generate_signature { 
+   my $class_obj = shift;
+   my @params = @{(shift)};
+   my $code = shift;
+
+    my $ret  = join(
+        "\n",
+        ( $class_obj ? '  my '.$class_obj." = shift;" :""),
+        map {
+            my $var = $_;
+            if ( $var =~ /^(\%|\@)(.*)$/) {
+                my $sigil = $1;
+                my $name =  $2;
+                "   my ".$var." = ".$sigil."{(shift)};";
+            } else {
+            "   my $var = shift;";
+            }
+            }  @params
+        )
+        . "\n\n"
+        . $code;
+    return $ret;
+}


More information about the Rt-commit mailing list