DoWhatIMeanSupport.st
changeset 4386 d5b6d7c0b6ee
parent 4385 d3381caeb327
child 4387 306eac46bcb1
equal deleted inserted replaced
4385:d3381caeb327 4386:d5b6d7c0b6ee
  1017 !DoWhatIMeanSupport class methodsFor:'typing distance'!
  1017 !DoWhatIMeanSupport class methodsFor:'typing distance'!
  1018 
  1018 
  1019 isKey:k1 nextTo:k2
  1019 isKey:k1 nextTo:k2
  1020     "return true, if k1 and k2 are adjacent keys on the keyboard.
  1020     "return true, if k1 and k2 are adjacent keys on the keyboard.
  1021      This is used to specially priorize plausible typing errors of adjacent keys.
  1021      This is used to specially priorize plausible typing errors of adjacent keys.
  1022      CAVEAT: hard coded us- and german keyboards here."
  1022      CAVEAT: hard coded us-, german and french keyboards here; data should come from somewhere else."
  1023 
  1023 
  1024     ^ self isKey:k1 nextTo:k2 onKeyboard:(self keyboard)
  1024     ^ self isKey:k1 nextTo:k2 onKeyboard:(self keyboard)
  1025 
  1025 
  1026     "
  1026     "
  1027      self isKey:$a nextTo:$a   
  1027      self isKey:$a nextTo:$a   
  1052      self isKey:$a nextTo:$x
  1052      self isKey:$a nextTo:$x
  1053     "
  1053     "
  1054 !
  1054 !
  1055 
  1055 
  1056 keyboard
  1056 keyboard
  1057     "the keyboard layout (useful to figure out which keys are nearby a key,
  1057     "the keyboard layout 
  1058      to find possible typing errors)"
  1058      (useful to figure out which keys are nearby a key, to find possible typing errors)
       
  1059      CAVEAT: hard coded us-, german and french keyboards here; data should come from somewhere else."
  1059 
  1060 
  1060     |lang|
  1061     |lang|
  1061 
  1062 
  1062     lang := UserPreferences current language.
  1063     lang := UserPreferences current language.
  1063     lang == #de ifTrue:[
  1064     lang == #de ifTrue:[
  1064         ^ #( 
  1065         ^ #( 
  1065                '1234567890-'
  1066                '1234567890-'
  1066                '*qwertzuiop'
  1067                '*qwertzuiop'
  1067                '**asdfghjkl:'
  1068                '**asdfghjkl:'
  1068                '***yxcvbnm' ).
  1069                '***yxcvbnm' 
       
  1070         ).
  1069     ].
  1071     ].
  1070 
  1072 
  1071     lang == #fr ifTrue:[
  1073     lang == #fr ifTrue:[
  1072         ^ #( 
  1074         ^ #( 
  1073                '1234567890'
  1075                '1234567890'
  1074                '*azertyuiop'
  1076                '*azertyuiop'
  1075                '**qsdfghjklm'
  1077                '**qsdfghjklm'
  1076                '***wxcvbn,' ).
  1078                '***wxcvbn,' 
       
  1079         ).
  1077     ].
  1080     ].
  1078 
  1081 
  1079     ^ #( 
  1082     ^ #( 
  1080            '1234567890-'
  1083            '1234567890-'
  1081            '*qwertyuiop'
  1084            '*qwertyuiop'
  1082            '**asdfghjkl:'
  1085            '**asdfghjkl:'
  1083            '***zxcvbnm' ).
  1086            '***zxcvbnm' 
       
  1087     ).
  1084 
  1088 
  1085     "
  1089     "
  1086      self keyboard 
  1090      self keyboard 
  1087     "
  1091     "
  1088 
  1092 
  1162                 "/ otherwise, a unary message is probably intended to be sent to the variable.
  1166                 "/ otherwise, a unary message is probably intended to be sent to the variable.
  1163                 "/ (however, no character is available to determine what is useful)
  1167                 "/ (however, no character is available to determine what is useful)
  1164                 forceNewMessageSend := true.
  1168                 forceNewMessageSend := true.
  1165             ].
  1169             ].
  1166         ] ifFalse:[
  1170         ] ifFalse:[
  1167             (node isUnary) ifTrue:[
  1171             (node isMessage and:[node isUnary]) ifTrue:[
  1168                 "/ expanding <rcvr> foo |<- cursor here (i.e. a space after foo)
  1172                 "/ expanding <rcvr> foo |<- cursor here (i.e. a space after foo)
  1169                 "/
  1173                 "/
  1170                 forceNewMessageSend := true.
  1174                 forceNewMessageSend := true.
  1171 "/                "/ can we see what we get from foo?
  1175 "/                "/ can we see what we get from foo?
  1172 "/                classOfReceiver := self 
  1176 "/                classOfReceiver := self 
  1650 codeCompletionForMessage:node into:actionBlock
  1654 codeCompletionForMessage:node into:actionBlock
  1651     |selector srchClass implClass 
  1655     |selector srchClass implClass 
  1652      bestSelectors selector2 bestSelectors2 allBest best info numArgs
  1656      bestSelectors selector2 bestSelectors2 allBest best info numArgs
  1653      newParts nSelParts oldLen newLen selectorParts 
  1657      newParts nSelParts oldLen newLen selectorParts 
  1654      findBest parentNode selectorsSentInCode split editAction parentNodeClassIfKnown 
  1658      findBest parentNode selectorsSentInCode split editAction parentNodeClassIfKnown 
  1655      otherMessagesToReceiver possibleClasses receiverNodeClassIfKnown|
  1659      otherMessagesToReceiver assignmentsToReceiver possibleClasses receiverNodeClassIfKnown|
  1656 
  1660 
  1657     "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil.
  1661     "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil.
  1658 
  1662 
  1659 "/    classOrNil notNil ifTrue:[
  1663 "/    classOrNil notNil ifTrue:[
  1660 "/        parser := Parser parseMethod:codeView contents string in:classOrNil ignoreErrors:true ignoreWarnings:true.
  1664 "/        parser := Parser parseMethod:codeView contents string in:classOrNil ignoreErrors:true ignoreWarnings:true.
  1687         ].
  1691         ].
  1688     ].
  1692     ].
  1689 
  1693 
  1690     bestSelectors := findBest value:node receiver value:selector.  
  1694     bestSelectors := findBest value:node receiver value:selector.  
  1691 
  1695 
  1692     "/ if the receiver is a variable, we can look for other messages being sent to that variable in the current method
  1696     "/ if the receiver is a variable, 
       
  1697     "/ we can look for other messages being sent to that variable in the current method.
       
  1698     "/ also, if there is an assignment like class new to it...
  1693     (tree notNil and:[ node receiver isVariable ])
  1699     (tree notNil and:[ node receiver isVariable ])
  1694     ifTrue:[
  1700     ifTrue:[
  1695         otherMessagesToReceiver := tree allMessageNodes 
  1701         assignmentsToReceiver := tree allAssignmentNodes 
  1696                                     select:[:eachMessageNode | 
  1702                                     collect:[:eachAssignmentNode |
  1697                                         node receiver = eachMessageNode receiver
  1703                                                 |cls|
  1698                                         and:[ selector ~= eachMessageNode selector]]
  1704 
  1699                                     thenCollect:[:eachNode | eachNode selector].
  1705                                                 (node receiver = eachAssignmentNode variable
  1700         possibleClasses := Smalltalk allClassesForWhich:[:cls |
  1706                                                     and:[ (cls := self classOfNode:eachAssignmentNode value) notNil ]
  1701                             otherMessagesToReceiver conform:[:eachSelectorSent | cls canUnderstand:eachSelectorSent]].
  1707                                                 ) ifTrue:[
  1702         possibleClasses := possibleClasses select:[:cls | cls isLoaded].
  1708                                                     cls
       
  1709                                                 ] ifFalse:[
       
  1710                                                     nil
       
  1711                                                 ]
       
  1712                                             ]
       
  1713                                     thenSelect:[:classOrNil | classOrNil notNil].
       
  1714         assignmentsToReceiver notEmptyOrNil ifTrue:[
       
  1715             possibleClasses := assignmentsToReceiver
       
  1716         ] ifFalse:[
       
  1717             otherMessagesToReceiver := tree allMessageNodes 
       
  1718                                         select:[:eachMessageNode | 
       
  1719                                                     node receiver = eachMessageNode receiver
       
  1720                                                     and:[ selector ~= eachMessageNode selector]]
       
  1721                                         thenCollect:[:eachNode | eachNode selector].
       
  1722             otherMessagesToReceiver := otherMessagesToReceiver asSet.
       
  1723             possibleClasses := Smalltalk allClassesForWhich:[:cls |
       
  1724                                 otherMessagesToReceiver conform:[:eachSelectorSent | cls includesSelector: "canUnderstand:" eachSelectorSent]].
       
  1725             possibleClasses := possibleClasses select:[:cls | cls isLoaded].
       
  1726         ].
  1703         (possibleClasses notEmpty and:[possibleClasses size < 10]) ifTrue:[
  1727         (possibleClasses notEmpty and:[possibleClasses size < 10]) ifTrue:[
  1704             bestSelectors := Set new.
  1728             bestSelectors := Set new.
  1705             possibleClasses do:[:eachClass |
  1729             possibleClasses do:[:eachClass |
  1706                 |bestSelectorsForClass|
  1730                 |bestSelectorsForClass|
  1707 
  1731 
  1905     self information:info.
  1929     self information:info.
  1906 ].
  1930 ].
  1907 
  1931 
  1908     editAction := 
  1932     editAction := 
  1909         [:index |
  1933         [:index |
  1910             |best|
  1934             |chosen|
  1911 
  1935 
  1912             best := allBest at:index.
  1936             chosen := allBest at:index.
  1913 
  1937 
  1914             best ~= selector ifTrue:[
  1938             chosen ~= selector ifTrue:[
  1915                 numArgs := best numArgs.
  1939                 numArgs := chosen numArgs.
  1916                 (bestSelectors2 notEmptyOrNil and:[bestSelectors2 includes:best]) ifTrue:[
  1940                 (bestSelectors2 notEmptyOrNil and:[bestSelectors2 includes:chosen]) ifTrue:[
  1917                     selectorParts := parentNode selectorParts , node selectorParts.
  1941                     selectorParts := parentNode selectorParts , node selectorParts.
  1918                 ] ifFalse:[
  1942                 ] ifFalse:[
  1919                     selectorParts := node selectorParts.
  1943                     selectorParts := node selectorParts.
  1920                 ].
  1944                 ].
  1921                 nSelParts := selectorParts size.
  1945                 nSelParts := selectorParts size.
  1922 
  1946 
  1923                 newParts := best asCollectionOfSubstringsSeparatedBy:$:.
  1947                 newParts := chosen asCollectionOfSubstringsSeparatedBy:$:.
  1924                 newParts := newParts select:[:part | part size > 0].
  1948                 newParts := newParts select:[:part | part size > 0].
  1925 
  1949 
  1926                 codeView
  1950                 codeView
  1927                     undoableDo:[
  1951                     undoableDo:[
  1928                         |newCursorPosition stop checkForArgumentTemplates|
  1952                         |newCursorPosition stop checkForArgumentTemplates|
  1929 
  1953 
  1930                         checkForArgumentTemplates := false.
  1954                         checkForArgumentTemplates := false.
  1931                         (selector isUnarySelector and:[best isKeywordSelector]) ifTrue:[ checkForArgumentTemplates := true ].
  1955                         (selector isUnarySelector and:[chosen isKeywordSelector]) ifTrue:[ checkForArgumentTemplates := true ].
  1932                         numArgs > nSelParts ifTrue:[
  1956                         numArgs > nSelParts ifTrue:[
  1933                             "/ new selector has more arguments; append them
  1957                             "/ new selector has more arguments; append them
  1934                             stop := selectorParts last stop.
  1958                             stop := selectorParts last stop.
  1935 
  1959 
  1936                             "/ append the rest ...
  1960                             "/ append the rest ...
  1937                             numArgs downTo:nSelParts+1 do:[:idx |
  1961                             numArgs downTo:nSelParts+1 do:[:idx |
  1938                                 |newPart|
  1962                                 |newPart|
  1939 
  1963 
  1940                                 newPart := newParts at:idx.
  1964                                 newPart := newParts at:idx.
  1941                                 (best endsWith:$:) ifTrue:[
  1965                                 (chosen endsWith:$:) ifTrue:[
  1942                                     newPart := newPart , ':'
  1966                                     newPart := newPart , ':'
  1943                                 ].
  1967                                 ].
  1944 
  1968 
  1945                                 (codeView characterAtCharacterPosition:stop) == $: ifFalse:[
  1969                                 (codeView characterAtCharacterPosition:stop) == $: ifFalse:[
  1946                                     newPart := ':' , newPart.
  1970                                     newPart := ':' , newPart.
  1960                             newPart := newParts at:idx.
  1984                             newPart := newParts at:idx.
  1961                             oldPartialToken := selectorParts at:idx.
  1985                             oldPartialToken := selectorParts at:idx.
  1962                             start := oldPartialToken start.
  1986                             start := oldPartialToken start.
  1963                             stop := oldPartialToken stop.
  1987                             stop := oldPartialToken stop.
  1964 
  1988 
  1965                             (best endsWith:$:) ifTrue:[
  1989                             (chosen endsWith:$:) ifTrue:[
  1966                                 (codeView characterAtCharacterPosition:stop+1) == $: ifFalse:[
  1990                                 (codeView characterAtCharacterPosition:stop+1) == $: ifFalse:[
  1967                                     newPart := newPart , ':'
  1991                                     newPart := newPart , ':'
  1968                                 ]
  1992                                 ]
  1969                             ] ifFalse:[
  1993                             ] ifFalse:[
  1970                                 (codeView characterAtCharacterPosition:stop) == $: ifTrue:[
  1994                                 (codeView characterAtCharacterPosition:stop) == $: ifTrue:[
  1998                             extra := hasSpace ifTrue:[''] ifFalse:[' '].  
  2022                             extra := hasSpace ifTrue:[''] ifFalse:[' '].  
  1999 
  2023 
  2000                             (
  2024                             (
  2001                                 #(
  2025                                 #(
  2002                                     'ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'and:' 'or:'
  2026                                     'ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'and:' 'or:'
  2003                                 ) includes:best
  2027                                 ) includes:chosen
  2004                             ) ifTrue:[
  2028                             ) ifTrue:[
  2005                                 codeView insertStringAtCursor:('[]',extra).
  2029                                 codeView insertStringAtCursor:('[]',extra).
  2006                                 codeView cursorLeft:1+extra size. 
  2030                                 codeView cursorLeft:1+extra size. 
  2007                             ].
  2031                             ].
  2008                             (
  2032                             (
  2009                                 #(
  2033                                 #(
  2010                                     'collect:' 'select:' 'reject:' 'do:'
  2034                                     'collect:' 'select:' 'reject:' 'do:'
  2011                                 ) includes:best
  2035                                 ) includes:chosen
  2012                             ) ifTrue:[
  2036                             ) ifTrue:[
  2013                                 codeView insertStringAtCursor:('[:each | ]',extra).
  2037                                 codeView insertStringAtCursor:('[:each | ]',extra).
  2014                                 codeView cursorLeft:1+extra size. 
  2038                                 codeView cursorLeft:1+extra size. 
  2015                             ].
  2039                             ].
  2016                         ].
  2040                         ].
  2035             [:suggestions :action :whatIsIt |
  2059             [:suggestions :action :whatIsIt |
  2036 
  2060 
  2037             |chosen|
  2061             |chosen|
  2038 
  2062 
  2039             chosen := self askUserForCompletion:whatIsIt for:codeView at:node start from:suggestions.
  2063             chosen := self askUserForCompletion:whatIsIt for:codeView at:node start from:suggestions.
  2040             action value:(suggestions indexOf:chosen)
  2064             chosen notNil ifTrue:[
       
  2065                 action value:(suggestions indexOf:chosen)
       
  2066             ].
  2041         ].
  2067         ].
  2042 
  2068 
  2043 "/    |crsrPos
  2069 "/    |crsrPos
  2044 "/     selectorSoFar matchingSelectors
  2070 "/     selectorSoFar matchingSelectors
  2045 "/     selectors distances best rest 
  2071 "/     selectors distances best rest 
  3995 ! !
  4021 ! !
  3996 
  4022 
  3997 !DoWhatIMeanSupport class methodsFor:'documentation'!
  4023 !DoWhatIMeanSupport class methodsFor:'documentation'!
  3998 
  4024 
  3999 version
  4025 version
  4000     ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.154 2013-09-12 14:01:17 cg Exp $'
  4026     ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.155 2013-09-15 10:43:18 cg Exp $'
  4001 !
  4027 !
  4002 
  4028 
  4003 version_CVS
  4029 version_CVS
  4004     ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.154 2013-09-12 14:01:17 cg Exp $'
  4030     ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.155 2013-09-15 10:43:18 cg Exp $'
  4005 ! !
  4031 ! !
  4006 
  4032