[squeak-dev] Merge Request: autoEncloseBeforeSpace.cs

Marcel Taeumel marcel.taeumel at hpi.de
Wed Dec 1 13:46:45 UTC 2021


Hi Chris, hi Christoph, hi Jaromir, hi all!

Please find attached another take on this idea. No extra preference. Just tweaking the current autoEnclose-feature. In this form, I would consider using it. :-D Together with "Enclose selection".

Best,
Marcel
Am 06.11.2021 23:34:06 schrieb christoph.thiede at student.hpi.uni-potsdam.de <christoph.thiede at student.hpi.uni-potsdam.de>:
Hi Chris,

> Hopefully also when the cursor is at the end of the text, too (I didn't test it).

Yes, it does. :-)

> It seems like this feature should not disrupt expression-editing at all,
> which is what I made autoEnclose for.

Sure, but without knowing everyone's personal preferences, anyone might be used the existing workflow. Shall we keep the old preference for this eventuality or would it be okay to remove until anyone shouts? :-)

Below the complete diff of the changeset for convenience, just because my new diff generators is so funny.

Best,
Christoph


=============== Postscript ===============

"Postscript:
Leave the line above, and replace the rest of this comment by a useful one.
Executable statements should follow this comment, and should
be separated by periods, with no exclamation points (!).
Be sure to put any further comments in double-quotes, like this one."

TextEditor autoEnclose: TextEditor autoEnclose.

=============== Diff ===============

PreferenceWizardMorph>>initializePage03Interaction {initialization - pages} · ct 11/1/2021 20:19 (changed)
initializePage03Interaction

    | currentPage pane |
    currentPage := pages add: self createPage.
    pane := self createScrollPane.
    
    currentPage addMorphBack: (self createLabel: 'Choose interaction settings' color: Color white).
    currentPage addMorphBack: pane.
    
    pane scroller firstSubmorph addAllMorphsBack: {
        self createCheckbox: 'Swap mouse buttons' translated for: #SwapMouseButtons help: #(swap mouse).
        self createCheckbox: 'Focus follows mouse' translated for: #FocusFollowsMouse help: #(mouse over keyboard).
        self createCheckbox: 'Mouse wheel to focus' translated for: #SendMouseWheelToKeyboardFocus help: #(wheel keyboard).
        self createVerticalSpace.
-         self createCheckbox: 'Auto enclose brackets' translated for: #AutoEnclose help: #(auto enclose).
+         self createCheckbox: 'Auto enclose all brackets' translated for: #AutoEncloseAlways help: #(auto enclose).
+         self createCheckbox: 'Auto enclose brackets before spaces only' translated for: #AutoEncloseBeforeSpaces help: #(auto enclose).
        self createCheckbox: 'Auto indent lines' translated for: #AutoIndent help: #(auto indent).
        self createCheckbox: 'Enclose text selections' translated for: #EncloseSelection help: #(enclose selection).
        self createVerticalSpace.
        self createCheckbox: 'Arrows in scrollbar' translated for: #ScrollBarsWithoutArrowButtons help: 'Whether to show arrows for scrolling or not.' translated.
        self createCheckbox: 'Menu in scrollbar' translated for: #ScrollBarsWithoutMenuButton help: 'Whether to show a menu button or not.' translated.
        self createCheckbox: 'Scrollbars on the right' translated for: #ScrollBarsOnRight help: #(right scroll).
        self createCheckbox: 'Retractable scrollbars' translated for: #UseRetractableScrollBars help: #(retractable).
        self createCheckbox: 'Narrow scrollbars' translated for: #ScrollBarsNarrow help: #(narrow scroll).
        
        }.

PreferenceWizardMorph>>stateAutoEncloseAlways {actions - buttons} · ct 11/1/2021 20:19
+ stateAutoEncloseAlways
+
+     ^ TextEditor autoEncloseAlways

