Tools__MethodRewriter.st
changeset 15200 9e2705b68633
parent 14388 8f404d61e5c8
child 15202 31fdbb042c81
--- a/Tools__MethodRewriter.st	Wed Feb 04 23:08:13 2015 +0100
+++ b/Tools__MethodRewriter.st	Wed Feb 04 23:34:40 2015 +0100
@@ -32,7 +32,10 @@
 		actionInProgresHolder infoHolder progressHolder
 		templateSearchPatternHolder templateReplacePatternHolder
 		selectedTemplateIndex templates selectedTabIndex
-		selectedClassesHolder'
+		selectedClassesHolder selectedRuleIndex rules
+		ruleReplacePatternHolder ruleSearchPatternHolder
+		ruleSearchAndReplacePatternHolder ruleForRewriteOrNilForAdHoc
+		adHocFindAndReplaceVisibleHolder ruleNameHolder'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Interface-MethodRewriter'
@@ -102,6 +105,14 @@
     "Created: / 04-07-2011 / 19:25:06 / cg"
 !
 
+templateReplaceIfNotNilByNotNilIfTrue
+
+    ^Array 
+        with:('Replace ','ifNotNil:' allBold,' by ','notNil ifTrue:' allBold)
+        with: '``@receiver ifNotNil: ``@block'
+        with: '``@receiver notNil ifTrue: ``@block'
+!
+
 templateReplaceIsNilOrEmptyCollectionByIsEmptyOrNil
 
     ^Array 
@@ -139,17 +150,20 @@
 !
 
 templates
+    "finds all methods here, which start with 'template'"
 
-    |templateSelectors|
+    |templateSelectors templatesHere|
 
     templateSelectors := 
         (self class selectors select:[:e|(e startsWith:'template') 
             and:[e ~= #templates and:[e ~= #templatesSpec]]]).
-    ^templateSelectors 
-        collect:[:e|self perform:e]
+
+    templatesHere := templateSelectors collect:[:e| (self perform:e) copyWith:nil ].
+    templatesHere := templatesHere sort:[:a :b | a first < b first].
+    ^ templatesHere 
 
     "
-        self templates
+     self templates
     "
 
     "Created: / 12-12-2007 / 11:03:32 / janfrog"
@@ -172,56 +186,210 @@
     <resource: #canvas>
 
     ^ 
-     #(FullSpec
-        name: classesSpec
-        window: 
-       (WindowSpec
-          label: 'Classes'
-          name: 'Classes'
-          min: (Point 10 10)
-          bounds: (Rectangle 0 0 300 300)
-        )
-        component: 
-       (SpecCollection
-          collection: (
-           (LabelSpec
-              label: 'Hint: drag''n''drop classes from browser'
-              name: 'HintLabel'
-              layout: (LayoutFrame 0 0 0 0 0 1 30 0)
-              translateLabel: true
-              adjust: left
-            )
-           (SelectionInListModelViewSpec
-              name: 'ClassesList'
-              layout: (LayoutFrame 0 0 30 0 0 1 -30 1)
-              model: selectedClassesHolder
-              hasHorizontalScrollBar: true
-              hasVerticalScrollBar: true
-              listModel: classes
-              multipleSelectOk: true
-              useIndex: false
-              highlightMode: line
-              properties: 
-             (PropertyListDictionary
-                dragArgument: nil
-                dropArgument: nil
-                canDropSelector: canDropClasses:
-                dropSelector: doDropClasses:
-              )
-            )
-           (ActionButtonSpec
-              label: 'Remove selected classes'
-              name: 'RemoveClassesButton'
-              layout: (LayoutFrame 5 0 -25 1 -5 1 -5 1)
-              translateLabel: true
-              model: removeSeletedClassesAction
-            )
+    #(FullSpec
+       name: classesSpec
+       window: 
+      (WindowSpec
+         label: 'Classes'
+         name: 'Classes'
+         min: (Point 10 10)
+         bounds: (Rectangle 0 0 300 300)
+       )
+       component: 
+      (SpecCollection
+         collection: (
+          (LabelSpec
+             label: 'Hint: drag''n''drop classes from browser'
+             name: 'HintLabel'
+             layout: (LayoutFrame 0 0 0 0 0 1 30 0)
+             translateLabel: true
+             adjust: left
+           )
+          (SelectionInListModelViewSpec
+             name: 'ClassesList'
+             layout: (LayoutFrame 0 0 30 0 0 1 -30 1)
+             model: selectedClassesHolder
+             hasHorizontalScrollBar: true
+             hasVerticalScrollBar: true
+             listModel: classes
+             multipleSelectOk: true
+             useIndex: false
+             highlightMode: line
+             properties: 
+            (PropertyListDictionary
+               canDropSelector: canDropClasses:
+               dropArgument: nil
+               dropSelector: doDropClasses:
+               dragArgument: nil
+             )
+           )
+          (HorizontalPanelViewSpec
+             name: 'HorizontalPanel1'
+             layout: (LayoutFrame 0 0 -30 1 -16 1 0 1)
+             horizontalLayout: center
+             verticalLayout: center
+             horizontalSpace: 3
+             verticalSpace: 3
+             component: 
+            (SpecCollection
+               collection: (
+                (ActionButtonSpec
+                   label: 'Remove Selected Classes'
+                   name: 'RemoveClassesButton'
+                   translateLabel: true
+                   model: removeSeletedClassesAction
+                   useDefaultExtent: true
+                 )
+                )
+              
+             )
+             keepSpaceForOSXResizeHandleH: true
+           )
+          )
+        
+       )
+     )
+!
+
+howToUseSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:Tools::MethodRewriter andSelector:#howToUseSpec
+     Tools::MethodRewriter new openInterface:#howToUseSpec
+    "
+
+    <resource: #canvas>
+
+    ^ 
+    #(FullSpec
+       name: howToUseSpec
+       window: 
+      (WindowSpec
+         label: 'Classes'
+         name: 'Classes'
+         min: (Point 10 10)
+         bounds: (Rectangle 0 0 300 300)
+       )
+       component: 
+      (SpecCollection
+         collection: (
+          (HTMLViewSpec
+             name: 'HTMLBrowser1'
+             layout: (LayoutFrame 0 0 0 0 0 1 0 1)
+             model: howToUseRewriteToolURL
+             hasHorizontalScrollBar: true
+             hasVerticalScrollBar: true
            )
-         
-        )
-      )
+          )
+        
+       )
+     )
+!
+
+rulesSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:Tools::MethodRewriter andSelector:#rulesSpec
+     Tools::MethodRewriter new openInterface:#rulesSpec
+    "
+
+    <resource: #canvas>
 
-    "Modified: / 12-12-2007 / 12:07:17 / janfrog"
+    ^ 
+    #(FullSpec
+       name: rulesSpec
+       window: 
+      (WindowSpec
+         label: 'Method Rewriter'
+         name: 'Method Rewriter'
+         min: (Point 10 10)
+         bounds: (Rectangle 0 0 472 354)
+       )
+       component: 
+      (SpecCollection
+         collection: (
+          (VariableVerticalPanelSpec
+             name: 'FindAndReplacePanel'
+             layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
+             showHandle: true
+             snapMode: both
+             component: 
+            (SpecCollection
+               collection: (
+                (SelectionInListModelViewSpec
+                   name: 'SelectionInListModelView1'
+                   model: selectedRuleIndex
+                   hasHorizontalScrollBar: true
+                   hasVerticalScrollBar: true
+                   listModel: ruleNameList
+                   highlightMode: line
+                 )
+                (ViewSpec
+                   name: 'ReplaceBox'
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (LabelSpec
+                         label: 'Finds and Replaces With:'
+                         name: 'ReplaceLabel'
+                         layout: (LayoutFrame 0 0 0 0 0 1 20 0)
+                         translateLabel: true
+                         adjust: left
+                       )
+                      (TextEditorSpec
+                         name: 'ReplaceText'
+                         layout: (LayoutFrame 0 0 20 0 0 1 0 1)
+                         model: ruleSearchAndReplacePatternHolder
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         isReadOnly: true
+                         hasKeyboardFocusInitially: false
+                       )
+                      )
+                    
+                   )
+                 )
+                )
+              
+             )
+             handles: (Any 0.5 1.0)
+           )
+          (HorizontalPanelViewSpec
+             name: 'HorizontalPanel1'
+             layout: (LayoutFrame 0 0 -30 1 -16 1 0 1)
+             horizontalLayout: center
+             verticalLayout: center
+             horizontalSpace: 3
+             verticalSpace: 3
+             component: 
+            (SpecCollection
+               collection: (
+                (ActionButtonSpec
+                   label: 'Use Rule'
+                   name: 'UseAsRuleButton'
+                   translateLabel: true
+                   model: useAsRuleAction
+                   useDefaultExtent: true
+                 )
+                )
+              
+             )
+             keepSpaceForOSXResizeHandleH: true
+           )
+          )
+        
+       )
+     )
 !
 
 searchAndReplaceSpec
