<body><div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000">
                                        I think we should extract and move those search algorithms to SystemNavigation so that we can use them without having to open a dialog box.<div><br></div><div>Best,</div><div>Marcel</div><div class="mb_sig"></div><blockquote class="history_container" type="cite" style="border-left-style:solid;border-width:1px; margin-top:20px; margin-left:0px;padding-left:10px;">
                        <p style="color: #AAAAAA; margin-top: 10px;">Am 21.07.2019 09:29:14 schrieb Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:</p><div style="font-family:Arial,Helvetica,sans-serif">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le mer. 17 juil. 2019 à 08:18, <<a href="mailto:commits@source.squeak.org">commits@source.squeak.org</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Marcel Taeumel uploaded a new version of ToolBuilder-Kernel to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/ToolBuilder-Kernel-ul.128.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/trunk/ToolBuilder-Kernel-ul.128.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: ToolBuilder-Kernel-ul.128<br>
Author: ul<br>
Time: 16 July 2019, 11:36:38.782463 pm<br>
UUID: 7153b8e4-a085-4af2-b2a8-3f14585475b0<br>
Ancestors: ToolBuilder-Kernel-mt.127<br>
<br>
Further improvements:<br>
- do not convert potentialNames from Array to OrderedCollection<br>
- removed unnecessary ifEmpty: check<br>
- use #indexOf:startingAt: to search for a single character in a string<br>
- applied JIT tricks<br>
- simplified/restructured wildcard/feature-based searches<br>
<br>
Ideas not implemented:<br>
- suggestedTypeNames could become suggestedTypeNamesDo:<br>
<br>
=============== Diff against ToolBuilder-Kernel-mt.127 ===============<br>
<br>
Item was changed:<br>
  ----- Method: UIManager>>classOrTraitFrom:pattern:label: (in category 'system introspecting') -----<br>
  classOrTraitFrom: environment pattern: pattern label: label<br>
        "Given a pattern and an environment, try to find a class or trait using several strategies:<br>
                - EXACT: If there is a class or trait whose name exactly given by pattern, return it.<br>
                - UPPER: If the pattern is upper-case only, find camel-case letters with that sequence.<br>
                - WILD: Try the pattern as-is for regular wild-card search.<br>
                - FEATURE: Split patterns at feature boundaries and insert wild cards between.<br>
                - FUZZY: Split patterns at feature boundaries BUT treat each feature as a full class name.<br>
        If there is only one class or trait in the given environment whose name matches pattern, return it. Otherwise, put up a menu offering the names of all classes that match pattern, and return the class chosen, else nil if nothing chosen.<br>
<br>
        !!!! In any case, separator characters in the pattern are ignored."<br>
<br>
        | toMatch potentialNames names selectedIndex |<br>
<br>
        "If there's a class or trait named as pattern, then return it."<br>
        (environment classOrTraitNamed: pattern) ifNotNil: [:classOrTrait | ^ classOrTrait].<br>
<br>
        "Validate pattern."     <br>
        toMatch := pattern copyWithoutAll: Character separators.<br></blockquote><div>Note that pattern copyWithoutAll: CharacterSet separators is a tiny bit faster than Character separators.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
        toMatch := toMatch asLowercase copyWithout: $..<br>
        toMatch ifEmpty: [ ^nil ].<br>
<br>
        "Fetch search space."<br>
        names := OrderedCollection new.<br>
+       potentialNames := environment classAndTraitNames.<br>
-       potentialNames := environment classAndTraitNames asOrderedCollection.<br>
<br>
        "Try uppercase-only patterns for patterns such as 'WKD' to find 'WeakIdentityKeyDictionary' etc."<br>
