--- a/DoWhatIMeanSupport.st Wed Jan 09 21:41:17 2008 +0100
+++ b/DoWhatIMeanSupport.st Thu Jan 10 13:02:28 2008 +0100
@@ -62,8 +62,9 @@
interval := codeView selectedInterval.
interval isEmpty ifTrue:[
- crsrPos := codeView characterPositionOfCursor - 1.
- char := codeView characterUnderCursor.
+ crsrPos := codeView characterPositionOfCursor-1.
+ char := codeView characterAtCharacterPosition:crsrPos.
+
[crsrPos > 1 and:[char isSeparator or:['.' includes:char]]] whileTrue:[
crsrPos := crsrPos - 1.
char := codeView characterAtCharacterPosition:crsrPos.
@@ -77,6 +78,8 @@
[node isNil] whileTrue:[
"/ expand to the left ...
interval start > 1 ifFalse:[
+ crsrPos := codeView characterPositionOfCursor.
+self halt.
self information:'No parseNode found'.
^ self.
].
@@ -92,10 +95,12 @@
checkedNode := node.
[checkedNode notNil] whileTrue:[
checkedNode isMessage ifTrue:[
+ "/ completion in a message-send
self codeCompletionForMessage:checkedNode inClass:cls codeView:codeView.
^ self
].
checkedNode isMethod ifTrue:[
+ "/ completion in a methods selector pattern
self codeCompletionForMethod:checkedNode inClass:cls codeView:codeView.
^ self.
].
@@ -320,14 +325,18 @@
!
codeCompletionForMethod:node inClass:cls codeView:codeView
+ "completion in a methods selector pattern"
+
|crsrPos
selectorSoFar matchingSelectors
- selectors distances best rest|
+ selectors distances best rest
+ allExistingMethods namesOfArguments
+ nameBag namesByCount|
crsrPos := codeView characterPositionOfCursor - 1.
selectorSoFar := ''.
- node selectorParts do:[:partToken |
+ node selectorParts doWithIndex:[:partToken :argNr|
|part|
part := partToken value.
@@ -349,23 +358,48 @@
theSet.
].
selectors := matchingSelectors asOrderedCollection.
- distances := selectors collect:[:each | each spellAgainst:selectorSoFar].
- distances sortWith:selectors.
- selectors reverse.
- best := self askUserForCompletion:'selector' for:codeView from:selectors.
- best isNil ifTrue:[^ self].
+ "/ if there is only one, and user has already entered it, he might want to complete the argument-name
+ (selectors size == 1
+ and:[selectors first = selectorSoFar]) ifTrue:[
+ allExistingMethods := (Smalltalk allImplementorsOf:selectorSoFar asSymbol)
+ collect:[:cls | cls compiledMethodAt:selectorSoFar asSymbol].
+ namesOfArguments := allExistingMethods collect:[:eachMethod | eachMethod methodArgNames].
+ nameBag := Bag new.
+ namesOfArguments do:[:eachNameVector | nameBag add:(eachNameVector at:argNr)].
+ namesByCount := nameBag valuesAndCounts sort:[:a :b | a value < b value].
+ "/ take the one which occurs most often
+ best := self askUserForCompletion:'argument' for:codeView from:(namesByCount collect:[:a | a key]).
- rest := best copyFrom:selectorSoFar size.
- codeView
- undoableDo:[
- codeView
- replaceFromCharacterPosition:crsrPos
- to:crsrPos
- with:rest
- ]
- info:'completion'.
- codeView cursorToCharacterPosition:(crsrPos + rest size - 1).
- codeView cursorRight.
+ codeView
+ undoableDo:[
+ (crsrPos+1) >= codeView contents size ifTrue:[
+ codeView paste:best.
+ ] ifFalse:[
+ codeView insertString:best atCharacterPosition:crsrPos+1.
+ ]
+ ]
+ info:'completion'.
+ codeView cursorToCharacterPosition:(crsrPos + best size - 1).
+ ] ifFalse:[
+ distances := selectors collect:[:each | each spellAgainst:selectorSoFar].
+ distances sortWith:selectors.
+ selectors reverse.
+ best := self askUserForCompletion:'selector' for:codeView from:selectors.
+ best isNil ifTrue:[^ self].
+
+ rest := best copyFrom:selectorSoFar size.
+
+ codeView
+ undoableDo:[
+ codeView
+ replaceFromCharacterPosition:crsrPos
+ to:crsrPos
+ with:rest
+ ]
+ info:'completion'.
+ codeView cursorToCharacterPosition:(crsrPos + rest size - 1).
+ ].
+ codeView cursorRight. "/ kludge to make it visible
].
].
@@ -615,7 +649,7 @@
!
findNodeForInterval:interval in:source allowErrors:allowErrors
- |tree node "errCount"|
+ |tree "errCount"|
interval isEmpty ifTrue: [^ nil].
RBParser isNil ifTrue: [^ nil].
@@ -626,8 +660,9 @@
|nodes|
allowErrors ifTrue:[
- nodes := nodesSoFar collect:[:nd | nd whichNodeIntersects:interval].
- nodes := nodes select:[:nd | nd notNil ].
+ nodes := nodesSoFar
+ collect:[:nd | nd whichNodeIntersects:interval]
+ thenSelect:[:nd | nd notNil ].
nodes size == 1 ifTrue:[
^ nodes first
].
@@ -637,11 +672,18 @@
"/ onError: [:str :err | errCount := (errCount?0) + 1. self halt.]
"/ proceedAfterError:true.
- tree isNil ifTrue:[^ nil].
+ ^ self findNodeForInterval:interval inParseTree:tree.
+!
+
+findNodeForInterval:interval inParseTree:parseTree
+ |node|
- node := tree whichNodeIsContainedBy:interval.
+ interval isEmpty ifTrue: [^ nil].
+ parseTree isNil ifTrue:[^ nil].
+
+ node := parseTree whichNodeIsContainedBy:interval.
node isNil ifTrue: [
- node := self findNodeIn:tree forInterval:interval
+ node := self findNodeIn:parseTree forInterval:interval
].
^ node
@@ -1482,5 +1524,5 @@
!DoWhatIMeanSupport class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.25 2008-01-07 13:49:18 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.26 2008-01-10 12:02:28 cg Exp $'
! !