PreferenceWizardMorph>>stateAutoEncloseBeforeSpaces {actions - buttons} · ct 11/1/2021 20:19
+ stateAutoEncloseBeforeSpaces
+
+     ^ TextEditor autoEncloseBeforeSpaces

PreferenceWizardMorph>>toggleAutoEncloseAlways {actions - buttons} · ct 11/1/2021 20:20
+ toggleAutoEncloseAlways
+
+     TextEditor autoEncloseAlways: TextEditor autoEncloseAlways not.    
+     self
+         changed: #stateAutoEncloseAlways;
+         changed: #stateAutoEncloseBeforeSpaces.

PreferenceWizardMorph>>toggleAutoEncloseBeforeSpaces {actions - buttons} · ct 11/1/2021 20:20
+ toggleAutoEncloseBeforeSpaces
+
+     TextEditor autoEncloseBeforeSpaces: TextEditor autoEncloseBeforeSpaces not.    
+     self
+         changed: #stateAutoEncloseAlways;
+         changed: #stateAutoEncloseBeforeSpaces.

ReleaseBuilder class>>setPreferences {scripts} · ct 11/1/2021 20:18 (changed)
setPreferences
    "Preferences class defaultValueTableForCurrentRelease"
-     "    Preferences outOfTheBox."
-     "<-- uncomment after #defaultValueTableForCurrentRelease is fixed up."
-     "General User interaction"

+ "    Preferences outOfTheBox." "<-- uncomment after #defaultValueTableForCurrentRelease is fixed up."
+
+     "General User interaction"
    Preferences
-         enable: #generalizedYellowButtonMenu;
+         enable: #generalizedYellowButtonMenu ;
        enable: #swapMouseButtons;
        disable: #mouseOverForKeyboardFocus.
    Morph indicateKeyboardFocus: true.
    Project uiManager openToolsAttachedToMouseCursor: false.
    SearchBar useScratchPad: false.
    
    HandMorph sendMouseWheelToKeyboardFocus: false.
    HandMorph synthesizeMouseWheelEvents: true.
    
    "Text input."
    TextEditor
-         autoEnclose: true;
-         autoIndent: true;
-         encloseSelection: false;
-         destructiveBackWord: false;
-         blinkingCursor: true;
-         dumbbellCursor: false.
+          autoEnclose: #beforeSpaces ;
+          autoIndent: true ;
+          encloseSelection: false ;
+          destructiveBackWord: false ;
+          blinkingCursor: true ;
+          dumbbellCursor: false.
    PluggableTextMorph simpleFrameAdornments: false.
    TextMorphForEditView draggableTextSelection: true.
-     "Windows"
    
+     "Windows"
    SystemWindow reuseWindows: false.
    SystemWindow windowsRaiseOnClick: true.
    SystemWindow windowTitleActiveOnFirstClick: true.
-     Model windowActiveOnFirstClick: false.
-     "Not good for little screen real estate."
-     Model useColorfulWindows: false.
-     
-     Preferences disable: #fastDragWindowForMorphic.
+     Model windowActiveOnFirstClick: false. "Not good for little screen real estate."
+     Model useColorfulWindows: false.
+
+     Preferences
+         disable: #fastDragWindowForMorphic.
    AbstractResizerMorph
        gripThickness: 4;
        handleLength: 25.
    CornerGripMorph
        drawCornerResizeHandles: false;
        drawEdgeResizeHandles: false.
    ProportionalSplitterMorph
        showSplitterHandles: false;
        smartHorizontalSplitters: false;
        smartVerticalSplitters: false.
-     
+
    "Scroll bars."
    Preferences
        enable: #scrollBarsNarrow;
        enable: #scrollBarsOnRight;
        enable: #alwaysHideHScrollbar;
        disable: #alwaysShowHScrollbar;
        disable: #alwaysShowVScrollbar.
    ScrollBar
        scrollBarsWithoutArrowButtons: true;
        scrollBarsWithoutMenuButton: true.
