• Stars
    star
    1,073
  • Rank 43,114 (Top 0.9 %)
  • Language
    Swift
  • License
    Other
  • Created over 2 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Performant and reusable text view component (TextKit 2), with line numbers and more. UITextView / NSTextView replacement.

STTextView

Performant macOS TextView with line numbers and much more. (NSTextView replacement)

The goal of this project is to build NSTextView replacement component utilizing TextKit 2 framework. due to many good reasons.

The component is developed to serve Swift Studio needs as a source code editor.

Screenshot 2023-04-24 at 02 03 51

sttextview-demo-small.mp4

TextKit 2 was announced during WWDC 2021 as a TextKit 1 replacement for text layout and whatnot. Apple announced that NSTextView, the view component specialized for text editing, will adopt TextKit 2 and provide support along TextKit 1 bits. As I started to learn more about NSTextView + TextKit2, I realized as of today (Feb 2022), neither NSTextView is fully functional, nor TextKit 2 classes are fully functional. Along the way, I reported several bug reports to Apple requested DTS (support tickets). Eventually, I've got blocked by specific bugs that pushed me to start this project.

Features

  • macOS text system integration
  • Performant Text editing
  • Line numbers in a ruler view
  • Ruler Markers support
  • Customization of colors and fonts
  • Toggle line wrapping on and off
  • Adjust height of lines
  • Highlight/Select ranges in the text view
  • Multi-cursor editing
  • Search/Replace the text
  • Customizable Completion support
  • Smooth scrolling of long content
  • Anchored annotations
  • LTR (Left To Right) / RTL (Right To Left) layout
  • Undo/Redo

🗓️ Roadmap

STTextView is already well suited as a text editor component, however it still need improvements before release v1.0

Suggest or vote for new features: Feature Requests

Known issues

  • undo/redo while typing need fixes
  • no text dragging

🚀 Getting Started

STTextView is distributed using the Swift Package Manager. Install it in a project by adding it as a dependency in your Package.swift manifest or through “Package Dependencies” in Xcode project settings

let package = Package(
    dependencies: [
        .package(url: "https://github.com/krzyzanowskim/STTextView", from: "0.4.0")
    ]
)

Usage

SwiftUI

The TextView is a SwiftUI view that wraps the STTextView.

import STTextViewUI

struct ContentView: View {

    @State private var text = "Hello World!"

    var body: some View {
        TextView(
            text: $text,
            font: NSFont.monospacedSystemFont(ofSize: 0, weight: .regular),
            options: [.wrapLines, .highlightSelectedLine]
        )
    }
}

Create a TextView

The STTextView is a subclass of NSView and as such can be initialized like any other view. It has an API that is similar to the one of NSTextView.

import STTextView

let textView = STTextView()
view.addSubView(textView)
let textView = STTextView()
let scrollView = NSScrollView()
scrollView.documentView = textView
let scrollView = STTextView.scrollableTextView()
let textView = scrollView.documentView as! STTextView

Customize

The text view can be customized in a variety of ways.

let paragraph = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
// Set the line-height to 110%
paragraph.lineHeightMultiple = 1.1
paragraph.defaultTabInterval = 28

// Default Paragraph style
textView.typingAttributes[.paragraphStyle] = paragraph

// Set default font
textView.font = NSFont.monospacedSystemFont(ofSize: 14, weight: .regular)

// Set default text color
textView.textColor = .textColor

// Set text value
textView.string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ornare lobortis sem a vulputate."
textView.addAttributes([.foregroundColor: NSColor.red], range: NSRange(location: 10, length: 5))

// Wrap lines to editor width
textView.widthTracksTextView = true

// Highlight the selected line.
textView.highlightSelectedLine = true

Add line numbers using specialized STLineNumberRulerView (specialized subclass of NSRulerView)

let textView = STTextView()
let scrollView = NSScrollView()
scrollView.documentView = textView

// Line numbers
let rulerView = STLineNumberRulerView(textView: textView)
// Configure the ruler view
rulerView.highlightSelectedLine = true
// Set text color of the selected line number
rulerView.highlightLineNumberColor = .textColor
// Allows to set markers.
// rulerView.allowsMarkers = true

// Add to NSScrollView containing STTextView
scrollView.verticalRulerView = rulerView
scrollView.rulersVisible = true

Enable an optional search-and-replace find interface inside a view, usually a scroll view.

textView.textFinder.isIncrementalSearchingEnabled = true
textView.textFinder.incrementalSearchingShouldDimContentView = true

🐛 TextKit 2 Bug Reports List

List of TextKit 2 issues and bugs related to NSTextView and the TextKit framework I reported to Apple so far:

  • FB9856587: TextKit2 unexpected additional line fragment for last line
  • FB9925766: NSTextSelectionNavigation.deletionRanges only works at the end of the word
  • FB9925647: NSTextLayoutManager.replaceContents(in range: with attributedString:) is documented but is not part of the public API
  • FB9907261: NSTextElementProvider.replaceContents(in:with:) does not replace content as documented
  • FB9692714: Rendering attributes does not draw properly
  • FB9886911: NSTextView can't properly layout and display long lines (this one is nasty since it causes the view "jump" whenever text attribute updates)
  • FB9713415: NSTextView drawInsertionPoint(in:color:turnedOn) is never called
  • FB9971054: NSLayoutManager.enumerateCaretOffsetsInLineFragment ignores starting location
  • FB9971054: NSTextView assert on selection when setup with TextKit2
  • FB9743449, FB10019859: NSTextContentStorage.textElements(for:) returns no element, while enumerateTextElements does return elements
  • FB11898356: textSelections(interactingAt:inContainerAt:anchors:modifiers:selecting:bounds:) produces wrong selections for certain locations