@@ -239,112 +407,197 @@
     <resource: #canvas>
 
     ^ 
-     #(FullSpec
-        name: searchAndReplaceSpec
-        window: 
-       (WindowSpec
-          label: 'Method Rewriter'
-          name: 'Method Rewriter'
-          min: (Point 10 10)
-          bounds: (Rectangle 0 0 418 294)
-        )
-        component: 
-       (SpecCollection
-          collection: (
-           (VariableVerticalPanelSpec
-              name: 'FindAndReplacePanel'
-              layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
-              showHandle: true
-              snapMode: both
-              component: 
-             (SpecCollection
-                collection: (
-                 (ViewSpec
-                    name: 'FindBox'
-                    component: 
-                   (SpecCollection
-                      collection: (
-                       (LabelSpec
-                          label: 'Find:'
-                          name: 'FindLabel'
-                          layout: (LayoutFrame 0 0 0 0 0 1 20 0)
-                          translateLabel: true
-                          adjust: left
-                        )
-                       (TextEditorSpec
-                          name: 'FindText'
-                          layout: (LayoutFrame 0 0 20 0 0 1 0 1)
-                          hasHorizontalScrollBar: true
-                          hasVerticalScrollBar: true
-                          postBuildCallback: postBuildFindTextView:
-                        )
+    #(FullSpec
+       name: searchAndReplaceSpec
+       window: 
+      (WindowSpec
+         label: 'Method Rewriter'
+         name: 'Method Rewriter'
+         min: (Point 10 10)
+         bounds: (Rectangle 0 0 418 294)
+       )
+       component: 
+      (SpecCollection
+         collection: (
+          (VariableVerticalPanelSpec
+             name: 'FindAndReplacePanel'
+             layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
+             visibilityChannel: adHocFindAndReplaceVisibleHolder
+             showHandle: true
+             snapMode: both
+             component: 
+            (SpecCollection
+               collection: (
+                (ViewSpec
+                   name: 'FindBox'
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (LabelSpec
+                         label: 'Find:'
+                         name: 'FindLabel'
+                         layout: (LayoutFrame 0 0 0 0 0 1 20 0)
+                         translateLabel: true
+                         adjust: left
+                       )
+                      (TextEditorSpec
+                         name: 'FindText'
+                         layout: (LayoutFrame 0 0 20 0 0 1 0 1)
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         hasKeyboardFocusInitially: false
+                         postBuildCallback: postBuildFindTextView:
+                       )
+                      )
+                    
+                   )
+                 )
+                (ViewSpec
+                   name: 'ReplaceBox'
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (LabelSpec
+                         label: 'Replace with:'
+                         name: 'ReplaceLabel'
+                         layout: (LayoutFrame 0 0 0 0 0 1 20 0)
+                         translateLabel: true
+                         adjust: left
+                       )
+                      (TextEditorSpec
+                         name: 'ReplaceText'
+                         layout: (LayoutFrame 0 0 20 0 0 1 0 1)
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         hasKeyboardFocusInitially: false
+                         postBuildCallback: postBuildReplaceTextView:
                        )
-                     
-                    )
-                  )
-                 (ViewSpec
-                    name: 'ReplaceBox'
-                    component: 
-                   (SpecCollection
-                      collection: (
-                       (LabelSpec
-                          label: 'Replace with:'
-                          name: 'ReplaceLabel'
-                          layout: (LayoutFrame 0 0 0 0 0 1 20 0)
-                          translateLabel: true
-                          adjust: left
-                        )
-                       (TextEditorSpec
-                          name: 'ReplaceText'
-                          layout: (LayoutFrame 0 0 20 0 0 1 0 1)
-                          hasHorizontalScrollBar: true
-                          hasVerticalScrollBar: true
-                          postBuildCallback: postBuildReplaceTextView:
-                        )
-                       )
-                     
-                    )
-                  )
+                      )
+                    
+                   )
+                 )
+                )
+              
+             )
+             handles: (Any 0.5 1.0)
+           )
+          (ViewSpec
+             name: 'ExecuteRuleBox'
+             layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
+             visibilityChannel: ruleExecutionVisibleHolder
+             component: 
+            (SpecCollection
+               collection: (
+                (LabelSpec
+                   label: 'Rule:'
+                   name: 'Label2'
+                   layout: (LayoutFrame 0 0 0 0 100 0 25 0)
+                   translateLabel: true
+                   adjust: left
+                 )
+                (LabelSpec
+                   name: 'Label4'
+                   layout: (LayoutFrame 100 0 0 0 0 1 25 0)
+                   translateLabel: true
+                   labelChannel: ruleNameHolder
+                 )
+                (TextEditorSpec
+                   name: 'TextEditor1'
+                   layout: (LayoutFrame 0 0 25 0 0 1 0 1)
+                   model: ruleSearchAndReplacePatternHolder
+                   hasHorizontalScrollBar: true
+                   hasVerticalScrollBar: true
+                   isReadOnly: true
+                   hasKeyboardFocusInitially: false
+                 )
+                )
+              
+             )
+           )
+          (ViewSpec
+             name: 'Box1'
+             layout: (LayoutFrame 0 0 -30 1 -16 1 0 1)
+             component: 
+            (SpecCollection
+               collection: (
+                (LabelSpec
+                   label: 'Enjoy'
+                   name: 'Label1'
+                   layout: (LayoutFrame 5 0 -25 1 205 0 -5 1)
+                   visibilityChannel: actionInProgresHolder
+                   translateLabel: true
+                   labelChannel: infoHolder
+                   adjust: left
+                 )
+                (ProgressIndicatorSpec
+                   name: 'ProgressIndicator1'
+                   layout: (LayoutFrame 210 0 -25 1 -215 1 -5 1)
+                   visibilityChannel: actionInProgresHolder
+                   model: progressHolder
                  )
-               
-              )
-              handles: (Any 0.5 1.0)
-            )
-           (LabelSpec
-              label: 'Enjoy'
-              name: 'InfoLabel'
-              layout: (LayoutFrame 5 0 -25 1 205 0 -5 1)
-              visibilityChannel: actionInProgresHolder
-              translateLabel: true
-              labelChannel: infoHolder
-              adjust: left
-            )
-           (ProgressIndicatorSpec
-              name: 'ProgressIndicator'
-              layout: (LayoutFrame 210 0 -25 1 -215 1 -5 1)
-              visibilityChannel: actionInProgresHolder
-              model: progressHolder
-            )
-           (ActionButtonSpec
-              label: 'Search'
-              name: 'SearchButton'
-              layout: (LayoutFrame -210 1 -25 1 -110 1 -5 1)
-              translateLabel: true
-              model: doSearchAction
-            )
-           (ActionButtonSpec
-              label: 'Rewrite'
-              name: 'RewriteButton'
-              layout: (LayoutFrame -105 1 -25 1 -5 1 -5 1)
-              translateLabel: true
-              model: doRewriteAction
-            )
+                (ActionButtonSpec
+                   label: 'Search'
+                   name: 'Button2'
+                   layout: (LayoutFrame -210 1 -26 1 -110 1 -5 1)
+                   translateLabel: true
+                   model: doSearchAction
+                 )
+                (ActionButtonSpec
+                   label: 'Rewrite'
+                   name: 'Button1'
+                   layout: (LayoutFrame -105 1 -25 1 -5 1 -5 1)
+                   translateLabel: true
+                   model: doRewriteAction
+                 )
+                )
+              
+             )
+             keepSpaceForOSXResizeHandleH: true
            )
-         
-        )
-      )
+          )
+        
+       )
+     )
+!
+
+searchPatternHelpSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:Tools::MethodRewriter andSelector:#searchPatternHelpSpec
+     Tools::MethodRewriter new openInterface:#searchPatternHelpSpec
+    "
+
+    <resource: #canvas>
 