-     ScrollPane useRetractableScrollBars: false.
-     
+     ScrollPane
+         useRetractableScrollBars: false.
+
    "Rounded corners."
    Morph preferredCornerRadius: 8.
    SystemWindow roundedWindowCorners: false.
    DialogWindow roundedDialogCorners: false.
    MenuMorph roundedMenuCorners: false.
    PluggableButtonMorph roundedButtonCorners: false.
    ScrollBar roundedScrollBarLook: false.
    
    "Gradients."
    SystemWindow gradientWindow: false.
    DialogWindow gradientDialog: false.
    MenuMorph gradientMenu: false.
    PluggableButtonMorph gradientButton: false.
    ScrollBar gradientScrollBar: false.
-     
+
    "Shadows"
    Preferences enable: #menuAppearance3d.
    Morph useSoftDropShadow: true.
    
    "Lists and Trees"
    PluggableListMorph
        filterableLists: true;
        clearFilterAutomatically: false;
        clearFilterDelay: 500;
        highlightHoveredRow: true;
        highlightPreSelection: false;
        menuRequestUpdatesSelection: true.
    PluggableTreeMorph
        filterByLabelsOnly: false;
        maximumSearchDepth: 1.
    
    "Standard Tools"
    TheWorldMainDockingBar
        showWorldMainDockingBar: true;
        showSecondsInClock: true;
        twentyFourHourClock: true.
    SearchBar useSmartSearch: true.
    Workspace shouldStyle: false.
    TranscriptStream
        forceUpdate: true;
        redirectToStdOut: false;
        characterLimit: 20000.
    Browser
        listClassesHierarchically: true;
        showClassIcons: true;
        showMessageIcons: true;
        sortMessageCategoriesAlphabetically: true.
    SystemBrowser browseWithDragNDrop: true.
    MessageSet useUnifiedMessageLabels: true.
    Preferences
        enable: #annotationPanes;
-         defaultAnnotationRequests: #(#timeStamp #author #messageCategory #implementorsCount #allChangeSets);
+         defaultAnnotationRequests: #(timeStamp author messageCategory implementorsCount allChangeSets);
        enable: #optionalButtons;
        disable: #diffsWithPrettyPrint;
        enable: #traceMessages;
        enable: #alternativeBrowseIt;
        enable: #menuWithIcons;
        enable: #visualExplorer.
    Preferences disable: #debugLogTimestamp.
+
    "Halo"
-     
    Preferences
-         enable: #showBoundsInHalo;
+         enable: #showBoundsInHalo ;
        disable: #alternateHandlesLook;
        disable: #showDirectionHandles.
    Morph
        haloForAll: true;
        metaMenuForAll: true.
-     
+
    "System"
-     NetNameResolver enableIPv6: true.
+     NetNameResolver enableIPv6: false.
    Scanner
        allowUnderscoreAsAssignment: true;
        prefAllowUnderscoreSelectors: true.
-     
+         
    Deprecation showDeprecationWarnings: true
+
    "that's all, folks"

TextEditor class>>autoEnclose {preferences} · ct 11/1/2021 20:26 (changed)
autoEnclose
-     <preference: 'Auto enclose brackets () {} []'
-         categoryList: #('Morphic' 'editing')
-         description: 'When true, typing an opening parenthesis, bracket or square-bracket will also add its corresponding closing character after the cursor so you can type within the bracket.'
-         type: #Boolean>
-         
-     ^ AutoEnclose ifNil: [ false ]
+
+     ^ AutoEnclose ifNil: [#never]

TextEditor class>>autoEnclose: {preferences} · ct 11/1/2021 20:30 (changed)
- autoEnclose: aBoolean
-     AutoEnclose := aBoolean
+ autoEnclose: aSymbol
+
+     aSymbol == true ifTrue: [
+         "backward compatibility."
+         ^ self autoEnclose: #always].
+     
+     self assert: [#(always beforeSpaces never) includes: aSymbol].
+     
+     AutoEnclose := aSymbol.

TextEditor class>>autoEncloseAlways {preferences} · ct 11/1/2021 21:48
+ autoEncloseAlways
+     <preference: 'Auto enclose all brackets () {} [] '''' "" || <>'
+         categoryList: #('Morphic' 'editing')
+         description: 'When true, typing an opening character will ALWAYS add its corresponding closing character after the cursor so you can type within the bracket.'
+         type: #Boolean>
+         
+     ^ self autoEnclose = #always

TextEditor class>>autoEncloseAlways: {preferences} · ct 11/1/2021 20:32
+ autoEncloseAlways: aBoolean
+
+     self autoEnclose: (aBoolean
+         ifTrue: [#always]
+         ifFalse: [#never]).

TextEditor class>>autoEncloseBeforeSpaces {preferences} · ct 11/1/2021 21:49
+ autoEncloseBeforeSpaces
+     <preference: 'Auto enclose brackets before spaces only () {} [] '''' "" || <>'
+         categoryList: #('Morphic' 'editing')
+         description: 'When true, typing an opening character BEFORE some space will add its corresponding closing character after the cursor so you can type within the bracket.'
+         type: #Boolean>
+         
+     ^ self autoEnclose = #beforeSpaces

TextEditor class>>autoEncloseBeforeSpaces: {preferences} · ct 11/1/2021 20:32
+ autoEncloseBeforeSpaces: aBoolean
+
+     self autoEnclose: (aBoolean
+         ifTrue: [#beforeSpaces]
+         ifFalse: [#never]).

TextEditor>>autoEncloseFor: {typing support} · ct 11/1/2021 20:28 (changed)
autoEncloseFor: typedChar
    "Answer whether typeChar was handled by auto-enclosure. Caller should call normalCharacter if not."
    | openers closers |
+     self class autoEnclose = #never
+         ifTrue: [ ^ false ].
+     (self class autoEnclose = #beforeSpaces
+         ==> [ self string at: self startIndex ifPresent: [:c | c isSeparator] ifAbsent: [true] ])
+             ifFalse: [ ^ false ].
+     
    openers := '([{'.
    closers := ')]}'.
    (closers includes: typedChar) ifTrue:
        [ | pos |
        self blinkPrevParen: typedChar.
        ((pos := self indexOfNextNonwhitespaceCharacter) notNil and: [ (paragraph string at: pos) = typedChar ])
            ifTrue:
                [ self
                    moveCursor: [ : position | position + pos - pointBlock stringIndex + 1 ]
                    forward: true
                    select: false.
                ^ true ]
            ifFalse: [ ^ false ] ].
    (openers includes: typedChar) ifTrue:
        [ self
            openTypeIn;
            addString: typedChar asString;
            addString: (closers at: (openers indexOf: typedChar)) asString;
            insertAndCloseTypeIn;
            
            moveCursor: [ : position | position - 1 ]
            forward: false
            select: false.
        ^ true ].
    ^ false

TextEditor>>dispatchOnKeyboardEvent: {typing support} · ct 11/1/2021 20:28 (changed)
dispatchOnKeyboardEvent: aKeyboardEvent
    "Carry out the action associated with this character, if any. Type-ahead is passed so some routines can flush or use it."
    
    | honorCommandKeys typedChar |
    typedChar := aKeyboardEvent keyCharacter.
    
    "Handle one-line input fields."
    (typedChar == Character cr and: [morph acceptOnCR])
        ifTrue: [^ true].
    
    "Clear highlight for last opened parenthesis."
    self clearParens.
    
    "Handle line breaks and auto indent."
    typedChar == Character cr ifTrue: [
        aKeyboardEvent controlKeyPressed
            ifTrue: [^ self normalCharacter: aKeyboardEvent].
        aKeyboardEvent shiftPressed
            ifTrue: [^ self lf: aKeyboardEvent].
        aKeyboardEvent commandKeyPressed
            ifTrue: [^ self crlf: aKeyboardEvent].
        ^ self crWithIndent: aKeyboardEvent].

    "Handle indent/outdent with selected text block."
    typedChar == Character tab ifTrue: [
        aKeyboardEvent shiftPressed
            ifTrue: [self outdent: aKeyboardEvent. ^ true]
            ifFalse: [self hasMultipleLinesSelected
                ifTrue: [self indent: aKeyboardEvent. ^ true]]].

    honorCommandKeys := Preferences cmdKeysInText.

    (honorCommandKeys and: [typedChar == Character enter])
        ifTrue: [^ self dispatchOnEnterWith: aKeyboardEvent].
    
    "Special keys overwrite crtl+key combinations - at least on Windows. To resolve this
    conflict, assume that keys other than cursor keys aren't used together with Crtl."
    ((self class specialShiftCmdKeys includes: aKeyboardEvent keyValue)
        and: [aKeyboardEvent keyValue < 27])
            ifTrue: [^ aKeyboardEvent controlKeyPressed
                ifTrue: [self
                            perform: (self class shiftCmdActions at: aKeyboardEvent keyValue + 1)
                            with: aKeyboardEvent]
                ifFalse: [self
                            perform: (self class cmdActions at: aKeyboardEvent keyValue + 1)
                            with: aKeyboardEvent]].
            
    "backspace, and escape keys (ascii 8 and 27) are command keys"
    ((honorCommandKeys and: [aKeyboardEvent commandKeyPressed])
        or: [self class specialShiftCmdKeys includes: aKeyboardEvent keyValue])
            ifTrue: [ ^ aKeyboardEvent shiftPressed
                ifTrue: [self
                            perform: (self class shiftCmdActions at: aKeyboardEvent keyValue + 1)
                            with: aKeyboardEvent]
                ifFalse: [self
                            perform: (self class cmdActions at: aKeyboardEvent keyValue + 1)
                            with: aKeyboardEvent]].

    "the control key can be used to invoke shift-cmd shortcuts"
    (honorCommandKeys and: [ aKeyboardEvent controlKeyPressed ])
        ifTrue: [^ self
                    perform: (self class shiftCmdActions at: aKeyboardEvent keyValue + 1)
                    with: aKeyboardEvent].

    "Enclose selection with brackets etc."
    ((self class encloseSelection and: [self hasSelection]) and: [self enclose: aKeyboardEvent])
        ifTrue: [^ true].

    "Automatically enclose paired characters such as brackets."
-     (self class autoEnclose and: [self autoEncloseFor: typedChar])
+     (self autoEncloseFor: typedChar)
        ifTrue: [^ true].
        
    "Even if no enclosing feature was used, highlight the matching bracket when closing one."
    (')]}' includes: typedChar)
        ifTrue: [self blinkPrevParen: typedChar].
                    
    self normalCharacter: aKeyboardEvent.
    ^ false

---
Sent from Squeak Inbox Talk [https://github.com/hpi-swa-lab/squeak-inbox-talk]

On 2021-11-05T19:46:16-05:00, asqueaker at gmail.com wrote:

> Hi Christoph,
>
> This changeset refines the existing autoEnclose mechanism. Instead of
> > having inserted enclosing brackets always, you can now activate a new
> > preference to only insert these characters if there is any space after the
> > cursor.
>
>
> Hopefully also when the cursor is at the end of the text, too (I didn't
> test it).
>
> > I am not sure whether a single preference would fit everyone's needs.
>
> It seems like this feature should not disrupt expression-editing at all,
> which is what I made autoEnclose for.
>
> Thanks,
> Chris
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211105/7d2cc226/attachment.html>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211201/9eecd3ee/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: TextEditor-autoEncloseFor.st
Type: application/octet-stream
Size: 1261 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211201/9eecd3ee/attachment.obj>


More information about the Squeak-dev mailing list