Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-ct.1158.mcz
==================== Summary ====================
Name: Tools-ct.1158
Author: ct
Time: 17 May 2022, 1:04:37.206327 pm
UUID: 1cb879ce-2df7-174b-b4ba-d443e4fdc011
Ancestors: Tools-mt.1157
Do not update process browsers from inactive projects. Before this fix, an auto-updating process browser from a Morphic project would raise periodic errors after entering an MVC project, and an auto-updating process browser from a MVC project would cause spooky screen updates after entering a Morphic project.
Note that a better solution strategy would consist of something like StepMessages for MVC, which however do not exist as of today.
=============== Diff against Tools-mt.1157 ===============
Item was changed:
----- Method: ProcessBrowser>>startAutoUpdate (in category 'updating') -----
startAutoUpdate
self isAutoUpdatingPaused
ifTrue: [^ autoUpdateProcess resume].
+ self isAutoUpdating ifFalse:
+ [| project |
+ project := Project current.
+ autoUpdateProcess :=
+ [[[self hasView] whileTrue:
+ [2 seconds wait.
+ project addDeferredUIMessage: [self updateProcessList]].
+ autoUpdateProcess := nil]
+ ensure: [self removeActionsForEvent: #aboutToEnterWorld]] fork.
+ project world
+ when: #aboutToLeaveWorld send: #pauseAutoUpdate to: self;
+ when: #aboutToEnterWorld send: #startAutoUpdate to: self].
+ self updateProcessList.!
- self isAutoUpdating
- ifFalse: [autoUpdateProcess := [[self hasView]
- whileTrue: [(Delay forSeconds: 2) wait.
- Project current addDeferredUIMessage: [self updateProcessList]].
- autoUpdateProcess := nil] fork].
- self updateProcessList
- !
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-ct.1159.mcz
==================== Summary ====================
Name: Tools-ct.1159
Author: ct
Time: 20 May 2022, 1:41:35.47049 pm
UUID: f2890075-119c-c948-bd42-93a392abcca9
Ancestors: Tools-mt.1158
Fixes a tedious #codeChangedElsewhere bug in the class definition view of system browsers.
The original bug report:
1. Open a browser on any method of any class.
2. Change the source so that it contains a new - as yet undeclared - instance variable.
3. Accept the new method and answer the "unknown variable" dialog with "declare instance variable".
4. Click on the instance button of the browser.
5. Try to type into the class definition or to reaccept it.
The text cursor would jump to beginning of the text field every second until you started to type. After that, a red triangle would appear at the text field, and when you tried to accept the changes, a "may have been changed elsewhere" warning would appear.
Cause:
Declaring the new instance variable converts the class into a new behavior instance, but the browser kept a reference on the prior version of the class. Thus Browser>>#didCodeChangeElsewhere answered true because of the divergent class definitions, but CodeHolder>>#updateCodePaneIfNeeded was unable to fix that divergence.
Solution:
Add override Browser>>#updateCodePaneIfNeeded and send #setClassDefinition if necessary to apply the pending update.
=============== Diff against Tools-mt.1158 ===============
Item was added:
+ ----- Method: Browser>>updateCodePaneIfNeeded (in category 'self-updating') -----
+ updateCodePaneIfNeeded
+
+ super updateCodePaneIfNeeded.
+
+ (self didCodeChangeElsewhere and: [self hasUnacceptedEdits not])
+ ifTrue:
+ [self setClassDefinition.
+ self contentsChanged].!
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-ct.1211.mcz
==================== Summary ====================
Name: Tools-ct.1211
Author: ct
Time: 1 June 2023, 8:26:54.735263 pm
UUID: 0b71a9d8-b26d-854e-83ae-89d560db27a4
Ancestors: Tools-ct.1210
Proposal: In truncated file lists, inserts a link for reading the entire file. More observable than the context menu. Uses color and emphasis for highlighting the truncation message.
=============== Diff against Tools-ct.1210 ===============
Item was added:
+ ----- Method: FileList>>decorateTruncatedText:size:limit: (in category 'private') -----
+ decorateTruncatedText: truncatedText size: size limit: limit
+
+ | args |
+ args := {
+ fileName. size. limit.
+ 'Click here' translated asText
+ addAttribute: (PluggableTextAttribute evalBlock: [self get]);
+ addAttribute: TextEmphasis bold;
+ yourself }.
+ ^ Text streamContents: [:stream |
+ stream withAttributes: {TextColor red. TextEmphasis italic} do: [
+ stream nextPutAll: ('File ''{1}'' is {2} bytes long.
+ {4} to read the entire file.
+
+ Here are the first {3} characters...
+ ------------------------------------------
+ ' translated
+ asText format: args)].
+ stream nextPutAll: truncatedText.
+ stream withAttributes: {TextColor red. TextEmphasis italic} do: [
+ stream nextPutAll: ('
+ ------------------------------------------
+ ... end of the first {3} characters.
+ {4} to read the entire file.' translated
+ asText format: args)]]!
Item was changed:
----- Method: FileList>>readContentsBrief: (in category 'private') -----
readContentsBrief: brevityFlag
"Read the contents of the receiver's selected file, unless it is too long, in which case show just the first 5000 characters. Don't create a file if it doesn't already exist."
| f fileSize first5000 |
brevityFlag ifTrue: [
directory isRemoteDirectory ifTrue: [^ self readServerBrief]].
f := directory oldFileOrNoneNamed: self fullName.
f ifNil: [^ 'For some reason, this file cannot be read' translated].
self setDefaultEncoderFor: f.
(brevityFlag not or: [(fileSize := f size) <= 100000]) ifTrue:
+ [brevityState := #fullFile. "don't change till actually read"
+ ^ contents := f contentsOfEntireFile].
- [contents := f contentsOfEntireFile.
- brevityState := #fullFile. "don't change till actually read"
- ^ contents].
"if brevityFlag is true, don't display long files when first selected"
first5000 := f next: 5000.
f close.
- contents := 'File ''{1}'' is {2} bytes long.
- You may use the ''get'' command to read the entire file.
-
- Here are the first 5000 characters...
- ------------------------------------------
- {3}
- ------------------------------------------
- ... end of the first 5000 characters.' translated format: {fileName. fileSize. first5000}.
brevityState := #briefFile. "don't change till actually read"
+ ^ contents := self decorateTruncatedText: first5000 size: fileSize limit: 5000!
- ^ contents.
- !
Item was changed:
----- Method: FileList>>readContentsHex: (in category 'private') -----
readContentsHex: brevity
"retrieve the contents from the external file unless it is too long.
Don't create a file here. Check if exists."
| f size data hexData s |
f := directory oldFileOrNoneNamed: self fullName.
f == nil ifTrue: [^ 'For some reason, this file cannot be read' translated].
f binary.
((size := f size)) > 5000 & brevity
ifTrue: [data := f next: 10000. f close. brevityState := #briefHex]
ifFalse: [data := f contentsOfEntireFile. brevityState := #fullHex].
s := WriteStream on: (String new: data size*4).
0 to: data size-1 by: 16 do:
[:loc | s nextPutAll: loc printStringHex; space;
nextPut: $(; print: loc; nextPut: $); space; tab.
loc+1 to: (loc+16 min: data size) do: [:i | s nextPutAll: (data at: i) printStringHex; space].
s cr].
hexData := s contents.
+ (brevity not or: [size <= 5000]) ifTrue: [
+ ^ contents := hexData].
+
+ ^ contents := self decorateTruncatedText: hexData size: size limit: 5000!
- ^ contents := ((size > 5000) & brevity
- ifTrue: ['File ''{1}'' is {2} bytes long.
- You may use the ''get'' command to read the entire file.
-
- Here are the first 5000 characters...
- ------------------------------------------
- {3}
- ------------------------------------------
- ... end of the first 5000 characters.' translated format: {fileName. size. hexData}]
- ifFalse: [hexData]).
- !
Item was changed:
----- Method: FileList>>readServerBrief (in category 'private') -----
readServerBrief
+ | lString sizeStr fsize ff first3500 parts |
- | lString sizeStr fsize ff first5000 parts |
"If file on server is known to be long, just read the beginning. Cheat badly by reading the fileList string."
listIndex = 0 ifTrue: [^ self].
"Get size from file list entry"
lString := list at: listIndex.
parts := lString findTokens: '()'.
sortMode = #name ifTrue: [sizeStr := (parts second findTokens: ' ') third].
sortMode = #date ifTrue: [sizeStr := (parts first findTokens: ' ') third].
sortMode = #size ifTrue: [sizeStr := (parts first findTokens: ' ') first].
fsize := (sizeStr copyWithout: $,) asNumber.
fsize <= 50000 ifTrue:
[ff := directory oldFileOrNoneNamed: self fullName.
ff ifNil: [^ 'For some reason, this file cannot be read' translated].
contents := ff contentsOfEntireFile.
brevityState := #fullFile. "don't change till actually read"
^ contents].
"if brevityFlag is true, don't display long files when first selected"
+ first3500 := directory getOnly: 3500 from: fileName.
- first5000 := directory getOnly: 3500 from: fileName.
- contents := 'File ''{1}'' is {2} bytes long.
- You may use the ''get'' command to read the entire file.
-
- Here are the first 3500 characters...
- ------------------------------------------
- {3}
- ------------------------------------------
- ... end of the first 3500 characters.' translated format: {fileName. sizeStr. first5000}.
brevityState := #briefFile. "don't change till actually read"
+ ^ contents := self decorateTruncatedText: first3500 size: sizeStr limit: 3500!
- ^ contents.
-
- !
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-ct.1214.mcz
==================== Summary ====================
Name: Tools-ct.1214
Author: ct
Time: 3 June 2023, 6:52:38.283136 pm
UUID: b37182a9-07fd-6045-a122-9e5c2458c589
Ancestors: Tools-ct.1213
Proposal: Sort classes in ClassListBrowser, analogously to SystemNavigation>>#allMethodsSelect:.
=============== Diff against Tools-ct.1213 ===============
Item was changed:
----- Method: ClassListBrowser class>>browseClassesSatisfying:title: (in category 'instance creation') -----
browseClassesSatisfying: classBlock title: aTitle
"Put up a ClassListBrowser showing all classes that satisfy the classBlock."
self newOnClassesNamed:
(self systemNavigation allClasses select: [:c | (classBlock value: c) == true]
+ thenCollect: [:c | c name]) sorted
- thenCollect: [:c | c name])
label: aTitle!
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-ct.1217.mcz
==================== Summary ====================
Name: Tools-ct.1217
Author: ct
Time: 3 June 2023, 10:27:19.522136 pm
UUID: 0c2e8345-da8a-b74d-a527-510fdf8c7ce5
Ancestors: Tools-ct.1216
Fixes change logging for methods that are recompiled from a browser without its existing category being selected. Previously, this kept the organization in the image intact but logged a {nil} category to the change set and to the changes file.
=============== Diff against Tools-ct.1216 ===============
Item was changed:
----- Method: Browser>>defineMessageFrom:notifying: (in category 'message functions') -----
defineMessageFrom: aString notifying: aController
"Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer the selector obtained if compilation succeeds, nil otherwise."
| currentSelector selector category oldMessageList selectedClassOrMetaClass |
currentSelector := self selectedMessageName.
oldMessageList := self messageList.
selectedClassOrMetaClass := self selectedClassOrMetaClass.
contents := nil.
selector := (selectedClassOrMetaClass newParser parseSelector: aString).
(self metaClassIndicated
and: [(selectedClassOrMetaClass includesSelector: selector) not
and: [Metaclass isScarySelector: selector]])
ifTrue: ["A first-time definition overlaps the protocol of Metaclasses"
(self confirm: ((selector , ' is used in the existing class system.
Overriding it could cause serious problems.
Is this really what you want to do?') asText makeBoldFrom: 1 to: selector size))
ifFalse: [^nil]].
category := currentSelector
+ ifNil: [ self selectedMessageCategoryName ifNil: [ selectedClassOrMetaClass whichCategoryIncludesSelector: selector ] ]
- ifNil: [ self selectedMessageCategoryName ]
ifNotNil: [ (selectedClassOrMetaClass >> selectedMessageName) methodReference ifNotNil: [ : ref | ref category ]].
selector := selectedClassOrMetaClass
compile: aString
classified: category
notifying: aController.
selector ifNil: [^ nil].
contents := aString copy.
self changed: #messageCategoryList. "Because the 'as yet unclassified' might just appear."
self changed: #messageList. "Because we have code-dependent list formatting by now such as #isDeprecated."
selector ~~ currentSelector
ifTrue:
[category = ClassOrganizer nullCategory
ifTrue: [self changed: #classSelectionChanged.
self changed: #classList.
self messageCategoryListIndex: 1].
self setClassOrganizer. "In case organization not cached"
(oldMessageList includes: selector)
ifFalse: [self changed: #messageList].
self messageListIndex: (self messageList indexOf: selector)].
^ selector!