Firefly is a pure swift iOS & macOS syntax highlighter based of off Sourceful, SavannaKit, SyntaxKit, and previously Highlightr. Highlighter has since been remove from the project in favor of a pure swift solution.
If you want to get in contact about Firefly, the Jellycuts Discord is the best place to talk.
Issues are hosted on both this repo and the Jellycuts Issue Repo. This is done because a lot of issues that occur with Firefly are reported through Jellycuts and it does not make sense to mirror them across to this repo.
Firefly is written in pure swift, and uses NSRegularExpressions for detecting tokens to highlight. Once tokens are detected they are colored based on the current theme.
If you are going to use Firefly in your project, I request that you include a link back to this github page somewhere. If you would like to you can also email me and I will add you into the list of apps that use Firefly on this page.
This project was inspired by Paul Hudson’s (@twostraws) Sourceful syntax highlighter and Highlightr by J.P Illanes (@raspu). Sourceful is a project combining Louis D’hauwe's SavannaKit and Source Editor. Highlightr merges Highlight.js with swift.
- Line Numbers
- Changeable Themes
- Changeable Languages
- Basic String, Parentheses, and Bracket completion
- 2 Languages
- 61 Themes
To start using you can either create a UIView in storyboards and assign it the class SyntaxTextView, or by creating a SyntaxTextView programmatically. You can then assign the editors language inside your View Controller. Firefly also supports setting up with Swift UI.
A basic setup for a Firefly View
import UIKit
import Firefly
class ViewController: UIViewController {
@IBOutlet weak var fireflyView: FireflySyntaxView!
override func viewDidLoad() {
super.viewDidLoad()
// Use the setup function
fireflyView.setup(theme: themeName, language: "jelly", font: "system", offsetKeyboard: true, keyboardOffset: 10, dynamicGutter: true, gutterWidth: 20, placeholdersAllowed: true, linkPlaceholders: false)
}
}
Using the .setup function is the same on macOS as it is on iOS.
This allows you to set almost all ascpets of the view at once so you do not accidently cause extra highlight calls.
fireflyView.setup(theme: themeName, language: "jelly", font: "system", offsetKeyboard: true, keyboardOffset: 10, dynamicGutter: true, gutterWidth: 20, placeholdersAllowed: true, linkPlaceholders: false)
fireflyView.text = “My code string”
fireflyView.setTheme(name: "Basic")
fireflyView.setLanguage(nLanguage: "default")
fireView.setGutterWidth(width: 20)
The keyboard offset is the space between the bottom of firefly view and the keyboard frame. You should use this to make space for any keyboard input views.
fireflyView.setKeyboardOffset(offset: 85)
fireView.setShouldOffsetKeyboard(bool: true)
fireflyView.setFont(font: "Source Code Pro")
fireflyView.setDynamicGutter(bool: true)
A placeholder can be used to deeplink to a different part of your app or open a link. Used for documentation in Jellycuts.
fireView.setPlaceholdersAllowed(bool: true)
fireView.setLinkPlaceholders(bool: true)
This returns the value for the current theme. You can use this to get details about what the View looks like and color other parts of your app accordingly.
let theme = fireflyView.getCurrentTheme()
fireflyView().availableLanguages()
fireflyView().availableThemes()
Swift UI is not fully supported but it is still supported. An example view for Swift UI is below. This will set you up with a basic swift UI Fiefly view.
struct ContentView: View {
@State var text = """
if(x == 3) {
quickLook()
}
import Shortcuts 1090.2
#Color: red, #Icon: shortcuts
Function()
functionWithParams(test: test)
// This is a comment
/*
This is a multi line comment
*/
"String"
\"""
Multi Line Text
More Text
\"""
"""
@State var theme: String = "Xcode Dark"
@State var fontName: String = "system"
@State var update: Bool = false
@State var dynamicGutter: Bool = false
@State var gutterWidth: CGFloat = 40
@State var placeholdersAllowed: Bool = true
@State var linkPlaceholders: Bool = false
@State var lineNumbers: Bool = true
@State var fontSize: CGFloat = 14
var body: some View {
FireflySyntaxEditor(text: $text, language: .constant("Jelly"), theme: $theme, fontName: $fontName, fontSize: $fontSize, dynamicGutter: $dynamicGutter, gutterWidth: $gutterWidth, placeholdersAllowed: $placeholdersAllowed, linkPlaceholders: $linkPlaceholders, lineNumbers: $lineNumbers, cursorPosition: $cursorPosition) { editor in
print("Did change text")
} didChangeSelectedRange: { editor, range in
print("Did change selected range")
} textViewDidBeginEditing: { editor in
print("Did begin editing")
}
}
}
Languages are a dictionary of definitions that tell the syntax highlighter how to detect a token.
Example of a language definition:
let defaultLanguage: [String: Any] = [
"comment": [
"regex": "//.*?(\\n|$)", // The regex used for highlighting
"group": 0, // The regex group that should be highlighted
"relevance": 5, // The releavance over other tokens
"options": [], // Regular expression options
"multiline": false // If the token is multiline
],
"multi_comment": [
"regex": "/\\*.*?\\*/", // The regex used for highlighting
"group": 0, // The regex group that should be highlighted
"relevance": 5, // The releavance over other tokens
"options": [NSRegularExpression.Options.dotMatchesLineSeparators], // Regular expression options
"multiline": true // If the token is multiline
],
]
To add your own language to the languages array within the languages dictionary.
let languages: [String: [String: Any]] = [
"default": defaultLanguage,
"jelly": jellyLanguage,
"swift": swiftLanguage
]
Themes are a dictionary with color values telling the highlighter what color to highlight different tokens.
Example of a theme definition:
"Basic": [
"default": "#000000", // The default font color
"background": "#FFFFFF", // The background color
"currentLine": "#F3F3F4", // Color of the current line
"selection": "#A4CDFF", // The selection color of the text view
"cursor": "#000000", // The cursor color of the text view
"definitions": [ // These are the definitions that tell the highlighter what color to highlight different types of definitions.
"function": "#2B839F",
"keyword": "#0000FF",
"identifier": "#2B839F",
"string": "#A31515",
"mult_string": "#A31515",
"comment": "#008000",
"multi_comment": "#008000",
"numbers": "#000000",
"url": "#0000FF"
]
]
-
Support for Theme Changing
-
Support for Language Changing
-
Dynmaically creating Gutter and Line styles
-
Fix issues with themes not showing the correct colors when the token has a font weight modifier - Not really fixed, just a workaround currently.
-
Modify, update and implement SavannaKit / SyntaxKit LineNumberLayoutManager for better and faster line numbers
-
Speed increasments for loading larger files
-
Multi-line string support
-
Swift UI support
-
Placeholders
-
Collapsable lines
-
More languages
-
Rewrite the NSTextStorage subclass in obj-c. This will bring speed improvments.
-
Support VSCode Themes or a converter for VSCode -> Firefly theme
-
Highlight current line with tinting of line number and line fragmenet
Sourceful is a project merging together SavannaKit and SourceEditor, and then udpdated too a modern version of Swift. It is maintained by Paul Hudson. This project was used as a starting ground for Firefly but has been largely removed from the working copy. Sourceful is licensed under the MIT license; see Sourceful LICENSE for more information.
Highlightr is a project taking Highlight.js and allowing it to interact with Swift. Highlighter has been removed from the working copy in favor of a full swift approach. Highlightr is licensed under the MIT license; see Highlightr LICENSE for more information.
SyntaxKit is a project created by Palle Klewitz for iOS syntax highlighting. This project was used as a reference for issues in code. SyntaxKit is licensed under the MIT license; see SyntaxKit LICENSE for more information.
SavannaKit is a project created by Louis D'hauwe. Firefly uses a modified version of LineNumberLayoutManager. SavannaKit is licensed under the MIT license; see SavannaKit LICENSE for more information.