The Inbox: Tools-eem.915.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

The Inbox: Tools-eem.915.mcz

commits-2
A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver.  Key the context text by the method.  Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
  ----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
  formattedLabel: aString forSelector: aSymbol inClass: aClass
  "Show deprecated messages differently so that users recognize them quickly to avoid them."
 
  | formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].
 
  formattedLabel := aString asText.
 
  (self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
  formattedLabel addAttribute: textAttribute].
 
+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
  CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
  classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
  poolDictionaries: ''
  category: 'Tools-Debugger'!
 
  !Debugger commentStamp: '<historical>' prior: 0!
  I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.
 
  Special note on recursive errors:
  Some errors affect Squeak's ability to present a debugger.  This is normally an unrecoverable situation.  However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger.  Here is the chain of events in such a recovery.
 
  * A recursive error is detected.
  * The current project is queried for an isolationHead
  * Changes in the isolationHead are revoked
  * The parent project of isolated project is returned to
  * The debugger is opened there and execution resumes.
 
  If the user closes that debugger, execution continues in the outer project and layer.  If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+    and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
  ----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
  contextStackIndex: anInteger oldContextWas: oldContext
  "Change the context stack index to anInteger, perhaps in response to user selection."
 
  | isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
  contextStackIndex := anInteger.
  anInteger = 0 ifTrue:
  [currentCompiledMethod := contents := nil.
  self changed: #contextStackIndex.
  self decorateButtons.
  self contentsChanged.
  contextVariablesInspector object: nil.
  receiverInspector object: self receiver.
  ^self].
  selectedContextSlotName := contextVariablesInspector selectedSlotName.
  isNewMethod := oldContext == nil
  or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
  isNewMethod ifTrue:
  [contents := self selectedMessage.
  self contentsChanged.
  self pcRange].
  self changed: #contextStackIndex.
  self decorateButtons.
  contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
  ((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
  and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
  [contextVariablesInspector toggleIndex: index].
  receiverInspector object: self receiver.
+ self setReceiverInspectorText.
  isNewMethod ifFalse:
  [self changed: #contentsSelection]!

Item was changed:
  ----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
  receiverInspectorObject: obj context: ctxt
 
  "set context before object so it can refer to context when building field list"
  receiverInspector context: ctxt.
  receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Tools-eem.915.mcz

marcel.taeumel
Hi, there.

I like this idea, but I will try to implement it differently during the next days. :-)

Since we do have MorphicDebugger, I don't think we need #hasTextMorph from Morphic.eem.1591

Best,
Marcel

Am 28.11.2019 00:33:28 schrieb [hidden email] <[hidden email]>:

A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver. Key the context text by the method. Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
formattedLabel: aString forSelector: aSymbol inClass: aClass
"Show deprecated messages differently so that users recognize them quickly to avoid them."

| formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].

formattedLabel := aString asText.

(self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
formattedLabel addAttribute: textAttribute].

+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!

!Debugger commentStamp: '' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.

Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.

* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.

If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+ and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
contextStackIndex: anInteger oldContextWas: oldContext
"Change the context stack index to anInteger, perhaps in response to user selection."

| isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
contextStackIndex := anInteger.
anInteger = 0 ifTrue:
[currentCompiledMethod := contents := nil.
self changed: #contextStackIndex.
self decorateButtons.
self contentsChanged.
contextVariablesInspector object: nil.
receiverInspector object: self receiver.
^self].
selectedContextSlotName := contextVariablesInspector selectedSlotName.
isNewMethod := oldContext == nil
or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
isNewMethod ifTrue:
[contents := self selectedMessage.
self contentsChanged.
self pcRange].
self changed: #contextStackIndex.
self decorateButtons.
contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
[contextVariablesInspector toggleIndex: index].
receiverInspector object: self receiver.
+ self setReceiverInspectorText.
isNewMethod ifFalse:
[self changed: #contentsSelection]!

Item was changed:
----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
receiverInspectorObject: obj context: ctxt

"set context before object so it can refer to context when building field list"
receiverInspector context: ctxt.
receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Tools-eem.915.mcz

Chris Muller-3
Hi Eliot.  Hi Marcel, while you're in there, would you mind seeing if you can find a good solution to list-filtering on the stack pane?  THAT is how I like to solve Eliots use-case (IIUC).  I type a string that matches the name of the method which contains the nested blocks, voila!, I can arrow down through them, seeing the highlighted code jump between the layers of blocks, all the while keeping "self" selected, which works because the receiver is always the same.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

On Thu, Nov 28, 2019 at 1:20 AM Marcel Taeumel <[hidden email]> wrote:
Hi, there.

I like this idea, but I will try to implement it differently during the next days. :-)

Since we do have MorphicDebugger, I don't think we need #hasTextMorph from Morphic.eem.1591

Best,
Marcel

Am 28.11.2019 00:33:28 schrieb [hidden email] <[hidden email]>:

A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver. Key the context text by the method. Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
formattedLabel: aString forSelector: aSymbol inClass: aClass
"Show deprecated messages differently so that users recognize them quickly to avoid them."

| formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].

formattedLabel := aString asText.

(self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
formattedLabel addAttribute: textAttribute].

+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!

!Debugger commentStamp: '' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.

Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.

* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.

If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+ and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
contextStackIndex: anInteger oldContextWas: oldContext
"Change the context stack index to anInteger, perhaps in response to user selection."

| isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
contextStackIndex := anInteger.
anInteger = 0 ifTrue:
[currentCompiledMethod := contents := nil.
self changed: #contextStackIndex.
self decorateButtons.
self contentsChanged.
contextVariablesInspector object: nil.
receiverInspector object: self receiver.
^self].
selectedContextSlotName := contextVariablesInspector selectedSlotName.
isNewMethod := oldContext == nil
or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
isNewMethod ifTrue:
[contents := self selectedMessage.
self contentsChanged.
self pcRange].
self changed: #contextStackIndex.
self decorateButtons.
contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
[contextVariablesInspector toggleIndex: index].
receiverInspector object: self receiver.
+ self setReceiverInspectorText.
isNewMethod ifFalse:
[self changed: #contentsSelection]!

Item was changed:
----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
receiverInspectorObject: obj context: ctxt

"set context before object so it can refer to context when building field list"
receiverInspector context: ctxt.
receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!





Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Tools-eem.915.mcz

marcel.taeumel
Hi Chris.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

I did already add that look-up index to make filtering work with such string-identical items. When did the issue you mentioned occur the last time? :-)



Best,
Marcel

Am 28.11.2019 22:15:08 schrieb Chris Muller <[hidden email]>:

Hi Eliot.  Hi Marcel, while you're in there, would you mind seeing if you can find a good solution to list-filtering on the stack pane?  THAT is how I like to solve Eliots use-case (IIUC).  I type a string that matches the name of the method which contains the nested blocks, voila!, I can arrow down through them, seeing the highlighted code jump between the layers of blocks, all the while keeping "self" selected, which works because the receiver is always the same.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

On Thu, Nov 28, 2019 at 1:20 AM Marcel Taeumel <[hidden email]> wrote:
Hi, there.

I like this idea, but I will try to implement it differently during the next days. :-)

Since we do have MorphicDebugger, I don't think we need #hasTextMorph from Morphic.eem.1591

Best,
Marcel

Am 28.11.2019 00:33:28 schrieb [hidden email] <[hidden email]>:

A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver. Key the context text by the method. Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
formattedLabel: aString forSelector: aSymbol inClass: aClass
"Show deprecated messages differently so that users recognize them quickly to avoid them."

| formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].

formattedLabel := aString asText.

(self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
formattedLabel addAttribute: textAttribute].

+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!

!Debugger commentStamp: '' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.

Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.

* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.

If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+ and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
contextStackIndex: anInteger oldContextWas: oldContext
"Change the context stack index to anInteger, perhaps in response to user selection."

| isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
contextStackIndex := anInteger.
anInteger = 0 ifTrue:
[currentCompiledMethod := contents := nil.
self changed: #contextStackIndex.
self decorateButtons.
self contentsChanged.
contextVariablesInspector object: nil.
receiverInspector object: self receiver.
^self].
selectedContextSlotName := contextVariablesInspector selectedSlotName.
isNewMethod := oldContext == nil
or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
isNewMethod ifTrue:
[contents := self selectedMessage.
self contentsChanged.
self pcRange].
self changed: #contextStackIndex.
self decorateButtons.
contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
[contextVariablesInspector toggleIndex: index].
receiverInspector object: self receiver.
+ self setReceiverInspectorText.
isNewMethod ifFalse:
[self changed: #contentsSelection]!

Item was changed:
----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
receiverInspectorObject: obj context: ctxt

"set context before object so it can refer to context when building field list"
receiverInspector context: ctxt.
receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!





Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Tools-eem.915.mcz

marcel.taeumel
Hi Eliot,

works in Trunk now (Tools-mt.921). Please report any quirks in case I understood your feature request differently. :-)

Best,
Marcel

Am 29.11.2019 09:06:25 schrieb Marcel Taeumel <[hidden email]>:

Hi Chris.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

I did already add that look-up index to make filtering work with such string-identical items. When did the issue you mentioned occur the last time? :-)



Best,
Marcel

Am 28.11.2019 22:15:08 schrieb Chris Muller <[hidden email]>:

Hi Eliot.  Hi Marcel, while you're in there, would you mind seeing if you can find a good solution to list-filtering on the stack pane?  THAT is how I like to solve Eliots use-case (IIUC).  I type a string that matches the name of the method which contains the nested blocks, voila!, I can arrow down through them, seeing the highlighted code jump between the layers of blocks, all the while keeping "self" selected, which works because the receiver is always the same.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

On Thu, Nov 28, 2019 at 1:20 AM Marcel Taeumel <[hidden email]> wrote:
Hi, there.

I like this idea, but I will try to implement it differently during the next days. :-)

Since we do have MorphicDebugger, I don't think we need #hasTextMorph from Morphic.eem.1591

Best,
Marcel

Am 28.11.2019 00:33:28 schrieb [hidden email] <[hidden email]>:

A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver. Key the context text by the method. Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
formattedLabel: aString forSelector: aSymbol inClass: aClass
"Show deprecated messages differently so that users recognize them quickly to avoid them."

| formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].

formattedLabel := aString asText.

(self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
formattedLabel addAttribute: textAttribute].

+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!

!Debugger commentStamp: '' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.

Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.

* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.

If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+ and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
contextStackIndex: anInteger oldContextWas: oldContext
"Change the context stack index to anInteger, perhaps in response to user selection."

| isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
contextStackIndex := anInteger.
anInteger = 0 ifTrue:
[currentCompiledMethod := contents := nil.
self changed: #contextStackIndex.
self decorateButtons.
self contentsChanged.
contextVariablesInspector object: nil.
receiverInspector object: self receiver.
^self].
selectedContextSlotName := contextVariablesInspector selectedSlotName.
isNewMethod := oldContext == nil
or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
isNewMethod ifTrue:
[contents := self selectedMessage.
self contentsChanged.
self pcRange].
self changed: #contextStackIndex.
self decorateButtons.
contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
[contextVariablesInspector toggleIndex: index].
receiverInspector object: self receiver.
+ self setReceiverInspectorText.
isNewMethod ifFalse:
[self changed: #contentsSelection]!

Item was changed:
----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
receiverInspectorObject: obj context: ctxt

"set context before object so it can refer to context when building field list"
receiverInspector context: ctxt.
receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!





Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Tools-eem.915.mcz

Christoph Thiede

Oh gee, I've already implemented a similar solution in Tools-ct.900 ... It will be a mess to merge this ...
(InspectorFieldSpec is still on my list and keeps moving up :)))

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 29. November 2019 11:54:58
An: Chris Muller; John Pfersich via Squeak-dev
Betreff: Re: [squeak-dev] The Inbox: Tools-eem.915.mcz
 
Hi Eliot,

works in Trunk now (Tools-mt.921). Please report any quirks in case I understood your feature request differently. :-)

Best,
Marcel

Am 29.11.2019 09:06:25 schrieb Marcel Taeumel <[hidden email]>:

Hi Chris.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

I did already add that look-up index to make filtering work with such string-identical items. When did the issue you mentioned occur the last time? :-)



Best,
Marcel

Am 28.11.2019 22:15:08 schrieb Chris Muller <[hidden email]>:

Hi Eliot.  Hi Marcel, while you're in there, would you mind seeing if you can find a good solution to list-filtering on the stack pane?  THAT is how I like to solve Eliots use-case (IIUC).  I type a string that matches the name of the method which contains the nested blocks, voila!, I can arrow down through them, seeing the highlighted code jump between the layers of blocks, all the while keeping "self" selected, which works because the receiver is always the same.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

On Thu, Nov 28, 2019 at 1:20 AM Marcel Taeumel <[hidden email]> wrote:
Hi, there.

I like this idea, but I will try to implement it differently during the next days. :-)

Since we do have MorphicDebugger, I don't think we need #hasTextMorph from Morphic.eem.1591

Best,
Marcel

Am 28.11.2019 00:33:28 schrieb [hidden email] <[hidden email]>:

A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver. Key the context text by the method. Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
formattedLabel: aString forSelector: aSymbol inClass: aClass
"Show deprecated messages differently so that users recognize them quickly to avoid them."

| formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].

formattedLabel := aString asText.

(self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
formattedLabel addAttribute: textAttribute].

+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!

!Debugger commentStamp: '' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.

Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.

* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.

If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+ and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
contextStackIndex: anInteger oldContextWas: oldContext
"Change the context stack index to anInteger, perhaps in response to user selection."

| isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
contextStackIndex := anInteger.
anInteger = 0 ifTrue:
[currentCompiledMethod := contents := nil.
self changed: #contextStackIndex.
self decorateButtons.
self contentsChanged.
contextVariablesInspector object: nil.
receiverInspector object: self receiver.
^self].
selectedContextSlotName := contextVariablesInspector selectedSlotName.
isNewMethod := oldContext == nil
or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
isNewMethod ifTrue:
[contents := self selectedMessage.
self contentsChanged.
self pcRange].
self changed: #contextStackIndex.
self decorateButtons.
contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
[contextVariablesInspector toggleIndex: index].
receiverInspector object: self receiver.
+ self setReceiverInspectorText.
isNewMethod ifFalse:
[self changed: #contentsSelection]!

Item was changed:
----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
receiverInspectorObject: obj context: ctxt

"set context before object so it can refer to context when building field list"
receiverInspector context: ctxt.
receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!





Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Tools-eem.915.mcz

marcel.taeumel
Hi Christoph,

hmm... should not be that bad because the changes in Inspecter where minimal as the re-use happens in Debugger only. We should also talk about this #refreshContentsIfChanged ... because I think there is a better design possible to tackle this issue. :-)

You are right, tracking within Inspectors could also be beneficial and be more reusable if clients switch that inspected object frequently. Then, the debugger code would be cleaner again. :-)

Best,
Marcel

Am 07.12.2019 00:14:37 schrieb Thiede, Christoph <[hidden email]>:

Oh gee, I've already implemented a similar solution in Tools-ct.900 ... It will be a mess to merge this ...
(InspectorFieldSpec is still on my list and keeps moving up :)))

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 29. November 2019 11:54:58
An: Chris Muller; John Pfersich via Squeak-dev
Betreff: Re: [squeak-dev] The Inbox: Tools-eem.915.mcz
 
Hi Eliot,

works in Trunk now (Tools-mt.921). Please report any quirks in case I understood your feature request differently. :-)

Best,
Marcel

Am 29.11.2019 09:06:25 schrieb Marcel Taeumel <[hidden email]>:

Hi Chris.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

I did already add that look-up index to make filtering work with such string-identical items. When did the issue you mentioned occur the last time? :-)



Best,
Marcel

Am 28.11.2019 22:15:08 schrieb Chris Muller <[hidden email]>:

Hi Eliot.  Hi Marcel, while you're in there, would you mind seeing if you can find a good solution to list-filtering on the stack pane?  THAT is how I like to solve Eliots use-case (IIUC).  I type a string that matches the name of the method which contains the nested blocks, voila!, I can arrow down through them, seeing the highlighted code jump between the layers of blocks, all the while keeping "self" selected, which works because the receiver is always the same.

BUT, the problem is the string content of some of those those stack pane selections are *exactly* identical, which confuses the selection and causes it to wrap at the wrong place.   It's almost like filtering needs some way to make each rows contents "unique" for input purposes, even if they're not.  The idea in the back of my mind (without having had time yet to check the impl), was to see if their array index could somehow be prepended, (without seeing it, of course)...   Does it make sense?

On Thu, Nov 28, 2019 at 1:20 AM Marcel Taeumel <[hidden email]> wrote:
Hi, there.

I like this idea, but I will try to implement it differently during the next days. :-)

Since we do have MorphicDebugger, I don't think we need #hasTextMorph from Morphic.eem.1591

Best,
Marcel

Am 28.11.2019 00:33:28 schrieb [hidden email] <[hidden email]>:

A new version of Tools was added to project The Inbox:
http://source.squeak.org/inbox/Tools-eem.915.mcz

==================== Summary ====================

Name: Tools-eem.915
Author: eem
Time: 27 November 2019, 3:33:17.283843 pm
UUID: 0bbf0438-4f72-4865-9a46-10dd783724ac
Ancestors: Tools-mt.914

Save and restore the texts in the receiver and context inspectors when changing selection. Key the receiver text by the class of receiver. Key the context text by the method. Hence, much like the current Pharo debugger, text state stays around and can be extended as one investigates several methods in the stack.

Needs Morphic.eem.1591 (we hope cuz it ain't been committed yet).

=============== Diff against Tools-mt.914 ===============

Item was changed:
----- Method: CodeHolder>>formattedLabel:forSelector:inClass: (in category 'message list') -----
formattedLabel: aString forSelector: aSymbol inClass: aClass
"Show deprecated messages differently so that users recognize them quickly to avoid them."

| formattedLabel |
+ aClass ifNotNil:
+ [(aSymbol = #Definition or: [aSymbol = #Comment])
+ ifTrue:
+ [aClass isDeprecated ifFalse:
+ [^ aString]]
+ ifFalse:
+ [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated]) ifFalse:
+ [^ aString]]].
- (aSymbol = #Definition or: [aSymbol = #Comment])
- ifTrue: [aClass isDeprecated
- ifFalse: [^ aString]]
- ifFalse: [(aClass isDeprecated or: [(aClass compiledMethodAt: aSymbol ifAbsent: [^ aString]) isDeprecated])
- ifFalse: [^ aString]].

formattedLabel := aString asText.

(self userInterfaceTheme deprecatedMessageAttributes ifNil: [{TextColor gray. TextEmphasis struckOut}]) do: [:textAttribute |
formattedLabel addAttribute: textAttribute].

+ ^ formattedLabel!
- ^ formattedLabel.!

Item was changed:
CodeHolder subclass: #Debugger
+ instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression receiverInspectorTexts contextInspectorTexts'
- instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!

!Debugger commentStamp: '' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.

Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.

* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.

If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !

Item was added:
+ ----- Method: Debugger>>contextAndReceiverInspectorTextMorphsDo: (in category 'user interface') -----
+ contextAndReceiverInspectorTextMorphsDo: aBinaryBlock
+ "If both contextVariablesInspector and receiverInspector have
+ text morphs then evaluate aBinaryBlock with the two morphs."
+ ^(contextVariablesInspector notNil
+ and: [receiverInspector notNil]) ifTrue:
+ [aBinaryBlock
+ value: (contextVariablesInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])
+ value: (receiverInspector dependents
+ detect: [:d| d hasTextMorph and: [d textMorph isTextMorph]]
+ ifNone: [^nil])]!

Item was changed:
----- Method: Debugger>>contextStackIndex:oldContextWas: (in category 'private') -----
contextStackIndex: anInteger oldContextWas: oldContext
"Change the context stack index to anInteger, perhaps in response to user selection."

| isNewMethod selectedContextSlotName index |
+ self saveInspectorTexts.
contextStackIndex := anInteger.
anInteger = 0 ifTrue:
[currentCompiledMethod := contents := nil.
self changed: #contextStackIndex.
self decorateButtons.
self contentsChanged.
contextVariablesInspector object: nil.
receiverInspector object: self receiver.
^self].
selectedContextSlotName := contextVariablesInspector selectedSlotName.
isNewMethod := oldContext == nil
or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)].
isNewMethod ifTrue:
[contents := self selectedMessage.
self contentsChanged.
self pcRange].
self changed: #contextStackIndex.
self decorateButtons.
contextVariablesInspector object: self selectedContext.
+ self setContextInspectorText.
((index := contextVariablesInspector fieldList indexOf: selectedContextSlotName) ~= 0
and: [index ~= contextVariablesInspector selectionIndex]) ifTrue:
[contextVariablesInspector toggleIndex: index].
receiverInspector object: self receiver.
+ self setReceiverInspectorText.
isNewMethod ifFalse:
[self changed: #contentsSelection]!

Item was changed:
----- Method: Debugger>>receiverInspectorObject:context: (in category 'accessing') -----
receiverInspectorObject: obj context: ctxt

"set context before object so it can refer to context when building field list"
receiverInspector context: ctxt.
receiverInspector object: obj.
+ self setReceiverInspectorText!
- !

Item was added:
+ ----- Method: Debugger>>saveInspectorTexts (in category 'user interface') -----
+ saveInspectorTexts
+ "Save the texts in the two inspectors in the relevant dictionaries, keyed by either the method, in the case of
+ the contextVariablesInspector, or the receiver's class, in the case of the receiverInspector. Later we will
+ restore these texts if a context with the smae method or receiver with the same class are inspected again."
+ self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :receiverTextMorph| | key |
+ key := contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method].
+ key ifNotNil:
+ [contextTextMorph text isEmpty
+ ifTrue:
+ [contextInspectorTexts ifNotNil:
+ [contextInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [contextInspectorTexts ifNil: [contextInspectorTexts := IdentityDictionary new].
+ contextInspectorTexts at: key put: contextTextMorph text]].
+ key := receiverInspector object.
+ receiverTextMorph text isEmpty
+ ifTrue:
+ [receiverInspectorTexts ifNotNil:
+ [receiverInspectorTexts removeKey: key ifAbsent: []]]
+ ifFalse:
+ [receiverInspectorTexts ifNil: [receiverInspectorTexts := IdentityDictionary new].
+ receiverInspectorTexts at: key put: receiverTextMorph text]]!

Item was added:
+ ----- Method: Debugger>>setContextInspectorText (in category 'user interface') -----
+ setContextInspectorText
+ (contextVariablesInspector object isContext ifTrue: [contextVariablesInspector object method]) ifNotNil:
+ [:key|
+ (contextInspectorTexts notNil
+ and: [contextInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:contextTextMorph :shunnedReceiverTextMorph|
+ contextTextMorph setText: (contextInspectorTexts at: key)]]]!

Item was added:
+ ----- Method: Debugger>>setReceiverInspectorText (in category 'user interface') -----
+ setReceiverInspectorText
+ | key |
+ key := receiverInspector object.
+ (receiverInspectorTexts notNil
+ and: [receiverInspectorTexts includesKey: key]) ifTrue:
+ [self contextAndReceiverInspectorTextMorphsDo:
+ [:shunnedContextTextMorph :receiverTextMorph|
+ receiverTextMorph setText: (receiverInspectorTexts at: key)]]!