Skip to content

Commit b96f270

Browse files
Find: Replace and Match Case Toggle (#301)
### Description This PR adds the following functionality to the source editor find panel: - Replace: Enables replacing matched text with the specified replacement. - Toggle Match Navigation Wrap-Around: Allows cycling through matches from the beginning when reaching the end. - Toggle Match Case: Adds an option to filter matches by case sensitivity. - Made find panel responsive at small sizes using `ViewThatFits`. ### Related Issues * #295 * CodeEditApp/CodeEditTextView#1 ### Checklist <!--- Add things that are not yet implemented above --> - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots https://github.com/user-attachments/assets/ec23ffe7-6d24-48b7-889a-11a92ec6c147 https://github.com/user-attachments/assets/cfca6d8e-7b97-4258-ae2e-ee82bbf6b9af --------- Co-authored-by: Khan Winter <35942988+thecoolwinter@users.noreply.github.com>
1 parent 3dccebd commit b96f270

34 files changed

+1489
-646
lines changed

Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
"version" : "0.1.20"
1010
}
1111
},
12+
{
13+
"identity" : "codeeditsymbols",
14+
"kind" : "remoteSourceControl",
15+
"location" : "https://github.com/CodeEditApp/CodeEditSymbols.git",
16+
"state" : {
17+
"revision" : "ae69712b08571c4469c2ed5cd38ad9f19439793e",
18+
"version" : "0.2.3"
19+
}
20+
},
1221
{
1322
"identity" : "codeedittextview",
1423
"kind" : "remoteSourceControl",

Package.resolved

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
"version" : "0.1.20"
1010
}
1111
},
12+
{
13+
"identity" : "codeeditsymbols",
14+
"kind" : "remoteSourceControl",
15+
"location" : "https://github.com/CodeEditApp/CodeEditSymbols.git",
16+
"state" : {
17+
"revision" : "ae69712b08571c4469c2ed5cd38ad9f19439793e",
18+
"version" : "0.2.3"
19+
}
20+
},
1221
{
1322
"identity" : "codeedittextview",
1423
"kind" : "remoteSourceControl",

Package.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ let package = Package(
2424
url: "https://github.com/CodeEditApp/CodeEditLanguages.git",
2525
exact: "0.1.20"
2626
),
27+
// CodeEditSymbols
28+
.package(
29+
url: "https://github.com/CodeEditApp/CodeEditSymbols.git",
30+
exact: "0.2.3"
31+
),
2732
// SwiftLint
2833
.package(
2934
url: "https://github.com/lukepistrol/SwiftLintPlugin",
@@ -43,7 +48,8 @@ let package = Package(
4348
dependencies: [
4449
"CodeEditTextView",
4550
"CodeEditLanguages",
46-
"TextFormation"
51+
"TextFormation",
52+
"CodeEditSymbols"
4753
],
4854
plugins: [
4955
.plugin(name: "SwiftLint", package: "SwiftLintPlugin")

Sources/CodeEditSourceEditor/Controller/TextViewController+Cursor.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import AppKit
1111
extension TextViewController {
1212
/// Sets new cursor positions.
1313
/// - Parameter positions: The positions to set. Lines and columns are 1-indexed.
14-
public func setCursorPositions(_ positions: [CursorPosition]) {
14+
public func setCursorPositions(_ positions: [CursorPosition], scrollToVisible: Bool = false) {
1515
if isPostingCursorNotification { return }
1616
var newSelectedRanges: [NSRange] = []
1717
for position in positions {
@@ -33,6 +33,10 @@ extension TextViewController {
3333
}
3434
}
3535
textView.selectionManager.setSelectedRanges(newSelectedRanges)
36+
37+
if scrollToVisible {
38+
textView.scrollSelectionToVisible()
39+
}
3640
}
3741

3842
/// Update the ``TextViewController/cursorPositions`` variable with new text selections from the text view.

Sources/CodeEditSourceEditor/Controller/TextViewController+FindPanelTarget.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
// Created by Khan Winter on 3/16/25.
66
//
77

8-
import Foundation
8+
import AppKit
99
import CodeEditTextView
1010

1111
extension TextViewController: FindPanelTarget {
12+
var findPanelTargetView: NSView {
13+
textView
14+
}
15+
1216
func findPanelWillShow(panelHeight: CGFloat) {
1317
updateContentInsets()
1418
}
@@ -17,6 +21,10 @@ extension TextViewController: FindPanelTarget {
1721
updateContentInsets()
1822
}
1923

24+
func findPanelModeDidChange(to mode: FindPanelMode) {
25+
updateContentInsets()
26+
}
27+
2028
var emphasisManager: EmphasisManager? {
2129
textView?.emphasisManager
2230
}

Sources/CodeEditSourceEditor/Controller/TextViewController+LoadView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ extension TextViewController {
220220
self.findViewController?.showFindPanel()
221221
return nil
222222
case (0, "\u{1b}"): // Escape key
223-
self.findViewController?.findPanel.dismiss()
223+
self.findViewController?.hideFindPanel()
224224
return nil
225225
case (_, _):
226226
return event

Sources/CodeEditSourceEditor/Controller/TextViewController+StyleViews.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ extension TextViewController {
9696
minimapView.scrollView.contentInsets.bottom += additionalTextInsets?.bottom ?? 0
9797

9898
// Inset the top by the find panel height
99-
let findInset = (findViewController?.isShowingFindPanel ?? false) ? FindPanel.height : 0
99+
let findInset: CGFloat = if findViewController?.viewModel.isShowingFindPanel ?? false {
100+
findViewController?.viewModel.panelHeight ?? 0
101+
} else {
102+
0
103+
}
100104
scrollView.contentInsets.top += findInset
101105
minimapView.scrollView.contentInsets.top += findInset
102106

Sources/CodeEditSourceEditor/Find/FindPanelDelegate.swift

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// FindPanelMode.swift
3+
// CodeEditSourceEditor
4+
//
5+
// Created by Khan Winter on 4/18/25.
6+
//
7+
8+
enum FindPanelMode: CaseIterable {
9+
case find
10+
case replace
11+
12+
var displayName: String {
13+
switch self {
14+
case .find:
15+
return "Find"
16+
case .replace:
17+
return "Replace"
18+
}
19+
}
20+
}

Sources/CodeEditSourceEditor/Find/FindPanelTarget.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
// Created by Khan Winter on 3/10/25.
66
//
77

8-
import Foundation
8+
import AppKit
99
import CodeEditTextView
1010

1111
protocol FindPanelTarget: AnyObject {
12-
var emphasisManager: EmphasisManager? { get }
13-
var text: String { get }
12+
var textView: TextView! { get }
13+
var findPanelTargetView: NSView { get }
1414

1515
var cursorPositions: [CursorPosition] { get }
16-
func setCursorPositions(_ positions: [CursorPosition])
16+
func setCursorPositions(_ positions: [CursorPosition], scrollToVisible: Bool)
1717
func updateCursorPosition()
1818

1919
func findPanelWillShow(panelHeight: CGFloat)
2020
func findPanelWillHide(panelHeight: CGFloat)
21+
func findPanelModeDidChange(to mode: FindPanelMode)
2122
}

Sources/CodeEditSourceEditor/Find/FindViewController+FindPanelDelegate.swift

Lines changed: 0 additions & 191 deletions
This file was deleted.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy