88
99import Foundation
1010import XcodeKit
11+ import SwiftyJSON
1112
1213class SourceEditorCommand : NSObject , XCSourceEditorCommand {
1314
@@ -21,17 +22,68 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand {
2122 deinit {
2223 }
2324
24- // func convertToDictionary(text: String) -> [String: Any]? {
25- // if let data = text.data(using: .utf8) {
26- // do {
27- // return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
28- // } catch {
29- // print(error.localizedDescription)
30- // }
31- // }
32- // return nil
33- // }
25+ func isInsertionPoint( range: XCSourceTextRange ) -> Bool {
26+
27+ if ( range. start. line != range. end. line) {
28+ return false
29+ }
30+
31+ if ( range. start. column != range. end. column) {
32+ return false
33+ }
34+
35+ return true
36+ }
37+
38+ func checkLineNumber( lineNumber: Int , nLinesInBuffer: Int ) -> Int {
39+ var checkedLineNumber = - 1 //TODO: probably better to use an optional
40+
41+ if ( lineNumber < 0 ) {
42+ checkedLineNumber = 0
43+ }
44+ else if ( lineNumber >= nLinesInBuffer) {
45+ checkedLineNumber = nLinesInBuffer - 1
46+ }
47+ else {
48+ checkedLineNumber = lineNumber
49+ }
50+
51+ return checkedLineNumber
52+ }
53+
54+ func getLineLength( lineNumber: Int , nLinesInBuffer: Int , buffer: XCSourceTextBuffer ) -> Int {
55+ let text = buffer. lines [ checkLineNumber ( lineNumber: lineNumber, nLinesInBuffer: nLinesInBuffer) ] as! String
56+ return text. characters. count
57+ }
58+
59+ func makeRange( startLine: Int , endLine: Int , nLinesInBuffer: Int , startColumn: Int = 0 , endColumn: Int = 0 , numberOfColumnsInLine: Int = 0 ) -> XCSourceTextRange {
60+ let newRange = XCSourceTextRange ( )
61+
62+ if ( startColumn < 0 ) {
63+ newRange. start. column = 0
64+ }
65+ else if ( startColumn > numberOfColumnsInLine) {
66+ newRange. start. column = numberOfColumnsInLine
67+ }
68+ else {
69+ newRange. start. column = startColumn
70+ }
71+
72+ if ( endColumn < 0 ) {
73+ newRange. end. column = 0
74+ }
75+ else if ( endColumn > numberOfColumnsInLine) {
76+ newRange. end. column = numberOfColumnsInLine
77+ }
78+ else {
79+ newRange. end. column = endColumn
80+ }
3481
82+ newRange. start. line = checkLineNumber ( lineNumber: startLine, nLinesInBuffer: nLinesInBuffer)
83+ newRange. end. line = checkLineNumber ( lineNumber: endLine, nLinesInBuffer: nLinesInBuffer)
84+
85+ return newRange
86+ }
3587
3688 func perform( with invocation: XCSourceEditorCommandInvocation , completionHandler: @escaping ( Error ? ) -> Void ) -> Void
3789 {
@@ -46,46 +98,88 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand {
4698 //NSLog(buffer.contentUTI)
4799 NSLog ( command)
48100
49- // let dict = convertToDictionary(text: command)
50- //
51- // switch(dict!["id"]) {
52- //
53- // case "initial-state":
54- // NSLog("initial state - not handled")
55- // break
56- // case "editor:move-to-line-number":
57- // let newRange = XCSourceTextRange()
58- // newRange.start.column = 0
59- // newRange.start.line = 3
60- // newRange.end.column = 0
61- // newRange.end.line = 3
62- //
63- // buffer.selections[0] = newRange
64- // break
65- // case "editor:move-to-line-number-and-way-right":
66- // break
67- // case "editor:move-to-line-number-and-way-left":
68- // break
69- // case "editor:insert-under-line-number":
70- // break
71- // case "editor:select-line-number":
72- // break
101+ let dataFromString = command. data ( using: . utf8)
102+ let json = try ? JSON ( data: dataFromString!)
103+ let nLinesInBuffer = buffer. lines. count
104+
105+ switch ( json![ " id " ] . stringValue) {
106+
107+ case " initial-state " :
108+ NSLog ( " initial state - not handled " )
109+ break
110+ // MARK: -
111+ // MARK: Editor overrides
112+ case " editor:move-to-line-number " :
113+ let line = json![ " line " ] . intValue - 1
114+ buffer. selections [ 0 ] = makeRange ( startLine: line, endLine: line, nLinesInBuffer: nLinesInBuffer)
115+ break
116+ case " editor:move-to-line-number-and-way-right " :
117+ let line = json![ " line " ] . intValue - 1
118+ let lineLength = getLineLength ( lineNumber: line, nLinesInBuffer: nLinesInBuffer, buffer: buffer)
119+
120+ buffer. selections [ 0 ] = makeRange ( startLine: line, endLine: line, nLinesInBuffer: nLinesInBuffer, startColumn: lineLength - 1 , endColumn: lineLength - 1 , numberOfColumnsInLine: lineLength)
121+ // TODO: tell xcode 2 navigate to selection in case selection was offscreen
122+ break
123+ case " editor:move-to-line-number-and-way-left " :
124+ let line = json![ " line " ] . intValue - 1
125+ let lineLength = getLineLength ( lineNumber: line, nLinesInBuffer: nLinesInBuffer, buffer: buffer)
126+
127+ buffer. selections [ 0 ] = makeRange ( startLine: line, endLine: line, nLinesInBuffer: nLinesInBuffer, startColumn: 0 , endColumn: 0 , numberOfColumnsInLine: lineLength)
128+ // TODO: tell xcode 2 navigate to selection in case selection was offscreen
129+ break
130+ case " editor:insert-under-line-number " :
131+ let line = checkLineNumber ( lineNumber: json![ " line " ] . intValue - 1 , nLinesInBuffer: nLinesInBuffer)
132+ //TODO: probably better to use an optional
133+ if line > - 1 {
134+ buffer. lines. insert ( " " , at: line)
135+ }
136+ break
137+ case " editor:select-line-number " :
138+ let line = json![ " line " ] . intValue - 1
139+ let lineLength = getLineLength ( lineNumber: line, nLinesInBuffer: nLinesInBuffer, buffer: buffer)
140+
141+ buffer. selections [ 0 ] = makeRange ( startLine: line, endLine: line, nLinesInBuffer: nLinesInBuffer, startColumn: 0 , endColumn: lineLength, numberOfColumnsInLine: lineLength)
142+
143+ // TODO: tell xcode 2 navigate to selection in case selection was offscreen
144+ break
73145// case "editor:expand-selection-to-scope":
74146// break
75147// case "editor:click-expand-selection-to-scope":
76148// break
77- // case "editor:select-line-number-range":
78- // break
79- // case "editor:extend-selection-to-line-number":
80- // break
81- // case "editor:insert-from-line-number":
82- // break
149+ case " editor:select-line-number-range " :
150+ let firstLine = json![ " first " ] . intValue - 1
151+ let lastLine = json![ " last " ] . intValue - 1
152+ let lineLength = getLineLength ( lineNumber: lastLine, nLinesInBuffer: nLinesInBuffer, buffer: buffer)
153+
154+ buffer. selections [ 0 ] = makeRange ( startLine: firstLine, endLine: lastLine, nLinesInBuffer: nLinesInBuffer, startColumn: 0 , endColumn: lineLength, numberOfColumnsInLine: lineLength)
155+
156+ // TODO: tell xcode 2 navigate to selection in case selection was offscreen
157+ break
158+ case " editor:extend-selection-to-line-number " :
159+ break
160+ case " editor:insert-from-line-number " :
161+ //TODO: this is not quite working
162+ let line = json![ " line " ] . intValue - 1
163+ let checkedLine = checkLineNumber ( lineNumber: line, nLinesInBuffer: nLinesInBuffer)
164+ //TODO: probably better to use an optional
165+ let range = buffer. selections [ 0 ] as! XCSourceTextRange
166+ if checkedLine > - 1 && isInsertionPoint ( range: range) {
167+ var currentLine = buffer. lines [ range. start. line] as! String
168+ let textToInsert = buffer. lines [ checkedLine] as! String
169+ let insertIndex = currentLine. index ( currentLine. startIndex, offsetBy: range. start. column)
170+ currentLine. insert ( contentsOf: textToInsert. characters, at: insertIndex)
171+ buffer. lines. replaceObject ( at: range. start. line, with: currentLine)
172+ }
173+ break
83174// case "editor:toggle-comments":
84175// break
85176// case "editor:insert-code-template":
86177// break
87178// case "editor:complete-code-template":
88179// break
180+
181+ // MARK: -
182+ // MARK: Selection overrides
89183// case "selection:previous-occurrence":
90184// break
91185// case "selection:next-occurrence":
@@ -108,11 +202,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand {
108202// break
109203// case "selection:next-word-by-surrounding-characters":
110204// break
111- // default:
112- // NSLog("not handled")
113- // }
205+ default :
206+ NSLog ( " not handled " )
207+ }
114208
115- //TODO: do something with the invocation buffer
116209 connection. invalidate ( )
117210 completionHandler ( nil )
118211 }
0 commit comments