@@ -11,11 +11,7 @@ import AppKit
1111extension TextViewController {
1212 // swiftlint:disable:next function_body_length
1313 override public func loadView( ) {
14- let stackView = NSStackView ( )
15- stackView. orientation = . vertical
16- stackView. spacing = 10
17- stackView. alignment = . leading
18- stackView. translatesAutoresizingMaskIntoConstraints = false
14+ super. loadView ( )
1915
2016 scrollView = NSScrollView ( )
2117 textView. postsFrameChangedNotifications = true
@@ -39,46 +35,12 @@ extension TextViewController {
3935 for: . horizontal
4036 )
4137
42- searchField = NSTextField ( )
43- searchField. placeholderString = " Search... "
44- searchField. controlSize = . regular // TODO: a
45- searchField. focusRingType = . none
46- searchField. bezelStyle = . roundedBezel
47- searchField. drawsBackground = true
48- searchField. translatesAutoresizingMaskIntoConstraints = false
49- searchField. action = #selector( onSubmit)
50- searchField. target = self
51-
52- prevButton = NSButton ( title: " ◀︎ " , target: self , action: #selector( prevButtonClicked) )
53- prevButton. bezelStyle = . texturedRounded
54- prevButton. controlSize = . small
55- prevButton. translatesAutoresizingMaskIntoConstraints = false
56-
57- nextButton = NSButton ( title: " ▶︎ " , target: self , action: #selector( nextButtonClicked) )
58- nextButton. bezelStyle = . texturedRounded
59- nextButton. controlSize = . small
60- nextButton. translatesAutoresizingMaskIntoConstraints = false
61-
62- stackview = NSStackView ( )
63- stackview. orientation = . horizontal
64- stackview. spacing = 8
65- stackview. edgeInsets = NSEdgeInsets ( top: 5 , left: 10 , bottom: 5 , right: 10 )
66- stackview. translatesAutoresizingMaskIntoConstraints = false
67-
68- stackview. addView ( searchField, in: . leading)
69- stackview. addView ( prevButton, in: . trailing)
70- stackview. addView ( nextButton, in: . trailing)
38+ let searchController = SearchViewController ( target: self , childView: scrollView)
39+ addChild ( searchController)
40+ self . view. addSubview ( searchController. view)
41+ searchController. view. viewDidMoveToSuperview ( )
42+ self . searchController = searchController
7143
72- NotificationCenter . default. addObserver (
73- self ,
74- selector: #selector( searchFieldUpdated ( _: ) ) ,
75- name: NSControl . textDidChangeNotification,
76- object: searchField
77- )
78-
79- stackView. addArrangedSubview ( stackview)
80- stackView. addArrangedSubview ( scrollView)
81- self . view = stackView
8244 if let _undoManager {
8345 textView. setUndoManager ( _undoManager)
8446 }
@@ -90,15 +52,10 @@ extension TextViewController {
9052 setUpTextFormation ( )
9153
9254 NSLayoutConstraint . activate ( [
93- stackView. leadingAnchor. constraint ( equalTo: view. leadingAnchor) ,
94- stackView. trailingAnchor. constraint ( equalTo: view. trailingAnchor) ,
95- stackView. topAnchor. constraint ( equalTo: view. topAnchor) ,
96- stackView. bottomAnchor. constraint ( equalTo: view. bottomAnchor)
97-
98- // scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
99- // scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
100- // scrollView.topAnchor.constraint(equalTo: view.topAnchor),
101- // scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
55+ searchController. view. leadingAnchor. constraint ( equalTo: view. leadingAnchor) ,
56+ searchController. view. trailingAnchor. constraint ( equalTo: view. trailingAnchor) ,
57+ searchController. view. topAnchor. constraint ( equalTo: view. topAnchor) ,
58+ searchController. view. bottomAnchor. constraint ( equalTo: view. bottomAnchor)
10259 ] )
10360
10461 if !cursorPositions. isEmpty {
@@ -162,18 +119,64 @@ extension TextViewController {
162119 if let localEventMonitor = self . localEvenMonitor {
163120 NSEvent . removeMonitor ( localEventMonitor)
164121 }
165- self . localEvenMonitor = NSEvent . addLocalMonitorForEvents ( matching: . keyDown) { [ weak self] event in
122+ self . localEvenMonitor = NSEvent . addLocalMonitorForEvents ( matching: . keyDown) { [ weak self] event -> NSEvent ? in
166123 guard self ? . view. window? . firstResponder == self ? . textView else { return event }
124+ let modifierFlags = event. modifierFlags. intersection ( . deviceIndependentFlagsMask)
125+
126+ switch ( modifierFlags, event. charactersIgnoringModifiers? . lowercased ( ) ) {
127+ case ( . command, " / " ) :
128+ self ? . handleCommandSlash ( )
129+ return nil
130+ case ( . command, " f " ) :
131+ _ = self ? . textView. resignFirstResponder ( )
132+ self ? . searchController? . showSearchBar ( )
133+ return nil
134+ case ( [ ] , " \u{1b} " ) : // Escape key
135+ self ? . searchController? . hideSearchBar ( )
136+ _ = self ? . textView. becomeFirstResponder ( )
137+ self ? . textView. selectionManager. setSelectedRanges (
138+ self ? . textView. selectionManager. textSelections. map { $0. range } ?? [ ]
139+ )
140+ return nil
141+ default :
142+ return event
143+ }
144+ }
145+ }
146+ func handleCommand( event: NSEvent , modifierFlags: UInt ) -> NSEvent ? {
147+ let commandKey = NSEvent . ModifierFlags. command. rawValue
148+
149+ switch ( modifierFlags, event. charactersIgnoringModifiers) {
150+ case ( commandKey, " / " ) :
151+ handleCommandSlash ( )
152+ return nil
153+ case ( commandKey, " [ " ) :
154+ handleIndent ( inwards: true )
155+ return nil
156+ case ( commandKey, " ] " ) :
157+ handleIndent ( )
158+ return nil
159+ case ( _, _) :
160+ return event
161+ }
162+ }
167163
168- let tabKey : UInt16 = 0x30
169- let modifierFlags = event. modifierFlags. intersection ( . deviceIndependentFlagsMask) . rawValue
164+ /// Handles the tab key event.
165+ /// If the Shift key is pressed, it handles unindenting. If no modifier key is pressed, it checks if multiple lines
166+ /// are highlighted and handles indenting accordingly.
167+ ///
168+ /// - Returns: The original event if it should be passed on, or `nil` to indicate handling within the method.
169+ func handleTab( event: NSEvent , modifierFalgs: UInt ) -> NSEvent ? {
170+ let shiftKey = NSEvent . ModifierFlags. shift. rawValue
170171
171- if event. keyCode == tabKey {
172- return self ? . handleTab ( event: event, modifierFalgs: modifierFlags)
173- } else {
174- return self ? . handleCommand ( event: event, modifierFlags: modifierFlags)
175- }
172+ if modifierFalgs == shiftKey {
173+ handleIndent ( inwards: true )
174+ } else {
175+ // Only allow tab to work if multiple lines are selected
176+ guard multipleLinesHighlighted ( ) else { return event }
177+ handleIndent ( )
176178 }
179+ return nil
177180 }
178181 func handleCommand( event: NSEvent , modifierFlags: UInt ) -> NSEvent ? {
179182 let commandKey = NSEvent . ModifierFlags. command. rawValue
0 commit comments