Skip to content

Commit

Permalink
Merge pull request #1115 from Obverser/swift-extension
Browse files Browse the repository at this point in the history
Swift Language support
  • Loading branch information
cxxxr authored Sep 29, 2023
2 parents 6ba0886 + 19cd1ea commit f244af9
Show file tree
Hide file tree
Showing 5 changed files with 386 additions and 0 deletions.
4 changes: 4 additions & 0 deletions extensions/swift-mode/lem-swift-mode.asd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(defsystem "lem-swift-mode"
:depends-on ("lem" "yason")
:serial t
:components ((:file "swift-mode") (:file "lsp-config")))
12 changes: 12 additions & 0 deletions extensions/swift-mode/lsp-config.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(defpackage :lem-swift-mode/lsp-config
(:use :cl :lem-lsp-mode :lem-lsp-base/type))

(in-package :lem-swift-mode/lsp-config)

(define-language-spec (swift-spec lem-swift-mode:swift-mode)
:language-id "swift"
:root-uri-patterns '("Package.swift")
:command '("xcrun" "--toolchain" "swift" "sourcekit-lsp") ;; either behind $PATH or 'xcrun --toolchain swift sourcekit-lsp'
:install-command "" ;; It kinda..has to be installed?
:readme-url "https://github.com/apple/sourcekit-lsp"
:connection-mode :stdio)
41 changes: 41 additions & 0 deletions extensions/swift-mode/swift-mode.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
(defpackage :lem-swift-mode
(:use :cl :lem :lem/completion-mode :lem/language-mode)
(:import-from :lem/tmlanguage :load-tmlanguage)
(:export :*swift-mode-hook* :swift-mode))

(in-package :lem-swift-mode)