-    "Modified: / 12-12-2007 / 11:15:58 / janfrog"
+    ^ 
+    #(FullSpec
+       name: searchPatternHelpSpec
+       window: 
+      (WindowSpec
+         label: 'Classes'
+         name: 'Classes'
+         min: (Point 10 10)
+         bounds: (Rectangle 0 0 300 300)
+       )
+       component: 
+      (SpecCollection
+         collection: (
+          (HTMLViewSpec
+             name: 'HTMLBrowser1'
+             layout: (LayoutFrame 0 0 0 0 0 1 0 1)
+             model: searchPatternHelpURL
+             hasHorizontalScrollBar: true
+             hasVerticalScrollBar: true
+           )
+          )
+        
+       )
+     )
 !
 
 templatesSpec
@@ -362,98 +615,115 @@
     <resource: #canvas>
 
     ^ 
-     #(FullSpec
-        name: templatesSpec
-        window: 
-       (WindowSpec
-          label: 'Method Rewriter'
-          name: 'Method Rewriter'
-          min: (Point 10 10)
-          bounds: (Rectangle 0 0 472 354)
-        )
-        component: 
-       (SpecCollection
-          collection: (
-           (VariableVerticalPanelSpec
-              name: 'FindAndReplacePanel'
-              layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
-              showHandle: true
-              snapMode: both
-              component: 
-             (SpecCollection
-                collection: (
-                 (SelectionInListModelViewSpec
-                    name: 'SelectionInListModelView1'
-                    model: selectedTemplateIndex
-                    hasHorizontalScrollBar: true
-                    hasVerticalScrollBar: true
-                    listModel: templateNameList
-                    highlightMode: line
-                  )
-                 (ViewSpec
-                    name: 'FindBox'
-                    component: 
-                   (SpecCollection
-                      collection: (
-                       (LabelSpec
-                          label: 'Find:'
-                          name: 'FindLabel'
-                          layout: (LayoutFrame 0 0 0 0 0 1 20 0)
-                          translateLabel: true
-                          adjust: left
-                        )
-                       (TextEditorSpec
-                          name: 'FindText'
-                          layout: (LayoutFrame 0 0 20 0 0 1 0 1)
-                          model: templateSearchPatternHolder
-                          hasHorizontalScrollBar: true
-                          hasVerticalScrollBar: true
-                        )
+    #(FullSpec
+       name: templatesSpec
+       window: 
+      (WindowSpec
+         label: 'Method Rewriter'
+         name: 'Method Rewriter'
+         min: (Point 10 10)
+         bounds: (Rectangle 0 0 472 354)
+       )
+       component: 
+      (SpecCollection
+         collection: (
+          (VariableVerticalPanelSpec
+             name: 'FindAndReplacePanel'
+             layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
+             showHandle: true
+             snapMode: both
+             component: 
+            (SpecCollection
+               collection: (
+                (SelectionInListModelViewSpec
+                   name: 'SelectionInListModelView1'
+                   model: selectedTemplateIndex
+                   hasHorizontalScrollBar: true
+                   hasVerticalScrollBar: true
+                   listModel: templateNameList
+                   highlightMode: line
+                 )
+                (ViewSpec
+                   name: 'FindBox'
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (LabelSpec
+                         label: 'Find:'
+                         name: 'FindLabel'
+                         layout: (LayoutFrame 0 0 0 0 0 1 20 0)
+                         translateLabel: true
+                         adjust: left
+                       )
+                      (TextEditorSpec
+                         name: 'FindText'
+                         layout: (LayoutFrame 0 0 20 0 0 1 0 1)
+                         enableChannel: templateSearchPatternIsEditable
+                         model: templateSearchPatternHolder
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         hasKeyboardFocusInitially: false
                        )
-                     
-                    )
-                  )
-                 (ViewSpec
-                    name: 'ReplaceBox'
-                    component: 
-                   (SpecCollection
-                      collection: (
-                       (LabelSpec
-                          label: 'Replace with:'
-                          name: 'ReplaceLabel'
-                          layout: (LayoutFrame 0 0 0 0 0 1 20 0)
-                          translateLabel: true
-                          adjust: left
-                        )
-                       (TextEditorSpec
-                          name: 'ReplaceText'
-                          layout: (LayoutFrame 0 0 20 0 0 1 0 1)
-                          model: templateReplacePatternHolder
-                          hasHorizontalScrollBar: true
-                          hasVerticalScrollBar: true
-                        )
+                      )
+                    
+                   )
+                 )
+                (ViewSpec
+                   name: 'ReplaceBox'
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (LabelSpec
+                         label: 'Replace With:'
+                         name: 'ReplaceLabel'
+                         layout: (LayoutFrame 0 0 0 0 0 1 20 0)
+                         translateLabel: true
+                         adjust: left
+                       )
+                      (TextEditorSpec
+                         name: 'ReplaceText'
+                         layout: (LayoutFrame 0 0 20 0 0 1 0 1)
+                         enableChannel: templateReplacePatternIsEditable
+                         model: templateReplacePatternHolder
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         hasKeyboardFocusInitially: false
                        )
-                     
-                    )
-                  )
+                      )
+                    
+                   )
                  )
-               
-              )
-              handles: (Any 0.2 0.6 1.0)
-            )
-           (ActionButtonSpec
-              label: 'Use as template'
-              name: 'UseAsTemplateButton'
-              layout: (LayoutFrame 0 0 -25 1 -5 1 -5 1)
-              translateLabel: true
-              model: useAsTemplateAction
-            )
+                )
+              
+             )
+             handles: (Any 0.20000000000000001 0.59999999999999998 1.0)
            )
-         
-        )
-      )
-
-    "Modified: / 12-12-2007 / 11:23:34 / janfrog"
+          (HorizontalPanelViewSpec
+             name: 'HorizontalPanel1'
+             layout: (LayoutFrame 0 0 -30 1 -16 1 0 1)
+             horizontalLayout: center
+             verticalLayout: center
+             horizontalSpace: 3
+             verticalSpace: 3
+             component: 
+            (SpecCollection
+               collection: (
+                (ActionButtonSpec
+                   label: 'Use as Template'
+                   name: 'UseAsTemplateButton'
+                   translateLabel: true
+                   model: useAsTemplateAction
+                   useDefaultExtent: true
+                 )
+                )
+              
+             )
+             keepSpaceForOSXResizeHandleH: true
+           )
+          )
+        
+       )
+     )
 !
 
 windowSpec
