Skip to content

Add Ribbon View, Demo Fold Provider, Ribbon Toggles #315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: feat/code-folding
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@
"version" : "0.1.20"
}
},
{
"identity" : "codeedittextview",
"kind" : "remoteSourceControl",
"location" : "https://github.com/CodeEditApp/CodeEditTextView.git",
"state" : {
"revision" : "a5912e60f6bac25cd1cdf8bb532e1125b21cf7f7",
"version" : "0.10.1"
}
},
{
"identity" : "rearrange",
"kind" : "remoteSourceControl",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct ContentView: View {
@State private var settingsIsPresented: Bool = false
@State private var treeSitterClient = TreeSitterClient()
@AppStorage("showMinimap") private var showMinimap: Bool = true
@AppStorage("showFoldingRibbon") private var showFoldingRibbon: Bool = true
@State private var indentOption: IndentOption = .spaces(count: 4)
@AppStorage("reformatAtColumn") private var reformatAtColumn: Int = 80
@AppStorage("showReformattingGuide") private var showReformattingGuide: Bool = false
Expand Down Expand Up @@ -56,7 +57,8 @@ struct ContentView: View {
useSystemCursor: useSystemCursor,
showMinimap: showMinimap,
reformatAtColumn: reformatAtColumn,
showReformattingGuide: showReformattingGuide
showReformattingGuide: showReformattingGuide,
showFoldingRibbon: showFoldingRibbon
)
.overlay(alignment: .bottom) {
StatusBar(
Expand All @@ -71,7 +73,8 @@ struct ContentView: View {
showMinimap: $showMinimap,
indentOption: $indentOption,
reformatAtColumn: $reformatAtColumn,
showReformattingGuide: $showReformattingGuide
showReformattingGuide: $showReformattingGuide,
showFoldingRibbon: $showFoldingRibbon
)
}
.ignoresSafeArea()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct StatusBar: View {
@Binding var indentOption: IndentOption
@Binding var reformatAtColumn: Int
@Binding var showReformattingGuide: Bool
@Binding var showFoldingRibbon: Bool

var body: some View {
HStack {
Expand All @@ -43,6 +44,7 @@ struct StatusBar: View {
.onChange(of: reformatAtColumn) { _, newValue in
reformatAtColumn = max(1, min(200, newValue))
}
Toggle("Show Folding Ribbon", isOn: $showFoldingRibbon)
if #available(macOS 14, *) {
Toggle("Use System Cursor", isOn: $useSystemCursor)
} else {
Expand Down
9 changes: 0 additions & 9 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@
"version" : "0.1.20"
}
},
{
"identity" : "codeedittextview",
"kind" : "remoteSourceControl",
"location" : "https://github.com/CodeEditApp/CodeEditTextView.git",
"state" : {
"revision" : "a5912e60f6bac25cd1cdf8bb532e1125b21cf7f7",
"version" : "0.10.1"
}
},
{
"identity" : "rearrange",
"kind" : "remoteSourceControl",
Expand Down
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ let package = Package(
dependencies: [
// A fast, efficient, text view for code.
.package(
url: "https://github.com/CodeEditApp/CodeEditTextView.git",
from: "0.10.1"
path: "../CodeEditTextView"
// url: "https://github.com/CodeEditApp/CodeEditTextView.git",
// from: "0.10.1"
),
// tree-sitter languages
.package(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,22 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
/// the default `TreeSitterClient` highlighter.
/// - contentInsets: Insets to use to offset the content in the enclosing scroll view. Leave as `nil` to let the
/// scroll view automatically adjust content insets.
/// - additionalTextInsets: An additional amount to inset the text of the editor by.
/// - additionalTextInsets: A set of extra text insets to indent only *text* content. Does not effect
/// decorations like the find panel.
/// - isEditable: A Boolean value that controls whether the text view allows the user to edit text.
/// - isSelectable: A Boolean value that controls whether the text view allows the user to select text. If this
/// value is true, and `isEditable` is false, the editor is selectable but not editable.
/// - letterSpacing: The amount of space to use between letters, as a percent. Eg: `1.0` = no space, `1.5` = 1/2 a
/// character's width between characters, etc. Defaults to `1.0`
/// - bracketPairEmphasis: The type of highlight to use to highlight bracket pairs.
/// See `BracketPairHighlight` for more information. Defaults to `nil`
/// - useSystemCursor: If true, uses the system cursor on `>=macOS 14`.
/// - useSystemCursor: Use the system cursor instead of the default line cursor. Only available after macOS 14.
/// - undoManager: The undo manager for the text view. Defaults to `nil`, which will create a new CEUndoManager
/// - coordinators: Any text coordinators for the view to use. See ``TextViewCoordinator`` for more information.
/// - showMinimap: Whether to show the minimap
/// - showMinimap: Toggle the visibility of the minimap.
/// - reformatAtColumn: The column to reformat at
/// - showReformattingGuide: Whether to show the reformatting guide
/// - showFoldingRibbon: Toggle the visibility of the line folding ribbon.
public init(
_ text: Binding<String>,
language: CodeLanguage,
Expand All @@ -77,7 +79,8 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
coordinators: [any TextViewCoordinator] = [],
showMinimap: Bool,
reformatAtColumn: Int,
showReformattingGuide: Bool
showReformattingGuide: Bool,
showFoldingRibbon: Bool
) {
self.text = .binding(text)
self.language = language
Expand Down Expand Up @@ -107,6 +110,7 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
self.showMinimap = showMinimap
self.reformatAtColumn = reformatAtColumn
self.showReformattingGuide = showReformattingGuide
self.showFoldingRibbon = showFoldingRibbon
}

/// Initializes a Text Editor
Expand All @@ -127,18 +131,22 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
/// the default `TreeSitterClient` highlighter.
/// - contentInsets: Insets to use to offset the content in the enclosing scroll view. Leave as `nil` to let the
/// scroll view automatically adjust content insets.
/// - additionalTextInsets: A set of extra text insets to indent only *text* content. Does not effect
/// decorations like the find panel.
/// - isEditable: A Boolean value that controls whether the text view allows the user to edit text.
/// - isSelectable: A Boolean value that controls whether the text view allows the user to select text. If this
/// value is true, and `isEditable` is false, the editor is selectable but not editable.
/// - letterSpacing: The amount of space to use between letters, as a percent. Eg: `1.0` = no space, `1.5` = 1/2 a
/// character's width between characters, etc. Defaults to `1.0`
/// - bracketPairEmphasis: The type of highlight to use to highlight bracket pairs.
/// See `BracketPairEmphasis` for more information. Defaults to `nil`
/// - useSystemCursor: Use the system cursor instead of the default line cursor. Only available after macOS 14.
/// - undoManager: The undo manager for the text view. Defaults to `nil`, which will create a new CEUndoManager
/// - coordinators: Any text coordinators for the view to use. See ``TextViewCoordinator`` for more information.
/// - showMinimap: Whether to show the minimap
/// - showMinimap: Toggle the visibility of the minimap.
/// - reformatAtColumn: The column to reformat at
/// - showReformattingGuide: Whether to show the reformatting guide
/// - showFoldingRibbon: Toggle the visibility of the line folding ribbon.
public init(
_ text: NSTextStorage,
language: CodeLanguage,
Expand All @@ -163,7 +171,8 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
coordinators: [any TextViewCoordinator] = [],
showMinimap: Bool,
reformatAtColumn: Int,
showReformattingGuide: Bool
showReformattingGuide: Bool,
showFoldingRibbon: Bool
) {
self.text = .storage(text)
self.language = language
Expand Down Expand Up @@ -193,6 +202,7 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
self.showMinimap = showMinimap
self.reformatAtColumn = reformatAtColumn
self.showReformattingGuide = showReformattingGuide
self.showFoldingRibbon = showFoldingRibbon
}

package var text: TextAPI
Expand All @@ -219,6 +229,7 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
package var showMinimap: Bool
private var reformatAtColumn: Int
private var showReformattingGuide: Bool
package var showFoldingRibbon: Bool

public typealias NSViewControllerType = TextViewController

Expand Down Expand Up @@ -247,7 +258,8 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
coordinators: coordinators,
showMinimap: showMinimap,
reformatAtColumn: reformatAtColumn,
showReformattingGuide: showReformattingGuide
showReformattingGuide: showReformattingGuide,
showFoldingRibbon: showFoldingRibbon
)
switch text {
case .binding(let binding):
Expand Down Expand Up @@ -336,6 +348,7 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
controller.contentInsets = contentInsets
controller.additionalTextInsets = additionalTextInsets
controller.showMinimap = showMinimap
controller.showFoldingRibbon = showFoldingRibbon

if controller.indentOption != indentOption {
controller.indentOption = indentOption
Expand Down Expand Up @@ -397,6 +410,7 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
controller.showMinimap == showMinimap &&
controller.reformatAtColumn == reformatAtColumn &&
controller.showReformattingGuide == showReformattingGuide &&
controller.showFoldingRibbon == showFoldingRibbon &&
areHighlightProvidersEqual(controller: controller, coordinator: coordinator)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
import Foundation

extension TextViewController: GutterViewDelegate {
public func gutterViewWidthDidUpdate(newWidth: CGFloat) {
gutterView?.frame.size.width = newWidth
textView?.textInsets = textViewInsets
public func gutterViewWidthDidUpdate() {
updateTextInsets()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ import CodeEditTextView
import AppKit

extension TextViewController {
override public func viewWillAppear() {
super.viewWillAppear()
// The calculation this causes cannot be done until the view knows it's final position
updateTextInsets()
minimapView.layout()
}

override public func loadView() {
super.loadView()

Expand Down Expand Up @@ -106,9 +113,7 @@ extension TextViewController {
object: scrollView.contentView,
queue: .main
) { [weak self] notification in
guard let clipView = notification.object as? NSClipView,
let textView = self?.textView else { return }
textView.updatedViewport(self?.scrollView.documentVisibleRect ?? .zero)
guard let clipView = notification.object as? NSClipView else { return }
self?.gutterView.needsDisplay = true
self?.minimapXConstraint?.constant = clipView.bounds.origin.x
}
Expand All @@ -120,7 +125,6 @@ extension TextViewController {
object: scrollView.contentView,
queue: .main
) { [weak self] _ in
self?.textView.updatedViewport(self?.scrollView.documentVisibleRect ?? .zero)
self?.gutterView.needsDisplay = true
self?.emphasisManager?.removeEmphases(for: EmphasisGroup.brackets)
self?.updateTextInsets()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extension TextViewController {
gutterView.selectedLineTextColor = nil
gutterView.selectedLineColor = .clear
}
gutterView.showFoldingRibbon = showFoldingRibbon
}

/// Style the scroll view.
Expand Down
28 changes: 14 additions & 14 deletions Sources/CodeEditSourceEditor/Controller/TextViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ public class TextViewController: NSViewController { // swiftlint:disable:this ty
}
}

/// Toggles the line folding ribbon in the gutter view.
public var showFoldingRibbon: Bool {
didSet {
gutterView?.showFoldingRibbon = showFoldingRibbon
}
}

var textCoordinators: [WeakCoordinator] = []

var highlighter: Highlighter?
Expand All @@ -229,7 +236,7 @@ public class TextViewController: NSViewController { // swiftlint:disable:this ty

package var textViewInsets: HorizontalEdgeInsets {
HorizontalEdgeInsets(
left: gutterView.gutterWidth,
left: gutterView?.frame.width ?? 0.0,
right: textViewTrailingInset
)
}
Expand Down Expand Up @@ -265,6 +272,9 @@ public class TextViewController: NSViewController { // swiftlint:disable:this ty
}
}

/// A default `NSParagraphStyle` with a set `lineHeight`
package lazy var paragraphStyle: NSMutableParagraphStyle = generateParagraphStyle()

// MARK: Init

init(
Expand All @@ -291,7 +301,8 @@ public class TextViewController: NSViewController { // swiftlint:disable:this ty
coordinators: [TextViewCoordinator] = [],
showMinimap: Bool,
reformatAtColumn: Int = 80,
showReformattingGuide: Bool = false
showReformattingGuide: Bool = false,
showFoldingRibbon: Bool
) {
self.language = language
self.font = font
Expand All @@ -314,6 +325,7 @@ public class TextViewController: NSViewController { // swiftlint:disable:this ty
self.showMinimap = showMinimap
self.reformatAtColumn = reformatAtColumn
self.showReformattingGuide = showReformattingGuide
self.showFoldingRibbon = showFoldingRibbon

super.init(nibName: nil, bundle: nil)

Expand Down Expand Up @@ -362,18 +374,6 @@ public class TextViewController: NSViewController { // swiftlint:disable:this ty
self.gutterView.setNeedsDisplay(self.gutterView.frame)
}

// MARK: Paragraph Style

/// A default `NSParagraphStyle` with a set `lineHeight`
package lazy var paragraphStyle: NSMutableParagraphStyle = generateParagraphStyle()

override public func viewWillAppear() {
super.viewWillAppear()
// The calculation this causes cannot be done until the view knows it's final position
updateTextInsets()
minimapView.layout()
}

deinit {
if let highlighter {
textView.removeStorageDelegate(highlighter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ extension TextView: TextInterface {
in: mutation.range,
replacementLength: (mutation.string as NSString).length
)
layoutManager.setNeedsLayout()
}
}
Loading