;; Syntax highlighting (like the go implementation) is effectively
;; a json file from Atom's system. Eventually, I will have to
;; update the json for Swift 5.9's macros and new syntax
(defvar *swift-syntax-table*
(let ((table (make-syntax-table
:space-chars '(#\space #\tab #\newline)
:symbol-chars '(#\_)
:paren-pairs '((#\( . #\))
(#\{ . #\})
(#\[ . #\]))
:string-quote-chars '(#\" #\#)
:line-comment-string "//"
:block-comment-pairs '(("/*" . "*/"))))
(tmlanguage (load-tmlanguage
(merge-pathnames "swift.json"
(asdf:system-source-directory :lem-swift-mode)))))
(set-syntax-parser table tmlanguage)
table))

(define-major-mode swift-mode language-mode
(:name "Swift"
:syntax-table *swift-syntax-table*
:mode-hook *swift-mode-hook*)
(setf (variable-value 'enable-syntax-highlight) t)
(setf (variable-value 'tab-width) 2) ;; Can be 4, Swift OSS is 2
(setf (variable-value 'line-comment) "//")
(setf (variable-value 'insertion-line-comment) "// "))

(define-file-type ("swift") swift-mode)





328 changes: 328 additions & 0 deletions extensions/swift-mode/swift.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "Swift",
"scopeName": "source.swift",
"patterns": [
{
"include": "#comment"
},
{
"include": "#constant"
},
{
"include": "#entity"
},
{
"include": "#invalid"
},
{
"include": "#keyword"
},
{
"include": "#meta"
},
{
"include": "#operator"
},
{
"include": "#punctuation"
},
{
"include": "#storage"
},
{
"include": "#string"
},
{
"include": "#support"
},
{
"include": "#type"
},
{
"include": "#variable"
}
],
"repository": {
"comment": {
"patterns": [
{
"name": "comment.block.swift",
"begin": "/\\*",
"end": "\\*/",
"captures": {
"0": {
"name": "punctuation.definition.comment.swift"
}
}
},
{
"name": "comment.line.double-slash.swift",
"begin": "//",
"end": "$",
"beginCaptures": {
"0": {
"name": "punctuation.definition.comment.swift"
}
}
}
]
},
"constant": {
"patterns": [
{
"name": "constant.language.swift",
"match": "\\b(true|false|nil|none)\\b"
},
{
"name": "constant.numeric.swift",
"match": "(?x)(0b[0-1]+)|(0x[0-9a-fA-F]+)|(0o[0-7]+)|([+-]?([0-9]*[.])?[0-9]+)"
},
{
"name": "constant.character.escape.swift",
"match": "\\\\[0\\\\tnr\"']"
},
{
"name": "constant.character.escape.swift",
"match": "\\\\(x\\h{2}|u\\h{4}|U\\h{8})"
}
]
},
"entity": {
"patterns": [
{
"match": "([a-zA-Z!][a-zA-Z_]+)(?=[(])",
"name": "entity.name.function.swift"
},
{
"match": "(?<=protocol\\s)([a-zA-Z][a-zA-Z_]+)",
"captures": {
"1": {
"name": "entity.name.function.protocol.swift"
}
}
},
{
"match": "(?<=extension\\s)([a-zA-Z][a-zA-Z_]+)",
"captures": {
"1": {
"name": "entity.name.function.extension.swift"
}
}
},
{
"match": "(?<=enum\\s)([a-zA-Z][a-zA-Z_]+)",
"captures": {
"1": {
"name": "entity.name.type.enum.swift"
}
}
},
{
"match": "(?<=class\\s)([a-zA-Z][a-zA-Z_]+)",
"captures": {
"1": {
"name": "entity.name.class.swift"
}
}
},
{
"match": "(?<=import\\s)([a-zA-Z][a-zA-Z_]+)",
"captures": {
"1": {
"name": "entity.name.type.module.swift"
}
}
},
{
"match": "(?<=struct\\s)([a-zA-Z][a-zA-Z_]+)",
"captures": {
"1": {
"name": "entity.name.type.struct.swift"
}
}
},
{
"match": "\\b(func)\\s+([^\\t\\n\\x20\\x28]+)",
"captures": {
"1": {
"name": "storage.type.function.swift"
},
"2": {
"name": "entity.name.function.swift"
}
}
}
]
},
"invalid": {
"patterns": []
},
"keyword": {
"patterns": [
{
"name": "keyword.statement.swift",
"match": "\\b(break|case|continue|catch|do|default|defer|else|fallthrough|for|guard|if|in|repeat|return|switch|try|where|while)\\b"
},
{
"name": "keyword.declaration.swift",
"match": "\\b(deinit|import|init|subscript)\\b"
},
{
"name": "keyword.other.placeholder.swift",
"match": "\\b(_)\\b"
},
{
"name": "variable.language.swift",
"match": "\\b(new|super)\\b"
},
{
"name": "keyword.reserved.swift",
"match": "\\b(associativity|didSet|get|infix|inout|left|mutating|nonmutating|operator|override|postfix|precedence|prefix|right|set|unowned|unowned(safe)|unowned(unsafe)|weak|willSet)\\b"
}
]
},
"meta": {
"patterns": []
},
"operator": {
"patterns": [
{
"name": "keyword.operator.swift",
"match": "\\B[\\/=\\-+!*%<>&|^~\\?:]\\B"
},
{
"name": "keyword.operator.access.swift",
"match": "[.](?!\\d)"
}
]
},
"punctuation": {
"patterns": [
{
"name": "punctuation.other.comma.swift",
"match": ","
},
{
"name": "punctuation.other.paren.swift",
"match": "[)(]"
}
]
},
"storage": {
"patterns": [
{
"name": "storage.modifier.swift",
"match": "\\b(final|internal|private|fileprivate|public|open|override|static|required|convenience)\\b"
},
{
"name": "storage.type.swift",
"match": "\\b(class|enum|extension|protocol|precedencegroup|struct|typealias)\\b"
},
{
"name": "storage.type.swift",
"match": "\\b(typealias|precedencegroup)\\b"
}
]
},
"escaped-char": {
"patterns": [
{
"name": "constant.character.escape.swift",
"match": "\\\\[0\\\\tnr\"']"
},
{
"name": "constant.character.escape.swift",
"match": "\\\\(x\\h{2}|u\\h{4}|U\\h{8})"
},
{
"name": "invalid.illegal.constant.character.escape.swift",
"match": "\\\\[^uxU]"
}
]
},
"string": {
"patterns": [
{
"name": "string.quoted.single.swift",
"begin": "'",
"end": "'"
},
{
"name": "string.quoted.double.swift",
"begin": "\"",
"end": "\"",
"patterns": [
{
"begin": "\\\\\\(",
"end": "\\)",
"beginCaptures": {
"0": {
"name": "punctuation.section.embedded.begin.swift"
}
},
"endCaptures": {
"0": {
"name": "punctuation.section.embedded.end.swift"
}
},
"patterns": [
{
"name": "meta.embedded.line.swift",
"match": "."
}
]
},
{
"include": "#escaped-char"
}
]
}
]
},
"support": {
"patterns": []
},
"type": {
"patterns": [
{
"match": "(?<=->\\s)([a-zA-Z][a-zA-Z_?]+)",
"captures": {
"1": {
"name": "entity.name.type.return_type.swift"
}
}
},
{
"name": "support.type.swift",
"match": "(?x) \\b(Character|U?Int|U?Int(8|16|32|64) |Float|Double|Float(32|64)|Bool|String|Date|Data|URL |(double|float)[234]|(double|float)[234]x[234] |Any |AnyObject |Error |Equatable |Hashable |Comparable |CustomDebugStringConvertible |CustomStringConvertible |OptionSet |ManagedBuffer |ManagedBufferPointer |BitwiseOperations |CountedSet |Counter |Directions |ExpressibleByArrayLiteral |ExpressibleByBooleanLiteral |ExpressibleByDictionaryLiteral |ExpressibleByExtendedGraphemeClusterLiteral |ExpressibleByFloatLitera |ExpressibleByIntegerLiteral |ExpressibleByNilLiteral |ExpressibleByStringInterpolation |ExpressibleByStringLiteral |ExpressibleByUnicodeScalarLiteral |OrderedSet |PaperSize |RawRepresentable |(UI|NS|CF|CG)[A-Z][a-zA-Z0-9]+ |Stream |(In|Out)putStream |FileManager |Array |Unsafe[a-zA-Z]*Pointer |Bundle |Jex)\\b[?]?"
}
]
},
"variable": {
"patterns": [
{
"match": "\\b(self)\\b",
"name": "variable.language.self.swift"
},
{
"match": "\\b(let|var)\\s([a-zA-Z0-9]+)(:?)\\s([a-zA-Z0-9]+)?",
"captures": {
"1": {
"name": "storage.type.swift"
},
"2": {
"name": "variable.other.swift"
},
"3": {
"name": "punctuation.definition.type.swift"
},
"4": {
"name": "entity.name.type.swift"
}
}
}
]
}
}
}
1 change: 1 addition & 0 deletions lem.asd
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
"lem-lisp-mode"
#+sbcl
"lem-go-mode"
"lem-swift-mode"

"lem-c-mode"
"lem-xml-mode"
Expand Down

0 comments on commit f244af9

Please sign in to comment.