@@ -531,6 +801,21 @@
           createNewBuilder: false
           minorKey: templatesSpec
         )
+       (TabItem
+          label: 'Existing Rules'
+          createNewBuilder: false
+          minorKey: rulesSpec
+        )
+       (TabItem
+          label: 'How To Use This Tool'
+          createNewBuilder: false
+          minorKey: howToUseSpec
+        )
+       (TabItem
+          label: 'Pattern Info'
+          createNewBuilder: false
+          minorKey: searchPatternHelpSpec
+        )
        )
      
       collect:[:aTab| TabItem new fromLiteralArrayEncoding:aTab ]
@@ -586,6 +871,52 @@
     "Created: / 12-12-2007 / 11:38:22 / janfrog"
 !
 
+ruleTemplate
+
+    ^self rules at:self selectedRuleIndex value
+!
+
+rules
+    rules isNil ifTrue:[
+        |knownRules separator1 separator2 separator3|
+
+        "/ construct a pseudo list from existing transformation rules
+        separator1 := '----------- search for:' asText colorizeAllWith:Color grey.
+        separator2 := '----------- replace by:' asText colorizeAllWith:Color grey.   
+        separator3 := '\=================================================================================\' withCRs asText colorizeAllWith:Color grey.
+
+        knownRules := OrderedCollection new.
+        (RBTransformationRule allSubclasses asNewOrderedCollection sort:[:a :b | a basicNew name < b basicNew name]) 
+        do:[:each |
+            |rule | 
+
+            rule := each new.
+            knownRules add:{ rule .
+                             (rule rewriteRule searches 
+                                collectAll:[:each |
+                                    { 
+                                      separator1.
+                                      each searchString 
+                                        asText backgroundColorizeAllWith:(Color red lightened lightened lightened) .
+                                      separator2.
+                                      each replaceString asText 
+                                        asText backgroundColorizeAllWith:(Color green lightened lightened lightened) .
+                                      separator3
+                                    }
+                                ]
+                             ) asStringCollection asString.
+                           }
+        ].
+
+        rules := knownRules
+    ].
+    ^ rules
+
+    "
+     self new rules
+    "
+!
+
 searchPattern
     ^ searchTextView contents trimSeparators
 
@@ -606,6 +937,16 @@
     "Created: / 12-12-2007 / 12:02:03 / janfrog"
 !
 
+selectedRule
+
+    ^self selectedRuleSpec first
+!
+
+selectedRuleSpec
+
+    ^self rules at:(self selectedRuleIndex value)
+!
+
 selectedTemplate
 
     ^self templates at:self selectedTemplateIndex value
@@ -624,45 +965,6 @@
 
 !MethodRewriter methodsFor:'actions'!
 
-doRewrite
-    | methodsMatching anyChange compositeChangeCollector |
-
-    compositeChangeCollector := CompositeRefactoryChange new.
-    compositeChangeCollector name:'Rewrite Change'.
-
-    anyChange := false.
-
-    methodsMatching := self methodsMatching.
-    methodsMatching isEmptyOrNil ifTrue:[^Dialog warn:'No methods matching'].
-    methodsMatching do:[:mth|
-        | newTree change |
-
-        newTree := ParseTreeRewriter new
-                    replace: self searchPattern 
-                    with: self replacePattern;
-                    executeTree: mth parseTree;
-                    tree.
-
-        change := InteractiveAddMethodChange compile:(newTree formattedCode) in:mth mclass classified:mth category.
-
-        "/ collect in order to have only one change in the undo-list (instead of many)
-        compositeChangeCollector addChange:change.
-        anyChange := true.
-
-"/        mth mclass 
-"/            compile: newTree formattedCode
-"/            classified: mth category
-    ].
-
-    anyChange ifTrue:[
-        RefactoryChangeManager performChange:compositeChangeCollector.
-    ].
-
-    "Created: / 20-07-2007 / 16:03:47 / janfrog"
-    "Modified: / 21-07-2007 / 06:55:42 / janfrog"
-    "Modified: / 04-08-2011 / 19:05:25 / cg"
-!
-
 doRewrite: methodsMatching
     | changes compositeChangeCollector |
 
@@ -709,41 +1011,54 @@
 
 doRewriteAction
 
-    self doSearch: self searchPattern withResultDo: [:methodsMatching|
-        self doRewrite:  methodsMatching
+    self replacePattern isEmptyOrNil ifTrue:[
+        (Dialog confirm:'No replace-pattern given.\\Proceed to delete that code.') ifFalse:[
+            AbortSignal raise
+        ].
     ].
 
+    self 
+        doSearchPattern: self searchPattern 
+        withResultDo: [:methodsMatching|
+            self doRewrite:  methodsMatching
+        ].
+
     "Created: / 12-12-2007 / 11:14:19 / janfrog"
     "Modified: / 22-03-2012 / 18:23:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-doSearch
-    |methods|
-
-    methods := self methodsMatching.
-    methods isEmpty 
-        ifTrue:
-            [Dialog warn:'Nothing found']
-        ifFalse:
-            [self showMethods:methods
-                  title:'Methods matching ' , self searchPattern]
+doSearchAction
+    |methods what|
 
-    "Created: / 20-07-2007 / 16:08:08 / janfrog"
-    "Modified: / 21-07-2007 / 06:51:58 / janfrog"
-!
-
-doSearchAction
-
-   self 
-        doSearch: self searchPattern 
-        withResultDo: 
-            [:matchingMethods|
-            matchingMethods isEmpty
-                ifTrue:[Dialog warn:'No methods found']
-                ifFalse:
-                    [self
-                        showMethods: matchingMethods asArray
-                        title: 'Methods matching ', self searchPattern]]
+    ruleForRewriteOrNilForAdHoc notNil ifTrue:[
+       self 
+            doSearchRule: self selectedRule 
+            withResultDo:[:matchingMethods|
+                matchingMethods isEmpty
+                    ifTrue:[
+                        Dialog warn:'No methods found by rule: ', self selectedRule name
+                    ]
+                    ifFalse:[
+                        self
+                            showMethods: matchingMethods asArray
+                            title: 'Methods matching rule: ', self selectedRule name
+                    ]
+            ]
+    ] ifFalse:[
+       self 
+            doSearchPattern: self searchPattern 
+            withResultDo:[:matchingMethods|
+                matchingMethods isEmpty
+                    ifTrue:[
+                        Dialog warn:'No methods found for search pattern'
+                    ]
+                    ifFalse:[
+                        self
+                            showMethods: matchingMethods asArray
+                            title: 'Methods matching ', self searchPattern
+                    ]
+            ]
+    ]
 
     "Created: / 12-12-2007 / 11:14:25 / janfrog"
 !
@@ -755,8 +1070,17 @@
     "Created: / 12-12-2007 / 12:05:15 / janfrog"
 !
 
+useAsRuleAction
+    self adHocFindAndReplaceVisibleHolder value:false.
+    ruleForRewriteOrNilForAdHoc := self selectedRule.
+    ruleNameHolder value: ruleForRewriteOrNilForAdHoc name.
+    
+    self selectedTabIndex value:1
+!
+
 useAsTemplateAction
-
+    self adHocFindAndReplaceVisibleHolder value:true.
+    ruleForRewriteOrNilForAdHoc := nil. "/ ad hoc
     self searchPattern: self templateSearchPatternHolder value.
     self replacePattern: self templateReplacePatternHolder value.
     self selectedTabIndex value:1
@@ -767,37 +1091,28 @@
 !MethodRewriter methodsFor:'aspects'!
 
 actionInProgresHolder
-    "automatically generated by UIPainter ..."
-
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
-
     actionInProgresHolder isNil ifTrue:[
         actionInProgresHolder := true asValue.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       actionInProgresHolder addDependent:self.
-"/       actionInProgresHolder onChangeSend:#actionInProgresHolderChanged to:self.
     ].
     ^ actionInProgresHolder.
 
     "Created: / 12-12-2007 / 10:00:05 / janfrog"
 !
 
-infoHolder
-    "automatically generated by UIPainter ..."
+adHocFindAndReplaceVisibleHolder
+    adHocFindAndReplaceVisibleHolder isNil ifTrue:[
+        adHocFindAndReplaceVisibleHolder := true asValue.
+    ].
+    ^ adHocFindAndReplaceVisibleHolder.
+!
 
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
+howToUseRewriteToolURL
+    ^ HTMLDocumentFrame documentFileFor:'help/Browser/RewriteToolHelp.html'
+!
 
+infoHolder
     infoHolder isNil ifTrue:[
         infoHolder := 'Really cool tool!!' asValue.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       infoHolder addDependent:self.
-"/       infoHolder onChangeSend:#infoHolderChanged to:self.
     ].
     ^ infoHolder.
 
@@ -806,56 +1121,62 @@
 !
 
 progressHolder
-    "automatically generated by UIPainter ..."
-
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
-
     progressHolder isNil ifTrue:[
         progressHolder := 0 asValue
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       progressHolder addDependent:self.
-"/       progressHolder onChangeSend:#progressHolderChanged to:self.
     ].
     ^ progressHolder.
 
     "Created: / 12-12-2007 / 10:00:05 / janfrog"
 !
 
-selectedClassesHolder
-    "automatically generated by UIPainter ..."
+ruleExecutionVisibleHolder
+    ^ BlockValue forLogicalNot:self adHocFindAndReplaceVisibleHolder 
+!
+
+ruleNameHolder
+    ruleNameHolder isNil ifTrue:[
+        ruleNameHolder := '' asValue.
+    ].
+    ^ ruleNameHolder.
+!
+
+ruleNameList
 
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
+    ^self rules collect:[:ruleSpec | ruleSpec first name ]
+!
 
+ruleSearchAndReplacePatternHolder
+    ruleSearchAndReplacePatternHolder isNil ifTrue:[
+        ruleSearchAndReplacePatternHolder := '' asValue.
+    ].
+    ^ ruleSearchAndReplacePatternHolder.
+!
+
+searchPatternHelpURL
+    ^ HTMLDocumentFrame documentFileFor:'help/Browser/RBSearchPatterns.html'
+!
+
+selectedClassesHolder
     selectedClassesHolder isNil ifTrue:[
         selectedClassesHolder := ValueHolder new.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       selectedClassesHolder addDependent:self.
-"/       selectedClassesHolder onChangeSend:#selectedClassesHolderChanged to:self.
     ].
     ^ selectedClassesHolder.
 
     "Created: / 12-12-2007 / 12:01:40 / janfrog"
 !
 
-selectedTabIndex
-    "automatically generated by UIPainter ..."
+selectedRuleIndex
 
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
+    selectedRuleIndex isNil ifTrue:[
+        selectedRuleIndex := ValueHolder new.
+        selectedRuleIndex onChangeSend:#selectedRuleIndexChanged to:self.
+    ].
+    ^ selectedRuleIndex.
+!
 
+selectedTabIndex
     selectedTabIndex isNil ifTrue:[
         selectedTabIndex := ValueHolder new.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       selectedTabIndex addDependent:self.
-"/       selectedTabIndex onChangeSend:#selectedTabIndexChanged to:self.
     ].
     ^ selectedTabIndex.
 
@@ -894,49 +1215,74 @@
 !
 
 templateReplacePatternHolder
-    "automatically generated by UIPainter ..."
-
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
-
     templateReplacePatternHolder isNil ifTrue:[
         templateReplacePatternHolder := '' asValue.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       templateReplacePatternHolder addDependent:self.
-"/       templateReplacePatternHolder onChangeSend:#templateReplacePatternHolderChanged to:self.
     ].
     ^ templateReplacePatternHolder.
 
     "Created: / 12-12-2007 / 11:17:16 / janfrog"
 !
 
-templateSearchPatternHolder
-    "automatically generated by UIPainter ..."
+templateReplacePatternIsEditable
+    |holder|
 
-    "*** the code below creates a default model when invoked."
-    "*** (which may not be the one you wanted)"
-    "*** Please change as required and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
+    (holder := builder bindingAt:#templateReplacePatternIsEditable) isNil ifTrue:[
+        builder aspectAt:#templateReplacePatternIsEditable put:(holder := true asValue).
+    ].
+    ^ holder.
+!
 
+templateSearchPatternHolder
     templateSearchPatternHolder isNil ifTrue:[
         templateSearchPatternHolder := '' asValue.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       templateSearchPatternHolder addDependent:self.
-"/       templateSearchPatternHolder onChangeSend:#templateSearchPatternHolderChanged to:self.
     ].
     ^ templateSearchPatternHolder.
 
     "Created: / 12-12-2007 / 11:17:16 / janfrog"
+!
+
+templateSearchPatternIsEditable
+    |holder|
+
+    (holder := builder bindingAt:#templateSearchPatternIsEditable) isNil ifTrue:[
+        builder aspectAt:#templateSearchPatternIsEditable put:(holder := true asValue).
+    ].
+    ^ holder.
 ! !
 
 !MethodRewriter methodsFor:'change & update'!
 
+selectedRuleIndexChanged
+    |selectedRuleSpec|
+
+    selectedRuleSpec := self selectedRuleSpec.
+    "/ entries are:
+    "/ 1) rule
+    "/ 2) search & replacement pattern
+
+    self ruleSearchAndReplacePatternHolder value: selectedRuleSpec second.
+!
+
 selectedTemplateIndexChanged
+    |selectedTemplate|
 
-    self templateSearchPatternHolder value: self selectedTemplate second.
-    self templateReplacePatternHolder value: self selectedTemplate third.
+    selectedTemplate := self selectedTemplate.
+    "/ entries are:
+    "/ 1) name
+    "/ 2) search pattern
+    "/ 3) replacement pattern
+    "/ 4) rule or nil; nil for ad-hoc rewrite
+    selectedTemplate fourth isNil ifTrue:[
+        "/ ad hoc
+        self templateReplacePatternIsEditable value:true.
+        self templateSearchPatternIsEditable value:true.
+    ] ifFalse:[
+        "/ existing rule
+        self templateReplacePatternIsEditable value:false.
+        self templateSearchPatternIsEditable value:false.
+    ].
+    self templateSearchPatternHolder value: selectedTemplate second.
+    self templateReplacePatternHolder value: selectedTemplate third.
 
     "Created: / 12-12-2007 / 11:20:16 / janfrog"
 ! !
@@ -987,21 +1333,72 @@
 
 !MethodRewriter methodsFor:'private'!
 
-doSearch: pattern withResultDo: block
+doSearchPattern: pattern withResultDo: block
 
     | matchingMethods |
+
+    pattern isEmptyOrNil ifTrue:[
+        Dialog warn:'No searchpattern given.'.
+        AbortSignal raise
+    ].
+
     matchingMethods := Set new.
     self
-        withMethodsDo:
-            [:mth| | tree |
-            tree := mth parseTree.
-            tree ifNil:[self breakPoint: #jv] ifNotNil:[
-            (ParseTreeSearcher new)
-                matches:self searchPattern do:[:aNode :answer | matchingMethods add:mth ];
-               executeTree: tree]
-            ]
-        finallyDo: 
-            [block value: matchingMethods]
+        withMethodsDo:[:mthd| 
+            | tree |
+            tree := mthd parseTree.
+            tree 
+                ifNil:[
+                    Transcript showCR:'MethodRewriter: parse tree error in ',mthd whoString.
+                    self breakPoint: #jv
+                ] 
+                ifNotNil:[
+                    (ParseTreeSearcher new)
+                        matches:pattern do:[:aNode :answer | matchingMethods add:mthd ];
+                       executeTree: tree
+                ]
+        ]
+        finallyDo:[
+            block value: matchingMethods
+        ]
+
+    "Created: / 12-12-2007 / 10:34:50 / janfrog"
+    "Modified: / 07-04-2011 / 22:02:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doSearchRule: rule withResultDo: block
+
+    | matchingMethods searcher currentMethod|
+
+    rule isNil ifTrue:[
+        Dialog warn:'No rule selected.'.
+        AbortSignal raise
+    ].
+
+    searcher := ParseTreeSearcher new.
+    rule rewriteRule searches do:[:eachSearch |
+        searcher matchesTree:eachSearch searchTree do:[:aNode :answer | matchingMethods add:currentMethod ] 
+    ].
+
+    matchingMethods := Set new.
+    self
+        withMethodsDo:[:mthd| 
+            | tree |
+
+            tree := mthd parseTree.
+            tree 
+                ifNil:[
+                    Transcript showCR:'MethodRewriter: parse tree error in ',mthd whoString.
+                    self breakPoint: #jv
+                ] 
+                ifNotNil:[
+                    currentMethod := mthd.
+                    searcher executeTree: tree
+                ]
+        ]
+        finallyDo:[
+            block value: matchingMethods
+        ]
 
     "Created: / 12-12-2007 / 10:34:50 / janfrog"
     "Modified: / 07-04-2011 / 22:02:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
@@ -1036,18 +1433,17 @@
     "Created: / 21-07-2007 / 06:25:42 / janfrog"
 !
 
-methodsMatching
-
-    ^self methodsMatching: self searchPattern
+methodsMatchingPattern: searchPattern
+    |methods matchingMethods|
 
-    "Created: / 21-07-2007 / 06:26:44 / janfrog"
-!
-
-methodsMatching: searchPattern
-    |matchingMethods|
+    searchPattern isEmptyOrNil ifTrue:[
+        Dialog warn:'No searchpattern given'.
+        AbortSignal raise
+    ].
+    methods := self methodsToSearchOrAbortIfNone.
 
     matchingMethods := OrderedCollection new.
-    self methods do:[:mth | 
+    methods do:[:mth | 
         (ParseTreeSearcher new)
             matches:searchPattern do:[:aNode :answer | matchingMethods add:mth ];
             executeTree:mth parseTree.
@@ -1057,6 +1453,35 @@
     "Created: / 21-07-2007 / 06:26:19 / janfrog"
 !
 
+methodsMatchingRule: rule
+    |methods matchingMethods|
+
+    rule isNil ifTrue:[
+        Dialog warn:'No rule given'.
+        AbortSignal raise
+    ].
+    methods := self methodsToSearchOrAbortIfNone.
+
+    matchingMethods := OrderedCollection new.
+    methods do:[:mth | 
+        |searcher|
+
+        searcher := ParseTreeSearcher new.
+        rule searches halt.
+"/            matches:searchPattern do:[:aNode :answer | matchingMethods add:mth ];
+"/            executeTree:mth parseTree.
+    ].
+    ^ matchingMethods
+!
+
+methodsToSearchOrAbortIfNone
+    (methods := self methods) isEmptyOrNil ifTrue:[
+        Dialog warn:'No methods or classes defined for search'.
+        AbortSignal raise.
+    ].
+    ^ methods
+!
+
 showMethods: methods title: title
 
     NewSystemBrowser 
@@ -1096,7 +1521,7 @@
 withMethodsDo: methodBlock finallyDo: finallyBlock
 
    ^self 
-        withMethods: self methods asArray
+        withMethods: self methodsToSearchOrAbortIfNone asArray
         do: methodBlock
         finallyDo: finallyBlock
 
@@ -1115,10 +1540,10 @@
 !MethodRewriter class methodsFor:'documentation'!
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libtool/Tools__MethodRewriter.st,v 1.19 2014-05-23 08:09:07 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/Tools__MethodRewriter.st,v 1.20 2015-02-04 22:34:40 cg Exp $'
 !
 
 version_SVN
-    ^ '$Id: Tools__MethodRewriter.st,v 1.19 2014-05-23 08:09:07 stefan Exp $'
+    ^ '$Id: Tools__MethodRewriter.st,v 1.20 2015-02-04 22:34:40 cg Exp $'
 ! !