... I'm aware that the list of issues is not complete. I managed to workaround most of the problems in STTextView.

Why ST?

(ST prefix stands for "Swift sTudio" because SS is not good prefix since 1939)

Suggestions or Feedback

Start a new discussion topic or a pull request.

I'd love to hear from you! Get in touch via twitter @krzyzanowskim, mastodon @[email protected].

License

Open Source license

If you are creating an open source application under a license compatible with the GNU GPL license v3, you may use STTextView under the terms of the GPLv3.

Commercial license

Get one starting from €5.

If you want to use STTextView to develop non open sourced product, and applications, the Commercial license is the appropriate license. With this option, your source code is kept proprietary. Which means, you won't have to change your whole application source code to an open source license. Purchase a STTextView Commercial License

More Repositories

1

CryptoSwift

CryptoSwift is a growing collection of standard and secure cryptographic algorithms implemented in Swift
Swift
10,176
star
2

Natalie

Natalie - Storyboard Code Generator (for Swift)
Swift
1,167
star
3

OpenSSL

OpenSSL package for SwiftPM, CocoaPod, and Carthage, multiplatform
C
919
star
4

ObjectivePGP

ObjectivePGP is an open-source library for iOS and macOS that provides developers with tools for implementing OpenPGP encryption and decryption, digital signing, and signature verification in their applications, thereby enhancing security and data integrity.
Objective-C
667
star
5

OnlineSwiftPlayground

Online Swift Playground
Swift
245
star
6

CoreTextSwift

CoreText Swift bindings
Swift
158
star
7

NSTableView-Sections

NSTableView with sections (similar to UITableView)
Swift
89
star
8

SwiftUI.TextEdit

SwiftUI proof-of-concept text edit component
Swift
87
star
9

JSONCodable

JSON Codable is what we need 90% of the time
Swift
75
star
10

unnetpgp

*Deprecated* NetPGP wrapper. Use ObjectivePGP
C
67
star
11

reorder

Reorder Swift functions
Swift
57
star
12

SwiftUI.AnimatedImage

SwiftUI AnimatedImage View
Swift
56
star
13

SwiftUI.SplitView

Swift
48
star
14

RepetitiveTask

Swift
40
star
15

tree-sitter-xcframework

binary build of tree-sitter for apple platforms
C
37
star
16

BoyerMoore

Boyer-Moore algorithm sample
Swift
37
star
17

GeneratedResults-UITableView

Practical Swift: pages generator - build once, use many
Swift
36
star
18

STTextView-Plugin-Neon

Source Code Syntax Highlighting
C
33
star
19

STTextKitPlus

Collection of TextKit 2 helpers used to build STTextView.
Swift
28
star
20

MKDataScanner

NSScanner for NSData and files.
Objective-C
16
star
21

antlr-swift-playground

Antlr Swift Parser playground
Swift
14
star
22

CollectionSafeIndex

Get the element at the specified index only if it is within bounds, otherwise nil
Swift
11
star
23

CoreTextWorkshop

Take a look at the CoreText API - a foundation of layout and drawing text on macOS and iOS. In this workshop we’ll attempt to build Text Label (akin UILabel), learn about layers of CoreText API and how to use it.
Swift
10
star
24

AES256CBC

Most convenient AES256-CBC encryption for Swift 2 & 3
Swift
8
star
25

OpenSSL-Package

OpenSSL package for SwiftPM
Swift
8
star
26

RawData

Swift RawData CollectionType
Swift
7
star
27

STTextView-Plugin-Annotations

Annotations Plugin
Swift
7
star
28

STTextView-Plugin-Template

Template Plugin repository for STTextView
Swift
7
star
29

CodeEditView

custom text view implementation
Swift
6
star
30

Kitura-Session-Kuery

Kitura-Session store using Swift-Kuery (SQL database abstraction layer) as the backing store
Swift
6
star
31

CloudKitWebServices

CloudKit Web Services framework for everyone else...
6
star
32

TouchImageView

iOS UIImageView with convenient touch delegate
Objective-C
6
star
33

language-server-protocol

Language Server Protocol
Swift
6
star
34

sendable.wtf

HTML
5
star
35

Google1Password

1Password integration for Google sign-in view.
Objective-C
5
star
36

ChorusBirdie

Birdie singing songs game. SwiftCrunch hackathon project. Created over few hours from zero.
Swift
3
star
37

monaco-editor-vue-component

MonacoEditor component for Vue.js
Vue
2
star
38

AppleRadar-FileProviderEnumeratorNotificationSample

NSFileProviderManager.signalEnumerator does not trigger update of UIDocumentBrowserViewController
Swift
2
star
39

GNUGadu

GNU Gadu is instant messaging client designed to work with protocols common in Poland (but not only). Contrary to its name, is not part of the GNU project.
C
2
star
40

MKScrollView

Alternative to UIScrollView. Proof of concept implementation.
Objective-C
1
star