+       (pattern allSatisfy: [:char | char isUppercase]) ifTrue: [<br>
+               | patternSize |<br>
+               patternSize := pattern size.<br>
+               potentialNames do: [ :eachName | <br>
+                       | lookupIndex characterIndex |<br>
+                       lookupIndex := 0.<br>
+                       characterIndex := 1.<br>
+                       [ (lookupIndex := eachName<br>
+                                       indexOf: (pattern at: characterIndex)<br>
+                                       startingAt: lookupIndex + 1) > 0<br>
+                               and: [ (characterIndex := characterIndex + 1) <= patternSize ] ] whileTrue.<br>
+                       lookupIndex > 0 ifTrue: [ names add: eachName ] ] ].<br>
-       names ifEmpty: [<br>
-               (pattern allSatisfy: [:char | char isUppercase]) ifTrue: [              <br>
-                       (potentialNames do: [:eachName | <br>
-                               | isMatch lookupIndex |<br>
-                               isMatch := true.<br>
-                               lookupIndex := 0.<br>
-                               1 to: pattern size do: [:charIndex | | char |<br>
-                                       char := pattern at: charIndex.<br>
-                                       isMatch ifTrue: [<br>
-                                               lookupIndex := (eachName findString: char asString startingAt: lookupIndex+1 caseSensitive: true).<br>
-                                               isMatch := lookupIndex > 0]].<br>
-                               isMatch ifTrue: [names add: eachName] ])]].<br>
<br>
        "Try wildcard search for patterns such as 'Weak*Dict*' to find 'WeakIdentityKeyDictionary' etc."<br>
        names ifEmpty: [<br>
+               potentialNames do: [ :each | (toMatch match: each) ifTrue: [ names add: each ] ].<br>
+               "Try feature-based search for patterns such as 'WeakDict' to find 'WeakIdentityKeyDictionary' etc."<br>
+               names ifEmpty: [<br>
-               potentialNames do: [ :each | (toMatch match: each) ifTrue: [names add: each] ]].<br>
-       <br>
-       "Try feature-based search for patterns such as 'WeakDict' to find 'WeakIdentityKeyDictionary' etc."<br>
-       names ifEmpty: [<br>
-               toMatch := pattern copyWithoutAll: '.*#'.<br>
-               toMatch findFeatures in: [:features |<br>
                        "1) Insert wildcards between features and at the end."<br>
+                       toMatch := ((pattern copyWithoutAll: '.*#') findFeatures joinSeparatedBy: '*'), '*'.<br>
+                       potentialNames do: [ :each | (toMatch match: each) ifTrue: [ names add: each ] ].<br>
-                       toMatch := (features joinSeparatedBy: '*'), '*'.<br>
-                       names := potentialNames select: [ :each | toMatch match: each ].<br>
                        names ifEmpty: [        <br>
                                "2) Insert wildcards before, between, and after features."<br>
+                               toMatch := '*', toMatch.<br>
+                               potentialNames do: [ :each | (toMatch match: each) ifTrue: [ names add: each ] ] ] ] ].<br>
-                               toMatch := '*', (features joinSeparatedBy: '*'), '*'.<br>
-                               names := potentialNames select: [ :each | toMatch match: each ] ]] ].<br>
<br>
        "Try some fuzzy matching."<br>
+       pattern suggestedTypeNames do: [ :each |<br>
+               (potentialNames includes: each) ifTrue: [ names add: each ] ].<br>
-       names addAll: (pattern suggestedTypeNames select: [ :each | potentialNames includes: each ]).<br>
<br>
        "Still no match?"<br>
+       names ifEmpty: [ ^nil ].<br>
-       names ifEmpty: [ ^ nil ].<br>
<br>
        "Let the user select if there's more than one possible match. This may give surprising results."        <br>
        selectedIndex := names size = 1<br>
                ifTrue: [ 1 ]<br>
                ifFalse: [ self chooseFrom: names title: label ].<br>
        selectedIndex = 0 ifTrue: [ ^nil ].<br>
        ^environment at: (names at: selectedIndex) asSymbol!<br>
<br>
<br>
</blockquote></div></div>
</div></blockquote>
                                        </div></body>