From 91de9deb5d1009d810c9bfd67f296faf0f498762 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 23 Oct 2017 15:19:04 +0530 Subject: [PATCH 01/56] Updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 34acba8..4756ac9 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,13 @@ ## Mac App Store -Linex can be downloaded free on the Mac App Store. +Linex can be *purchased* on the Mac App Store. Please purchase the plugin as it would help me to maintain it. Mac App Store -## Manual +## Manual(Free) 1. Download the latest [Linex.app](https://github.com/kaunteya/Linex/releases/latest). 2. Move the Linex.app to Applications folder. 3. Open and Close it. From 49492b401901b5bc584a17c8ed55505fbfff4f77 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 23 Oct 2017 14:08:03 +0000 Subject: [PATCH 02/56] Updated README --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4756ac9..1f77497 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ ## Mac App Store -Linex can be *purchased* on the Mac App Store. Please purchase the plugin as it would help me to maintain it. +Linex can be *purchased* on the Mac App Store. Please consider purchasing the plugin as it would help me to maintain it. Mac App Store @@ -149,6 +149,9 @@ These shortcuts also toggles `true`, `false`, `YES` & `NO` | Increment | CTRL++ | | Decrement | CTRL+- | +# Todo +- Expand selection + # Contributing Pull requests with bug fixes or with new failing Test cases are welcomed. From 96ed109c159a414562b188f135cfe8bfba14be0a Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 26 Oct 2017 10:59:32 +0000 Subject: [PATCH 03/56] Updated readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1f77497..3b97c1f 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,13 @@ ## Mac App Store -Linex can be *purchased* on the Mac App Store. Please consider purchasing the plugin as it would help me to maintain it. +Linex can be downloaded from the Mac App Store. Mac App Store -## Manual(Free) +## Manual 1. Download the latest [Linex.app](https://github.com/kaunteya/Linex/releases/latest). 2. Move the Linex.app to Applications folder. 3. Open and Close it. @@ -133,7 +133,7 @@ These shortcuts also toggles `true`, `false`, `YES` & `NO` | Duplicate | | | Open New Line Below | CTRL+return | | Open New Line Above | CTRL+SHIFT+return | -| Commented Duplicate | Cmd+CTRL+/ | +| Commented Duplicate | CMD+CTRL+/ | | Delete Line | CTRL+OPTN+L | | Join Line | CTRL+J | | Line Beginning | CTRL+A | @@ -143,7 +143,7 @@ These shortcuts also toggles `true`, `false`, `YES` & `NO` | Select Line | CTRL+L | | Select Line up | CTRL+SHIFT+L | | One Space | OPTN+Space | -| Align | Cmd+CTRL+X | +| Align | CMD+CTRL+X | | | | | `Convert` | | | Increment | CTRL++ | From a7568d313bbb89713aa849f884aca2661ca1e9f6 Mon Sep 17 00:00:00 2001 From: kaunteya Date: Sat, 6 Jan 2018 13:01:10 +0530 Subject: [PATCH 04/56] Updated for Swift 4 --- Common.swift | 12 ++++++------ Line/SourceEditorCommand.swift | 6 +++--- Selection/Util.swift | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Common.swift b/Common.swift index 8f442df..a829cae 100644 --- a/Common.swift +++ b/Common.swift @@ -49,7 +49,7 @@ extension String { /// " var foo" -> 4 func lineIndentationOffset() -> Int { var i = 0 - for a in self.characters { + for a in self { if a == " " { i += 1 } else { break } @@ -75,7 +75,7 @@ extension String { func replacedRegex(pattern: String, with template: String) -> String { let regex = try! NSRegularExpression(pattern: pattern) - let range = NSMakeRange(0, characters.count) + let range = NSMakeRange(0, count) let modString = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: template) return modString } @@ -91,7 +91,7 @@ extension String { } var end = pin - while end < self.characters.count && self[end] == " " { + while end < self.count && self[end] == " " { end += 1 } @@ -115,10 +115,10 @@ extension String { func selectWord(pin: Int) -> Range? { var pin = pin - guard pin <= self.characters.count else { + guard pin <= self.count else { return nil } - guard self.characters.count > 1 else { + guard self.count > 1 else { return nil } @@ -138,7 +138,7 @@ extension String { } var end = pin - while end < characters.count && (self[end] as String).rangeOfCharacter(from: validChars) != nil { + while end < count && (self[end] as String).rangeOfCharacter(from: validChars) != nil { end += 1 } if start == end { return nil } diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index df22ee3..5ecc118 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -114,8 +114,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { //Selection/CaretPosition let range = buffer.selections.lastObject as! XCSourceTextRange - range.start.column = firstLine.characters.count + 1 - range.end.column = firstLine.characters.count + 1 + range.start.column = firstLine.count + 1 + range.end.column = firstLine.count + 1 case .lines(_, _): let range = buffer.selections.firstObject as! XCSourceTextRange @@ -134,7 +134,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { //Selection/CaretPosition range.end.line = range.start.line - range.end.column = joinedLine.characters.count + range.end.column = joinedLine.count case .multiLocation(_): break } diff --git a/Selection/Util.swift b/Selection/Util.swift index 57934c4..0d526de 100644 --- a/Selection/Util.swift +++ b/Selection/Util.swift @@ -16,7 +16,7 @@ extension Array where Element == String { for str in self { let seperated = str.components(separatedBy: subStr) if seperated.count == 2 { - let offset = seperated.first!.trimmedEnd().characters.count + let offset = seperated.first!.trimmedEnd().count if offset > farthest { farthest = offset } } } @@ -34,8 +34,8 @@ extension Array where Element == String { indexSet.append(i) let split = line.condensedWhitespace.components(separatedBy: " ") if split.count > 2 { - if farthestOffset < split[1].characters.count { - farthestOffset = split[1].characters.count + if farthestOffset < split[1].count { + farthestOffset = split[1].count } } } From d77f9a05a00bfb2406600b22d79bfa9d669ca69c Mon Sep 17 00:00:00 2001 From: kaunteya Date: Sat, 6 Jan 2018 13:05:06 +0530 Subject: [PATCH 05/56] Duplicate Lines -> Copy lines --- Line/Info.plist | 112 ++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/Line/Info.plist b/Line/Info.plist index 162022c..2b71a47 100644 --- a/Line/Info.plist +++ b/Line/Info.plist @@ -28,62 +28,62 @@ XCSourceEditorCommandDefinitions - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).duplicate - XCSourceEditorCommandName - Duplicate Line - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).openNewLineBelow - XCSourceEditorCommandName - Open New Line Below - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).openNewLineAbove - XCSourceEditorCommandName - Open New Line Above - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).commentedDuplicate - XCSourceEditorCommandName - Commented Duplicate - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).deleteLine - XCSourceEditorCommandName - Delete Line - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).join - XCSourceEditorCommandName - Join Line - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).lineBeginning - XCSourceEditorCommandName - Line Beginning - + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).duplicate + XCSourceEditorCommandName + Copy Lines + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).openNewLineBelow + XCSourceEditorCommandName + Open New Line Below + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).openNewLineAbove + XCSourceEditorCommandName + Open New Line Above + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).commentedDuplicate + XCSourceEditorCommandName + Commented Duplicate + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).deleteLine + XCSourceEditorCommandName + Delete Line + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).join + XCSourceEditorCommandName + Join Line + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).lineBeginning + XCSourceEditorCommandName + Line Beginning + XCSourceEditorExtensionPrincipalClass $(PRODUCT_MODULE_NAME).SourceEditorExtension From 0a7702087522e99c486a0f3c2e75ef3799e7ee11 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 6 Jan 2018 13:17:18 +0530 Subject: [PATCH 06/56] Updated readme for copy lines --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b97c1f..b423ed1 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Linex can be downloaded from the Mac App Store. # Key Features - [Line](#line) - - [Duplicate](#duplicate) + - [Copy Line](#copy-line) - [Open new Line below](#open-new-line-below) - [Open New Line Above](#open-new-line-above) - [Commented Duplicate](#commented-duplicate) @@ -62,7 +62,7 @@ Linex can be downloaded from the Mac App Store. - [Decrement](#convert) ## Line -### Duplicate +### Copy Lines Duplicates current line or selected line ### Open New Line Below @@ -130,11 +130,11 @@ These shortcuts also toggles `true`, `false`, `YES` & `NO` | Action | Shortcut | | -------------------- | :--------------------------------------------------: | | `Line` | | -| Duplicate | | +| Copy Lines | OPTN+ | | Open New Line Below | CTRL+return | | Open New Line Above | CTRL+SHIFT+return | | Commented Duplicate | CMD+CTRL+/ | -| Delete Line | CTRL+OPTN+L | +| Delete Line | CTRL+OPTN+L | | Join Line | CTRL+J | | Line Beginning | CTRL+A | | | | From bf6e2c16f863fa13a1791bcfcc6d34cda4a745bc Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 25 Jan 2018 15:16:00 +0530 Subject: [PATCH 07/56] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b423ed1..a1b8445 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ ## Mac App Store -Linex can be downloaded from the Mac App Store. +Linex can be downloaded from the Mac App Store at a very modest price. Please consider purchasing it. Mac App Store From 28ce8a34c034d11c08561c92d3adcf5ce8541452 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 19 Apr 2018 19:00:40 +0530 Subject: [PATCH 08/56] Line selection first selects line without indentation-whitespace --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ .../xcschemes/xcschememanagement.plist | 20 +++++-------------- Selection/SourceEditorCommand.swift | 17 +++++++++++++--- 3 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 Linex.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Linex.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Linex.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Linex.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist b/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist index 0b5f9f8..0c9e804 100644 --- a/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist @@ -4,6 +4,11 @@ SchemeUserState + Convert.xcscheme + + orderHint + 3 + Line.xcscheme orderHint @@ -32,21 +37,6 @@ primary - E359423A1F55565E009EFA35 - - primary - - - E39E226C1F59876A00354A5F - - primary - - - E3F543921F5A84FC008F426E - - primary - - diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index f3e8cd7..f83474e 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -24,9 +24,20 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { switch Options(command: invocation.commandIdentifier)! { case .selectLine: let range = buffer.selections.lastObject as! XCSourceTextRange - range.start.column = 0 - range.end.line += 1 - range.end.column = 0 + switch selectedRanges { + case .none(let line, _): + let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() + range.start.column = indentationOffset + range.end.column = (buffer.lines[line] as! String).count - 1 + + case .words(_, _, _), + .lines(_, _): + range.start.column = 0 + range.end.line += 1 + range.end.column = 0 + + case .multiLocation(_): break + } case .selectLineAbove: let range = buffer.selections.lastObject as! XCSourceTextRange From c33820ea3d39b0bceb64f1f306dd46458fba294d Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 19 Apr 2018 19:12:18 +0530 Subject: [PATCH 09/56] Version update --- Linex/Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linex/Info.plist b/Linex/Info.plist index 6a141d9..95499b4 100644 --- a/Linex/Info.plist +++ b/Linex/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.4 + 0.6 CFBundleVersion - 5 + 7 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion From 2f4001e64f1fba2fc66edd5dd6346fbb0f820541 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Fri, 20 Apr 2018 09:54:49 +0530 Subject: [PATCH 10/56] Updated readme --- README.md | 96 ++++++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index a1b8445..41f41e4 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ # Content - [📦 Installation](#installation) -- [⭐️ Key Features](#key-features) +- [⭐️ Key Features](#features) - [⌨️ Shortcuts](#shortcuts) - [👩‍💻 Contributing](#contributing) - [📃 License](#license) @@ -42,83 +42,79 @@ Linex can be downloaded from the Mac App Store at a very modest price. Please co Extension preferences -# Key Features -- [Line](#line) - - [Copy Line](#copy-line) - - [Open new Line below](#open-new-line-below) - - [Open New Line Above](#open-new-line-above) - - [Commented Duplicate](#commented-duplicate) - - [Delete Line](#delete-line) - - [Join Line](#join-line) - - [Line beginning](#line-beginning) -- [Selection](#selection) - - [Select Word](#select-word) - - [Select Line](#select-line) - - [Select Line up](#select-line-up) - - [One Space](#one-space) - - [Align](#align) -- [Convert](#convert) - - [Increment](#convert) - - [Decrement](#convert) - -## Line -### Copy Lines -Duplicates current line or selected line - -### Open New Line Below +# Features + +Copy Line + +
Open new Line below + Inserts new blank line below current line. This allows you to create a new indented line irrespective of your current caret postion. ![](/Images/opennewline.gif) +
-### Open New Line Above -Inserts new blank line above current line +
Open New Line Above + + Inserts new blank line above current line ![](/Images/openlineabove.gif) +
-### Commented Duplicate -Duplicate+Comment current line or selected lines. It can be used to check variations in code +
Commented Duplicate + + Duplicate+Comment current line or selected lines. It can be used to check variations in code ![](/Images/commentedduplicate.gif) +
-### Delete Line -Delete current line or selected lines +Delete Line -### Join Line -Joins the line below or all the selected lines +
Join Line + + Joins the line below or all the selected lines ![](/Images/join.gif) -![](/Images/join-selection.gif) +
-### Line Beginning -Toggles the caret between indented beginning and the real begninning +
Line beginning + + Toggles the caret between indented beginning and the real begninning ![Line Beginning](/Images/togglehome.gif) +
-## Selection -### Select Word -Selects the word around the caret +Select Word -### Select Line -Selects line. After selecting current line starts selecting next lines +
Select Line + + Selects line. After selecting current line starts selecting next lines ![Select line](/Images/selectline.gif) +
-### Select Line up -Selects line above the caret one-by-one +
Select Line up + + Selects line above the caret one-by-one Combination of `Select line` and `Select line up` can be used to expand selection above and below as seen below ![Select line up](/Images/selectdownup.gif) +
-### One Space -Replace consecutive spaces with one space. Press again to toggle between `one space` and `no space` +
One Space + + Replace consecutive spaces with one space. Press again to toggle between `one space` and `no space` ![One Space](/Images/onespace.gif) +
+ +
Align -### Align -Smart align code. + Smart align code. ![Align](/Images/propertyalign.gif) +
-## Convert -### Increment & Decrement -Increment & Decrement using quick shortcuts. +
Increment / Decrement + + Increment & Decrement using quick shortcuts. ![Increment Decrement](/Images/incrementdecrement.gif) These shortcuts also toggles `true`, `false`, `YES` & `NO` ![True false](/Images/incdec.gif) +
# Shortcuts From b2297f2ef2ab4a32423a1fd6a8e1a50f2201397d Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sun, 29 Apr 2018 12:55:37 +0530 Subject: [PATCH 11/56] Added .DS_Store to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5d84a1a..c29b7fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ +.DS_Store + # Xcode -# build/ *.pbxuser !default.pbxuser From 2266f06463651379ea4fc891ee3289180dd183d0 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sun, 29 Apr 2018 12:56:45 +0530 Subject: [PATCH 12/56] Updated alignment --- Linex.xcodeproj/project.pbxproj | 12 ++++++------ Selection/{Util.swift => Alignment.swift} | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) rename Selection/{Util.swift => Alignment.swift} (95%) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 67db3b3..2e1f8b3 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -20,8 +20,8 @@ E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35942421F55565E009EFA35 /* SourceEditorExtension.swift */; }; E35942451F55565E009EFA35 /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35942441F55565E009EFA35 /* SourceEditorCommand.swift */; }; E35942491F55565E009EFA35 /* Line.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E359423B1F55565E009EFA35 /* Line.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - E359BCF61F604E000071246B /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359BCF51F604E000071246B /* Util.swift */; }; - E359BD0A1F6063A70071246B /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359BCF51F604E000071246B /* Util.swift */; }; + E359BCF61F604E000071246B /* Alignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359BCF51F604E000071246B /* Alignment.swift */; }; + E359BD0A1F6063A70071246B /* Alignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359BCF51F604E000071246B /* Alignment.swift */; }; E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; @@ -105,7 +105,7 @@ E35942421F55565E009EFA35 /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; E35942441F55565E009EFA35 /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; E35942461F55565E009EFA35 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E359BCF51F604E000071246B /* Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; + E359BCF51F604E000071246B /* Alignment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alignment.swift; sourceTree = ""; }; E35F567A1F7BEFA100905225 /* propertyalign.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = propertyalign.gif; sourceTree = ""; }; E383F00A1F7A13A900429B4D /* TestPad.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestPad.m; sourceTree = ""; }; E39E226D1F59876A00354A5F /* Selection.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Selection.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -258,7 +258,7 @@ children = ( E39E22721F59876A00354A5F /* SourceEditorExtension.swift */, E39E22741F59876A00354A5F /* SourceEditorCommand.swift */, - E359BCF51F604E000071246B /* Util.swift */, + E359BCF51F604E000071246B /* Alignment.swift */, E39E22761F59876A00354A5F /* Info.plist */, E39E22701F59876A00354A5F /* Supporting Files */, ); @@ -506,7 +506,7 @@ files = ( E39E22821F59C59300354A5F /* Common.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, - E359BD0A1F6063A70071246B /* Util.swift in Sources */, + E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -530,7 +530,7 @@ E39E22811F59C59200354A5F /* Common.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, - E359BCF61F604E000071246B /* Util.swift in Sources */, + E359BCF61F604E000071246B /* Alignment.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Selection/Util.swift b/Selection/Alignment.swift similarity index 95% rename from Selection/Util.swift rename to Selection/Alignment.swift index 0d526de..b285591 100644 --- a/Selection/Util.swift +++ b/Selection/Alignment.swift @@ -10,7 +10,7 @@ import Foundation extension Array where Element == String { // Return nil when offset is not found in any line - func farthestOffsetFor(subStr: String) -> Int? { + private func farthestOffsetFor(subStr: String) -> Int? { guard self.count > 0 else { return nil; } var farthest: Int = 0 for str in self { @@ -23,7 +23,7 @@ extension Array where Element == String { return farthest } - func alignedDefineStatements() -> [String] { + private func alignedDefineStatements() -> [String] { var farthestOffset = 0 var indexSet = [Int]() var alignedLines = self @@ -56,7 +56,7 @@ extension Array where Element == String { return alignedLines } - func alignedPropertyStatements() -> [String]? { + private func alignedPropertyStatements() -> [String]? { let pattern = "@property\\s*(\\([\\w,= ]+\\))*\\s*(\\w+)\\s*(\\*)*\\s*(\\w+);(.*)" let mainRegex = try! NSRegularExpression(pattern: pattern) @@ -105,7 +105,7 @@ extension Array where Element == String { } } - func aligned(seperator: String) -> [String]? { + private func aligned(seperator: String) -> [String]? { guard self.count > 1 else { assert(self.count == 1) return self From e5fd316c595bf53c1d475b3a9c1534cbec2071d8 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 00:09:47 +0530 Subject: [PATCH 13/56] Updated expand --- Balanced.swift | 95 +++++++++++++++++++++ Common.swift | 15 ++-- Convert/SourceEditorCommand.swift | 3 +- Linex.xcodeproj/project.pbxproj | 16 +++- LinexTests/SelectionTests.swift | 22 +++++ Selection/SourceEditorCommand.swift | 128 ++++++++++++++++++++++++++-- 6 files changed, 258 insertions(+), 21 deletions(-) create mode 100644 Balanced.swift create mode 100644 LinexTests/SelectionTests.swift diff --git a/Balanced.swift b/Balanced.swift new file mode 100644 index 0000000..a350116 --- /dev/null +++ b/Balanced.swift @@ -0,0 +1,95 @@ +// +// Balanced.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 02/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +import XcodeKit + +extension Character { + var isOpening: Bool { + let openStopper = CharacterSet(charactersIn: "{[(") + return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) + } + var isClosing:Bool { + let openStopper = CharacterSet(charactersIn: "}])") + return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) + } + func isPresent(in characterSet:CharacterSet) -> Bool { + return CharacterSet(charactersIn: String(self)).isSubset(of: characterSet) + } + var closing: Character { + assert(self.isOpening, "Only opening characters can have closing characters") + return ["{":"}", "(":")", "[":"]"][self]! + } + var opening: Character { + assert(self.isClosing, "Only closing characters can have opening characters") + return ["}":"{", ")":"(", "]":"["][self]! + } +} + +private let closingFor = ["{":"}", "(":")", "[":"]"] +private let openingFor = ["}":"{", ")":"(", "]":"["] + +extension XCSourceTextBuffer { + func findClosing(for openingChar: Character, + at position: XCSourceTextPosition) -> XCSourceTextPosition? { + let closingChar = openingChar.closing + var stackCount = 0 + + var currentPosition = position.next(in: self) + while currentPosition != nil { + let currentChar = self.char(at: currentPosition!) + switch currentChar { + case openingChar: stackCount += 1 + case closingChar: + if stackCount == 0 { + return XCSourceTextPosition(line: currentPosition!.line, + column: currentPosition!.column + 1) + } + stackCount -= 1 + default: break + } + currentPosition = currentPosition!.next(in: self) + } + return nil + } +} + +extension XCSourceTextBuffer { + var lastPosition: XCSourceTextPosition { + let lastLine = self.lines[self.lines.count - 1] as! String + return XCSourceTextPosition(line: self.lines.count - 1, column: lastLine.count - 1) + } + + func isEnd(position: XCSourceTextPosition) -> Bool { + return lastPosition == position + } + + func char(at position: XCSourceTextPosition) -> Character { + let currentLine = self.lines[position.line] as! String + return currentLine[position.column] as Character + } +} + +extension XCSourceTextPosition { + func next(in buffer: XCSourceTextBuffer) -> XCSourceTextPosition? { + guard self != buffer.lastPosition else { return nil } + + let currentLine = buffer.lines[self.line] as! String + if self.column == currentLine.count - 1 { + return XCSourceTextPosition(line: self.line + 1, column: 0) + } + let newPosition = XCSourceTextPosition(line: self.line, column: self.column + 1) + return newPosition + } +} + +extension XCSourceTextPosition: Equatable { + public static func == (lhs: XCSourceTextPosition, rhs: XCSourceTextPosition) -> Bool { + return lhs.line == rhs.line && lhs.column == rhs.column + } +} diff --git a/Common.swift b/Common.swift index a829cae..83bbcd8 100644 --- a/Common.swift +++ b/Common.swift @@ -108,12 +108,12 @@ extension String { return (start, newString) } - func selectWord(pin: Int) -> Range? { - guard let range:Range = selectWord(pin: pin) else { return nil } + func selectWord(pin: Int, validChars: CharacterSet) -> Range? { + guard let range:Range = selectWord(pin: pin, validChars: validChars) else { return nil } return self.indexRangeFor(range: range) } - func selectWord(pin: Int) -> Range? { + func selectWord(pin: Int, validChars: CharacterSet) -> Range? { var pin = pin guard pin <= self.count else { return nil @@ -123,13 +123,8 @@ extension String { } // Move pin to one position left when it is after last character - let invalidLastChars = CharacterSet(charactersIn: " :!?,.") - var validChars = CharacterSet.alphanumerics - validChars.insert(charactersIn: "@_") - if (pin > 0), let _ = (self[pin] as String).rangeOfCharacter(from: invalidLastChars) { - if let _ = (self[pin - 1] as String).rangeOfCharacter(from: validChars) { - pin -= 1 - } + if (pin > 0), let _ = (self[pin - 1] as String).rangeOfCharacter(from: validChars) { + pin -= 1 } var start = pin diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 8d04ec2..88ae89d 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -36,7 +36,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .decrement: currentLine.replaceSubrange(currentRange, with: "\(num - 1)") } } else { - if let selectionRange:Range = currentLine.selectWord(pin: column) { + let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) + if let selectionRange:Range = currentLine.selectWord(pin: column, validChars: validChars) { let selectedSubString = currentLine[selectionRange] if let newString = toggle(boolString: selectedSubString) { currentLine.replaceSubrange(selectionRange, with: newString) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 2e1f8b3..c167798 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -22,6 +22,10 @@ E35942491F55565E009EFA35 /* Line.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E359423B1F55565E009EFA35 /* Line.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; E359BCF61F604E000071246B /* Alignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359BCF51F604E000071246B /* Alignment.swift */; }; E359BD0A1F6063A70071246B /* Alignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359BCF51F604E000071246B /* Alignment.swift */; }; + E37DDA782099DD5700D86394 /* Balanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA762099D9D100D86394 /* Balanced.swift */; }; + E37DDA792099DD5800D86394 /* Balanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA762099D9D100D86394 /* Balanced.swift */; }; + E37DDA7A2099DD5900D86394 /* Balanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA762099D9D100D86394 /* Balanced.swift */; }; + E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA7C2099E65900D86394 /* SelectionTests.swift */; }; E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; @@ -107,6 +111,8 @@ E35942461F55565E009EFA35 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E359BCF51F604E000071246B /* Alignment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alignment.swift; sourceTree = ""; }; E35F567A1F7BEFA100905225 /* propertyalign.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = propertyalign.gif; sourceTree = ""; }; + E37DDA762099D9D100D86394 /* Balanced.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Balanced.swift; sourceTree = ""; }; + E37DDA7C2099E65900D86394 /* SelectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionTests.swift; sourceTree = ""; }; E383F00A1F7A13A900429B4D /* TestPad.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestPad.m; sourceTree = ""; }; E39E226D1F59876A00354A5F /* Selection.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Selection.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E39E22711F59876A00354A5F /* Selection.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Selection.entitlements; sourceTree = ""; }; @@ -168,6 +174,7 @@ children = ( E39E227E1F59C58E00354A5F /* Common.swift */, E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */, + E37DDA762099D9D100D86394 /* Balanced.swift */, E35F56791F7BEFA100905225 /* Images */, E35942191F55564C009EFA35 /* Linex */, E359422B1F55564D009EFA35 /* LinexTests */, @@ -210,6 +217,7 @@ isa = PBXGroup; children = ( E359422C1F55564D009EFA35 /* LinexTests.swift */, + E37DDA7C2099E65900D86394 /* SelectionTests.swift */, E356FD811F66F55C004558F1 /* TestPad.swift */, E383F00A1F7A13A900429B4D /* TestPad.m */, E359422E1F55564D009EFA35 /* Info.plist */, @@ -507,6 +515,7 @@ E39E22821F59C59300354A5F /* Common.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, + E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -515,6 +524,7 @@ buildActionMask = 2147483647; files = ( E356FD7E1F66D281004558F1 /* XcodeKitExt.swift in Sources */, + E37DDA782099DD5700D86394 /* Balanced.swift in Sources */, E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, E31FD4741F5712540044765A /* Extras.swift in Sources */, E39E22801F59C59100354A5F /* Common.swift in Sources */, @@ -527,6 +537,7 @@ buildActionMask = 2147483647; files = ( E356FD7F1F66D282004558F1 /* XcodeKitExt.swift in Sources */, + E37DDA792099DD5800D86394 /* Balanced.swift in Sources */, E39E22811F59C59200354A5F /* Common.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, @@ -542,6 +553,7 @@ E3F543A61F5ABA48008F426E /* Common.swift in Sources */, E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, + E37DDA7A2099DD5900D86394 /* Balanced.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -694,7 +706,7 @@ CODE_SIGN_ENTITLEMENTS = Linex/Linex.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = KQQ77ZBE5E; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; @@ -712,7 +724,7 @@ CODE_SIGN_ENTITLEMENTS = Linex/Linex.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = KQQ77ZBE5E; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; diff --git a/LinexTests/SelectionTests.swift b/LinexTests/SelectionTests.swift new file mode 100644 index 0000000..5094734 --- /dev/null +++ b/LinexTests/SelectionTests.swift @@ -0,0 +1,22 @@ +// +// SelectionTests.swift +// LinexTests +// +// Created by Kaunteya Suryawanshi on 02/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import XCTest +@testable import Linex + +class SelectionTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + func testFoo() { + find + } +} diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index f83474e..da3bae3 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -16,14 +16,16 @@ enum Options: String { class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { - + defer { + completionHandler(nil) + } let buffer = invocation.buffer let selectedRanges: SelectionType = selectionRanges(of: buffer) let selectionIndex: IndexSet = selectedLinesIndexSet(for: selectedRanges) + let range = buffer.selections.lastObject as! XCSourceTextRange switch Options(command: invocation.commandIdentifier)! { case .selectLine: - let range = buffer.selections.lastObject as! XCSourceTextRange switch selectedRanges { case .none(let line, _): let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() @@ -40,7 +42,6 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .selectLineAbove: - let range = buffer.selections.lastObject as! XCSourceTextRange range.start.column = 0 range.start.line = max(range.start.line - 1, 0) range.end.column = 0 @@ -48,7 +49,6 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .oneSpace: switch selectedRanges { case .none(let line, let column): - let range = buffer.selections.lastObject as! XCSourceTextRange let currentLine = buffer.lines[line] as! String let (newOffset, newLine) = currentLine.lineOneSpaceAt(pin: column) buffer.lines.replaceObject(at: line, with: newLine) @@ -62,14 +62,82 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .expand: switch selectedRanges { case .none(let line, let column): - let range = buffer.selections.lastObject as! XCSourceTextRange let currentLine = buffer.lines[line] as! String + if currentLine.count == 0 { return } + let lineEnd = currentLine.count - 1 + var rightChar: Character? + if column < lineEnd { + rightChar = currentLine[column] as Character + } + var leftChar: Character? + if (column > 0) { + leftChar = currentLine[column - 1] as Character + } + + if let rightChar = rightChar, rightChar.isOpening { + if let position = buffer.findClosing(for: rightChar, at: XCSourceTextPosition(line: line, column: column)) { + range.end = position + } + } - if let selectionRange:Range = currentLine.selectWord(pin: column) { + let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) + if let selectionRange:Range = currentLine.selectWord(pin: column, validChars: validChars) { range.start.column = selectionRange.lowerBound range.end.column = selectionRange.upperBound } - case .words(_, _, _): break + case .words(let line, let colStart, let colEnd): + let currentLine = buffer.lines[line] as! String + let indentationIndex = currentLine.lineIndentationOffset() + let lineEnd = currentLine.count - 1 + let currentStart = currentLine[colStart] as Character + let currentEnd = currentLine[colEnd - 1] as Character + let borderStart = currentLine[colStart - 1] as Character + let borderEnd = currentLine[colEnd] as Character + + if (borderStart == "." || borderEnd == ".") { + let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_.")) + if let selectionRange:Range = currentLine.selectWord(pin: colStart, validChars: validChars) { + range.start.column = selectionRange.lowerBound + range.end.column = selectionRange.upperBound + } + return + } + if (borderEnd == "(") { + if let end = currentLine.findClosingPosition(from: colEnd + 1) { + range.end.column = end + 1 + } + } + if (colStart == indentationIndex) { + range.end.column = lineEnd + return + } + + if (colEnd == lineEnd) { + range.start.column = currentLine.lineIndentationOffset() + return + } + + switch (borderStart, borderEnd) { + case ("\"","\""), ("{", "}"), ("[","]"), ("(",")"): + range.start.column = colStart - 1 + range.end.column = colEnd + 1 + return + default: break + } + + if (currentStart == "(" && currentEnd == ")" && colEnd == lineEnd) { + range.start.column = currentLine.lineIndentationOffset() + return + } + + if let start = currentLine.findOpeningPosition(from: colStart) { + range.start.column = start + } + + if let end = currentLine.findClosingPosition(from: colEnd) { + range.end.column = end + } + case .lines(_, _): break case .multiLocation(_): break } @@ -87,7 +155,51 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .multiLocation(_): break } } - completionHandler(nil) + // completionHandler(nil) } } + +let openStopper = CharacterSet(charactersIn: "{[(\"") +let closeStopper = CharacterSet(charactersIn: "}])\"") +extension String { + func findOpeningPosition(from: Int) -> Int? { + var from = from - 1 + var onTheWayBrackets = 0 + while from >= 0 { + let currentChar = self[from] as String + + if currentChar.rangeOfCharacter(from: openStopper) != nil { + if onTheWayBrackets == 0 { + return from + 1 + } + onTheWayBrackets -= 1 + } + if currentChar.rangeOfCharacter(from: closeStopper) != nil { + onTheWayBrackets += 1 + } + from -= 1 + } + return nil + } + func findClosingPosition(from: Int) -> Int? { + var from = from + var onTheWayBrackets = 0 + let endOfLine = self.count + while from < endOfLine { + let currentChar = self[from] as String + + if currentChar.rangeOfCharacter(from: closeStopper) != nil { + if onTheWayBrackets == 0 { + return from + } + onTheWayBrackets -= 1 + } + if currentChar.rangeOfCharacter(from: openStopper) != nil { + onTheWayBrackets += 1 + } + from += 1 + } + return nil + } +} From 4bbd85bd4093c0fec656a8e20b8d2ddf2702fe5c Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 00:14:21 +0530 Subject: [PATCH 14/56] Update none selection --- Convert/SourceEditorCommand.swift | 10 +++++----- XcodeKitExt.swift | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 88ae89d..332b7eb 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -23,10 +23,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { if let command = Options(command: invocation.commandIdentifier) { switch selectedRanges { - case .none(let line, let column): + case .none(let position): let range = buffer.selections.firstObject as! XCSourceTextRange - var currentLine = buffer.lines[line] as! String - let currentChar = currentLine[column] as String + var currentLine = buffer.lines[position.line] as! String + let currentChar = currentLine[position.column] as String //If caret is beside number if let _ = currentChar.rangeOfCharacter(from: .decimalDigits), let num = Int(currentChar) { @@ -37,14 +37,14 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } } else { let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) - if let selectionRange:Range = currentLine.selectWord(pin: column, validChars: validChars) { + if let selectionRange:Range = currentLine.selectWord(pin: position.column, validChars: validChars) { let selectedSubString = currentLine[selectionRange] if let newString = toggle(boolString: selectedSubString) { currentLine.replaceSubrange(selectionRange, with: newString) } } } - buffer.lines.replaceObject(at: line, with: currentLine) + buffer.lines.replaceObject(at: position.line, with: currentLine) case .words(let line, let colStart, let colEnd): var currentLine = buffer.lines[line] as! String diff --git a/XcodeKitExt.swift b/XcodeKitExt.swift index 62cb5d6..60398e6 100644 --- a/XcodeKitExt.swift +++ b/XcodeKitExt.swift @@ -10,7 +10,7 @@ import Foundation import XcodeKit enum SelectionType { - case none(line: Int, col: Int) + case none(position: XCSourceTextPosition) case words(line: Int, colStart: Int, colEnd: Int) case lines(start:XCSourceTextPosition, end: XCSourceTextPosition)//Complete line selection is counted multiline case multiLocation([XCSourceTextRange]) @@ -23,7 +23,7 @@ func selectionRanges(of buffer: XCSourceTextBuffer) -> SelectionType { let range = selections.first! if range.start.line == range.end.line { if range.start.column == range.end.column { - return .none(line: range.start.line, col: range.start.column) + return .none(position: XCSourceTextPosition(line: range.start.line, column: range.start.column)) } return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) } @@ -39,7 +39,7 @@ func selectionRanges(of buffer: XCSourceTextBuffer) -> SelectionType { /// - Returns: Returns nil if no selection func selectedLinesIndexSet(for selectedRanges: SelectionType) -> IndexSet { switch selectedRanges { - case .none(let line, _): return IndexSet(integer: line) + case .none(let position): return IndexSet(integer: position.line) case .words(let line, _, _): return IndexSet(integer: line) case .lines(let start, let end): return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) From 4c192c1859d13cb9956f34a378ab97224bac88e0 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 09:21:36 +0530 Subject: [PATCH 15/56] Fixes --- Line/SourceEditorCommand.swift | 68 +++++++++++++++---- Linex.xcodeproj/project.pbxproj | 6 +- .../xcschemes/Linex.xcscheme | 4 +- Selection/SourceEditorCommand.swift | 32 ++++----- 4 files changed, 76 insertions(+), 34 deletions(-) diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 5ecc118..d4bb132 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -29,8 +29,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { buffer.lines.insert(copyOfLines, at: selectionIndexSet) switch selectedRanges { - case .none(_, let column): - if column == 0 { + case .none(let position): + if position.column == 0 { range.start.line += 1 range.end.line += 1 } @@ -47,8 +47,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { buffer.lines.insert(commentedLines, at: selectionIndexSet) switch selectedRanges { - case .none(_, let column): - if column == 0 { + case .none(let position): + if position.column == 0 { range.start.line += 1 range.end.line += 1 } @@ -60,8 +60,17 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .openNewLineBelow: switch selectedRanges { - case .none(let line, _), - .words(let line, _, _): + case .none(let position): + let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() + buffer.lines.insert(offsetWhiteSpaces, at: position.line + 1) + //Selection + let position = XCSourceTextPosition(line: position.line + 1, column: indentationOffset) + let lineSelection = XCSourceTextRange(start: position, end: position) + buffer.selections.setArray([lineSelection]) + + case .words(let line, _, _): + let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: line + 1) @@ -76,8 +85,16 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .openNewLineAbove: switch selectedRanges { - case .none(let line, _), - .words(let line, _, _): + case .none(let position): + let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() + buffer.lines.insert(offsetWhiteSpaces, at: position.line) + //Selection + let position = XCSourceTextPosition(line: position.line, column: indentationOffset) + let lineSelection = XCSourceTextRange(start: position, end: position) + buffer.selections.setArray([lineSelection]) + + case .words(let line, _, _): let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: line) @@ -92,8 +109,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .deleteLine: switch selectedRanges { - case .none(let line, _), - .words(let line, _, _): + case .none(let position): + buffer.lines.removeObject(at: position.line) + + case .words(let line, _, _): buffer.lines.removeObject(at: line) case .lines(_, _): break @@ -102,8 +121,21 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .join: switch selectedRanges { - case .none(let line, _), - .words(let line, _, _): + case .none(let position): + if position.line == buffer.lines.count { return } + + let firstLine = (buffer.lines[position.line] as! String).trimmingCharacters(in: .newlines) + let newLine = (buffer.lines[position.line + 1] as! String).trimmingCharacters(in: .whitespaces) + + buffer.lines.replaceObject(at: position.line, with: "\(firstLine) \(newLine)") + buffer.lines.removeObject(at: position.line + 1) + + //Selection/CaretPosition + let range = buffer.selections.lastObject as! XCSourceTextRange + range.start.column = firstLine.count + 1 + range.end.column = firstLine.count + 1 + + case .words(let line, _, _): if line == buffer.lines.count { return } let firstLine = (buffer.lines[line] as! String).trimmingCharacters(in: .newlines) @@ -141,8 +173,16 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .lineBeginning: switch selectedRanges { - case .none(let line, _), - .words(let line, _, _): + case .none(let position): + let range = buffer.selections.lastObject as! XCSourceTextRange + let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + if range.start.column == indentationOffset { + range.start.column = 0; range.end.column = 0; + } else { + range.start.column = indentationOffset; range.end.column = indentationOffset; + } + + case .words(let line, _, _): let range = buffer.selections.lastObject as! XCSourceTextRange let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() if range.start.column == indentationOffset { diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index c167798..0928836 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -400,7 +400,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 0930; ORGANIZATIONNAME = "Kaunteya Suryawanshi"; TargetAttributes = { E35942161F55564C009EFA35 = { @@ -608,6 +608,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -615,6 +616,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -664,6 +666,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -671,6 +674,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; diff --git a/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/Linex.xcscheme b/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/Linex.xcscheme index c6ee9e4..2729c9a 100644 --- a/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/Linex.xcscheme +++ b/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/Linex.xcscheme @@ -1,6 +1,6 @@ 0) { - leftChar = currentLine[column - 1] as Character + if (position.column > 0) { + leftChar = currentLine[position.column - 1] as Character } if let rightChar = rightChar, rightChar.isOpening { - if let position = buffer.findClosing(for: rightChar, at: XCSourceTextPosition(line: line, column: column)) { + if let position = buffer.findClosing(for: rightChar, at: position) { range.end = position } } let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) - if let selectionRange:Range = currentLine.selectWord(pin: column, validChars: validChars) { + if let selectionRange:Range = currentLine.selectWord(pin: position.column, validChars: validChars) { range.start.column = selectionRange.lowerBound range.end.column = selectionRange.upperBound } @@ -144,7 +144,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .align: switch selectedRanges { - case .none(_, _): break + case .none(_): break case .words(_, _, _): break case .lines(_, _): let selectedLines = buffer.lines.objects(at: selectionIndex) as! [String] From a5832b22e6bb73aa82204744b356e4ffd4a6b03d Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 19:11:40 +0530 Subject: [PATCH 16/56] Minor changes --- Balanced.swift | 40 +++++++++++++++++++++++++---- Common.swift | 34 ++++++++++++------------ Convert/SourceEditorCommand.swift | 4 +-- Selection/SourceEditorCommand.swift | 37 +++++++++++++++----------- 4 files changed, 75 insertions(+), 40 deletions(-) diff --git a/Balanced.swift b/Balanced.swift index a350116..1d6589a 100644 --- a/Balanced.swift +++ b/Balanced.swift @@ -35,11 +35,10 @@ private let closingFor = ["{":"}", "(":")", "[":"]"] private let openingFor = ["}":"{", ")":"(", "]":"["] extension XCSourceTextBuffer { - func findClosing(for openingChar: Character, - at position: XCSourceTextPosition) -> XCSourceTextPosition? { + + func findClosing(for openingChar: Character, at position: XCSourceTextPosition) -> XCSourceTextPosition? { let closingChar = openingChar.closing var stackCount = 0 - var currentPosition = position.next(in: self) while currentPosition != nil { let currentChar = self.char(at: currentPosition!) @@ -57,6 +56,24 @@ extension XCSourceTextBuffer { } return nil } + + func findOpening(for closingChar: Character, at position: XCSourceTextPosition) -> XCSourceTextPosition? { + let openingChar = closingChar.opening + var stackCount = 0 + var currentPosition = position.previous(in: self)?.previous(in: self) + while currentPosition != nil { + let currentChar = self.char(at: currentPosition!) + switch currentChar { + case closingChar: stackCount += 1 + case openingChar: + if stackCount == 0 { return currentPosition! } + stackCount -= 1 + default: break + } + currentPosition = currentPosition?.previous(in: self) + } + return nil + } } extension XCSourceTextBuffer { @@ -76,6 +93,10 @@ extension XCSourceTextBuffer { } extension XCSourceTextPosition { + var isStart: Bool { + return self.line == 0 && self.column == 0 + } + func next(in buffer: XCSourceTextBuffer) -> XCSourceTextPosition? { guard self != buffer.lastPosition else { return nil } @@ -83,8 +104,17 @@ extension XCSourceTextPosition { if self.column == currentLine.count - 1 { return XCSourceTextPosition(line: self.line + 1, column: 0) } - let newPosition = XCSourceTextPosition(line: self.line, column: self.column + 1) - return newPosition + return XCSourceTextPosition(line: self.line, column: self.column + 1) + } + + func previous(in buffer: XCSourceTextBuffer) -> XCSourceTextPosition? { + guard !self.isStart else { return nil} + + if self.column == 0 { + let currentLine = buffer.lines[self.line - 1] as! String + return XCSourceTextPosition(line: self.line - 1, column: currentLine.count - 1) + } + return XCSourceTextPosition(line: self.line, column: self.column - 1) } } diff --git a/Common.swift b/Common.swift index 83bbcd8..b3f0b20 100644 --- a/Common.swift +++ b/Common.swift @@ -16,15 +16,11 @@ extension String { return components.filter { !$0.isEmpty }.joined(separator: " ") } - subscript (i: Int) -> Character { + subscript(i: Int) -> Character { return self[index(startIndex, offsetBy: i)] } - subscript (i: Int) -> String { - return String(self[i] as Character) - } - - subscript (range: Range) -> Substring { + subscript(range: Range) -> Substring { let rangeIndex:Range = self.indexRangeFor(range: range) return self[rangeIndex] } @@ -33,16 +29,20 @@ extension String { return (self as NSString).substring(with: range) } - func indexAt(offset: Int) -> Index { + func index(at offset: Int) -> Index { return self.index(self.startIndex, offsetBy: offset) } func indexRangeFor(range: Range) -> Range { - return indexAt(offset: range.lowerBound)..) -> ClosedRange { - return indexAt(offset: range.lowerBound)...indexAt(offset: range.upperBound) + return index(at: range.lowerBound)...index(at: range.upperBound) + } + + mutating func replace(range: Range, with replacement: String) { + self.replaceSubrange(self.index(at: range.lowerBound).. 0), let _ = (self[pin - 1] as String).rangeOfCharacter(from: validChars) { + if (pin > 0), self[pin - 1].isPresent(in: validChars) { pin -= 1 } var start = pin - while start >= 0 && (self[start] as String).rangeOfCharacter(from: validChars) != nil { + while start >= 0 && self[start].isPresent(in: validChars) { start -= 1 } var end = pin - while end < count && (self[end] as String).rangeOfCharacter(from: validChars) != nil { + while end < count && self[end].isPresent(in: validChars) { end += 1 } if start == end { return nil } diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 332b7eb..68bcd35 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -26,10 +26,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .none(let position): let range = buffer.selections.firstObject as! XCSourceTextRange var currentLine = buffer.lines[position.line] as! String - let currentChar = currentLine[position.column] as String + let currentChar = currentLine[position.column] //If caret is beside number - if let _ = currentChar.rangeOfCharacter(from: .decimalDigits), let num = Int(currentChar) { + if currentChar.isPresent(in: .decimalDigits), let num = Int(String(currentChar)) { let currentRange = currentLine.indexRangeFor(range: range.start.column...range.start.column) switch command { case .increment: currentLine.replaceSubrange(currentRange, with: "\(num + 1)") diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index d64bd58..c02b2e5 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -65,21 +65,26 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let currentLine = buffer.lines[position.line] as! String if currentLine.count == 0 { return } let lineEnd = currentLine.count - 1 - var rightChar: Character? + if position.column < lineEnd { - rightChar = currentLine[position.column] as Character - } - var leftChar: Character? - if (position.column > 0) { - leftChar = currentLine[position.column - 1] as Character + let rightChar = currentLine[position.column] as Character + if rightChar.isOpening { + if let position = buffer.findClosing(for: rightChar, at: position) { + range.end = position + } + } } - if let rightChar = rightChar, rightChar.isOpening { - if let position = buffer.findClosing(for: rightChar, at: position) { - range.end = position + if (position.column > 0) { + let leftChar = currentLine[position.column - 1] as Character + if leftChar.isClosing { + if let position = buffer.findOpening(for: leftChar, at: position) { + range.start = position + } } } + let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) if let selectionRange:Range = currentLine.selectWord(pin: position.column, validChars: validChars) { range.start.column = selectionRange.lowerBound @@ -162,40 +167,42 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let openStopper = CharacterSet(charactersIn: "{[(\"") let closeStopper = CharacterSet(charactersIn: "}])\"") + extension String { func findOpeningPosition(from: Int) -> Int? { var from = from - 1 var onTheWayBrackets = 0 while from >= 0 { - let currentChar = self[from] as String + let currentChar = self[from] - if currentChar.rangeOfCharacter(from: openStopper) != nil { + if currentChar.isPresent(in: openStopper) { if onTheWayBrackets == 0 { return from + 1 } onTheWayBrackets -= 1 } - if currentChar.rangeOfCharacter(from: closeStopper) != nil { + if currentChar.isPresent(in: closeStopper) { onTheWayBrackets += 1 } from -= 1 } return nil } + func findClosingPosition(from: Int) -> Int? { var from = from var onTheWayBrackets = 0 let endOfLine = self.count while from < endOfLine { - let currentChar = self[from] as String + let currentChar = self[from] - if currentChar.rangeOfCharacter(from: closeStopper) != nil { + if currentChar.isPresent(in: closeStopper) { if onTheWayBrackets == 0 { return from } onTheWayBrackets -= 1 } - if currentChar.rangeOfCharacter(from: openStopper) != nil { + if currentChar.isPresent(in: openStopper) { onTheWayBrackets += 1 } from += 1 From 1e64bd1624748df8965a44ebdcffaafddba51193 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 19:26:18 +0530 Subject: [PATCH 17/56] Changes --- Common.swift | 72 ------------------------- Line/SourceEditorCommand.swift | 12 ++--- Linex.xcodeproj/project.pbxproj | 10 ++++ Selection/Alignment.swift | 3 +- Selection/SourceEditorCommand.swift | 8 +-- String+Basic.swift | 81 +++++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 83 deletions(-) create mode 100644 String+Basic.swift diff --git a/Common.swift b/Common.swift index b3f0b20..ea41d14 100644 --- a/Common.swift +++ b/Common.swift @@ -8,78 +8,6 @@ import Foundation //MARK: - Basic -extension String { - - /// All multiple whitespaces are replaced by one whitespace - var condensedWhitespace: String { - let components = self.components(separatedBy: .whitespaces) - return components.filter { !$0.isEmpty }.joined(separator: " ") - } - - subscript(i: Int) -> Character { - return self[index(startIndex, offsetBy: i)] - } - - subscript(range: Range) -> Substring { - let rangeIndex:Range = self.indexRangeFor(range: range) - return self[rangeIndex] - } - - subscript(range: NSRange) -> String { - return (self as NSString).substring(with: range) - } - - func index(at offset: Int) -> Index { - return self.index(self.startIndex, offsetBy: offset) - } - - func indexRangeFor(range: Range) -> Range { - return index(at: range.lowerBound)..) -> ClosedRange { - return index(at: range.lowerBound)...index(at: range.upperBound) - } - - mutating func replace(range: Range, with replacement: String) { - self.replaceSubrange(self.index(at: range.lowerBound).. 4 - func lineIndentationOffset() -> Int { - var i = 0 - for a in self { - if a == " " { - i += 1 - } else { break } - } - return i - } - - func trimmedStart() -> String { - return self.replacingOccurrences(of: "^[ \t]+", - with: "", - options: CompareOptions.regularExpression) - } - - func trimmedEnd() -> String { - return self.replacingOccurrences(of: "[ \t]+$", - with: "", - options: CompareOptions.regularExpression) - } - - func repeating(count: Int) -> String { - return Array(repeating: self, count: count).joined() - } - - func replacedRegex(pattern: String, with template: String) -> String { - let regex = try! NSRegularExpression(pattern: pattern) - let range = NSMakeRange(0, count) - let modString = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: template) - return modString - } -} //MARK: Advance extension String { diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index d4bb132..9ed9f40 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -61,7 +61,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .openNewLineBelow: switch selectedRanges { case .none(let position): - let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: position.line + 1) //Selection @@ -71,7 +71,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .words(let line, _, _): - let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[line] as! String).indentationOffset let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: line + 1) //Selection @@ -86,7 +86,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .openNewLineAbove: switch selectedRanges { case .none(let position): - let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: position.line) //Selection @@ -95,7 +95,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { buffer.selections.setArray([lineSelection]) case .words(let line, _, _): - let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[line] as! String).indentationOffset let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: line) //Selection @@ -175,7 +175,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { switch selectedRanges { case .none(let position): let range = buffer.selections.lastObject as! XCSourceTextRange - let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset if range.start.column == indentationOffset { range.start.column = 0; range.end.column = 0; } else { @@ -184,7 +184,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .words(let line, _, _): let range = buffer.selections.lastObject as! XCSourceTextRange - let indentationOffset = (buffer.lines[line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[line] as! String).indentationOffset if range.start.column == indentationOffset { range.start.column = 0; range.end.column = 0; } else { diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 0928836..0a8fe86 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -26,6 +26,10 @@ E37DDA792099DD5800D86394 /* Balanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA762099D9D100D86394 /* Balanced.swift */; }; E37DDA7A2099DD5900D86394 /* Balanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA762099D9D100D86394 /* Balanced.swift */; }; E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37DDA7C2099E65900D86394 /* SelectionTests.swift */; }; + E3938E35209DEC32007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; + E3938E36209DEC32007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; + E3938E37209DEC33007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; + E3938E38209DEC34007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; @@ -114,6 +118,7 @@ E37DDA762099D9D100D86394 /* Balanced.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Balanced.swift; sourceTree = ""; }; E37DDA7C2099E65900D86394 /* SelectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionTests.swift; sourceTree = ""; }; E383F00A1F7A13A900429B4D /* TestPad.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestPad.m; sourceTree = ""; }; + E3938E33209DEC2B007F69E3 /* String+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Basic.swift"; sourceTree = ""; }; E39E226D1F59876A00354A5F /* Selection.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Selection.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E39E22711F59876A00354A5F /* Selection.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Selection.entitlements; sourceTree = ""; }; E39E22721F59876A00354A5F /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -173,6 +178,7 @@ isa = PBXGroup; children = ( E39E227E1F59C58E00354A5F /* Common.swift */, + E3938E33209DEC2B007F69E3 /* String+Basic.swift */, E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */, E37DDA762099D9D100D86394 /* Balanced.swift */, E35F56791F7BEFA100905225 /* Images */, @@ -514,6 +520,7 @@ files = ( E39E22821F59C59300354A5F /* Common.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, + E3938E35209DEC32007F69E3 /* String+Basic.swift in Sources */, E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, ); @@ -529,6 +536,7 @@ E31FD4741F5712540044765A /* Extras.swift in Sources */, E39E22801F59C59100354A5F /* Common.swift in Sources */, E35942451F55565E009EFA35 /* SourceEditorCommand.swift in Sources */, + E3938E36209DEC32007F69E3 /* String+Basic.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -542,6 +550,7 @@ E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, E359BCF61F604E000071246B /* Alignment.swift in Sources */, + E3938E37209DEC33007F69E3 /* String+Basic.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -554,6 +563,7 @@ E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, E37DDA7A2099DD5900D86394 /* Balanced.swift in Sources */, + E3938E38209DEC34007F69E3 /* String+Basic.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Selection/Alignment.swift b/Selection/Alignment.swift index b285591..4f21c79 100644 --- a/Selection/Alignment.swift +++ b/Selection/Alignment.swift @@ -67,7 +67,8 @@ extension Array where Element == String { let range = NSRange(location: 0, length: line.count) if let property = mainRegex.firstMatch(in: line, options: [], range: range) { let attributeRange = property.range(at: 1) - if attributeRange.lowerBound < attributeRange.upperBound && maxAttributeLength < line[attributeRange].count { + if attributeRange.lowerBound < attributeRange.upperBound && + maxAttributeLength < line[attributeRange].count { maxAttributeLength = line[attributeRange].count } let dataTypeRange = property.range(at: 2) diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index c02b2e5..cf9eca8 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -28,7 +28,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .selectLine: switch selectedRanges { case .none(let position): - let indentationOffset = (buffer.lines[position.line] as! String).lineIndentationOffset() + let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset range.start.column = indentationOffset range.end.column = (buffer.lines[position.line] as! String).count - 1 @@ -92,7 +92,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .words(let line, let colStart, let colEnd): let currentLine = buffer.lines[line] as! String - let indentationIndex = currentLine.lineIndentationOffset() + let indentationIndex = currentLine.indentationOffset let lineEnd = currentLine.count - 1 let currentStart = currentLine[colStart] as Character let currentEnd = currentLine[colEnd - 1] as Character @@ -118,7 +118,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } if (colEnd == lineEnd) { - range.start.column = currentLine.lineIndentationOffset() + range.start.column = currentLine.indentationOffset return } @@ -131,7 +131,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } if (currentStart == "(" && currentEnd == ")" && colEnd == lineEnd) { - range.start.column = currentLine.lineIndentationOffset() + range.start.column = currentLine.indentationOffset return } diff --git a/String+Basic.swift b/String+Basic.swift new file mode 100644 index 0000000..472d62f --- /dev/null +++ b/String+Basic.swift @@ -0,0 +1,81 @@ +// +// String+Basic.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 05/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +extension String { + + /// All multiple whitespaces are replaced by one whitespace + var condensedWhitespace: String { + let components = self.components(separatedBy: .whitespaces) + return components.filter { !$0.isEmpty }.joined(separator: " ") + } + + func index(at offset: Int) -> Index { + return index(startIndex, offsetBy: offset) + } + + subscript(i: Int) -> Character { + return self[index(at: i)] + } + + subscript(range: Range) -> Substring { + let rangeIndex:Range = self.indexRangeFor(range: range) + return self[rangeIndex] + } + + subscript(range: NSRange) -> String { + return (self as NSString).substring(with: range) + } + + func indexRangeFor(range: Range) -> Range { + return index(at: range.lowerBound)..) -> ClosedRange { + return index(at: range.lowerBound)...index(at: range.upperBound) + } + + mutating func replace(range: Range, with replacement: String) { + self.replaceSubrange(self.index(at: range.lowerBound).. 4 + var indentationOffset: Int { + var i = 0 + for a in self { + if a == " " { + i += 1 + } else { break } + } + return i + } + + func trimmedStart() -> String { + return self.replacingOccurrences(of: "^[ \t]+", + with: "", + options: CompareOptions.regularExpression) + } + + func trimmedEnd() -> String { + return self.replacingOccurrences(of: "[ \t]+$", + with: "", + options: CompareOptions.regularExpression) + } + + func repeating(count: Int) -> String { + return Array(repeating: self, count: count).joined() + } + + func replacedRegex(pattern: String, with template: String) -> String { + let regex = try! NSRegularExpression(pattern: pattern) + let range = NSMakeRange(0, count) + let modString = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: template) + return modString + } +} From 0b675af64175e0d84e5db7f27fa925ae45a51abe Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 19:52:31 +0530 Subject: [PATCH 18/56] Changes --- Convert/SourceEditorCommand.swift | 4 ++-- Line/SourceEditorCommand.swift | 32 ++++++++++++++--------------- Selection/SourceEditorCommand.swift | 18 ++++++++-------- XcodeKitExt.swift | 26 ++++++++++------------- 4 files changed, 38 insertions(+), 42 deletions(-) diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 68bcd35..5118f10 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -18,11 +18,11 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { let buffer = invocation.buffer - let selectedRanges: SelectionType = selectionRanges(of: buffer) + let selection = selectionType(of: buffer) if let command = Options(command: invocation.commandIdentifier) { - switch selectedRanges { + switch selection { case .none(let position): let range = buffer.selections.firstObject as! XCSourceTextRange var currentLine = buffer.lines[position.line] as! String diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 9ed9f40..2b33e22 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -19,16 +19,16 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { public func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Swift.Void) { let buffer = invocation.buffer - let selectedRanges: SelectionType = selectionRanges(of: buffer) - let selectionIndexSet: IndexSet = selectedLinesIndexSet(for: selectedRanges) + let selection = selectionType(of: buffer) + let selectedLines = selection.selectedLines switch Options(command: invocation.commandIdentifier)! { case .duplicate: let range = buffer.selections.firstObject as! XCSourceTextRange - let copyOfLines = buffer.lines.objects(at: selectionIndexSet) - buffer.lines.insert(copyOfLines, at: selectionIndexSet) + let copyOfLines = buffer.lines.objects(at: selectedLines) + buffer.lines.insert(copyOfLines, at: selectedLines) - switch selectedRanges { + switch selection { case .none(let position): if position.column == 0 { range.start.line += 1 @@ -42,11 +42,11 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .commentedDuplicate: let range = buffer.selections.firstObject as! XCSourceTextRange - let copyOfLines = buffer.lines.objects(at: selectionIndexSet) + let copyOfLines = buffer.lines.objects(at: selectedLines) let commentedLines = copyOfLines.map { "//" + ($0 as! String) } - buffer.lines.insert(commentedLines, at: selectionIndexSet) + buffer.lines.insert(commentedLines, at: selectedLines) - switch selectedRanges { + switch selection { case .none(let position): if position.column == 0 { range.start.line += 1 @@ -59,7 +59,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .openNewLineBelow: - switch selectedRanges { + switch selection { case .none(let position): let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() @@ -84,7 +84,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .openNewLineAbove: - switch selectedRanges { + switch selection { case .none(let position): let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() @@ -108,7 +108,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .deleteLine: - switch selectedRanges { + switch selection { case .none(let position): buffer.lines.removeObject(at: position.line) @@ -120,7 +120,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .join: - switch selectedRanges { + switch selection { case .none(let position): if position.line == buffer.lines.count { return } @@ -151,17 +151,17 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .lines(_, _): let range = buffer.selections.firstObject as! XCSourceTextRange - let selectedLines = buffer.lines.objects(at: selectionIndexSet) as! [String] + let lines = buffer.lines.objects(at: selectedLines) as! [String] var joinedLine = "" - for (i, line) in selectedLines.enumerated() { + for (i, line) in lines.enumerated() { if i == 0 { joinedLine += line.trimmingCharacters(in: .newlines) } else { joinedLine += " " + line.trimmedStart().trimmingCharacters(in: .newlines) } } - buffer.lines.removeObjects(at: selectionIndexSet) + buffer.lines.removeObjects(at: selectedLines) buffer.lines.insert(joinedLine, at: range.start.line) //Selection/CaretPosition @@ -172,7 +172,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .lineBeginning: - switch selectedRanges { + switch selection { case .none(let position): let range = buffer.selections.lastObject as! XCSourceTextRange let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index cf9eca8..2c304f1 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -20,13 +20,13 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { completionHandler(nil) } let buffer = invocation.buffer - let selectedRanges: SelectionType = selectionRanges(of: buffer) - let selectionIndex: IndexSet = selectedLinesIndexSet(for: selectedRanges) + let selection = selectionType(of: buffer) + let selectedLines = selection.selectedLines let range = buffer.selections.lastObject as! XCSourceTextRange switch Options(command: invocation.commandIdentifier)! { case .selectLine: - switch selectedRanges { + switch selection { case .none(let position): let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset range.start.column = indentationOffset @@ -47,7 +47,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { range.end.column = 0 case .oneSpace: - switch selectedRanges { + switch selection { case .none(let position): let currentLine = buffer.lines[position.line] as! String let (newOffset, newLine) = currentLine.lineOneSpaceAt(pin: position.column) @@ -60,7 +60,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .expand: - switch selectedRanges { + switch selection { case .none(let position): let currentLine = buffer.lines[position.line] as! String if currentLine.count == 0 { return } @@ -148,13 +148,13 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .align: - switch selectedRanges { + switch selection { case .none(_): break case .words(_, _, _): break case .lines(_, _): - let selectedLines = buffer.lines.objects(at: selectionIndex) as! [String] - if let aligned = selectedLines.autoAlign() { - buffer.lines.replaceObjects(at: selectionIndex, with: aligned) + let lines = buffer.lines.objects(at: selectedLines) as! [String] + if let aligned = lines.autoAlign() { + buffer.lines.replaceObjects(at: selectedLines, with: aligned) } case .multiLocation(_): break diff --git a/XcodeKitExt.swift b/XcodeKitExt.swift index 60398e6..864f4cb 100644 --- a/XcodeKitExt.swift +++ b/XcodeKitExt.swift @@ -14,10 +14,20 @@ enum SelectionType { case words(line: Int, colStart: Int, colEnd: Int) case lines(start:XCSourceTextPosition, end: XCSourceTextPosition)//Complete line selection is counted multiline case multiLocation([XCSourceTextRange]) + + var selectedLines: IndexSet { + switch self { + case .none(let position): return IndexSet(integer: position.line) + case .words(let line, _, _): return IndexSet(integer: line) + case .lines(let start, let end): + return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) + case .multiLocation(_): fatalError() + } + } } /// Returns nil if nothing is selected -func selectionRanges(of buffer: XCSourceTextBuffer) -> SelectionType { +func selectionType(of buffer: XCSourceTextBuffer) -> SelectionType { let selections = buffer.selections as! [XCSourceTextRange] if selections.count == 1 { let range = selections.first! @@ -32,17 +42,3 @@ func selectionRanges(of buffer: XCSourceTextBuffer) -> SelectionType { let textRangeList = buffer.selections.map { $0 as! XCSourceTextRange } return .multiLocation(textRangeList) } - - -/// Indexes of all the lines -/// -/// - Returns: Returns nil if no selection -func selectedLinesIndexSet(for selectedRanges: SelectionType) -> IndexSet { - switch selectedRanges { - case .none(let position): return IndexSet(integer: position.line) - case .words(let line, _, _): return IndexSet(integer: line) - case .lines(let start, let end): - return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) - case .multiLocation(_): fatalError() - } -} From b75b1ed95122ebb758a1dc7fb2d6ba3786678c95 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 19:59:10 +0530 Subject: [PATCH 19/56] Refactoring --- Balanced.swift | 54 +-------------------------------- Character+Linex.swift | 31 +++++++++++++++++++ Linex.xcodeproj/project.pbxproj | 20 ++++++++++++ TextPosition.swift | 45 +++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 Character+Linex.swift create mode 100644 TextPosition.swift diff --git a/Balanced.swift b/Balanced.swift index 1d6589a..3fe94cf 100644 --- a/Balanced.swift +++ b/Balanced.swift @@ -9,31 +9,10 @@ import Foundation import XcodeKit -extension Character { - var isOpening: Bool { - let openStopper = CharacterSet(charactersIn: "{[(") - return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) - } - var isClosing:Bool { - let openStopper = CharacterSet(charactersIn: "}])") - return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) - } - func isPresent(in characterSet:CharacterSet) -> Bool { - return CharacterSet(charactersIn: String(self)).isSubset(of: characterSet) - } - var closing: Character { - assert(self.isOpening, "Only opening characters can have closing characters") - return ["{":"}", "(":")", "[":"]"][self]! - } - var opening: Character { - assert(self.isClosing, "Only closing characters can have opening characters") - return ["}":"{", ")":"(", "]":"["][self]! - } -} - private let closingFor = ["{":"}", "(":")", "[":"]"] private let openingFor = ["}":"{", ")":"(", "]":"["] + extension XCSourceTextBuffer { func findClosing(for openingChar: Character, at position: XCSourceTextPosition) -> XCSourceTextPosition? { @@ -92,34 +71,3 @@ extension XCSourceTextBuffer { } } -extension XCSourceTextPosition { - var isStart: Bool { - return self.line == 0 && self.column == 0 - } - - func next(in buffer: XCSourceTextBuffer) -> XCSourceTextPosition? { - guard self != buffer.lastPosition else { return nil } - - let currentLine = buffer.lines[self.line] as! String - if self.column == currentLine.count - 1 { - return XCSourceTextPosition(line: self.line + 1, column: 0) - } - return XCSourceTextPosition(line: self.line, column: self.column + 1) - } - - func previous(in buffer: XCSourceTextBuffer) -> XCSourceTextPosition? { - guard !self.isStart else { return nil} - - if self.column == 0 { - let currentLine = buffer.lines[self.line - 1] as! String - return XCSourceTextPosition(line: self.line - 1, column: currentLine.count - 1) - } - return XCSourceTextPosition(line: self.line, column: self.column - 1) - } -} - -extension XCSourceTextPosition: Equatable { - public static func == (lhs: XCSourceTextPosition, rhs: XCSourceTextPosition) -> Bool { - return lhs.line == rhs.line && lhs.column == rhs.column - } -} diff --git a/Character+Linex.swift b/Character+Linex.swift new file mode 100644 index 0000000..3cafe4f --- /dev/null +++ b/Character+Linex.swift @@ -0,0 +1,31 @@ +// +// Character+Linex.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 05/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation + +extension Character { + var isOpening: Bool { + let openStopper = CharacterSet(charactersIn: "{[(") + return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) + } + var isClosing:Bool { + let openStopper = CharacterSet(charactersIn: "}])") + return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) + } + func isPresent(in characterSet:CharacterSet) -> Bool { + return CharacterSet(charactersIn: String(self)).isSubset(of: characterSet) + } + var closing: Character { + assert(self.isOpening, "Only opening characters can have closing characters") + return ["{":"}", "(":")", "[":"]"][self]! + } + var opening: Character { + assert(self.isClosing, "Only closing characters can have opening characters") + return ["}":"{", ")":"(", "]":"["][self]! + } +} diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 0a8fe86..385f5ff 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -30,6 +30,14 @@ E3938E36209DEC32007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; E3938E37209DEC33007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; E3938E38209DEC34007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E33209DEC2B007F69E3 /* String+Basic.swift */; }; + E3938E3B209DF622007F69E3 /* Character+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E39209DF605007F69E3 /* Character+Linex.swift */; }; + E3938E3C209DF623007F69E3 /* Character+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E39209DF605007F69E3 /* Character+Linex.swift */; }; + E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E39209DF605007F69E3 /* Character+Linex.swift */; }; + E3938E3E209DF626007F69E3 /* Character+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E39209DF605007F69E3 /* Character+Linex.swift */; }; + E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; + E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; + E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; + E3938E44209DF667007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; @@ -119,6 +127,8 @@ E37DDA7C2099E65900D86394 /* SelectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionTests.swift; sourceTree = ""; }; E383F00A1F7A13A900429B4D /* TestPad.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestPad.m; sourceTree = ""; }; E3938E33209DEC2B007F69E3 /* String+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Basic.swift"; sourceTree = ""; }; + E3938E39209DF605007F69E3 /* Character+Linex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Character+Linex.swift"; sourceTree = ""; }; + E3938E3F209DF64F007F69E3 /* TextPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextPosition.swift; sourceTree = ""; }; E39E226D1F59876A00354A5F /* Selection.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Selection.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E39E22711F59876A00354A5F /* Selection.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Selection.entitlements; sourceTree = ""; }; E39E22721F59876A00354A5F /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -181,6 +191,8 @@ E3938E33209DEC2B007F69E3 /* String+Basic.swift */, E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */, E37DDA762099D9D100D86394 /* Balanced.swift */, + E3938E3F209DF64F007F69E3 /* TextPosition.swift */, + E3938E39209DF605007F69E3 /* Character+Linex.swift */, E35F56791F7BEFA100905225 /* Images */, E35942191F55564C009EFA35 /* Linex */, E359422B1F55564D009EFA35 /* LinexTests */, @@ -518,11 +530,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E3938E3E209DF626007F69E3 /* Character+Linex.swift in Sources */, E39E22821F59C59300354A5F /* Common.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, E3938E35209DEC32007F69E3 /* String+Basic.swift in Sources */, E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, + E3938E44209DF667007F69E3 /* TextPosition.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -530,11 +544,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E3938E3B209DF622007F69E3 /* Character+Linex.swift in Sources */, E356FD7E1F66D281004558F1 /* XcodeKitExt.swift in Sources */, E37DDA782099DD5700D86394 /* Balanced.swift in Sources */, E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, E31FD4741F5712540044765A /* Extras.swift in Sources */, E39E22801F59C59100354A5F /* Common.swift in Sources */, + E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E35942451F55565E009EFA35 /* SourceEditorCommand.swift in Sources */, E3938E36209DEC32007F69E3 /* String+Basic.swift in Sources */, ); @@ -544,11 +560,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E3938E3C209DF623007F69E3 /* Character+Linex.swift in Sources */, E356FD7F1F66D282004558F1 /* XcodeKitExt.swift in Sources */, E37DDA792099DD5800D86394 /* Balanced.swift in Sources */, E39E22811F59C59200354A5F /* Common.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, + E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E359BCF61F604E000071246B /* Alignment.swift in Sources */, E3938E37209DEC33007F69E3 /* String+Basic.swift in Sources */, ); @@ -562,8 +580,10 @@ E3F543A61F5ABA48008F426E /* Common.swift in Sources */, E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, + E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */, E37DDA7A2099DD5900D86394 /* Balanced.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Basic.swift in Sources */, + E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/TextPosition.swift b/TextPosition.swift new file mode 100644 index 0000000..573afc4 --- /dev/null +++ b/TextPosition.swift @@ -0,0 +1,45 @@ +// +// TextPosition.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 05/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +import XcodeKit + +typealias TextPosition = XCSourceTextPosition + +extension TextPosition { + var isStart: Bool { + return self.line == 0 && self.column == 0 + } + + func next(in buffer: XCSourceTextBuffer) -> TextPosition? { + guard self != buffer.lastPosition else { return nil } + + let currentLine = buffer.lines[self.line] as! String + if self.column == currentLine.count - 1 { + return TextPosition(line: self.line + 1, column: 0) + } + + return TextPosition(line: self.line, column: self.column + 1) + } + + func previous(in buffer: XCSourceTextBuffer) -> TextPosition? { + guard !self.isStart else { return nil} + + if self.column == 0 { + let currentLine = buffer.lines[self.line - 1] as! String + return TextPosition(line: self.line - 1, column: currentLine.count - 1) + } + return TextPosition(line: self.line, column: self.column - 1) + } +} + +extension TextPosition: Equatable { + public static func == (lhs: XCSourceTextPosition, rhs: XCSourceTextPosition) -> Bool { + return lhs.line == rhs.line && lhs.column == rhs.column + } +} From e8504321bb6f5edc26eaa574a0d3e97e28021270 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 20:04:51 +0530 Subject: [PATCH 20/56] Changes --- Common.swift | 59 -------------------------- Linex.xcodeproj/project.pbxproj | 48 +++++++++++++-------- String+Linex.swift | 67 ++++++++++++++++++++++++++++++ Balanced.swift => TextBuffer.swift | 25 +++++------ 4 files changed, 110 insertions(+), 89 deletions(-) create mode 100644 String+Linex.swift rename Balanced.swift => TextBuffer.swift (71%) diff --git a/Common.swift b/Common.swift index ea41d14..e994b41 100644 --- a/Common.swift +++ b/Common.swift @@ -7,65 +7,6 @@ // import Foundation -//MARK: - Basic - -//MARK: Advance -extension String { - func lineOneSpaceAt(pin: Int) -> (Int, String) { - - var start = pin - while start > 0 && self[start - 1] == " " { - start -= 1 - } - - var end = pin - while end < self.count && self[end] == " " { - end += 1 - } - - var newString = self - if start == end {//No space - newString.replace(range: start.. Range? { - guard let range:Range = selectWord(pin: pin, validChars: validChars) else { return nil } - return self.indexRangeFor(range: range) - } - - func selectWord(pin: Int, validChars: CharacterSet) -> Range? { - var pin = pin - guard pin <= self.count else { - return nil - } - guard self.count > 1 else { - return nil - } - - // Move pin to one position left when it is after last character - if (pin > 0), self[pin - 1].isPresent(in: validChars) { - pin -= 1 - } - - var start = pin - while start >= 0 && self[start].isPresent(in: validChars) { - start -= 1 - } - - var end = pin - while end < count && self[end].isPresent(in: validChars) { - end += 1 - } - if start == end { return nil } - return start + 1.. (Int, String) { + var start = pin + while start > 0 && self[start - 1] == " " { + start -= 1 + } + + var end = pin + while end < self.count && self[end] == " " { + end += 1 + } + + var newString = self + if start == end {//No space + newString.replace(range: start.. Range? { + guard let range:Range = selectWord(pin: pin, validChars: validChars) else { return nil } + return self.indexRangeFor(range: range) + } + + func selectWord(pin: Int, validChars: CharacterSet) -> Range? { + var pin = pin + guard pin <= self.count else { + return nil + } + guard self.count > 1 else { + return nil + } + + // Move pin to one position left when it is after last character + if (pin > 0), self[pin - 1].isPresent(in: validChars) { + pin -= 1 + } + + var start = pin + while start >= 0 && self[start].isPresent(in: validChars) { + start -= 1 + } + + var end = pin + while end < count && self[end].isPresent(in: validChars) { + end += 1 + } + if start == end { return nil } + return start + 1.. XCSourceTextPosition? { + func findClosing(for openingChar: Character, at position: TextPosition) -> TextPosition? { let closingChar = openingChar.closing var stackCount = 0 var currentPosition = position.next(in: self) @@ -25,7 +26,7 @@ extension XCSourceTextBuffer { case openingChar: stackCount += 1 case closingChar: if stackCount == 0 { - return XCSourceTextPosition(line: currentPosition!.line, + return TextPosition(line: currentPosition!.line, column: currentPosition!.column + 1) } stackCount -= 1 @@ -36,7 +37,7 @@ extension XCSourceTextBuffer { return nil } - func findOpening(for closingChar: Character, at position: XCSourceTextPosition) -> XCSourceTextPosition? { + func findOpening(for closingChar: Character, at position: TextPosition) -> TextPosition? { let openingChar = closingChar.opening var stackCount = 0 var currentPosition = position.previous(in: self)?.previous(in: self) @@ -55,17 +56,17 @@ extension XCSourceTextBuffer { } } -extension XCSourceTextBuffer { - var lastPosition: XCSourceTextPosition { +extension TextBuffer { + var lastPosition: TextPosition { let lastLine = self.lines[self.lines.count - 1] as! String - return XCSourceTextPosition(line: self.lines.count - 1, column: lastLine.count - 1) + return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) } - func isEnd(position: XCSourceTextPosition) -> Bool { + func isEnd(position: TextPosition) -> Bool { return lastPosition == position } - func char(at position: XCSourceTextPosition) -> Character { + func char(at position: TextPosition) -> Character { let currentLine = self.lines[position.line] as! String return currentLine[position.column] as Character } From 7170221d78357d53b73bfa90567cca5c750222f0 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 20:13:26 +0530 Subject: [PATCH 21/56] Changes --- Convert/SourceEditorCommand.swift | 2 +- Line/SourceEditorCommand.swift | 2 +- Linex.xcodeproj/project.pbxproj | 10 ++++++ Selection/SourceEditorCommand.swift | 2 +- SelectionType.swift | 27 ++++++++++++++++ TextBuffer.swift | 43 +++++++++++++++++-------- XcodeKitExt.swift | 49 ++++++++++------------------- 7 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 SelectionType.swift diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 5118f10..6d0e95a 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -18,7 +18,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { let buffer = invocation.buffer - let selection = selectionType(of: buffer) + let selection = buffer.selectionType if let command = Options(command: invocation.commandIdentifier) { diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 2b33e22..a0d7d3a 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -19,7 +19,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { public func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Swift.Void) { let buffer = invocation.buffer - let selection = selectionType(of: buffer) + let selection = buffer.selectionType let selectedLines = selection.selectedLines switch Options(command: invocation.commandIdentifier)! { diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 21ea241..23d5b36 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -43,6 +43,10 @@ E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; E3938E4E209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; + E3938E50209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; + E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; + E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; + E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; @@ -135,6 +139,7 @@ E3938E3F209DF64F007F69E3 /* TextPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextPosition.swift; sourceTree = ""; }; E3938E45209DF772007F69E3 /* TextBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBuffer.swift; sourceTree = ""; }; E3938E4A209DF834007F69E3 /* String+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Basic.swift"; sourceTree = ""; }; + E3938E4F209DF8B0007F69E3 /* SelectionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionType.swift; sourceTree = ""; }; E39E226D1F59876A00354A5F /* Selection.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Selection.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E39E22711F59876A00354A5F /* Selection.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Selection.entitlements; sourceTree = ""; }; E39E22721F59876A00354A5F /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -197,6 +202,7 @@ E3938E4A209DF834007F69E3 /* String+Basic.swift */, E3938E33209DEC2B007F69E3 /* String+Linex.swift */, E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */, + E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, E3938E39209DF605007F69E3 /* Character+Linex.swift */, @@ -543,6 +549,7 @@ E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, E3938E35209DEC32007F69E3 /* String+Linex.swift in Sources */, E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, + E3938E50209DF8B0007F69E3 /* SelectionType.swift in Sources */, E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, E3938E44209DF667007F69E3 /* TextPosition.swift in Sources */, E3938E4B209DF834007F69E3 /* String+Basic.swift in Sources */, @@ -558,6 +565,7 @@ E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, E31FD4741F5712540044765A /* Extras.swift in Sources */, E39E22801F59C59100354A5F /* Common.swift in Sources */, + E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, @@ -575,6 +583,7 @@ E39E22811F59C59200354A5F /* Common.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, + E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E48209DF772007F69E3 /* TextBuffer.swift in Sources */, E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, @@ -593,6 +602,7 @@ E3938E49209DF772007F69E3 /* TextBuffer.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */, + E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Linex.swift in Sources */, E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */, E3938E4E209DF834007F69E3 /* String+Basic.swift in Sources */, diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index 2c304f1..d32024e 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -20,7 +20,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { completionHandler(nil) } let buffer = invocation.buffer - let selection = selectionType(of: buffer) + let selection = buffer.selectionType let selectedLines = selection.selectedLines let range = buffer.selections.lastObject as! XCSourceTextRange diff --git a/SelectionType.swift b/SelectionType.swift new file mode 100644 index 0000000..aca02eb --- /dev/null +++ b/SelectionType.swift @@ -0,0 +1,27 @@ +// +// SelectionType.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 05/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +import XcodeKit + +enum SelectionType { + case none(position: TextPosition) + case words(line: Int, colStart: Int, colEnd: Int) + case lines(start:TextPosition, end: TextPosition)//Complete line selection is counted multiline + case multiLocation([XCSourceTextRange]) + + var selectedLines: IndexSet { + switch self { + case .none(let position): return IndexSet(integer: position.line) + case .words(let line, _, _): return IndexSet(integer: line) + case .lines(let start, let end): + return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) + case .multiLocation(_): fatalError() + } + } +} diff --git a/TextBuffer.swift b/TextBuffer.swift index 6cc2325..3bb9ee4 100644 --- a/TextBuffer.swift +++ b/TextBuffer.swift @@ -14,6 +14,23 @@ typealias TextBuffer = XCSourceTextBuffer private let closingFor = ["{":"}", "(":")", "[":"]"] private let openingFor = ["}":"{", ")":"(", "]":"["] +extension TextBuffer { + var lastPosition: TextPosition { + let lastLine = self.lines[self.lines.count - 1] as! String + return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) + } + + func isEnd(position: TextPosition) -> Bool { + return lastPosition == position + } + + func char(at position: TextPosition) -> Character { + let currentLine = self.lines[position.line] as! String + return currentLine[position.column] as Character + } +} + + extension TextBuffer { func findClosing(for openingChar: Character, at position: TextPosition) -> TextPosition? { @@ -57,18 +74,18 @@ extension TextBuffer { } extension TextBuffer { - var lastPosition: TextPosition { - let lastLine = self.lines[self.lines.count - 1] as! String - return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) - } - - func isEnd(position: TextPosition) -> Bool { - return lastPosition == position - } - - func char(at position: TextPosition) -> Character { - let currentLine = self.lines[position.line] as! String - return currentLine[position.column] as Character + var selectionType: SelectionType { + let selections = self.selections as! [XCSourceTextRange] + if selections.count == 1 { + let range = selections.first! + if range.start.line == range.end.line { + if range.start.column == range.end.column { + return .none(position: TextPosition(line: range.start.line, column: range.start.column)) + } + return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) + } + return .lines(start: range.start, end: range.end) + } + return .multiLocation(selections) } } - diff --git a/XcodeKitExt.swift b/XcodeKitExt.swift index 864f4cb..4b73020 100644 --- a/XcodeKitExt.swift +++ b/XcodeKitExt.swift @@ -9,36 +9,19 @@ import Foundation import XcodeKit -enum SelectionType { - case none(position: XCSourceTextPosition) - case words(line: Int, colStart: Int, colEnd: Int) - case lines(start:XCSourceTextPosition, end: XCSourceTextPosition)//Complete line selection is counted multiline - case multiLocation([XCSourceTextRange]) - - var selectedLines: IndexSet { - switch self { - case .none(let position): return IndexSet(integer: position.line) - case .words(let line, _, _): return IndexSet(integer: line) - case .lines(let start, let end): - return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) - case .multiLocation(_): fatalError() - } - } -} - -/// Returns nil if nothing is selected -func selectionType(of buffer: XCSourceTextBuffer) -> SelectionType { - let selections = buffer.selections as! [XCSourceTextRange] - if selections.count == 1 { - let range = selections.first! - if range.start.line == range.end.line { - if range.start.column == range.end.column { - return .none(position: XCSourceTextPosition(line: range.start.line, column: range.start.column)) - } - return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) - } - return .lines(start: range.start, end: range.end) - } - let textRangeList = buffer.selections.map { $0 as! XCSourceTextRange } - return .multiLocation(textRangeList) -} +///// Returns nil if nothing is selected +//func selectionType(of buffer: XCSourceTextBuffer) -> SelectionType { +// let selections = buffer.selections as! [XCSourceTextRange] +// if selections.count == 1 { +// let range = selections.first! +// if range.start.line == range.end.line { +// if range.start.column == range.end.column { +// return .none(position: XCSourceTextPosition(line: range.start.line, column: range.start.column)) +// } +// return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) +// } +// return .lines(start: range.start, end: range.end) +// } +// let textRangeList = buffer.selections.map { $0 as! XCSourceTextRange } +// return .multiLocation(textRangeList) +//} From 010edd542a20a2813d4ccb33cd25553e416e2284 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 20:50:27 +0530 Subject: [PATCH 22/56] Removed images --- Linex.xcodeproj/project.pbxproj | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 23d5b36..cea8b65 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -131,7 +131,6 @@ E35942441F55565E009EFA35 /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; E35942461F55565E009EFA35 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E359BCF51F604E000071246B /* Alignment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alignment.swift; sourceTree = ""; }; - E35F567A1F7BEFA100905225 /* propertyalign.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = propertyalign.gif; sourceTree = ""; }; E37DDA7C2099E65900D86394 /* SelectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionTests.swift; sourceTree = ""; }; E383F00A1F7A13A900429B4D /* TestPad.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestPad.m; sourceTree = ""; }; E3938E33209DEC2B007F69E3 /* String+Linex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Linex.swift"; sourceTree = ""; }; @@ -206,7 +205,6 @@ E3938E45209DF772007F69E3 /* TextBuffer.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, E3938E39209DF605007F69E3 /* Character+Linex.swift */, - E35F56791F7BEFA100905225 /* Images */, E35942191F55564C009EFA35 /* Linex */, E359422B1F55564D009EFA35 /* LinexTests */, E359423F1F55565E009EFA35 /* Line */, @@ -284,14 +282,6 @@ name = "Supporting Files"; sourceTree = ""; }; - E35F56791F7BEFA100905225 /* Images */ = { - isa = PBXGroup; - children = ( - E35F567A1F7BEFA100905225 /* propertyalign.gif */, - ); - path = Images; - sourceTree = ""; - }; E39E226F1F59876A00354A5F /* Selection */ = { isa = PBXGroup; children = ( From 7c0f6a9517821b03e0dbaed8f590bb23429826e8 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 20:51:25 +0530 Subject: [PATCH 23/56] Updated folders --- Linex.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index cea8b65..4186c36 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -205,11 +205,11 @@ E3938E45209DF772007F69E3 /* TextBuffer.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, E3938E39209DF605007F69E3 /* Character+Linex.swift */, - E35942191F55564C009EFA35 /* Linex */, - E359422B1F55564D009EFA35 /* LinexTests */, E359423F1F55565E009EFA35 /* Line */, E39E226F1F59876A00354A5F /* Selection */, E3F543951F5A84FC008F426E /* Convert */, + E35942191F55564C009EFA35 /* Linex */, + E359422B1F55564D009EFA35 /* LinexTests */, E359423C1F55565E009EFA35 /* Frameworks */, E35942181F55564C009EFA35 /* Products */, ); From 5a87fe159ee37bbb47d6104bd978850550e019c4 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 21:03:08 +0530 Subject: [PATCH 24/56] Updates --- Line/Extras.swift | 26 -------------------------- Line/SourceEditorCommand.swift | 8 ++++---- Linex.xcodeproj/project.pbxproj | 12 ------------ XcodeKitExt.swift | 27 --------------------------- 4 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 Line/Extras.swift delete mode 100644 XcodeKitExt.swift diff --git a/Line/Extras.swift b/Line/Extras.swift deleted file mode 100644 index 6310949..0000000 --- a/Line/Extras.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// Extras.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 30/08/17. -// Copyright © 2017 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation -import XcodeKit - - -extension XCSourceEditorCommandInvocation { - - - func selectionRanges() -> [XCSourceTextRange]? { - assert(self.buffer.selections.count > 0, "Count can be zero. Wrong assumption") - - return self.buffer.selections.map { $0 as! XCSourceTextRange } - } - - func moveCursorTo(location: XCSourceTextPosition) { - let lineSelection = XCSourceTextRange(start: location, end: location) - buffer.selections.setArray([lineSelection]) - } -} diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index a0d7d3a..67320c4 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -65,7 +65,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: position.line + 1) //Selection - let position = XCSourceTextPosition(line: position.line + 1, column: indentationOffset) + let position = TextPosition(line: position.line + 1, column: indentationOffset) let lineSelection = XCSourceTextRange(start: position, end: position) buffer.selections.setArray([lineSelection]) @@ -75,7 +75,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: line + 1) //Selection - let position = XCSourceTextPosition(line: line + 1, column: indentationOffset) + let position = TextPosition(line: line + 1, column: indentationOffset) let lineSelection = XCSourceTextRange(start: position, end: position) buffer.selections.setArray([lineSelection]) @@ -90,7 +90,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: position.line) //Selection - let position = XCSourceTextPosition(line: position.line, column: indentationOffset) + let position = TextPosition(line: position.line, column: indentationOffset) let lineSelection = XCSourceTextRange(start: position, end: position) buffer.selections.setArray([lineSelection]) @@ -99,7 +99,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() buffer.lines.insert(offsetWhiteSpaces, at: line) //Selection - let position = XCSourceTextPosition(line: line, column: indentationOffset) + let position = TextPosition(line: line, column: indentationOffset) let lineSelection = XCSourceTextRange(start: position, end: position) buffer.selections.setArray([lineSelection]) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 4186c36..04f22c3 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -7,10 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - E31FD4741F5712540044765A /* Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = E31FD4731F5712540044765A /* Extras.swift */; }; - E356FD7E1F66D281004558F1 /* XcodeKitExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */; }; - E356FD7F1F66D282004558F1 /* XcodeKitExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */; }; - E356FD801F66D284004558F1 /* XcodeKitExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -110,10 +106,8 @@ /* Begin PBXFileReference section */ E31714C31F8385F40036CF07 /* Linex.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Linex.entitlements; sourceTree = ""; }; - E31FD4731F5712540044765A /* Extras.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extras.swift; sourceTree = ""; }; E330C82E1F796DE600ECC222 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; E330C82F1F796DF000ECC222 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; - E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeKitExt.swift; sourceTree = ""; }; E356FD811F66F55C004558F1 /* TestPad.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestPad.swift; sourceTree = ""; }; E35942171F55564C009EFA35 /* Linex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Linex.app; sourceTree = BUILT_PRODUCTS_DIR; }; E359421A1F55564C009EFA35 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -200,7 +194,6 @@ E39E227E1F59C58E00354A5F /* Common.swift */, E3938E4A209DF834007F69E3 /* String+Basic.swift */, E3938E33209DEC2B007F69E3 /* String+Linex.swift */, - E356FD7C1F66D266004558F1 /* XcodeKitExt.swift */, E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, @@ -267,7 +260,6 @@ children = ( E35942421F55565E009EFA35 /* SourceEditorExtension.swift */, E35942441F55565E009EFA35 /* SourceEditorCommand.swift */, - E31FD4731F5712540044765A /* Extras.swift */, E35942461F55565E009EFA35 /* Info.plist */, E35942401F55565E009EFA35 /* Supporting Files */, ); @@ -551,9 +543,7 @@ buildActionMask = 2147483647; files = ( E3938E3B209DF622007F69E3 /* Character+Linex.swift in Sources */, - E356FD7E1F66D281004558F1 /* XcodeKitExt.swift in Sources */, E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, - E31FD4741F5712540044765A /* Extras.swift in Sources */, E39E22801F59C59100354A5F /* Common.swift in Sources */, E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, @@ -569,7 +559,6 @@ buildActionMask = 2147483647; files = ( E3938E3C209DF623007F69E3 /* Character+Linex.swift in Sources */, - E356FD7F1F66D282004558F1 /* XcodeKitExt.swift in Sources */, E39E22811F59C59200354A5F /* Common.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, @@ -586,7 +575,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E356FD801F66D284004558F1 /* XcodeKitExt.swift in Sources */, E3F543A61F5ABA48008F426E /* Common.swift in Sources */, E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3938E49209DF772007F69E3 /* TextBuffer.swift in Sources */, diff --git a/XcodeKitExt.swift b/XcodeKitExt.swift deleted file mode 100644 index 4b73020..0000000 --- a/XcodeKitExt.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// XcodeKitExt.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 11/09/17. -// Copyright © 2017 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation -import XcodeKit - -///// Returns nil if nothing is selected -//func selectionType(of buffer: XCSourceTextBuffer) -> SelectionType { -// let selections = buffer.selections as! [XCSourceTextRange] -// if selections.count == 1 { -// let range = selections.first! -// if range.start.line == range.end.line { -// if range.start.column == range.end.column { -// return .none(position: XCSourceTextPosition(line: range.start.line, column: range.start.column)) -// } -// return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) -// } -// return .lines(start: range.start, end: range.end) -// } -// let textRangeList = buffer.selections.map { $0 as! XCSourceTextRange } -// return .multiLocation(textRangeList) -//} From 8cf0f85a3fa356e3851cc8539e06dab7f11eb2cb Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 21:28:26 +0530 Subject: [PATCH 25/56] . --- Line/SourceEditorCommand.swift | 2 +- Selection/SourceEditorCommand.swift | 2 +- TextBuffer.swift | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 67320c4..370d213 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -20,7 +20,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let buffer = invocation.buffer let selection = buffer.selectionType - let selectedLines = selection.selectedLines + let selectedLines = buffer.selectedLines switch Options(command: invocation.commandIdentifier)! { case .duplicate: diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index d32024e..5f0c113 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -21,7 +21,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } let buffer = invocation.buffer let selection = buffer.selectionType - let selectedLines = selection.selectedLines + let selectedLines = buffer.selectedLines let range = buffer.selections.lastObject as! XCSourceTextRange switch Options(command: invocation.commandIdentifier)! { diff --git a/TextBuffer.swift b/TextBuffer.swift index 3bb9ee4..a4fc5f9 100644 --- a/TextBuffer.swift +++ b/TextBuffer.swift @@ -74,6 +74,9 @@ extension TextBuffer { } extension TextBuffer { + var selectedLines: IndexSet { + return self.selectionType.selectedLines + } var selectionType: SelectionType { let selections = self.selections as! [XCSourceTextRange] if selections.count == 1 { From 401dc6f1b126d1f001af69320b72a4f3b8a9bee4 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 21:31:32 +0530 Subject: [PATCH 26/56] . --- Convert/SourceEditorCommand.swift | 2 +- String+Basic.swift | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 6d0e95a..c679dfc 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -19,12 +19,12 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let buffer = invocation.buffer let selection = buffer.selectionType + let range = buffer.selections.firstObject as! XCSourceTextRange if let command = Options(command: invocation.commandIdentifier) { switch selection { case .none(let position): - let range = buffer.selections.firstObject as! XCSourceTextRange var currentLine = buffer.lines[position.line] as! String let currentChar = currentLine[position.column] diff --git a/String+Basic.swift b/String+Basic.swift index 472d62f..08eba78 100644 --- a/String+Basic.swift +++ b/String+Basic.swift @@ -57,15 +57,11 @@ extension String { } func trimmedStart() -> String { - return self.replacingOccurrences(of: "^[ \t]+", - with: "", - options: CompareOptions.regularExpression) + return self.replacingOccurrences(of: "^[ \t]+", with: "", options: .regularExpression) } func trimmedEnd() -> String { - return self.replacingOccurrences(of: "[ \t]+$", - with: "", - options: CompareOptions.regularExpression) + return self.replacingOccurrences(of: "[ \t]+$", with: "", options: .regularExpression) } func repeating(count: Int) -> String { From 5ee6193ba3fe6b537bb5178776b59a50743675e8 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 5 May 2018 21:33:21 +0530 Subject: [PATCH 27/56] .. --- Line/SourceEditorCommand.swift | 2 +- Selection/Alignment.swift | 4 ++-- String+Basic.swift | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 370d213..0f64c6d 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -158,7 +158,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { if i == 0 { joinedLine += line.trimmingCharacters(in: .newlines) } else { - joinedLine += " " + line.trimmedStart().trimmingCharacters(in: .newlines) + joinedLine += " " + line.trimmedStart.trimmingCharacters(in: .newlines) } } buffer.lines.removeObjects(at: selectedLines) diff --git a/Selection/Alignment.swift b/Selection/Alignment.swift index 4f21c79..8cc3859 100644 --- a/Selection/Alignment.swift +++ b/Selection/Alignment.swift @@ -16,7 +16,7 @@ extension Array where Element == String { for str in self { let seperated = str.components(separatedBy: subStr) if seperated.count == 2 { - let offset = seperated.first!.trimmedEnd().count + let offset = seperated.first!.trimmedEnd.count if offset > farthest { farthest = offset } } } @@ -120,7 +120,7 @@ extension Array where Element == String { let component = str.components(separatedBy: seperator) if component.count == 2 { let a = component.first!.padding(toLength: alignOffset, withPad: " ", startingAt: 0) - return "\(a)\(seperator)\(component[1].trimmedStart())" + return "\(a)\(seperator)\(component[1].trimmedStart)" } return str } diff --git a/String+Basic.swift b/String+Basic.swift index 08eba78..8f751fa 100644 --- a/String+Basic.swift +++ b/String+Basic.swift @@ -56,11 +56,11 @@ extension String { return i } - func trimmedStart() -> String { + var trimmedStart: String { return self.replacingOccurrences(of: "^[ \t]+", with: "", options: .regularExpression) } - func trimmedEnd() -> String { + var trimmedEnd: String { return self.replacingOccurrences(of: "[ \t]+$", with: "", options: .regularExpression) } From 2e2481bdedc15a80d0a0087390246444a51de1f1 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Wed, 16 May 2018 18:34:55 +0530 Subject: [PATCH 28/56] Minor changes --- Selection/SourceEditorCommand.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index 5f0c113..b045944 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -67,7 +67,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let lineEnd = currentLine.count - 1 if position.column < lineEnd { - let rightChar = currentLine[position.column] as Character + let rightChar = currentLine[position.column] if rightChar.isOpening { if let position = buffer.findClosing(for: rightChar, at: position) { range.end = position @@ -76,7 +76,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } if (position.column > 0) { - let leftChar = currentLine[position.column - 1] as Character + let leftChar = currentLine[position.column - 1] if leftChar.isClosing { if let position = buffer.findOpening(for: leftChar, at: position) { range.start = position @@ -94,10 +94,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let currentLine = buffer.lines[line] as! String let indentationIndex = currentLine.indentationOffset let lineEnd = currentLine.count - 1 - let currentStart = currentLine[colStart] as Character - let currentEnd = currentLine[colEnd - 1] as Character - let borderStart = currentLine[colStart - 1] as Character - let borderEnd = currentLine[colEnd] as Character + let currentStart = currentLine[colStart] + let currentEnd = currentLine[colEnd - 1] + let borderStart = colStart == 0 ? nil : currentLine[colStart - 1] + let borderEnd = currentLine[colEnd] if (borderStart == "." || borderEnd == ".") { let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_.")) From f475c2a7581d1a12af11e77460144a08dc50a02c Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 17 May 2018 17:18:12 +0530 Subject: [PATCH 29/56] Changes --- Character+Linex.swift | 2 +- CharacterSet+Linex.swift | 15 +++++++ ConditionalAssignment.swift | 17 ++++++++ Convert/SourceEditorCommand.swift | 2 +- Linex.xcodeproj/project.pbxproj | 32 ++++++++++++--- .../xcschemes/xcschememanagement.plist | 15 +++++++ LinexTests/LinexTests.swift | 33 +++------------ LinexTests/SelectionTests.swift | 14 ++++++- Selection/SourceEditorCommand.swift | 41 ++++++++----------- String+Linex.swift | 9 ++-- TextBuffer.swift | 25 ++++++++++- TextDirection.swift | 13 ++++++ TextPosition.swift | 7 ++++ 13 files changed, 156 insertions(+), 69 deletions(-) create mode 100644 CharacterSet+Linex.swift create mode 100644 ConditionalAssignment.swift create mode 100644 TextDirection.swift diff --git a/Character+Linex.swift b/Character+Linex.swift index 3cafe4f..e6b3e30 100644 --- a/Character+Linex.swift +++ b/Character+Linex.swift @@ -17,7 +17,7 @@ extension Character { let openStopper = CharacterSet(charactersIn: "}])") return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) } - func isPresent(in characterSet:CharacterSet) -> Bool { + func presentIn(_ characterSet:CharacterSet) -> Bool { return CharacterSet(charactersIn: String(self)).isSubset(of: characterSet) } var closing: Character { diff --git a/CharacterSet+Linex.swift b/CharacterSet+Linex.swift new file mode 100644 index 0000000..53f13e9 --- /dev/null +++ b/CharacterSet+Linex.swift @@ -0,0 +1,15 @@ +// +// CharacterSet+Linex.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 16/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation + +extension CharacterSet { + static var validWordChars: CharacterSet { + return CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) + } +} diff --git a/ConditionalAssignment.swift b/ConditionalAssignment.swift new file mode 100644 index 0000000..a259507 --- /dev/null +++ b/ConditionalAssignment.swift @@ -0,0 +1,17 @@ +// +// ConditionalAssignment.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 17/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation + +infix operator ?= : AssignmentPrecedence + +func ?= ( left: inout T?, right: T?) { + if left == nil { + left = right + } +} diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index c679dfc..589cb5c 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -29,7 +29,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let currentChar = currentLine[position.column] //If caret is beside number - if currentChar.isPresent(in: .decimalDigits), let num = Int(String(currentChar)) { + if currentChar.presentIn(.decimalDigits), let num = Int(String(currentChar)) { let currentRange = currentLine.indexRangeFor(range: range.start.column...range.start.column) switch command { case .increment: currentLine.replaceSubrange(currentRange, with: "\(num + 1)") diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 04f22c3..e51bf01 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -7,6 +7,16 @@ objects = { /* Begin PBXBuildFile section */ + E30650FA20AC6A9C006B0BBF /* TextDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650F720AC68CD006B0BBF /* TextDirection.swift */; }; + E30650FB20AC6A9D006B0BBF /* TextDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650F720AC68CD006B0BBF /* TextDirection.swift */; }; + E30650FC20AC6A9E006B0BBF /* TextDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650F720AC68CD006B0BBF /* TextDirection.swift */; }; + E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; + E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; + E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; + E306510220AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; + E306510320AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; + E306510420AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; + E306510520ADA09D006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -30,8 +40,6 @@ E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; - E3938E44209DF667007F69E3 /* TextPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E3F209DF64F007F69E3 /* TextPosition.swift */; }; - E3938E46209DF772007F69E3 /* TextBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E45209DF772007F69E3 /* TextBuffer.swift */; }; E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E45209DF772007F69E3 /* TextBuffer.swift */; }; E3938E48209DF772007F69E3 /* TextBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E45209DF772007F69E3 /* TextBuffer.swift */; }; E3938E49209DF772007F69E3 /* TextBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E45209DF772007F69E3 /* TextBuffer.swift */; }; @@ -39,7 +47,6 @@ E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; E3938E4E209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; - E3938E50209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; @@ -105,6 +112,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + E30650F720AC68CD006B0BBF /* TextDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextDirection.swift; sourceTree = ""; }; + E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Linex.swift"; sourceTree = ""; }; + E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalAssignment.swift; sourceTree = ""; }; E31714C31F8385F40036CF07 /* Linex.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Linex.entitlements; sourceTree = ""; }; E330C82E1F796DE600ECC222 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; E330C82F1F796DF000ECC222 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; @@ -196,8 +206,11 @@ E3938E33209DEC2B007F69E3 /* String+Linex.swift */, E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, + E30650F720AC68CD006B0BBF /* TextDirection.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, E3938E39209DF605007F69E3 /* Character+Linex.swift */, + E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */, + E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */, E359423F1F55565E009EFA35 /* Line */, E39E226F1F59876A00354A5F /* Selection */, E3F543951F5A84FC008F426E /* Convert */, @@ -527,13 +540,11 @@ files = ( E3938E3E209DF626007F69E3 /* Character+Linex.swift in Sources */, E39E22821F59C59300354A5F /* Common.swift in Sources */, - E3938E46209DF772007F69E3 /* TextBuffer.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, E3938E35209DEC32007F69E3 /* String+Linex.swift in Sources */, E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, - E3938E50209DF8B0007F69E3 /* SelectionType.swift in Sources */, + E306510520ADA09D006B0BBF /* ConditionalAssignment.swift in Sources */, E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, - E3938E44209DF667007F69E3 /* TextPosition.swift in Sources */, E3938E4B209DF834007F69E3 /* String+Basic.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -545,8 +556,11 @@ E3938E3B209DF622007F69E3 /* Character+Linex.swift in Sources */, E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, E39E22801F59C59100354A5F /* Common.swift in Sources */, + E306510220AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */, E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, + E30650FA20AC6A9C006B0BBF /* TextDirection.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, + E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, E35942451F55565E009EFA35 /* SourceEditorCommand.swift in Sources */, @@ -560,14 +574,17 @@ files = ( E3938E3C209DF623007F69E3 /* Character+Linex.swift in Sources */, E39E22811F59C59200354A5F /* Common.swift in Sources */, + E30650FB20AC6A9D006B0BBF /* TextDirection.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */, + E306510320AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */, E3938E48209DF772007F69E3 /* TextBuffer.swift in Sources */, E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, E359BCF61F604E000071246B /* Alignment.swift in Sources */, E3938E37209DEC33007F69E3 /* String+Linex.swift in Sources */, + E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -578,8 +595,11 @@ E3F543A61F5ABA48008F426E /* Common.swift in Sources */, E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3938E49209DF772007F69E3 /* TextBuffer.swift in Sources */, + E306510420AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, + E30650FC20AC6A9E006B0BBF /* TextDirection.swift in Sources */, E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */, + E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Linex.swift in Sources */, E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */, diff --git a/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist b/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist index 0c9e804..691a383 100644 --- a/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Linex.xcodeproj/xcuserdata/kaunteya.xcuserdatad/xcschemes/xcschememanagement.plist @@ -37,6 +37,21 @@ primary
+ E359423A1F55565E009EFA35 + + primary + + + E39E226C1F59876A00354A5F + + primary + + + E3F543921F5A84FC008F426E + + primary + + diff --git a/LinexTests/LinexTests.swift b/LinexTests/LinexTests.swift index e8211f6..901b21c 100644 --- a/LinexTests/LinexTests.swift +++ b/LinexTests/LinexTests.swift @@ -20,10 +20,11 @@ class LinexTests: XCTestCase { } func testLineIndentatinOffset() { - XCTAssertEqual("".lineIndentationOffset(), 0) + "".indentationOffset + XCTAssertEqual("".indentationOffset, 0) // 123456 - XCTAssertEqual(" ".lineIndentationOffset(), 6) - XCTAssertEqual(" ABC".lineIndentationOffset(), 6) + XCTAssertEqual(" ".indentationOffset, 6) + XCTAssertEqual(" ABC".indentationOffset, 6) } @@ -49,31 +50,7 @@ class LinexTests: XCTestCase { XCTAssert(t1.lineOneSpaceAt(pin: 7) == (7, t1)) XCTAssert(t1.lineOneSpaceAt(pin: 8) == (8, t1)) } - - func testFarthestDistance() { - XCTAssertEqual(["var name = Kaunteya",].farthestOffsetFor(subStr: "=")!, 8) - - XCTAssertEqual(["var name = Kaunteya", - "self.lastupdated = createdOn", - ].farthestOffsetFor(subStr: "=")!,16) - - XCTAssertEqual(["var name = Kaunteya", - "self.lastupdated = createdOn", - "self.name = name", - ].farthestOffsetFor(subStr: "=")!, 16) - - XCTAssertEqual(["var name = Kaunteya", - "self.lastupdated = createdOn", - "self.name = name", - ].farthestOffsetFor(subStr: "=")!, 16) - - XCTAssertEqual(["var name = Kaunteya", - "self.lastupdated = createdOn", - "self.name = name", - ].farthestOffsetFor(subStr: "=")!, 16) - - } - + func testAlign() { XCTAssertEqual(["let name = \"Kaunteya\""].autoAlign()!, ["let name = \"Kaunteya\""]) diff --git a/LinexTests/SelectionTests.swift b/LinexTests/SelectionTests.swift index 5094734..5302519 100644 --- a/LinexTests/SelectionTests.swift +++ b/LinexTests/SelectionTests.swift @@ -16,7 +16,17 @@ class SelectionTests: XCTestCase { // Put setup code here. This method is called before the invocation of each test method in the class. } - func testFoo() { - find + func testConditionalAssignment() { + XCTAssert(true) + var a = Optional("Kaunteya") + a ?= "Mohan" + XCTAssertEqual(a!, "Kaunteya") + + var a1: String? + a1 ?= "Mohan" + XCTAssertEqual(a1!, "Mohan") + + a1 ?= "Raju" + XCTAssertEqual(a1!, "Mohan") } } diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index b045944..6f0d2ae 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -22,7 +22,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let buffer = invocation.buffer let selection = buffer.selectionType let selectedLines = buffer.selectedLines - let range = buffer.selections.lastObject as! XCSourceTextRange + var range = buffer.selections.lastObject as! TextRange switch Options(command: invocation.commandIdentifier)! { case .selectLine: @@ -66,30 +66,21 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { if currentLine.count == 0 { return } let lineEnd = currentLine.count - 1 - if position.column < lineEnd { - let rightChar = currentLine[position.column] - if rightChar.isOpening { - if let position = buffer.findClosing(for: rightChar, at: position) { - range.end = position - } - } - } + let rightChar: Character? = position.column < lineEnd ? currentLine[position.column] : nil - if (position.column > 0) { - let leftChar = currentLine[position.column - 1] - if leftChar.isClosing { - if let position = buffer.findOpening(for: leftChar, at: position) { - range.start = position - } - } - } + let leftChar: Character? = position.column > 0 ? currentLine[position.column - 1] : nil + if rightChar?.isOpening ?? false { + range.end = buffer.closingPosition(for: rightChar!, startingAt: position) ?? range.end + return + } - let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) - if let selectionRange:Range = currentLine.selectWord(pin: position.column, validChars: validChars) { - range.start.column = selectionRange.lowerBound - range.end.column = selectionRange.upperBound + if leftChar?.isClosing ?? false { + range.start = buffer.findOpening(for: leftChar!, at: position) ?? range.start + return } + range = buffer.wordSelectionRange(for: .validWordChars, at: position) + case .words(let line, let colStart, let colEnd): let currentLine = buffer.lines[line] as! String let indentationIndex = currentLine.indentationOffset @@ -175,13 +166,13 @@ extension String { while from >= 0 { let currentChar = self[from] - if currentChar.isPresent(in: openStopper) { + if currentChar.presentIn(openStopper) { if onTheWayBrackets == 0 { return from + 1 } onTheWayBrackets -= 1 } - if currentChar.isPresent(in: closeStopper) { + if currentChar.presentIn(closeStopper) { onTheWayBrackets += 1 } from -= 1 @@ -196,13 +187,13 @@ extension String { while from < endOfLine { let currentChar = self[from] - if currentChar.isPresent(in: closeStopper) { + if currentChar.presentIn(closeStopper) { if onTheWayBrackets == 0 { return from } onTheWayBrackets -= 1 } - if currentChar.isPresent(in: openStopper) { + if currentChar.presentIn(openStopper) { onTheWayBrackets += 1 } from += 1 diff --git a/String+Linex.swift b/String+Linex.swift index fa25fa8..02d17ce 100644 --- a/String+Linex.swift +++ b/String+Linex.swift @@ -47,21 +47,20 @@ extension String { } // Move pin to one position left when it is after last character - if (pin > 0), self[pin - 1].isPresent(in: validChars) { + if (pin > 0), self[pin - 1].presentIn(validChars) { pin -= 1 } var start = pin - while start >= 0 && self[start].isPresent(in: validChars) { + while start >= 0 && self[start].presentIn(validChars) { start -= 1 } var end = pin - while end < count && self[end].isPresent(in: validChars) { + while end < count && self[end].presentIn(validChars) { end += 1 } if start == end { return nil } return start + 1.. TextPosition? { + func wordSelectionRange(for chars: CharacterSet, at position: TextPosition) -> TextRange { + let end = nextPosition(.forward, from: position, until: chars) ?? position + let start = nextPosition(.backward, from: position, until: chars) ?? position + return TextRange(start: start, end: end) + } + + func nextPosition(_ direction: TextDirection, + from startPosition: TextPosition, + until charSet: CharacterSet) -> TextPosition? { + var currentPosition = Optional(startPosition) + if direction == .backward { currentPosition = startPosition.previous(in: self)} + + while currentPosition != nil { + let currentChar = self.char(at: currentPosition!) + if !currentChar.presentIn(charSet) { + return direction == .backward ? currentPosition!.next(in: self) : currentPosition + } + currentPosition = currentPosition!.move(direction, in: self) + } + return nil + } + + func closingPosition(for openingChar: Character, startingAt position: TextPosition) -> TextPosition? { let closingChar = openingChar.closing var stackCount = 0 var currentPosition = position.next(in: self) diff --git a/TextDirection.swift b/TextDirection.swift new file mode 100644 index 0000000..6423fa4 --- /dev/null +++ b/TextDirection.swift @@ -0,0 +1,13 @@ +// +// TextDirection.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 16/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation + +enum TextDirection { + case forward, backward +} diff --git a/TextPosition.swift b/TextPosition.swift index 573afc4..14bf746 100644 --- a/TextPosition.swift +++ b/TextPosition.swift @@ -16,6 +16,13 @@ extension TextPosition { return self.line == 0 && self.column == 0 } + func move(_ direction: TextDirection, in buffer: XCSourceTextBuffer) -> TextPosition? { + switch direction { + case .forward: return next(in: buffer) + case .backward: return previous(in: buffer) + } + } + func next(in buffer: XCSourceTextBuffer) -> TextPosition? { guard self != buffer.lastPosition else { return nil } From 5c7482fa31d1aea51935b087324d6819299b8865 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Fri, 18 May 2018 16:31:50 +0530 Subject: [PATCH 30/56] Changes --- Character+Linex.swift | 16 +++++++++------- CharacterSet+Linex.swift | 5 ++++- Convert/SourceEditorCommand.swift | 3 +-- Selection/SourceEditorCommand.swift | 6 +++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Character+Linex.swift b/Character+Linex.swift index e6b3e30..c7652e3 100644 --- a/Character+Linex.swift +++ b/Character+Linex.swift @@ -9,21 +9,23 @@ import Foundation extension Character { + func presentIn(_ characterSet:CharacterSet) -> Bool { + return CharacterSet(String(self)).isSubset(of: characterSet) + } + var isOpening: Bool { - let openStopper = CharacterSet(charactersIn: "{[(") - return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) + return self.presentIn(CharacterSet("{[(")) } + var isClosing:Bool { - let openStopper = CharacterSet(charactersIn: "}])") - return CharacterSet(charactersIn: String(self)).isSubset(of: openStopper) - } - func presentIn(_ characterSet:CharacterSet) -> Bool { - return CharacterSet(charactersIn: String(self)).isSubset(of: characterSet) + return self.presentIn(CharacterSet("}])")) } + var closing: Character { assert(self.isOpening, "Only opening characters can have closing characters") return ["{":"}", "(":")", "[":"]"][self]! } + var opening: Character { assert(self.isClosing, "Only closing characters can have opening characters") return ["}":"{", ")":"(", "]":"["][self]! diff --git a/CharacterSet+Linex.swift b/CharacterSet+Linex.swift index 53f13e9..2ecf032 100644 --- a/CharacterSet+Linex.swift +++ b/CharacterSet+Linex.swift @@ -9,7 +9,10 @@ import Foundation extension CharacterSet { + init(_ string: String) { + self.init(charactersIn: string) + } static var validWordChars: CharacterSet { - return CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) + return CharacterSet("@$_").union(.alphanumerics) } } diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 589cb5c..ea487ea 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -36,8 +36,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .decrement: currentLine.replaceSubrange(currentRange, with: "\(num - 1)") } } else { - let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_")) - if let selectionRange:Range = currentLine.selectWord(pin: position.column, validChars: validChars) { + if let selectionRange:Range = currentLine.selectWord(pin: position.column, validChars: .validWordChars) { let selectedSubString = currentLine[selectionRange] if let newString = toggle(boolString: selectedSubString) { currentLine.replaceSubrange(selectionRange, with: newString) diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index 6f0d2ae..9c04479 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -91,7 +91,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let borderEnd = currentLine[colEnd] if (borderStart == "." || borderEnd == ".") { - let validChars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@$_.")) + let validChars = CharacterSet("@$_.").union(.alphanumerics) if let selectionRange:Range = currentLine.selectWord(pin: colStart, validChars: validChars) { range.start.column = selectionRange.lowerBound range.end.column = selectionRange.upperBound @@ -156,8 +156,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } -let openStopper = CharacterSet(charactersIn: "{[(\"") -let closeStopper = CharacterSet(charactersIn: "}])\"") +let openStopper = CharacterSet("{[(\"") +let closeStopper = CharacterSet("}])\"") extension String { func findOpeningPosition(from: Int) -> Int? { From 4fc89ffbe9b948c2f8f303c4468a0eaecaf71320 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Fri, 18 May 2018 16:32:19 +0530 Subject: [PATCH 31/56] Changes --- ConditionalAssignment.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConditionalAssignment.swift b/ConditionalAssignment.swift index a259507..267d304 100644 --- a/ConditionalAssignment.swift +++ b/ConditionalAssignment.swift @@ -10,7 +10,7 @@ import Foundation infix operator ?= : AssignmentPrecedence -func ?= ( left: inout T?, right: T?) { +func ?= (left: inout T?, right: T?) { if left == nil { left = right } From 407d397b225e8a8077ed87a8e751e42a51364ab4 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Fri, 18 May 2018 16:36:33 +0530 Subject: [PATCH 32/56] Cahnges --- TextBuffer.swift | 3 --- TextPosition.swift | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/TextBuffer.swift b/TextBuffer.swift index b82925d..5745743 100644 --- a/TextBuffer.swift +++ b/TextBuffer.swift @@ -12,9 +12,6 @@ import XcodeKit typealias TextBuffer = XCSourceTextBuffer typealias TextRange = XCSourceTextRange -private let closingFor = ["{":"}", "(":")", "[":"]"] -private let openingFor = ["}":"{", ")":"(", "]":"["] - extension TextBuffer { var lastPosition: TextPosition { let lastLine = self.lines[self.lines.count - 1] as! String diff --git a/TextPosition.swift b/TextPosition.swift index 14bf746..26ee8dd 100644 --- a/TextPosition.swift +++ b/TextPosition.swift @@ -24,7 +24,7 @@ extension TextPosition { } func next(in buffer: XCSourceTextBuffer) -> TextPosition? { - guard self != buffer.lastPosition else { return nil } + guard !buffer.isEnd(position: self) else {return nil} let currentLine = buffer.lines[self.line] as! String if self.column == currentLine.count - 1 { From 97d08d3401d8fbe58ca39ff5c3508482408fd79f Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 19 May 2018 17:11:02 +0530 Subject: [PATCH 33/56] Changes --- Linex.xcodeproj/project.pbxproj | 16 ++++ Selection/SourceEditorCommand.swift | 127 +--------------------------- TextBuffer+Expand.swift | 98 +++++++++++++++++++++ TextBuffer.swift | 14 +-- TextRange.swift | 15 ++++ 5 files changed, 138 insertions(+), 132 deletions(-) create mode 100644 TextBuffer+Expand.swift create mode 100644 TextRange.swift diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index e51bf01..86ca099 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -17,6 +17,12 @@ E306510320AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; E306510420AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; E306510520ADA09D006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; + E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */; }; + E306510820AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */; }; + E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */; }; + E306510B20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; + E306510C20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; + E306510D20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -115,6 +121,8 @@ E30650F720AC68CD006B0BBF /* TextDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextDirection.swift; sourceTree = ""; }; E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Linex.swift"; sourceTree = ""; }; E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalAssignment.swift; sourceTree = ""; }; + E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Expand.swift"; sourceTree = ""; }; + E306510A20B0388C006B0BBF /* TextRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRange.swift; sourceTree = ""; }; E31714C31F8385F40036CF07 /* Linex.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Linex.entitlements; sourceTree = ""; }; E330C82E1F796DE600ECC222 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; E330C82F1F796DF000ECC222 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; @@ -205,7 +213,9 @@ E3938E4A209DF834007F69E3 /* String+Basic.swift */, E3938E33209DEC2B007F69E3 /* String+Linex.swift */, E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, + E306510A20B0388C006B0BBF /* TextRange.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, + E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */, E30650F720AC68CD006B0BBF /* TextDirection.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, E3938E39209DF605007F69E3 /* Character+Linex.swift */, @@ -560,6 +570,8 @@ E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, E30650FA20AC6A9C006B0BBF /* TextDirection.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, + E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, + E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, @@ -582,9 +594,11 @@ E3938E48209DF772007F69E3 /* TextBuffer.swift in Sources */, E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, + E306510820AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E359BCF61F604E000071246B /* Alignment.swift in Sources */, E3938E37209DEC33007F69E3 /* String+Linex.swift in Sources */, E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, + E306510C20B0388C006B0BBF /* TextRange.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -599,6 +613,8 @@ E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, E30650FC20AC6A9E006B0BBF /* TextDirection.swift in Sources */, E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */, + E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, + E306510D20B0388C006B0BBF /* TextRange.swift in Sources */, E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Linex.swift in Sources */, diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index 9c04479..76b4855 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -22,7 +22,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { let buffer = invocation.buffer let selection = buffer.selectionType let selectedLines = buffer.selectedLines - var range = buffer.selections.lastObject as! TextRange + let range = buffer.selections.lastObject as! TextRange switch Options(command: invocation.commandIdentifier)! { case .selectLine: @@ -59,84 +59,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .multiLocation(_): break } - case .expand: - switch selection { - case .none(let position): - let currentLine = buffer.lines[position.line] as! String - if currentLine.count == 0 { return } - let lineEnd = currentLine.count - 1 - - let rightChar: Character? = position.column < lineEnd ? currentLine[position.column] : nil - - let leftChar: Character? = position.column > 0 ? currentLine[position.column - 1] : nil - - if rightChar?.isOpening ?? false { - range.end = buffer.closingPosition(for: rightChar!, startingAt: position) ?? range.end - return - } - - if leftChar?.isClosing ?? false { - range.start = buffer.findOpening(for: leftChar!, at: position) ?? range.start - return - } - range = buffer.wordSelectionRange(for: .validWordChars, at: position) - - case .words(let line, let colStart, let colEnd): - let currentLine = buffer.lines[line] as! String - let indentationIndex = currentLine.indentationOffset - let lineEnd = currentLine.count - 1 - let currentStart = currentLine[colStart] - let currentEnd = currentLine[colEnd - 1] - let borderStart = colStart == 0 ? nil : currentLine[colStart - 1] - let borderEnd = currentLine[colEnd] - - if (borderStart == "." || borderEnd == ".") { - let validChars = CharacterSet("@$_.").union(.alphanumerics) - if let selectionRange:Range = currentLine.selectWord(pin: colStart, validChars: validChars) { - range.start.column = selectionRange.lowerBound - range.end.column = selectionRange.upperBound - } - return - } - if (borderEnd == "(") { - if let end = currentLine.findClosingPosition(from: colEnd + 1) { - range.end.column = end + 1 - } - } - if (colStart == indentationIndex) { - range.end.column = lineEnd - return - } - - if (colEnd == lineEnd) { - range.start.column = currentLine.indentationOffset - return - } - - switch (borderStart, borderEnd) { - case ("\"","\""), ("{", "}"), ("[","]"), ("(",")"): - range.start.column = colStart - 1 - range.end.column = colEnd + 1 - return - default: break - } - - if (currentStart == "(" && currentEnd == ")" && colEnd == lineEnd) { - range.start.column = currentLine.indentationOffset - return - } - - if let start = currentLine.findOpeningPosition(from: colStart) { - range.start.column = start - } - - if let end = currentLine.findClosingPosition(from: colEnd) { - range.end.column = end - } - - case .lines(_, _): break - case .multiLocation(_): break - } + case .expand: buffer.expand() case .align: switch selection { @@ -155,49 +78,3 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } } - -let openStopper = CharacterSet("{[(\"") -let closeStopper = CharacterSet("}])\"") - -extension String { - func findOpeningPosition(from: Int) -> Int? { - var from = from - 1 - var onTheWayBrackets = 0 - while from >= 0 { - let currentChar = self[from] - - if currentChar.presentIn(openStopper) { - if onTheWayBrackets == 0 { - return from + 1 - } - onTheWayBrackets -= 1 - } - if currentChar.presentIn(closeStopper) { - onTheWayBrackets += 1 - } - from -= 1 - } - return nil - } - - func findClosingPosition(from: Int) -> Int? { - var from = from - var onTheWayBrackets = 0 - let endOfLine = self.count - while from < endOfLine { - let currentChar = self[from] - - if currentChar.presentIn(closeStopper) { - if onTheWayBrackets == 0 { - return from - } - onTheWayBrackets -= 1 - } - if currentChar.presentIn(openStopper) { - onTheWayBrackets += 1 - } - from += 1 - } - return nil - } -} diff --git a/TextBuffer+Expand.swift b/TextBuffer+Expand.swift new file mode 100644 index 0000000..d1d034c --- /dev/null +++ b/TextBuffer+Expand.swift @@ -0,0 +1,98 @@ +// +// TextBuffer+Expand.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 18/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +import XcodeKit + +extension TextBuffer { + func expand() { + switch (selectionType) { + + case .none(let position): expandNoSelection(position) + case .words(let line, let colStart, let colEnd): + expandOnWordsSelection(line, colStart: colStart, colEnd: colEnd) + case .lines(let start, let end): + break + case .multiLocation(_): + break + } + } + + private func expandNoSelection(_ position: TextPosition) { + var range = selections.lastObject as! TextRange + + let currentLine = lines[position.line] as! String + if currentLine.count == 0 { return } + let lineEnd = currentLine.count - 1 + + let rightChar: Character? = position.column < lineEnd ? currentLine[position.column] : nil + + let leftChar: Character? = position.column > 0 ? currentLine[position.column - 1] : nil + + if rightChar?.isOpening ?? false { + range.end = findClosing(for: rightChar!, at: position) ?? range.end + return + } + + if leftChar?.isClosing ?? false { + range.start = findOpening(for: leftChar!.opening, at: position) ?? range.start + return + } + range.update(selection: wordSelectionRange(for: .validWordChars, at: position)) + } + + private func expandOnWordsSelection(_ line: Int, colStart: Int, colEnd: Int) { + let currentLine = lines[line] as! String + let indentationIndex = currentLine.indentationOffset + let lineEnd = currentLine.count - 1 + let currentStart = currentLine[colStart] + let currentEnd = currentLine[colEnd - 1] + let borderStart = colStart == 0 ? nil : currentLine[colStart - 1] + let borderEnd = currentLine[colEnd] + let range = selections.lastObject as! TextRange + + if (borderStart == "." || borderEnd == ".") { + let validChars = CharacterSet("@$_.").union(.alphanumerics) + range.update(selection: wordSelectionRange(for: validChars, at: TextPosition(line: line, column: colStart))) + return + } + if (borderEnd == "(") { + range.end = findClosing(for: "(", at: TextPosition(line: line, column: colEnd + 1)) ?? range.end + } + if (colStart == indentationIndex) { + range.end.column = lineEnd + return + } + + if (colEnd == lineEnd) { + range.start.column = currentLine.indentationOffset + return + } + + switch (borderStart, borderEnd) { + case ("\"","\""), ("{", "}"), ("[","]"), ("(",")"): + range.start.column = colStart - 1 + range.end.column = colEnd + 1 + return + default: break + } + + if (currentStart == "(" && currentEnd == ")" && colEnd == lineEnd) { + range.start.column = currentLine.indentationOffset + return + } + +// if let start = currentLine.findOpeningPosition(from: colStart) { +// range.start.column = start +// } +// +// if let end = currentLine.findClosingPosition(from: colEnd) { +// range.end.column = end +// } + } +} diff --git a/TextBuffer.swift b/TextBuffer.swift index 5745743..8adb9e2 100644 --- a/TextBuffer.swift +++ b/TextBuffer.swift @@ -53,15 +53,15 @@ extension TextBuffer { return nil } - func closingPosition(for openingChar: Character, startingAt position: TextPosition) -> TextPosition? { - let closingChar = openingChar.closing + func findClosing(for openingChar: Character, at position: TextPosition) -> TextPosition? { + assert(openingChar.isOpening, "Char must be opening") var stackCount = 0 var currentPosition = position.next(in: self) while currentPosition != nil { let currentChar = self.char(at: currentPosition!) switch currentChar { - case openingChar: stackCount += 1 - case closingChar: + case openingChar.closing: stackCount += 1 + case openingChar: if stackCount == 0 { return TextPosition(line: currentPosition!.line, column: currentPosition!.column + 1) @@ -75,14 +75,14 @@ extension TextBuffer { } func findOpening(for closingChar: Character, at position: TextPosition) -> TextPosition? { - let openingChar = closingChar.opening + assert(closingChar.isClosing, "'closingChar' must be '), }, ]'") var stackCount = 0 var currentPosition = position.previous(in: self)?.previous(in: self) while currentPosition != nil { let currentChar = self.char(at: currentPosition!) switch currentChar { - case closingChar: stackCount += 1 - case openingChar: + case closingChar.closing: stackCount += 1 + case closingChar: if stackCount == 0 { return currentPosition! } stackCount -= 1 default: break diff --git a/TextRange.swift b/TextRange.swift new file mode 100644 index 0000000..1006fd6 --- /dev/null +++ b/TextRange.swift @@ -0,0 +1,15 @@ +// +// TextRange.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 19/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +extension TextRange { + func update(selection: TextRange) { + self.start = selection.start + self.end = selection.end + } +} From e8ede683074ae0222228048cf26f80a835324329 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Tue, 22 May 2018 18:30:27 +0530 Subject: [PATCH 34/56] Changes --- Character+Linex.swift | 4 ++ TextBuffer+Expand.swift | 83 +++++++++++------------------------------ TextBuffer.swift | 78 ++++++++++++++++++++++++++++++++------ 3 files changed, 91 insertions(+), 74 deletions(-) diff --git a/Character+Linex.swift b/Character+Linex.swift index c7652e3..06e788c 100644 --- a/Character+Linex.swift +++ b/Character+Linex.swift @@ -9,6 +9,10 @@ import Foundation extension Character { + func presentIn(_ string: String) -> Bool { + return self.presentIn(CharacterSet(string)) + } + func presentIn(_ characterSet:CharacterSet) -> Bool { return CharacterSet(String(self)).isSubset(of: characterSet) } diff --git a/TextBuffer+Expand.swift b/TextBuffer+Expand.swift index d1d034c..ee7bb5d 100644 --- a/TextBuffer+Expand.swift +++ b/TextBuffer+Expand.swift @@ -10,89 +10,48 @@ import Foundation import XcodeKit extension TextBuffer { - func expand() { - switch (selectionType) { - - case .none(let position): expandNoSelection(position) - case .words(let line, let colStart, let colEnd): - expandOnWordsSelection(line, colStart: colStart, colEnd: colEnd) - case .lines(let start, let end): - break - case .multiLocation(_): - break - } - } - - private func expandNoSelection(_ position: TextPosition) { - var range = selections.lastObject as! TextRange - - let currentLine = lines[position.line] as! String - if currentLine.count == 0 { return } - let lineEnd = currentLine.count - 1 - let rightChar: Character? = position.column < lineEnd ? currentLine[position.column] : nil + func expand() { + let range = selections.lastObject as! TextRange + guard lines.count != 0 else { return } - let leftChar: Character? = position.column > 0 ? currentLine[position.column - 1] : nil - if rightChar?.isOpening ?? false { - range.end = findClosing(for: rightChar!, at: position) ?? range.end + if isSelectionEmpty, + let newRange = rangeForExpandedSelection(for: .validWordChars, at: range) { + range.update(selection: newRange) return } - if leftChar?.isClosing ?? false { - range.start = findOpening(for: leftChar!.opening, at: position) ?? range.start - return - } - range.update(selection: wordSelectionRange(for: .validWordChars, at: position)) - } - - private func expandOnWordsSelection(_ line: Int, colStart: Int, colEnd: Int) { - let currentLine = lines[line] as! String - let indentationIndex = currentLine.indentationOffset - let lineEnd = currentLine.count - 1 - let currentStart = currentLine[colStart] - let currentEnd = currentLine[colEnd - 1] - let borderStart = colStart == 0 ? nil : currentLine[colStart - 1] - let borderEnd = currentLine[colEnd] - let range = selections.lastObject as! TextRange + let borderStart: Character? = range.start.previous(in: self).map { char(at: $0)} + let borderEnd: Character? = char(at: range.end) if (borderStart == "." || borderEnd == ".") { - let validChars = CharacterSet("@$_.").union(.alphanumerics) - range.update(selection: wordSelectionRange(for: validChars, at: TextPosition(line: line, column: colStart))) + let validChars = CharacterSet("@$_.!?").union(.alphanumerics) + if let newRange = rangeForExpandedSelection(for: validChars, at: range) { + range.update(selection: newRange) + } return } - if (borderEnd == "(") { - range.end = findClosing(for: "(", at: TextPosition(line: line, column: colEnd + 1)) ?? range.end - } - if (colStart == indentationIndex) { - range.end.column = lineEnd + if (borderEnd?.presentIn("!?:") ?? false) {// Optionals + range.end.column += 1 return } - - if (colEnd == lineEnd) { - range.start.column = currentLine.indentationOffset + if (borderEnd == "(") { + range.end = findClosing(for: "(", at: range.end) ?? range.end return } switch (borderStart, borderEnd) { case ("\"","\""), ("{", "}"), ("[","]"), ("(",")"): - range.start.column = colStart - 1 - range.end.column = colEnd + 1 + range.start = range.start.previous(in: self) ?? range.start + range.end = range.end.next(in: self) ?? range.end return default: break } - if (currentStart == "(" && currentEnd == ")" && colEnd == lineEnd) { - range.start.column = currentLine.indentationOffset - return + if let newRange = smartExpand(current: range) { + range.update(selection: newRange) } - -// if let start = currentLine.findOpeningPosition(from: colStart) { -// range.start.column = start -// } -// -// if let end = currentLine.findClosingPosition(from: colEnd) { -// range.end.column = end -// } } + } diff --git a/TextBuffer.swift b/TextBuffer.swift index 8adb9e2..905415a 100644 --- a/TextBuffer.swift +++ b/TextBuffer.swift @@ -18,6 +18,10 @@ extension TextBuffer { return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) } + func isStart(postion: TextPosition) -> Bool { + return postion.line == 0 && postion.column == 0 + } + func isEnd(position: TextPosition) -> Bool { return lastPosition == position } @@ -31,9 +35,11 @@ extension TextBuffer { extension TextBuffer { - func wordSelectionRange(for chars: CharacterSet, at position: TextPosition) -> TextRange { - let end = nextPosition(.forward, from: position, until: chars) ?? position - let start = nextPosition(.backward, from: position, until: chars) ?? position + func rangeForExpandedSelection(for chars: CharacterSet, at range: TextRange) -> TextRange? { + guard let start = nextPosition(.backward, from: range.start, until: chars), + let end = nextPosition(.forward, from: range.end, until: chars) else { + return nil + } return TextRange(start: start, end: end) } @@ -59,44 +65,92 @@ extension TextBuffer { var currentPosition = position.next(in: self) while currentPosition != nil { let currentChar = self.char(at: currentPosition!) - switch currentChar { - case openingChar.closing: stackCount += 1 - case openingChar: + if currentChar.isOpening { stackCount += 1} + else if currentChar.isClosing { if stackCount == 0 { return TextPosition(line: currentPosition!.line, - column: currentPosition!.column + 1) + column: currentPosition!.column + 1) } stackCount -= 1 - default: break } + currentPosition = currentPosition!.next(in: self) } return nil } + /// Invoke this when cursor is on close bracket func findOpening(for closingChar: Character, at position: TextPosition) -> TextPosition? { assert(closingChar.isClosing, "'closingChar' must be '), }, ]'") var stackCount = 0 var currentPosition = position.previous(in: self)?.previous(in: self) while currentPosition != nil { let currentChar = self.char(at: currentPosition!) - switch currentChar { - case closingChar.closing: stackCount += 1 - case closingChar: + if currentChar.isClosing { stackCount += 1 } + else if currentChar.isOpening { if stackCount == 0 { return currentPosition! } stackCount -= 1 - default: break } + currentPosition = currentPosition?.previous(in: self) } return nil } + + func smartExpand(current range: TextRange) -> TextRange? { + guard let newStart = searchLeft(from: range.start), + let newEnd = searchRight(from: range.end) else { return nil } + return TextRange(start: newStart, end: newEnd) + } + + func searchLeft(from position: TextPosition) -> TextPosition? { + var stackCount = 0 + var currentPosition = position.previous(in: self)?.previous(in: self) + while currentPosition != nil { + let currentChar = self.char(at: currentPosition!) + if currentChar.isClosing { + stackCount += 1 + } else if currentChar.isOpening { + if stackCount == 0 { return currentPosition!.next(in: self)! } + stackCount -= 1 + } else if currentChar == "\"" { + if stackCount == 0 { return currentPosition! } + } + + currentPosition = currentPosition?.previous(in: self) + } + return nil + } + + func searchRight(from position: TextPosition) -> TextPosition? { + var stackCount = 0 + var currentPosition = position.next(in: self) + while currentPosition != nil { + let currentChar = self.char(at: currentPosition!) + if currentChar.isOpening { + stackCount += 1 + } else if currentChar.isClosing { + if stackCount == 0 { return currentPosition! } + stackCount -= 1 + } else if currentChar == "\"" { + if stackCount == 0 { return currentPosition! } + } + + currentPosition = currentPosition?.next(in: self) + } + return nil + } } extension TextBuffer { var selectedLines: IndexSet { return self.selectionType.selectedLines } + var isSelectionEmpty: Bool { + let selections = self.selections as! [XCSourceTextRange] + let range = selections.first! + return range.start == range.end + } var selectionType: SelectionType { let selections = self.selections as! [XCSourceTextRange] if selections.count == 1 { From 81c2433178fbf15f4e38fc0b8a27b037f5769b76 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 24 May 2018 23:48:43 +0530 Subject: [PATCH 35/56] Bug fixes --- TextBuffer.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TextBuffer.swift b/TextBuffer.swift index 905415a..4859a76 100644 --- a/TextBuffer.swift +++ b/TextBuffer.swift @@ -105,7 +105,7 @@ extension TextBuffer { func searchLeft(from position: TextPosition) -> TextPosition? { var stackCount = 0 - var currentPosition = position.previous(in: self)?.previous(in: self) + var currentPosition = position.previous(in: self) while currentPosition != nil { let currentChar = self.char(at: currentPosition!) if currentChar.isClosing { @@ -124,7 +124,7 @@ extension TextBuffer { func searchRight(from position: TextPosition) -> TextPosition? { var stackCount = 0 - var currentPosition = position.next(in: self) + var currentPosition: TextPosition? = position while currentPosition != nil { let currentChar = self.char(at: currentPosition!) if currentChar.isOpening { @@ -133,7 +133,7 @@ extension TextBuffer { if stackCount == 0 { return currentPosition! } stackCount -= 1 } else if currentChar == "\"" { - if stackCount == 0 { return currentPosition! } + if stackCount == 0 { return currentPosition!.next(in: self) } } currentPosition = currentPosition?.next(in: self) From 3dcd7152374461b0329415e522cb211de3866535 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 24 May 2018 23:58:12 +0530 Subject: [PATCH 36/56] Structure change --- ConditionalAssignment.swift | 17 ----- Linex.xcodeproj/project.pbxproj | 64 +++++++++---------- .../Character+Linex.swift | 0 .../CharacterSet+Linex.swift | 0 .../RawRepresentable.swift | 0 .../String+Basic.swift | 0 TextDirection.swift | 13 ---- .../SelectionType.swift | 0 .../TextBuffer+Expand.swift | 1 - TextBuffer.swift => XcodeKit/TextBuffer.swift | 1 - .../TextPosition.swift | 4 ++ TextRange.swift => XcodeKit/TextRange.swift | 4 ++ 12 files changed, 40 insertions(+), 64 deletions(-) delete mode 100644 ConditionalAssignment.swift rename Character+Linex.swift => Standard Extensions/Character+Linex.swift (100%) rename CharacterSet+Linex.swift => Standard Extensions/CharacterSet+Linex.swift (100%) rename Common.swift => Standard Extensions/RawRepresentable.swift (100%) rename String+Basic.swift => Standard Extensions/String+Basic.swift (100%) delete mode 100644 TextDirection.swift rename SelectionType.swift => XcodeKit/SelectionType.swift (100%) rename TextBuffer+Expand.swift => XcodeKit/TextBuffer+Expand.swift (99%) rename TextBuffer.swift => XcodeKit/TextBuffer.swift (99%) rename TextPosition.swift => XcodeKit/TextPosition.swift (96%) rename TextRange.swift => XcodeKit/TextRange.swift (84%) diff --git a/ConditionalAssignment.swift b/ConditionalAssignment.swift deleted file mode 100644 index 267d304..0000000 --- a/ConditionalAssignment.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// ConditionalAssignment.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 17/05/18. -// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation - -infix operator ?= : AssignmentPrecedence - -func ?= (left: inout T?, right: T?) { - if left == nil { - left = right - } -} diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 86ca099..3818656 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -7,22 +7,16 @@ objects = { /* Begin PBXBuildFile section */ - E30650FA20AC6A9C006B0BBF /* TextDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650F720AC68CD006B0BBF /* TextDirection.swift */; }; - E30650FB20AC6A9D006B0BBF /* TextDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650F720AC68CD006B0BBF /* TextDirection.swift */; }; - E30650FC20AC6A9E006B0BBF /* TextDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650F720AC68CD006B0BBF /* TextDirection.swift */; }; E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; - E306510220AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; - E306510320AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; - E306510420AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; - E306510520ADA09D006B0BBF /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */; }; E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */; }; E306510820AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */; }; E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */; }; E306510B20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; E306510C20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; E306510D20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; + E35783BE20B73B5A00D845A7 /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -60,14 +54,14 @@ E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; E39E22791F59876A00354A5F /* Selection.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E39E226D1F59876A00354A5F /* Selection.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - E39E22801F59C59100354A5F /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* Common.swift */; }; - E39E22811F59C59200354A5F /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* Common.swift */; }; - E39E22821F59C59300354A5F /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* Common.swift */; }; + E39E22801F59C59100354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; + E39E22811F59C59200354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; + E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; E3F543941F5A84FC008F426E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F543981F5A84FC008F426E /* SourceEditorExtension.swift */; }; E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F5439A1F5A84FC008F426E /* SourceEditorCommand.swift */; }; E3F5439F1F5A84FC008F426E /* Convert.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E3F543931F5A84FC008F426E /* Convert.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - E3F543A61F5ABA48008F426E /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* Common.swift */; }; + E3F543A61F5ABA48008F426E /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -118,9 +112,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - E30650F720AC68CD006B0BBF /* TextDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextDirection.swift; sourceTree = ""; }; E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Linex.swift"; sourceTree = ""; }; - E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalAssignment.swift; sourceTree = ""; }; E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Expand.swift"; sourceTree = ""; }; E306510A20B0388C006B0BBF /* TextRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRange.swift; sourceTree = ""; }; E31714C31F8385F40036CF07 /* Linex.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Linex.entitlements; sourceTree = ""; }; @@ -156,7 +148,7 @@ E39E22721F59876A00354A5F /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; E39E22741F59876A00354A5F /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; E39E22761F59876A00354A5F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E39E227E1F59C58E00354A5F /* Common.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = ""; }; + E39E227E1F59C58E00354A5F /* RawRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawRepresentable.swift; sourceTree = ""; }; E3F543931F5A84FC008F426E /* Convert.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Convert.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E3F543971F5A84FC008F426E /* Convert.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Convert.entitlements; sourceTree = ""; }; E3F543981F5A84FC008F426E /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -206,21 +198,35 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - E359420E1F55564C009EFA35 = { + E35783BD20B73AB700D845A7 /* Standard Extensions */ = { isa = PBXGroup; children = ( - E39E227E1F59C58E00354A5F /* Common.swift */, + E39E227E1F59C58E00354A5F /* RawRepresentable.swift */, E3938E4A209DF834007F69E3 /* String+Basic.swift */, - E3938E33209DEC2B007F69E3 /* String+Linex.swift */, + E3938E39209DF605007F69E3 /* Character+Linex.swift */, + E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */, + ); + path = "Standard Extensions"; + sourceTree = ""; + }; + E35783BF20B73B9A00D845A7 /* XcodeKit */ = { + isa = PBXGroup; + children = ( E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E306510A20B0388C006B0BBF /* TextRange.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */, - E30650F720AC68CD006B0BBF /* TextDirection.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, - E3938E39209DF605007F69E3 /* Character+Linex.swift */, - E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */, - E306510120AD9F92006B0BBF /* ConditionalAssignment.swift */, + ); + path = XcodeKit; + sourceTree = ""; + }; + E359420E1F55564C009EFA35 = { + isa = PBXGroup; + children = ( + E35783BD20B73AB700D845A7 /* Standard Extensions */, + E3938E33209DEC2B007F69E3 /* String+Linex.swift */, + E35783BF20B73B9A00D845A7 /* XcodeKit */, E359423F1F55565E009EFA35 /* Line */, E39E226F1F59876A00354A5F /* Selection */, E3F543951F5A84FC008F426E /* Convert */, @@ -549,13 +555,13 @@ buildActionMask = 2147483647; files = ( E3938E3E209DF626007F69E3 /* Character+Linex.swift in Sources */, - E39E22821F59C59300354A5F /* Common.swift in Sources */, + E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, E3938E35209DEC32007F69E3 /* String+Linex.swift in Sources */, E359BD0A1F6063A70071246B /* Alignment.swift in Sources */, - E306510520ADA09D006B0BBF /* ConditionalAssignment.swift in Sources */, E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, E3938E4B209DF834007F69E3 /* String+Basic.swift in Sources */, + E35783BE20B73B5A00D845A7 /* CharacterSet+Linex.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,10 +571,8 @@ files = ( E3938E3B209DF622007F69E3 /* Character+Linex.swift in Sources */, E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, - E39E22801F59C59100354A5F /* Common.swift in Sources */, - E306510220AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */, + E39E22801F59C59100354A5F /* RawRepresentable.swift in Sources */, E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, - E30650FA20AC6A9C006B0BBF /* TextDirection.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, @@ -585,12 +589,10 @@ buildActionMask = 2147483647; files = ( E3938E3C209DF623007F69E3 /* Character+Linex.swift in Sources */, - E39E22811F59C59200354A5F /* Common.swift in Sources */, - E30650FB20AC6A9D006B0BBF /* TextDirection.swift in Sources */, + E39E22811F59C59200354A5F /* RawRepresentable.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */, - E306510320AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */, E3938E48209DF772007F69E3 /* TextBuffer.swift in Sources */, E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, @@ -606,12 +608,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E3F543A61F5ABA48008F426E /* Common.swift in Sources */, + E3F543A61F5ABA48008F426E /* RawRepresentable.swift in Sources */, E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3938E49209DF772007F69E3 /* TextBuffer.swift in Sources */, - E306510420AD9F92006B0BBF /* ConditionalAssignment.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, - E30650FC20AC6A9E006B0BBF /* TextDirection.swift in Sources */, E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */, E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510D20B0388C006B0BBF /* TextRange.swift in Sources */, diff --git a/Character+Linex.swift b/Standard Extensions/Character+Linex.swift similarity index 100% rename from Character+Linex.swift rename to Standard Extensions/Character+Linex.swift diff --git a/CharacterSet+Linex.swift b/Standard Extensions/CharacterSet+Linex.swift similarity index 100% rename from CharacterSet+Linex.swift rename to Standard Extensions/CharacterSet+Linex.swift diff --git a/Common.swift b/Standard Extensions/RawRepresentable.swift similarity index 100% rename from Common.swift rename to Standard Extensions/RawRepresentable.swift diff --git a/String+Basic.swift b/Standard Extensions/String+Basic.swift similarity index 100% rename from String+Basic.swift rename to Standard Extensions/String+Basic.swift diff --git a/TextDirection.swift b/TextDirection.swift deleted file mode 100644 index 6423fa4..0000000 --- a/TextDirection.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// TextDirection.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 16/05/18. -// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation - -enum TextDirection { - case forward, backward -} diff --git a/SelectionType.swift b/XcodeKit/SelectionType.swift similarity index 100% rename from SelectionType.swift rename to XcodeKit/SelectionType.swift diff --git a/TextBuffer+Expand.swift b/XcodeKit/TextBuffer+Expand.swift similarity index 99% rename from TextBuffer+Expand.swift rename to XcodeKit/TextBuffer+Expand.swift index ee7bb5d..5ecd92f 100644 --- a/TextBuffer+Expand.swift +++ b/XcodeKit/TextBuffer+Expand.swift @@ -53,5 +53,4 @@ extension TextBuffer { range.update(selection: newRange) } } - } diff --git a/TextBuffer.swift b/XcodeKit/TextBuffer.swift similarity index 99% rename from TextBuffer.swift rename to XcodeKit/TextBuffer.swift index 4859a76..cd0e107 100644 --- a/TextBuffer.swift +++ b/XcodeKit/TextBuffer.swift @@ -10,7 +10,6 @@ import Foundation import XcodeKit typealias TextBuffer = XCSourceTextBuffer -typealias TextRange = XCSourceTextRange extension TextBuffer { var lastPosition: TextPosition { diff --git a/TextPosition.swift b/XcodeKit/TextPosition.swift similarity index 96% rename from TextPosition.swift rename to XcodeKit/TextPosition.swift index 26ee8dd..6c53f04 100644 --- a/TextPosition.swift +++ b/XcodeKit/TextPosition.swift @@ -11,6 +11,10 @@ import XcodeKit typealias TextPosition = XCSourceTextPosition +enum TextDirection { + case forward, backward +} + extension TextPosition { var isStart: Bool { return self.line == 0 && self.column == 0 diff --git a/TextRange.swift b/XcodeKit/TextRange.swift similarity index 84% rename from TextRange.swift rename to XcodeKit/TextRange.swift index 1006fd6..129b60f 100644 --- a/TextRange.swift +++ b/XcodeKit/TextRange.swift @@ -7,6 +7,10 @@ // import Foundation +import XcodeKit + +typealias TextRange = XCSourceTextRange + extension TextRange { func update(selection: TextRange) { self.start = selection.start From 158885e72a1784a6564b3f60844284079ee06e96 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Thu, 24 May 2018 23:58:46 +0530 Subject: [PATCH 37/56] update selection --- XcodeKit/TextBuffer+Expand.swift | 6 +++--- XcodeKit/TextRange.swift | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/XcodeKit/TextBuffer+Expand.swift b/XcodeKit/TextBuffer+Expand.swift index 5ecd92f..320c94b 100644 --- a/XcodeKit/TextBuffer+Expand.swift +++ b/XcodeKit/TextBuffer+Expand.swift @@ -18,7 +18,7 @@ extension TextBuffer { if isSelectionEmpty, let newRange = rangeForExpandedSelection(for: .validWordChars, at: range) { - range.update(selection: newRange) + range.updateSelection(range: newRange) return } @@ -28,7 +28,7 @@ extension TextBuffer { if (borderStart == "." || borderEnd == ".") { let validChars = CharacterSet("@$_.!?").union(.alphanumerics) if let newRange = rangeForExpandedSelection(for: validChars, at: range) { - range.update(selection: newRange) + range.updateSelection(range: newRange) } return } @@ -50,7 +50,7 @@ extension TextBuffer { } if let newRange = smartExpand(current: range) { - range.update(selection: newRange) + range.updateSelection(range: newRange) } } } diff --git a/XcodeKit/TextRange.swift b/XcodeKit/TextRange.swift index 129b60f..55e0eb6 100644 --- a/XcodeKit/TextRange.swift +++ b/XcodeKit/TextRange.swift @@ -12,8 +12,8 @@ import XcodeKit typealias TextRange = XCSourceTextRange extension TextRange { - func update(selection: TextRange) { - self.start = selection.start - self.end = selection.end + func updateSelection(range: TextRange) { + self.start = range.start + self.end = range.end } } From 740a2ccf4737f6dc902abcb643f701d9357b75c3 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Fri, 25 May 2018 00:00:33 +0530 Subject: [PATCH 38/56] Structure change --- Linex.xcodeproj/project.pbxproj | 8 ++++++++ XcodeKit/TextBuffer+Basic.swift | 32 ++++++++++++++++++++++++++++++++ XcodeKit/TextBuffer.swift | 21 --------------------- 3 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 XcodeKit/TextBuffer+Basic.swift diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 3818656..9951c43 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -17,6 +17,9 @@ E306510C20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; E306510D20B0388C006B0BBF /* TextRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = E306510A20B0388C006B0BBF /* TextRange.swift */; }; E35783BE20B73B5A00D845A7 /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; + E35783C120B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; + E35783C220B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; + E35783C320B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -119,6 +122,7 @@ E330C82E1F796DE600ECC222 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; E330C82F1F796DF000ECC222 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; E356FD811F66F55C004558F1 /* TestPad.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestPad.swift; sourceTree = ""; }; + E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Basic.swift"; sourceTree = ""; }; E35942171F55564C009EFA35 /* Linex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Linex.app; sourceTree = BUILT_PRODUCTS_DIR; }; E359421A1F55564C009EFA35 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E359421C1F55564C009EFA35 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -215,6 +219,7 @@ E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E306510A20B0388C006B0BBF /* TextRange.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, + E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */, E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, ); @@ -573,6 +578,7 @@ E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, E39E22801F59C59100354A5F /* RawRepresentable.swift in Sources */, E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, + E35783C120B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, @@ -601,6 +607,7 @@ E3938E37209DEC33007F69E3 /* String+Linex.swift in Sources */, E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E306510C20B0388C006B0BBF /* TextRange.swift in Sources */, + E35783C220B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -612,6 +619,7 @@ E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */, E3938E49209DF772007F69E3 /* TextBuffer.swift in Sources */, E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */, + E35783C320B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */, E3938E3D209DF624007F69E3 /* Character+Linex.swift in Sources */, E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510D20B0388C006B0BBF /* TextRange.swift in Sources */, diff --git a/XcodeKit/TextBuffer+Basic.swift b/XcodeKit/TextBuffer+Basic.swift new file mode 100644 index 0000000..9be1e43 --- /dev/null +++ b/XcodeKit/TextBuffer+Basic.swift @@ -0,0 +1,32 @@ +// +// TextBuffer+Basic.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 24/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +import XcodeKit + +typealias TextBuffer = XCSourceTextBuffer + +extension TextBuffer { + var lastPosition: TextPosition { + let lastLine = self.lines[self.lines.count - 1] as! String + return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) + } + + func isStart(postion: TextPosition) -> Bool { + return postion.line == 0 && postion.column == 0 + } + + func isEnd(position: TextPosition) -> Bool { + return lastPosition == position + } + + func char(at position: TextPosition) -> Character { + let currentLine = self.lines[position.line] as! String + return currentLine[position.column] as Character + } +} diff --git a/XcodeKit/TextBuffer.swift b/XcodeKit/TextBuffer.swift index cd0e107..a1cc082 100644 --- a/XcodeKit/TextBuffer.swift +++ b/XcodeKit/TextBuffer.swift @@ -9,27 +9,6 @@ import Foundation import XcodeKit -typealias TextBuffer = XCSourceTextBuffer - -extension TextBuffer { - var lastPosition: TextPosition { - let lastLine = self.lines[self.lines.count - 1] as! String - return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) - } - - func isStart(postion: TextPosition) -> Bool { - return postion.line == 0 && postion.column == 0 - } - - func isEnd(position: TextPosition) -> Bool { - return lastPosition == position - } - - func char(at position: TextPosition) -> Character { - let currentLine = self.lines[position.line] as! String - return currentLine[position.column] as Character - } -} extension TextBuffer { From 199c4cc05d60a5397d370ceffc6aa4ecde585479 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Fri, 25 May 2018 00:08:09 +0530 Subject: [PATCH 39/56] Updates --- Linex.xcodeproj/project.pbxproj | 8 ++++++ XcodeKit/TextBuffer+Expand.swift | 4 +-- XcodeKit/TextBuffer+Selection.swift | 36 +++++++++++++++++++++++++ XcodeKit/TextBuffer.swift | 42 ++++++++--------------------- 4 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 XcodeKit/TextBuffer+Selection.swift diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 9951c43..dd74e90 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -20,6 +20,9 @@ E35783C120B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; E35783C220B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; E35783C320B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; + E35783C520B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */; }; + E35783C620B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */; }; + E35783C720B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -123,6 +126,7 @@ E330C82F1F796DF000ECC222 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; E356FD811F66F55C004558F1 /* TestPad.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestPad.swift; sourceTree = ""; }; E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Basic.swift"; sourceTree = ""; }; + E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Selection.swift"; sourceTree = ""; }; E35942171F55564C009EFA35 /* Linex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Linex.app; sourceTree = BUILT_PRODUCTS_DIR; }; E359421A1F55564C009EFA35 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E359421C1F55564C009EFA35 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -219,6 +223,7 @@ E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E306510A20B0388C006B0BBF /* TextRange.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, + E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */, E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */, E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, @@ -583,6 +588,7 @@ E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, + E35783C520B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, E35942451F55565E009EFA35 /* SourceEditorCommand.swift in Sources */, @@ -603,6 +609,7 @@ E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, E306510820AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, + E35783C620B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, E359BCF61F604E000071246B /* Alignment.swift in Sources */, E3938E37209DEC33007F69E3 /* String+Linex.swift in Sources */, E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, @@ -624,6 +631,7 @@ E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510D20B0388C006B0BBF /* TextRange.swift in Sources */, E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, + E35783C720B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Linex.swift in Sources */, E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */, diff --git a/XcodeKit/TextBuffer+Expand.swift b/XcodeKit/TextBuffer+Expand.swift index 320c94b..73e3187 100644 --- a/XcodeKit/TextBuffer+Expand.swift +++ b/XcodeKit/TextBuffer+Expand.swift @@ -17,7 +17,7 @@ extension TextBuffer { if isSelectionEmpty, - let newRange = rangeForExpandedSelection(for: .validWordChars, at: range) { + let newRange = rangeForWordSelection(for: .validWordChars, at: range) { range.updateSelection(range: newRange) return } @@ -27,7 +27,7 @@ extension TextBuffer { if (borderStart == "." || borderEnd == ".") { let validChars = CharacterSet("@$_.!?").union(.alphanumerics) - if let newRange = rangeForExpandedSelection(for: validChars, at: range) { + if let newRange = rangeForWordSelection(for: validChars, at: range) { range.updateSelection(range: newRange) } return diff --git a/XcodeKit/TextBuffer+Selection.swift b/XcodeKit/TextBuffer+Selection.swift new file mode 100644 index 0000000..7f024e6 --- /dev/null +++ b/XcodeKit/TextBuffer+Selection.swift @@ -0,0 +1,36 @@ +// +// TextBuffer+Selection.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 25/05/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation +import XcodeKit + +extension TextBuffer { + var selectedLines: IndexSet { + return self.selectionType.selectedLines + } + var isSelectionEmpty: Bool { + let selections = self.selections as! [XCSourceTextRange] + let range = selections.first! + return range.start == range.end + } + var selectionType: SelectionType { + let selections = self.selections as! [XCSourceTextRange] + if selections.count == 1 { + let range = selections.first! + if range.start.line == range.end.line { + if range.start.column == range.end.column { + return .none(position: TextPosition(line: range.start.line, column: range.start.column)) + } + return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) + } + return .lines(start: range.start, end: range.end) + } + return .multiLocation(selections) + } +} + diff --git a/XcodeKit/TextBuffer.swift b/XcodeKit/TextBuffer.swift index a1cc082..28fccbd 100644 --- a/XcodeKit/TextBuffer.swift +++ b/XcodeKit/TextBuffer.swift @@ -9,11 +9,9 @@ import Foundation import XcodeKit - - +//MARK - Word selection extension TextBuffer { - - func rangeForExpandedSelection(for chars: CharacterSet, at range: TextRange) -> TextRange? { + func rangeForWordSelection(for chars: CharacterSet, at range: TextRange) -> TextRange? { guard let start = nextPosition(.backward, from: range.start, until: chars), let end = nextPosition(.forward, from: range.end, until: chars) else { return nil @@ -21,7 +19,7 @@ extension TextBuffer { return TextRange(start: start, end: end) } - func nextPosition(_ direction: TextDirection, + private func nextPosition(_ direction: TextDirection, from startPosition: TextPosition, until charSet: CharacterSet) -> TextPosition? { var currentPosition = Optional(startPosition) @@ -36,7 +34,10 @@ extension TextBuffer { } return nil } +} +//MARK - Find specific opening/closing bracket +extension TextBuffer { func findClosing(for openingChar: Character, at position: TextPosition) -> TextPosition? { assert(openingChar.isOpening, "Char must be opening") var stackCount = 0 @@ -74,14 +75,17 @@ extension TextBuffer { } return nil } +} +//MARK - Smart expansion +extension TextBuffer { func smartExpand(current range: TextRange) -> TextRange? { guard let newStart = searchLeft(from: range.start), let newEnd = searchRight(from: range.end) else { return nil } return TextRange(start: newStart, end: newEnd) } - func searchLeft(from position: TextPosition) -> TextPosition? { + private func searchLeft(from position: TextPosition) -> TextPosition? { var stackCount = 0 var currentPosition = position.previous(in: self) while currentPosition != nil { @@ -100,7 +104,7 @@ extension TextBuffer { return nil } - func searchRight(from position: TextPosition) -> TextPosition? { + private func searchRight(from position: TextPosition) -> TextPosition? { var stackCount = 0 var currentPosition: TextPosition? = position while currentPosition != nil { @@ -120,27 +124,3 @@ extension TextBuffer { } } -extension TextBuffer { - var selectedLines: IndexSet { - return self.selectionType.selectedLines - } - var isSelectionEmpty: Bool { - let selections = self.selections as! [XCSourceTextRange] - let range = selections.first! - return range.start == range.end - } - var selectionType: SelectionType { - let selections = self.selections as! [XCSourceTextRange] - if selections.count == 1 { - let range = selections.first! - if range.start.line == range.end.line { - if range.start.column == range.end.column { - return .none(position: TextPosition(line: range.start.line, column: range.start.column)) - } - return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) - } - return .lines(start: range.start, end: range.end) - } - return .multiLocation(selections) - } -} From 272b11ec66c3ae766b39d7fe2a3f158babadf361 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 16 Jun 2018 16:01:20 +0530 Subject: [PATCH 40/56] Fixed the bug of string replacement --- LinexTests/LinexTests.swift | 43 ++++++++++---------------- LinexTests/SelectionTests.swift | 14 --------- Standard Extensions/String+Basic.swift | 2 +- 3 files changed, 17 insertions(+), 42 deletions(-) diff --git a/LinexTests/LinexTests.swift b/LinexTests/LinexTests.swift index 901b21c..52c0a21 100644 --- a/LinexTests/LinexTests.swift +++ b/LinexTests/LinexTests.swift @@ -10,45 +10,34 @@ import XCTest @testable import Linex class LinexTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } func testLineIndentatinOffset() { - "".indentationOffset XCTAssertEqual("".indentationOffset, 0) // 123456 XCTAssertEqual(" ".indentationOffset, 6) XCTAssertEqual(" ABC".indentationOffset, 6) - } func testOneSpace() { - - XCTAssert(" ".lineOneSpaceAt(pin: 0) == (0, " ")) + XCTAssert(" ".lineOneSpaceAt(pin: 0) == (0, "")) XCTAssert(" ".lineOneSpaceAt(pin: 0) == (0, " ")) XCTAssert(" ".lineOneSpaceAt(pin: 1) == (0, " ")) - XCTAssert("ABC".lineOneSpaceAt(pin: 0) == (0, "ABC")) - XCTAssert("ABC".lineOneSpaceAt(pin: 1) == (1, "ABC")) - XCTAssert("ABC".lineOneSpaceAt(pin: 2) == (2, "ABC")) - - // 0123456789 - let t1 = "A BCD", t2 = "A BCD" - XCTAssert(t1.lineOneSpaceAt(pin: 0) == (0, t1)) - XCTAssert(t1.lineOneSpaceAt(pin: 1) == (1, t2)) - XCTAssert(t1.lineOneSpaceAt(pin: 2) == (1, t2)) - XCTAssert(t1.lineOneSpaceAt(pin: 3) == (1, t2)) - XCTAssert(t1.lineOneSpaceAt(pin: 4) == (1, t2)) - XCTAssert(t1.lineOneSpaceAt(pin: 5) == (1, t2)) - XCTAssert(t1.lineOneSpaceAt(pin: 6) == (6, t1)) - XCTAssert(t1.lineOneSpaceAt(pin: 7) == (7, t1)) - XCTAssert(t1.lineOneSpaceAt(pin: 8) == (8, t1)) + XCTAssert("ABC".lineOneSpaceAt(pin: 0) == (0, " ABC")) + XCTAssert("ABC".lineOneSpaceAt(pin: 1) == (1, "A BC")) + XCTAssert("ABC".lineOneSpaceAt(pin: 2) == (2, "AB C")) + XCTAssert("AB C".lineOneSpaceAt(pin: 2) == (2, "ABC")) + + // 0123456789 + XCTAssert("A BCD".lineOneSpaceAt(pin: 0) == (0, " A BCD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 1) == (1, "A BCD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 2) == (1, "A BCD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 3) == (1, "A BCD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 4) == (1, "A BCD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 5) == (1, "A BCD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 6) == (6, "A B CD")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 7) == (7, "A BC D")) + XCTAssert("A BCD".lineOneSpaceAt(pin: 8) == (8, "A BCD ")) } func testAlign() { diff --git a/LinexTests/SelectionTests.swift b/LinexTests/SelectionTests.swift index 5302519..7492404 100644 --- a/LinexTests/SelectionTests.swift +++ b/LinexTests/SelectionTests.swift @@ -15,18 +15,4 @@ class SelectionTests: XCTestCase { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - - func testConditionalAssignment() { - XCTAssert(true) - var a = Optional("Kaunteya") - a ?= "Mohan" - XCTAssertEqual(a!, "Kaunteya") - - var a1: String? - a1 ?= "Mohan" - XCTAssertEqual(a1!, "Mohan") - - a1 ?= "Raju" - XCTAssertEqual(a1!, "Mohan") - } } diff --git a/Standard Extensions/String+Basic.swift b/Standard Extensions/String+Basic.swift index 8f751fa..185ebeb 100644 --- a/Standard Extensions/String+Basic.swift +++ b/Standard Extensions/String+Basic.swift @@ -41,7 +41,7 @@ extension String { } mutating func replace(range: Range, with replacement: String) { - self.replaceSubrange(self.index(at: range.lowerBound).. Date: Mon, 18 Jun 2018 21:49:01 +0530 Subject: [PATCH 41/56] Initial of multiple cursors --- Convert/SourceEditorCommand.swift | 15 +++-- Line/SourceEditorCommand.swift | 7 +- Selection/SourceEditorCommand.swift | 100 +++++++++++++++------------- XcodeKit/SelectionType.swift | 25 ++++--- XcodeKit/TextBuffer+Expand.swift | 2 +- XcodeKit/TextBuffer+Selection.swift | 47 +++++++------ XcodeKit/TextRange.swift | 12 ++++ 7 files changed, 119 insertions(+), 89 deletions(-) diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index ea487ea..90f108e 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -17,12 +17,12 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { - let buffer = invocation.buffer - let selection = buffer.selectionType - let range = buffer.selections.firstObject as! XCSourceTextRange - - if let command = Options(command: invocation.commandIdentifier) { +// let buffer = invocation.buffer +// let selection = buffer.selectionType +// let range = buffer.selections.firstObject as! XCSourceTextRange +// if let command = Options(command: invocation.commandIdentifier) { +/* switch selection { case .none(let position): var currentLine = buffer.lines[position.line] as! String @@ -76,9 +76,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } case .lines(_, _): break - case .multiLocation(_): break } - } + */ + +// } completionHandler(nil) } diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 0f64c6d..ed6129a 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -17,10 +17,10 @@ enum Options: String { class SourceEditorCommand: NSObject, XCSourceEditorCommand { public func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Swift.Void) { - +/* let buffer = invocation.buffer - let selection = buffer.selectionType - let selectedLines = buffer.selectedLines +// let selection = buffer.selectionType +// let selectedLines = buffer.selectedLines switch Options(command: invocation.commandIdentifier)! { case .duplicate: @@ -194,6 +194,7 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .multiLocation(_): break } } + */ completionHandler(nil) } } diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index 76b4855..4d52158 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -15,66 +15,72 @@ enum Options: String { class SourceEditorCommand: NSObject, XCSourceEditorCommand { - func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { - defer { - completionHandler(nil) - } + func perform(with invocation: XCSourceEditorCommandInvocation, + completionHandler: @escaping (Error?) -> Void ) -> Void { let buffer = invocation.buffer - let selection = buffer.selectionType - let selectedLines = buffer.selectedLines - let range = buffer.selections.lastObject as! TextRange + +// let selection = buffer.selectionType +// let selectedLines = buffer.selectedLines +// let range = buffer.selections.lastObject as! TextRange switch Options(command: invocation.commandIdentifier)! { case .selectLine: - switch selection { - case .none(let position): - let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset - range.start.column = indentationOffset - range.end.column = (buffer.lines[position.line] as! String).count - 1 + buffer.selectionRanges.forEach { range in + if range.isSelectionEmpty { + let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset + range.start.column = indentationOffset + range.end.column = (buffer.lines[range.start.line] as! String).count - 1 + } else { + range.start.column = 0 + range.end.line += 1 + range.end.column = 0 + } + } - case .words(_, _, _), - .lines(_, _): + case .selectLineAbove: + buffer.selectionRanges.forEach { range in range.start.column = 0 - range.end.line += 1 + range.start.line = max(range.start.line - 1, 0) range.end.column = 0 - - case .multiLocation(_): break } - case .selectLineAbove: - range.start.column = 0 - range.start.line = max(range.start.line - 1, 0) - range.end.column = 0 - case .oneSpace: - switch selection { - case .none(let position): - let currentLine = buffer.lines[position.line] as! String - let (newOffset, newLine) = currentLine.lineOneSpaceAt(pin: position.column) - buffer.lines.replaceObject(at: position.line, with: newLine) - range.end.column = newOffset - range.start.column = newOffset - case .words(_, _, _): break - case .lines(_, _): break - case .multiLocation(_): break + buffer.selectionRanges.forEach { range in + if range.isSelectionEmpty { + let currentLine = buffer.lines[range.start.line] as! String + let (newOffset, newLine) = currentLine.lineOneSpaceAt(pin: range.start.column) + buffer.lines.replaceObject(at: range.start.line, with: newLine) + range.end.column = newOffset + range.start.column = newOffset + } } +// switch selection { +// case .none(let position): +// let currentLine = buffer.lines[position.line] as! String +// let (newOffset, newLine) = currentLine.lineOneSpaceAt(pin: position.column) +// buffer.lines.replaceObject(at: position.line, with: newLine) +// range.end.column = newOffset +// range.start.column = newOffset +// case .words(_, _, _): break +// case .lines(_, _): break +// } case .expand: buffer.expand() - case .align: - switch selection { - case .none(_): break - case .words(_, _, _): break - case .lines(_, _): - let lines = buffer.lines.objects(at: selectedLines) as! [String] - if let aligned = lines.autoAlign() { - buffer.lines.replaceObjects(at: selectedLines, with: aligned) - } - - case .multiLocation(_): break - } + case .align: break +// switch selection { +// case .none(_): break +// case .words(_, _, _): break +// case .lines(_, _): +// let lines = buffer.lines.objects(at: selectedLines) as! [String] +// if let aligned = lines.autoAlign() { +// buffer.lines.replaceObjects(at: selectedLines, with: aligned) +// } +// +// } } - // completionHandler(nil) - } - + defer { + completionHandler(nil) + } + } } diff --git a/XcodeKit/SelectionType.swift b/XcodeKit/SelectionType.swift index aca02eb..3636659 100644 --- a/XcodeKit/SelectionType.swift +++ b/XcodeKit/SelectionType.swift @@ -13,15 +13,20 @@ enum SelectionType { case none(position: TextPosition) case words(line: Int, colStart: Int, colEnd: Int) case lines(start:TextPosition, end: TextPosition)//Complete line selection is counted multiline - case multiLocation([XCSourceTextRange]) +// case multiLocation([XCSourceTextRange]) - var selectedLines: IndexSet { - switch self { - case .none(let position): return IndexSet(integer: position.line) - case .words(let line, _, _): return IndexSet(integer: line) - case .lines(let start, let end): - return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) - case .multiLocation(_): fatalError() - } - } +// var selectedLines: IndexSet { +// switch self { +// case .none(let position): return IndexSet(integer: position.line) +// case .words(let line, _, _): return IndexSet(integer: line) +// case .lines(let start, let end): +// return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) +// case .multiLocation(let ranges): +// let a = IndexSet() +// for range in ranges { +// range. +// } +// ranges.map +// } +// } } diff --git a/XcodeKit/TextBuffer+Expand.swift b/XcodeKit/TextBuffer+Expand.swift index 73e3187..cfebcd7 100644 --- a/XcodeKit/TextBuffer+Expand.swift +++ b/XcodeKit/TextBuffer+Expand.swift @@ -16,7 +16,7 @@ extension TextBuffer { guard lines.count != 0 else { return } - if isSelectionEmpty, + if range.isSelectionEmpty, let newRange = rangeForWordSelection(for: .validWordChars, at: range) { range.updateSelection(range: newRange) return diff --git a/XcodeKit/TextBuffer+Selection.swift b/XcodeKit/TextBuffer+Selection.swift index 7f024e6..73ae920 100644 --- a/XcodeKit/TextBuffer+Selection.swift +++ b/XcodeKit/TextBuffer+Selection.swift @@ -10,27 +10,32 @@ import Foundation import XcodeKit extension TextBuffer { - var selectedLines: IndexSet { - return self.selectionType.selectedLines - } - var isSelectionEmpty: Bool { - let selections = self.selections as! [XCSourceTextRange] - let range = selections.first! - return range.start == range.end - } - var selectionType: SelectionType { - let selections = self.selections as! [XCSourceTextRange] - if selections.count == 1 { - let range = selections.first! - if range.start.line == range.end.line { - if range.start.column == range.end.column { - return .none(position: TextPosition(line: range.start.line, column: range.start.column)) - } - return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) - } - return .lines(start: range.start, end: range.end) - } - return .multiLocation(selections) + var selectionRanges: [TextRange] { + return selections as! [TextRange] } +// var selectedLines: IndexSet { +// return self.selectionType.selectedLines +// } + +// var isSelectionEmpty: Bool { +// let selections = self.selections as! [XCSourceTextRange] +// let range = selections.first! +// return range.start == range.end +// } + +// var selectionType: SelectionType { +// let selections = self.selections as! [XCSourceTextRange] +// if selections.count == 1 { +// let range = selections.first! +// if range.start.line == range.end.line { +// if range.start.column == range.end.column { +// return .none(position: TextPosition(line: range.start.line, column: range.start.column)) +// } +// return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) +// } +// return .lines(start: range.start, end: range.end) +// } +// return .multiLocation(selections) +// } } diff --git a/XcodeKit/TextRange.swift b/XcodeKit/TextRange.swift index 55e0eb6..60d9f34 100644 --- a/XcodeKit/TextRange.swift +++ b/XcodeKit/TextRange.swift @@ -12,6 +12,18 @@ import XcodeKit typealias TextRange = XCSourceTextRange extension TextRange { + + var selectedLines: IndexSet { + if start.line == end.line { + return IndexSet(integer: start.line) + } + return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) + } + + var isSelectionEmpty: Bool { + return start == end + } + func updateSelection(range: TextRange) { self.start = range.start self.end = range.end From 777a4f3c5289a0e53b6ea9e405af8d59b7049dad Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 18 Jun 2018 21:54:41 +0530 Subject: [PATCH 42/56] Updated expand --- Selection/SourceEditorCommand.swift | 17 ++--------------- XcodeKit/TextBuffer+Expand.swift | 8 ++++++-- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index 4d52158..c337fa0 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -19,11 +19,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { completionHandler: @escaping (Error?) -> Void ) -> Void { let buffer = invocation.buffer -// let selection = buffer.selectionType -// let selectedLines = buffer.selectedLines -// let range = buffer.selections.lastObject as! TextRange - switch Options(command: invocation.commandIdentifier)! { + case .selectLine: buffer.selectionRanges.forEach { range in if range.isSelectionEmpty { @@ -54,18 +51,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { range.start.column = newOffset } } -// switch selection { -// case .none(let position): -// let currentLine = buffer.lines[position.line] as! String -// let (newOffset, newLine) = currentLine.lineOneSpaceAt(pin: position.column) -// buffer.lines.replaceObject(at: position.line, with: newLine) -// range.end.column = newOffset -// range.start.column = newOffset -// case .words(_, _, _): break -// case .lines(_, _): break -// } - case .expand: buffer.expand() + case .expand: buffer.outerExpand() case .align: break // switch selection { diff --git a/XcodeKit/TextBuffer+Expand.swift b/XcodeKit/TextBuffer+Expand.swift index cfebcd7..4906d1e 100644 --- a/XcodeKit/TextBuffer+Expand.swift +++ b/XcodeKit/TextBuffer+Expand.swift @@ -10,9 +10,13 @@ import Foundation import XcodeKit extension TextBuffer { + func outerExpand() { + selectionRanges.forEach { range in + expand(range) + } + } - func expand() { - let range = selections.lastObject as! TextRange + func expand(_ range: TextRange) { guard lines.count != 0 else { return } From b123015bec45d70391701357632c1727873212bf Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 18 Jun 2018 22:01:38 +0530 Subject: [PATCH 43/56] align --- Selection/SourceEditorCommand.swift | 24 ++++++++++++------------ XcodeKit/SelectionType.swift | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index c337fa0..f3e16cc 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -52,20 +52,20 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } } - case .expand: buffer.outerExpand() + case .expand: + buffer.outerExpand() - case .align: break -// switch selection { -// case .none(_): break -// case .words(_, _, _): break -// case .lines(_, _): -// let lines = buffer.lines.objects(at: selectedLines) as! [String] -// if let aligned = lines.autoAlign() { -// buffer.lines.replaceObjects(at: selectedLines, with: aligned) -// } -// -// } + case .align: + buffer.selectionRanges.forEach { range in + if range.start.line != range.end.line { + let lines = buffer.lines.objects(at: range.selectedLines) as! [String] + if let aligned = lines.autoAlign() { + buffer.lines.replaceObjects(at: range.selectedLines, with: aligned) + } + } + } } + defer { completionHandler(nil) } diff --git a/XcodeKit/SelectionType.swift b/XcodeKit/SelectionType.swift index 3636659..dbd7ed8 100644 --- a/XcodeKit/SelectionType.swift +++ b/XcodeKit/SelectionType.swift @@ -9,10 +9,10 @@ import Foundation import XcodeKit -enum SelectionType { - case none(position: TextPosition) - case words(line: Int, colStart: Int, colEnd: Int) - case lines(start:TextPosition, end: TextPosition)//Complete line selection is counted multiline +//enum SelectionType { +// case none(position: TextPosition) +// case words(line: Int, colStart: Int, colEnd: Int) +// case lines(start:TextPosition, end: TextPosition)//Complete line selection is counted multiline // case multiLocation([XCSourceTextRange]) // var selectedLines: IndexSet { @@ -29,4 +29,4 @@ enum SelectionType { // ranges.map // } // } -} +//} From 6ae0e98adabcbba2fc94f12d535d1268e8fef4d7 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 18 Jun 2018 22:02:04 +0530 Subject: [PATCH 44/56] . --- Selection/SourceEditorCommand.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index f3e16cc..dd4f7a0 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -17,10 +17,10 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { + let buffer = invocation.buffer switch Options(command: invocation.commandIdentifier)! { - case .selectLine: buffer.selectionRanges.forEach { range in if range.isSelectionEmpty { From 6a4837091bf59e5070aba3640dd34882b2205b8a Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 18 Jun 2018 22:52:11 +0530 Subject: [PATCH 45/56] Updated line commands --- Line/SourceEditorCommand.swift | 213 +++++++++++++-------------------- XcodeKit/TextRange.swift | 22 +++- 2 files changed, 102 insertions(+), 133 deletions(-) diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index ed6129a..105eb8c 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -16,142 +16,104 @@ enum Options: String { class SourceEditorCommand: NSObject, XCSourceEditorCommand { - public func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Swift.Void) { -/* + public func perform(with invocation: XCSourceEditorCommandInvocation, + completionHandler: @escaping (Error?) -> Swift.Void) { let buffer = invocation.buffer -// let selection = buffer.selectionType -// let selectedLines = buffer.selectedLines switch Options(command: invocation.commandIdentifier)! { case .duplicate: - let range = buffer.selections.firstObject as! XCSourceTextRange - let copyOfLines = buffer.lines.objects(at: selectedLines) - buffer.lines.insert(copyOfLines, at: selectedLines) - - switch selection { - case .none(let position): - if position.column == 0 { - range.start.line += 1 - range.end.line += 1 + buffer.selectionRanges.forEach { range in + let end = range.end//Required for updating selection + let copyOfLines = buffer.lines.objects(at: range.selectedLines) + buffer.lines.insert(copyOfLines, at: range.selectedLines) + + switch range.selection { + case .none: + if range.start.column == 0 { + range.start.line += 1 + range.end.line += 1 + } + case .words: break + case .lines: range.start = end } - case .words(_, _, _)://TODO: - break - case .lines(_, let endPosition): range.start = endPosition - case .multiLocation(_): break } case .commentedDuplicate: - let range = buffer.selections.firstObject as! XCSourceTextRange - let copyOfLines = buffer.lines.objects(at: selectedLines) - let commentedLines = copyOfLines.map { "//" + ($0 as! String) } - buffer.lines.insert(commentedLines, at: selectedLines) - - switch selection { - case .none(let position): - if position.column == 0 { - range.start.line += 1 - range.end.line += 1 + buffer.selectionRanges.forEach { range in + let end = range.end//Required for updating selection + let copyOfLines = buffer.lines.objects(at: range.selectedLines) + let commentedLines = copyOfLines.map { "//" + ($0 as! String) } + buffer.lines.insert(commentedLines, at: range.selectedLines) + + switch range.selection { + case .none: + if range.start.column == 0 { + range.start.line += 1 + range.end.line += 1 + } + case .words: break + case .lines: range.start = end } - case .words(_, _, _)://TODO: - break - case .lines(_, let endPosition): range.start = endPosition - case .multiLocation(_): break } case .openNewLineBelow: - switch selection { - case .none(let position): - let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset - let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() - buffer.lines.insert(offsetWhiteSpaces, at: position.line + 1) - //Selection - let position = TextPosition(line: position.line + 1, column: indentationOffset) - let lineSelection = XCSourceTextRange(start: position, end: position) - buffer.selections.setArray([lineSelection]) - - case .words(let line, _, _): - - let indentationOffset = (buffer.lines[line] as! String).indentationOffset - let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() - buffer.lines.insert(offsetWhiteSpaces, at: line + 1) - //Selection - let position = TextPosition(line: line + 1, column: indentationOffset) - let lineSelection = XCSourceTextRange(start: position, end: position) - buffer.selections.setArray([lineSelection]) - - case .lines(_, _): break - case .multiLocation(_): break + buffer.selectionRanges.forEach { range in + if range.isSelectionEmpty { + let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset + let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() + buffer.lines.insert(offsetWhiteSpaces, at: range.start.line + 1) + //Selection + let position = TextPosition(line: range.start.line + 1, column: indentationOffset) + let lineSelection = XCSourceTextRange(start: position, end: position) + buffer.selections.setArray([lineSelection]) + } } case .openNewLineAbove: - switch selection { - case .none(let position): - let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset - let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() - buffer.lines.insert(offsetWhiteSpaces, at: position.line) - //Selection - let position = TextPosition(line: position.line, column: indentationOffset) - let lineSelection = XCSourceTextRange(start: position, end: position) - buffer.selections.setArray([lineSelection]) - - case .words(let line, _, _): - let indentationOffset = (buffer.lines[line] as! String).indentationOffset - let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() - buffer.lines.insert(offsetWhiteSpaces, at: line) - //Selection - let position = TextPosition(line: line, column: indentationOffset) - let lineSelection = XCSourceTextRange(start: position, end: position) - buffer.selections.setArray([lineSelection]) - - case .lines(_, _): break - case .multiLocation(_): break + buffer.selectionRanges.forEach { range in + if range.isSelectionEmpty { + let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset + let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() + buffer.lines.insert(offsetWhiteSpaces, at: range.start.line) + //Selection + let position = TextPosition(line: range.start.line, column: indentationOffset) + let lineSelection = XCSourceTextRange(start: position, end: position) + buffer.selections.setArray([lineSelection]) + } } case .deleteLine: - switch selection { - case .none(let position): - buffer.lines.removeObject(at: position.line) + buffer.selectionRanges.forEach { range in + switch range.selection { + case .none, .words: + buffer.lines.removeObject(at: range.start.line) - case .words(let line, _, _): - buffer.lines.removeObject(at: line) + case .lines: break - case .lines(_, _): break - case .multiLocation(_): break + } } case .join: - switch selection { - case .none(let position): - if position.line == buffer.lines.count { return } + buffer.selectionRanges.forEach { range in - let firstLine = (buffer.lines[position.line] as! String).trimmingCharacters(in: .newlines) - let newLine = (buffer.lines[position.line + 1] as! String).trimmingCharacters(in: .whitespaces) - - buffer.lines.replaceObject(at: position.line, with: "\(firstLine) \(newLine)") - buffer.lines.removeObject(at: position.line + 1) - - //Selection/CaretPosition - let range = buffer.selections.lastObject as! XCSourceTextRange - range.start.column = firstLine.count + 1 - range.end.column = firstLine.count + 1 + switch range.selection { + case .none: + if range.start.line == buffer.lines.count { return } - case .words(let line, _, _): - if line == buffer.lines.count { return } + let firstLine = (buffer.lines[range.start.line] as! String).trimmingCharacters(in: .newlines) + let newLine = (buffer.lines[range.start.line + 1] as! String).trimmingCharacters(in: .whitespaces) - let firstLine = (buffer.lines[line] as! String).trimmingCharacters(in: .newlines) - let newLine = (buffer.lines[line + 1] as! String).trimmingCharacters(in: .whitespaces) - - buffer.lines.replaceObject(at: line, with: "\(firstLine) \(newLine)") - buffer.lines.removeObject(at: line + 1) + buffer.lines.replaceObject(at: range.start.line, with: "\(firstLine) \(newLine)") + buffer.lines.removeObject(at: range.start.line + 1) //Selection/CaretPosition - let range = buffer.selections.lastObject as! XCSourceTextRange range.start.column = firstLine.count + 1 range.end.column = firstLine.count + 1 - case .lines(_, _): - let range = buffer.selections.firstObject as! XCSourceTextRange - let lines = buffer.lines.objects(at: selectedLines) as! [String] + case .words: break + + case .lines: + let lines = buffer.lines.objects(at: range.selectedLines) as! [String] var joinedLine = "" for (i, line) in lines.enumerated() { @@ -161,40 +123,33 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { joinedLine += " " + line.trimmedStart.trimmingCharacters(in: .newlines) } } - buffer.lines.removeObjects(at: selectedLines) + buffer.lines.removeObjects(at: range.selectedLines) buffer.lines.insert(joinedLine, at: range.start.line) //Selection/CaretPosition range.end.line = range.start.line range.end.column = joinedLine.count - case .multiLocation(_): break - } + }//switch range.selection + }//for each range case .lineBeginning: - switch selection { - case .none(let position): - let range = buffer.selections.lastObject as! XCSourceTextRange - let indentationOffset = (buffer.lines[position.line] as! String).indentationOffset - if range.start.column == indentationOffset { - range.start.column = 0; range.end.column = 0; - } else { - range.start.column = indentationOffset; range.end.column = indentationOffset; - } - - case .words(let line, _, _): - let range = buffer.selections.lastObject as! XCSourceTextRange - let indentationOffset = (buffer.lines[line] as! String).indentationOffset - if range.start.column == indentationOffset { - range.start.column = 0; range.end.column = 0; - } else { - range.start.column = indentationOffset; range.end.column = indentationOffset; + buffer.selectionRanges.forEach { range in + switch range.selection { + case .none: + let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset + if range.start.column == indentationOffset { + range.start.column = 0; range.end.column = 0; + } else { + range.start.column = indentationOffset; range.end.column = indentationOffset; + } + case .words, .lines: break } - case .lines(_, _): break - case .multiLocation(_): break } } - */ - completionHandler(nil) + + defer { + completionHandler(nil) + } } } diff --git a/XcodeKit/TextRange.swift b/XcodeKit/TextRange.swift index 60d9f34..33cd912 100644 --- a/XcodeKit/TextRange.swift +++ b/XcodeKit/TextRange.swift @@ -13,15 +13,29 @@ typealias TextRange = XCSourceTextRange extension TextRange { + enum Selection { + //Complete line selection is counted multiline + case none, words, lines + } + var selectedLines: IndexSet { - if start.line == end.line { - return IndexSet(integer: start.line) + switch selection { + case .none, .words: return IndexSet(integer: start.line) + case .lines: return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) + } + } + + var selection: Selection { + if start == end { + return .none + } else if start.line == end.line { + return .words } - return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) + return .lines } var isSelectionEmpty: Bool { - return start == end + return selection == .none } func updateSelection(range: TextRange) { From 44e70dacbc03fe1424de5daed515446ac4f085bb Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Mon, 18 Jun 2018 23:21:29 +0530 Subject: [PATCH 46/56] Added line join --- Line/Array+Join.swift | 22 ++++++++++++++++++++++ Line/SourceEditorCommand.swift | 10 ++-------- Linex.xcodeproj/project.pbxproj | 6 ++++++ LinexTests/LinexTests.swift | 6 ++++++ 4 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 Line/Array+Join.swift diff --git a/Line/Array+Join.swift b/Line/Array+Join.swift new file mode 100644 index 0000000..dd3e59b --- /dev/null +++ b/Line/Array+Join.swift @@ -0,0 +1,22 @@ +// +// Array+Join.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 18/06/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation + +extension Array where Element == String { + var lineJoined: String { + guard self.count > 1 else { return self.first! } + + let offset = String(repeating: " ", count: self.first!.indentationOffset) + return + offset + + self + .map { $0.trimmingCharacters(in: .whitespacesAndNewlines)} + .joined(separator: " ") + } +} diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 105eb8c..666163d 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -115,14 +115,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .lines: let lines = buffer.lines.objects(at: range.selectedLines) as! [String] - var joinedLine = "" - for (i, line) in lines.enumerated() { - if i == 0 { - joinedLine += line.trimmingCharacters(in: .newlines) - } else { - joinedLine += " " + line.trimmedStart.trimmingCharacters(in: .newlines) - } - } + var joinedLine = lines.lineJoined + buffer.lines.removeObjects(at: range.selectedLines) buffer.lines.insert(joinedLine, at: range.start.line) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index dd74e90..cade1ce 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -63,6 +63,8 @@ E39E22801F59C59100354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; E39E22811F59C59200354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; + E3A56CCA20D8236E00A44165 /* Array+Join.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CC920D8236E00A44165 /* Array+Join.swift */; }; + E3A56CCB20D8236E00A44165 /* Array+Join.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CC920D8236E00A44165 /* Array+Join.swift */; }; E3F543941F5A84FC008F426E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F543981F5A84FC008F426E /* SourceEditorExtension.swift */; }; E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F5439A1F5A84FC008F426E /* SourceEditorCommand.swift */; }; @@ -157,6 +159,7 @@ E39E22741F59876A00354A5F /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; E39E22761F59876A00354A5F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E39E227E1F59C58E00354A5F /* RawRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawRepresentable.swift; sourceTree = ""; }; + E3A56CC920D8236E00A44165 /* Array+Join.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Join.swift"; sourceTree = ""; }; E3F543931F5A84FC008F426E /* Convert.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Convert.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E3F543971F5A84FC008F426E /* Convert.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Convert.entitlements; sourceTree = ""; }; E3F543981F5A84FC008F426E /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -299,6 +302,7 @@ children = ( E35942421F55565E009EFA35 /* SourceEditorExtension.swift */, E35942441F55565E009EFA35 /* SourceEditorCommand.swift */, + E3A56CC920D8236E00A44165 /* Array+Join.swift */, E35942461F55565E009EFA35 /* Info.plist */, E35942401F55565E009EFA35 /* Supporting Files */, ); @@ -564,6 +568,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E3A56CCA20D8236E00A44165 /* Array+Join.swift in Sources */, E3938E3E209DF626007F69E3 /* Character+Linex.swift in Sources */, E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, @@ -588,6 +593,7 @@ E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, + E3A56CCB20D8236E00A44165 /* Array+Join.swift in Sources */, E35783C520B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, diff --git a/LinexTests/LinexTests.swift b/LinexTests/LinexTests.swift index 52c0a21..afa5cc6 100644 --- a/LinexTests/LinexTests.swift +++ b/LinexTests/LinexTests.swift @@ -11,6 +11,12 @@ import XCTest class LinexTests: XCTestCase { + func testLineJoined() { + let arr = [" Kaunteya\n", " Suryawanshi\n"] + XCTAssertEqual(arr.lineJoined, " Kaunteya Suryawanshi", arr.lineJoined) + + } + func testLineIndentatinOffset() { XCTAssertEqual("".indentationOffset, 0) // 123456 From 53526af1e164f6389010333d0f1adea971b6e948 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Tue, 19 Jun 2018 09:33:08 +0530 Subject: [PATCH 47/56] Changes --- Line/Array+Join.swift | 14 +++---- Line/SourceEditorCommand.swift | 48 +++++++++++---------- Linex.xcodeproj/project.pbxproj | 18 ++++---- Selection/SourceEditorCommand.swift | 3 +- Standard Extensions/Line.swift | 58 ++++++++++++++++++++++++++ Standard Extensions/String+Basic.swift | 12 ------ XcodeKit/TextBuffer+Basic.swift | 34 +++++++++++++-- XcodeKit/TextBuffer+Selection.swift | 41 ------------------ XcodeKit/TextRange.swift | 10 +++-- 9 files changed, 139 insertions(+), 99 deletions(-) create mode 100644 Standard Extensions/Line.swift delete mode 100644 XcodeKit/TextBuffer+Selection.swift diff --git a/Line/Array+Join.swift b/Line/Array+Join.swift index dd3e59b..5cec79e 100644 --- a/Line/Array+Join.swift +++ b/Line/Array+Join.swift @@ -8,15 +8,13 @@ import Foundation -extension Array where Element == String { - var lineJoined: String { +extension Array where Element == Line { + func joined(separator: String, trimming: CharacterSet) -> Line { guard self.count > 1 else { return self.first! } + let joinedString = self + .map { $0.stringValue.trimmingCharacters(in: trimming)} + .joined(separator: separator) - let offset = String(repeating: " ", count: self.first!.indentationOffset) - return - offset + - self - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines)} - .joined(separator: " ") + return Line(joinedString) } } diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 666163d..739505e 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -28,8 +28,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { buffer.lines.insert(copyOfLines, at: range.selectedLines) switch range.selection { - case .none: - if range.start.column == 0 { + case .none(_, let column): + if column == 0 { range.start.line += 1 range.end.line += 1 } @@ -46,8 +46,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { buffer.lines.insert(commentedLines, at: range.selectedLines) switch range.selection { - case .none: - if range.start.column == 0 { + case .none(_, let column): + if column == 0 { range.start.line += 1 range.end.line += 1 } @@ -59,8 +59,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .openNewLineBelow: buffer.selectionRanges.forEach { range in if range.isSelectionEmpty { - let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset - let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() + let indentationOffset = buffer[range.start.line].indentationOffset + let offsetWhiteSpaces = String(repeating: " ", count: indentationOffset) buffer.lines.insert(offsetWhiteSpaces, at: range.start.line + 1) //Selection let position = TextPosition(line: range.start.line + 1, column: indentationOffset) @@ -72,8 +72,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .openNewLineAbove: buffer.selectionRanges.forEach { range in if range.isSelectionEmpty { - let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset - let offsetWhiteSpaces = Array(repeating: " ", count: indentationOffset).joined() + let indentationOffset = buffer[range.start.line].indentationOffset + let offsetWhiteSpaces = String(repeating: " ", count: indentationOffset) buffer.lines.insert(offsetWhiteSpaces, at: range.start.line) //Selection let position = TextPosition(line: range.start.line, column: indentationOffset) @@ -97,25 +97,29 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { buffer.selectionRanges.forEach { range in switch range.selection { - case .none: - if range.start.line == buffer.lines.count { return } + case .none(let line, _): + if line == buffer.lines.count { return } - let firstLine = (buffer.lines[range.start.line] as! String).trimmingCharacters(in: .newlines) - let newLine = (buffer.lines[range.start.line + 1] as! String).trimmingCharacters(in: .whitespaces) + let caretOffset = buffer[line].count + 1 + let lineIndexSet = IndexSet(arrayLiteral: line, line + 1) + let lines = buffer[lineIndexSet] - buffer.lines.replaceObject(at: range.start.line, with: "\(firstLine) \(newLine)") - buffer.lines.removeObject(at: range.start.line + 1) + var joinedLine = lines.joined(separator: " ", trimming: .whitespacesAndNewlines) + joinedLine.indent(by: lines.first!.indentationOffset) + + buffer.lines.replaceObject(at: line, with: joinedLine) + buffer.lines.removeObject(at: line + 1) //Selection/CaretPosition - range.start.column = firstLine.count + 1 - range.end.column = firstLine.count + 1 + range.start.column = caretOffset + range.end.column = caretOffset case .words: break case .lines: - let lines = buffer.lines.objects(at: range.selectedLines) as! [String] - - var joinedLine = lines.lineJoined + let lines = buffer[range.selectedLines] + var joinedLine = lines.joined(separator: " ", trimming: .whitespacesAndNewlines) + joinedLine.indent(by: lines.first!.indentationOffset) buffer.lines.removeObjects(at: range.selectedLines) buffer.lines.insert(joinedLine, at: range.start.line) @@ -130,9 +134,9 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .lineBeginning: buffer.selectionRanges.forEach { range in switch range.selection { - case .none: - let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset - if range.start.column == indentationOffset { + case .none(let line, let column): + let indentationOffset = buffer[line].indentationOffset + if column == indentationOffset { range.start.column = 0; range.end.column = 0; } else { range.start.column = indentationOffset; range.end.column = indentationOffset; diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index cade1ce..145a73b 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -20,9 +20,6 @@ E35783C120B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; E35783C220B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; E35783C320B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */; }; - E35783C520B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */; }; - E35783C620B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */; }; - E35783C720B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */; }; E359421B1F55564C009EFA35 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421A1F55564C009EFA35 /* AppDelegate.swift */; }; E359421D1F55564C009EFA35 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E359421C1F55564C009EFA35 /* ViewController.swift */; }; E359421F1F55564C009EFA35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E359421E1F55564C009EFA35 /* Assets.xcassets */; }; @@ -65,6 +62,10 @@ E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; E3A56CCA20D8236E00A44165 /* Array+Join.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CC920D8236E00A44165 /* Array+Join.swift */; }; E3A56CCB20D8236E00A44165 /* Array+Join.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CC920D8236E00A44165 /* Array+Join.swift */; }; + E3A56CCD20D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; + E3A56CCE20D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; + E3A56CCF20D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; + E3A56CD020D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; E3F543941F5A84FC008F426E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E3F543991F5A84FC008F426E /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F543981F5A84FC008F426E /* SourceEditorExtension.swift */; }; E3F5439B1F5A84FC008F426E /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F5439A1F5A84FC008F426E /* SourceEditorCommand.swift */; }; @@ -128,7 +129,6 @@ E330C82F1F796DF000ECC222 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; E356FD811F66F55C004558F1 /* TestPad.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestPad.swift; sourceTree = ""; }; E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Basic.swift"; sourceTree = ""; }; - E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Selection.swift"; sourceTree = ""; }; E35942171F55564C009EFA35 /* Linex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Linex.app; sourceTree = BUILT_PRODUCTS_DIR; }; E359421A1F55564C009EFA35 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E359421C1F55564C009EFA35 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -160,6 +160,7 @@ E39E22761F59876A00354A5F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E39E227E1F59C58E00354A5F /* RawRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawRepresentable.swift; sourceTree = ""; }; E3A56CC920D8236E00A44165 /* Array+Join.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Join.swift"; sourceTree = ""; }; + E3A56CCC20D82AD400A44165 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; E3F543931F5A84FC008F426E /* Convert.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Convert.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E3F543971F5A84FC008F426E /* Convert.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Convert.entitlements; sourceTree = ""; }; E3F543981F5A84FC008F426E /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -213,6 +214,7 @@ isa = PBXGroup; children = ( E39E227E1F59C58E00354A5F /* RawRepresentable.swift */, + E3A56CCC20D82AD400A44165 /* Line.swift */, E3938E4A209DF834007F69E3 /* String+Basic.swift */, E3938E39209DF605007F69E3 /* Character+Linex.swift */, E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */, @@ -226,7 +228,6 @@ E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, E306510A20B0388C006B0BBF /* TextRange.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, - E35783C420B73C7700D845A7 /* TextBuffer+Selection.swift */, E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */, E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */, E3938E3F209DF64F007F69E3 /* TextPosition.swift */, @@ -577,6 +578,7 @@ E37DDA7D2099E65900D86394 /* SelectionTests.swift in Sources */, E3938E4B209DF834007F69E3 /* String+Basic.swift in Sources */, E35783BE20B73B5A00D845A7 /* CharacterSet+Linex.swift in Sources */, + E3A56CCD20D82AD400A44165 /* Line.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -594,9 +596,9 @@ E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E3A56CCB20D8236E00A44165 /* Array+Join.swift in Sources */, - E35783C520B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, + E3A56CCE20D82AD400A44165 /* Line.swift in Sources */, E35942451F55565E009EFA35 /* SourceEditorCommand.swift in Sources */, E3938E36209DEC32007F69E3 /* String+Linex.swift in Sources */, ); @@ -615,10 +617,10 @@ E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, E306510820AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, - E35783C620B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, E359BCF61F604E000071246B /* Alignment.swift in Sources */, E3938E37209DEC33007F69E3 /* String+Linex.swift in Sources */, E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, + E3A56CCF20D82AD400A44165 /* Line.swift in Sources */, E306510C20B0388C006B0BBF /* TextRange.swift in Sources */, E35783C220B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */, ); @@ -637,7 +639,7 @@ E306510920AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510D20B0388C006B0BBF /* TextRange.swift in Sources */, E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, - E35783C720B73C7700D845A7 /* TextBuffer+Selection.swift in Sources */, + E3A56CD020D82AD400A44165 /* Line.swift in Sources */, E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Linex.swift in Sources */, E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */, diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index dd4f7a0..cac0dcb 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -24,7 +24,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .selectLine: buffer.selectionRanges.forEach { range in if range.isSelectionEmpty { - let indentationOffset = (buffer.lines[range.start.line] as! String).indentationOffset + + let indentationOffset = buffer[range.start.line].indentationOffset range.start.column = indentationOffset range.end.column = (buffer.lines[range.start.line] as! String).count - 1 } else { diff --git a/Standard Extensions/Line.swift b/Standard Extensions/Line.swift new file mode 100644 index 0000000..8a8b2a4 --- /dev/null +++ b/Standard Extensions/Line.swift @@ -0,0 +1,58 @@ +// +// Line.swift +// Linex +// +// Created by Kaunteya Suryawanshi on 18/06/18. +// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. +// + +import Foundation + +struct Line { + var stringValue: String + + init(_ stringValue: String) { + self.stringValue = stringValue + } + + var indentationOffset: Int { + //TODO: Replace with firstIndex { where } in Swift 4.2 + var i = 0 + for a in stringValue { + if a == " " { + i += 1 + } else { break } + } + return i + } + + mutating func indent(by offset: Int) { + let offsetString = String(repeating: " ", count: offset) + stringValue = offsetString + stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + } +} + +extension Line: Collection { + typealias Index = String.Index + typealias Element = String.Element + + subscript(position: String.Index) -> Element { + return stringValue[position] + } + + subscript (position: Int) -> Element { + let index = self.index(self.startIndex, offsetBy: position) + return self[index] + } + + func index(after i: String.Index) -> Index { + return stringValue.index(after: i) + } + + var startIndex: Line.Index { + return stringValue.startIndex + } + var endIndex: Line.Index { + return stringValue.endIndex + } +} diff --git a/Standard Extensions/String+Basic.swift b/Standard Extensions/String+Basic.swift index 185ebeb..fec4e80 100644 --- a/Standard Extensions/String+Basic.swift +++ b/Standard Extensions/String+Basic.swift @@ -44,18 +44,6 @@ extension String { self.replaceSubrange(self.index(at: range.lowerBound).. 4 - var indentationOffset: Int { - var i = 0 - for a in self { - if a == " " { - i += 1 - } else { break } - } - return i - } - var trimmedStart: String { return self.replacingOccurrences(of: "^[ \t]+", with: "", options: .regularExpression) } diff --git a/XcodeKit/TextBuffer+Basic.swift b/XcodeKit/TextBuffer+Basic.swift index 9be1e43..4bb5d01 100644 --- a/XcodeKit/TextBuffer+Basic.swift +++ b/XcodeKit/TextBuffer+Basic.swift @@ -12,9 +12,24 @@ import XcodeKit typealias TextBuffer = XCSourceTextBuffer extension TextBuffer { + + subscript (offset: Int) -> Line { + return Line(lines[offset] as! String) + } + + subscript (indexSet: IndexSet) -> [Line] { + return indexSet.map { self[$0] } + } + + var selectionRanges: [TextRange] { + return selections as! [TextRange] + } + var lastPosition: TextPosition { - let lastLine = self.lines[self.lines.count - 1] as! String - return TextPosition(line: self.lines.count - 1, column: lastLine.count - 1) + let lastLineIndex = self.lines.count - 1 + let lastLine = self[lastLineIndex] + + return TextPosition(line: lastLineIndex, column: lastLine.count - 1) } func isStart(postion: TextPosition) -> Bool { @@ -26,7 +41,18 @@ extension TextBuffer { } func char(at position: TextPosition) -> Character { - let currentLine = self.lines[position.line] as! String - return currentLine[position.column] as Character + let currentLine = self[position.line] + return currentLine[position.column] } } + + + + + + + + + + + diff --git a/XcodeKit/TextBuffer+Selection.swift b/XcodeKit/TextBuffer+Selection.swift deleted file mode 100644 index 73ae920..0000000 --- a/XcodeKit/TextBuffer+Selection.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// TextBuffer+Selection.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 25/05/18. -// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation -import XcodeKit - -extension TextBuffer { - var selectionRanges: [TextRange] { - return selections as! [TextRange] - } -// var selectedLines: IndexSet { -// return self.selectionType.selectedLines -// } - -// var isSelectionEmpty: Bool { -// let selections = self.selections as! [XCSourceTextRange] -// let range = selections.first! -// return range.start == range.end -// } - -// var selectionType: SelectionType { -// let selections = self.selections as! [XCSourceTextRange] -// if selections.count == 1 { -// let range = selections.first! -// if range.start.line == range.end.line { -// if range.start.column == range.end.column { -// return .none(position: TextPosition(line: range.start.line, column: range.start.column)) -// } -// return .words(line: range.start.line, colStart: range.start.column, colEnd: range.end.column) -// } -// return .lines(start: range.start, end: range.end) -// } -// return .multiLocation(selections) -// } -} - diff --git a/XcodeKit/TextRange.swift b/XcodeKit/TextRange.swift index 33cd912..ffa59e5 100644 --- a/XcodeKit/TextRange.swift +++ b/XcodeKit/TextRange.swift @@ -15,7 +15,8 @@ extension TextRange { enum Selection { //Complete line selection is counted multiline - case none, words, lines + case none(line: Int, column: Int) + case words, lines } var selectedLines: IndexSet { @@ -27,7 +28,7 @@ extension TextRange { var selection: Selection { if start == end { - return .none + return .none(line: start.line, column: start.column) } else if start.line == end.line { return .words } @@ -35,7 +36,10 @@ extension TextRange { } var isSelectionEmpty: Bool { - return selection == .none + if case Selection.none(_, _) = selection { + return true + } + return false } func updateSelection(range: TextRange) { From 48e440f0fe63f5b0b5df3069e08c9ed634a37dcc Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Tue, 19 Jun 2018 13:42:53 +0530 Subject: [PATCH 48/56] Cleanup --- Line/SourceEditorCommand.swift | 4 ++-- Linex.xcodeproj/project.pbxproj | 10 +-------- Selection/SourceEditorCommand.swift | 1 - XcodeKit/SelectionType.swift | 32 ----------------------------- XcodeKit/TextRange.swift | 9 +++++--- 5 files changed, 9 insertions(+), 47 deletions(-) delete mode 100644 XcodeKit/SelectionType.swift diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 739505e..8ea7886 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -128,8 +128,8 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { range.end.line = range.start.line range.end.column = joinedLine.count - }//switch range.selection - }//for each range + } + } case .lineBeginning: buffer.selectionRanges.forEach { range in diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 145a73b..3f9262b 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -50,9 +50,6 @@ E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; E3938E4E209DF834007F69E3 /* String+Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4A209DF834007F69E3 /* String+Basic.swift */; }; - E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; - E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; - E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3938E4F209DF8B0007F69E3 /* SelectionType.swift */; }; E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E359423D1F55565E009EFA35 /* Cocoa.framework */; }; E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22721F59876A00354A5F /* SourceEditorExtension.swift */; }; E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E22741F59876A00354A5F /* SourceEditorCommand.swift */; }; @@ -152,7 +149,6 @@ E3938E3F209DF64F007F69E3 /* TextPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextPosition.swift; sourceTree = ""; }; E3938E45209DF772007F69E3 /* TextBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBuffer.swift; sourceTree = ""; }; E3938E4A209DF834007F69E3 /* String+Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Basic.swift"; sourceTree = ""; }; - E3938E4F209DF8B0007F69E3 /* SelectionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionType.swift; sourceTree = ""; }; E39E226D1F59876A00354A5F /* Selection.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Selection.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E39E22711F59876A00354A5F /* Selection.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Selection.entitlements; sourceTree = ""; }; E39E22721F59876A00354A5F /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; @@ -225,12 +221,11 @@ E35783BF20B73B9A00D845A7 /* XcodeKit */ = { isa = PBXGroup; children = ( - E3938E4F209DF8B0007F69E3 /* SelectionType.swift */, + E3938E3F209DF64F007F69E3 /* TextPosition.swift */, E306510A20B0388C006B0BBF /* TextRange.swift */, E3938E45209DF772007F69E3 /* TextBuffer.swift */, E35783C020B73BF700D845A7 /* TextBuffer+Basic.swift */, E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */, - E3938E3F209DF64F007F69E3 /* TextPosition.swift */, ); path = XcodeKit; sourceTree = ""; @@ -589,7 +584,6 @@ E3938E3B209DF622007F69E3 /* Character+Linex.swift in Sources */, E35942431F55565E009EFA35 /* SourceEditorExtension.swift in Sources */, E39E22801F59C59100354A5F /* RawRepresentable.swift in Sources */, - E3938E51209DF8B0007F69E3 /* SelectionType.swift in Sources */, E35783C120B73BF700D845A7 /* TextBuffer+Basic.swift in Sources */, E3938E47209DF772007F69E3 /* TextBuffer.swift in Sources */, E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, @@ -612,7 +606,6 @@ E39E22811F59C59200354A5F /* RawRepresentable.swift in Sources */, E39E22731F59876A00354A5F /* SourceEditorExtension.swift in Sources */, E39E22751F59876A00354A5F /* SourceEditorCommand.swift in Sources */, - E3938E52209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E48209DF772007F69E3 /* TextBuffer.swift in Sources */, E3938E42209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4D209DF834007F69E3 /* String+Basic.swift in Sources */, @@ -640,7 +633,6 @@ E306510D20B0388C006B0BBF /* TextRange.swift in Sources */, E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, E3A56CD020D82AD400A44165 /* Line.swift in Sources */, - E3938E53209DF8B0007F69E3 /* SelectionType.swift in Sources */, E3938E38209DEC34007F69E3 /* String+Linex.swift in Sources */, E3938E43209DF666007F69E3 /* TextPosition.swift in Sources */, E3938E4E209DF834007F69E3 /* String+Basic.swift in Sources */, diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index cac0dcb..b7d8121 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -24,7 +24,6 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .selectLine: buffer.selectionRanges.forEach { range in if range.isSelectionEmpty { - let indentationOffset = buffer[range.start.line].indentationOffset range.start.column = indentationOffset range.end.column = (buffer.lines[range.start.line] as! String).count - 1 diff --git a/XcodeKit/SelectionType.swift b/XcodeKit/SelectionType.swift deleted file mode 100644 index dbd7ed8..0000000 --- a/XcodeKit/SelectionType.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// SelectionType.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 05/05/18. -// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation -import XcodeKit - -//enum SelectionType { -// case none(position: TextPosition) -// case words(line: Int, colStart: Int, colEnd: Int) -// case lines(start:TextPosition, end: TextPosition)//Complete line selection is counted multiline -// case multiLocation([XCSourceTextRange]) - -// var selectedLines: IndexSet { -// switch self { -// case .none(let position): return IndexSet(integer: position.line) -// case .words(let line, _, _): return IndexSet(integer: line) -// case .lines(let start, let end): -// return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) -// case .multiLocation(let ranges): -// let a = IndexSet() -// for range in ranges { -// range. -// } -// ranges.map -// } -// } -//} diff --git a/XcodeKit/TextRange.swift b/XcodeKit/TextRange.swift index ffa59e5..1e4504b 100644 --- a/XcodeKit/TextRange.swift +++ b/XcodeKit/TextRange.swift @@ -14,15 +14,18 @@ typealias TextRange = XCSourceTextRange extension TextRange { enum Selection { - //Complete line selection is counted multiline case none(line: Int, column: Int) case words, lines } var selectedLines: IndexSet { switch selection { - case .none, .words: return IndexSet(integer: start.line) - case .lines: return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) + case .none, .words: + return IndexSet(integer: start.line) + + //Complete line selection is counted multiline + case .lines: + return IndexSet(integersIn: start.line...(end.column == 0 ? end.line - 1 : end.line)) } } From da56f3ca4aceb0dfe7c179aaf29ca0c1c3e5a1be Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 14 Jul 2018 19:07:15 +0530 Subject: [PATCH 49/56] Minor changes --- Convert/SourceEditorCommand.swift | 23 +++++++++++++++++++---- Line/Array+Join.swift | 20 -------------------- Line/SourceEditorCommand.swift | 6 ++++-- Linex.xcodeproj/project.pbxproj | 6 ------ LinexTests/LinexTests.swift | 14 ++++++++------ Standard Extensions/Line.swift | 24 ++++++++++++++++++++---- XcodeKit/TextBuffer+Basic.swift | 16 +++------------- 7 files changed, 54 insertions(+), 55 deletions(-) delete mode 100644 Line/Array+Join.swift diff --git a/Convert/SourceEditorCommand.swift b/Convert/SourceEditorCommand.swift index 90f108e..b16d2ec 100644 --- a/Convert/SourceEditorCommand.swift +++ b/Convert/SourceEditorCommand.swift @@ -17,11 +17,26 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { -// let buffer = invocation.buffer -// let selection = buffer.selectionType -// let range = buffer.selections.firstObject as! XCSourceTextRange + let buffer = invocation.buffer + + let command = Options(command: invocation.commandIdentifier)! + buffer.selectionRanges.forEach { range in + switch range.selection { + + case .none(let line, let column): + let currentLine = buffer[line] + let currentChar = currentLine[column] + if currentChar.presentIn(.decimalDigits), var num = Int(String(currentChar)) { + switch command { + case .increment: num += 1 + case .decrement: num -= 1//currentLine.replaceSubrange(currentRange, with: "\(num - 1)") + } + } + + default: break + } + } -// if let command = Options(command: invocation.commandIdentifier) { /* switch selection { case .none(let position): diff --git a/Line/Array+Join.swift b/Line/Array+Join.swift deleted file mode 100644 index 5cec79e..0000000 --- a/Line/Array+Join.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Array+Join.swift -// Linex -// -// Created by Kaunteya Suryawanshi on 18/06/18. -// Copyright © 2018 Kaunteya Suryawanshi. All rights reserved. -// - -import Foundation - -extension Array where Element == Line { - func joined(separator: String, trimming: CharacterSet) -> Line { - guard self.count > 1 else { return self.first! } - let joinedString = self - .map { $0.stringValue.trimmingCharacters(in: trimming)} - .joined(separator: separator) - - return Line(joinedString) - } -} diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index 8ea7886..e9d7582 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -137,9 +137,11 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { case .none(let line, let column): let indentationOffset = buffer[line].indentationOffset if column == indentationOffset { - range.start.column = 0; range.end.column = 0; + range.start.column = 0; + range.end.column = 0; } else { - range.start.column = indentationOffset; range.end.column = indentationOffset; + range.start.column = indentationOffset; + range.end.column = indentationOffset; } case .words, .lines: break } diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 3f9262b..c98329a 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -57,8 +57,6 @@ E39E22801F59C59100354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; E39E22811F59C59200354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39E227E1F59C58E00354A5F /* RawRepresentable.swift */; }; - E3A56CCA20D8236E00A44165 /* Array+Join.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CC920D8236E00A44165 /* Array+Join.swift */; }; - E3A56CCB20D8236E00A44165 /* Array+Join.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CC920D8236E00A44165 /* Array+Join.swift */; }; E3A56CCD20D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; E3A56CCE20D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; E3A56CCF20D82AD400A44165 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A56CCC20D82AD400A44165 /* Line.swift */; }; @@ -155,7 +153,6 @@ E39E22741F59876A00354A5F /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; E39E22761F59876A00354A5F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E39E227E1F59C58E00354A5F /* RawRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawRepresentable.swift; sourceTree = ""; }; - E3A56CC920D8236E00A44165 /* Array+Join.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Join.swift"; sourceTree = ""; }; E3A56CCC20D82AD400A44165 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; E3F543931F5A84FC008F426E /* Convert.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Convert.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E3F543971F5A84FC008F426E /* Convert.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Convert.entitlements; sourceTree = ""; }; @@ -298,7 +295,6 @@ children = ( E35942421F55565E009EFA35 /* SourceEditorExtension.swift */, E35942441F55565E009EFA35 /* SourceEditorCommand.swift */, - E3A56CC920D8236E00A44165 /* Array+Join.swift */, E35942461F55565E009EFA35 /* Info.plist */, E35942401F55565E009EFA35 /* Supporting Files */, ); @@ -564,7 +560,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E3A56CCA20D8236E00A44165 /* Array+Join.swift in Sources */, E3938E3E209DF626007F69E3 /* Character+Linex.swift in Sources */, E39E22821F59C59300354A5F /* RawRepresentable.swift in Sources */, E359422D1F55564D009EFA35 /* LinexTests.swift in Sources */, @@ -589,7 +584,6 @@ E306510720AEEC48006B0BBF /* TextBuffer+Expand.swift in Sources */, E306510B20B0388C006B0BBF /* TextRange.swift in Sources */, E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */, - E3A56CCB20D8236E00A44165 /* Array+Join.swift in Sources */, E3938E41209DF665007F69E3 /* TextPosition.swift in Sources */, E3938E4C209DF834007F69E3 /* String+Basic.swift in Sources */, E3A56CCE20D82AD400A44165 /* Line.swift in Sources */, diff --git a/LinexTests/LinexTests.swift b/LinexTests/LinexTests.swift index afa5cc6..d3325ba 100644 --- a/LinexTests/LinexTests.swift +++ b/LinexTests/LinexTests.swift @@ -12,16 +12,18 @@ import XCTest class LinexTests: XCTestCase { func testLineJoined() { - let arr = [" Kaunteya\n", " Suryawanshi\n"] - XCTAssertEqual(arr.lineJoined, " Kaunteya Suryawanshi", arr.lineJoined) - + let arr = [Line(" Kaunteya\n"), Line(" Suryawanshi\n")] + XCTAssertEqual( + arr.joined(separator: " ", trimming: .whitespacesAndNewlines), + Line("Kaunteya Suryawanshi") + ) } func testLineIndentatinOffset() { - XCTAssertEqual("".indentationOffset, 0) + XCTAssertEqual(Line("").indentationOffset, 0) // 123456 - XCTAssertEqual(" ".indentationOffset, 6) - XCTAssertEqual(" ABC".indentationOffset, 6) + XCTAssertEqual(Line(" ").indentationOffset, 6) + XCTAssertEqual(Line(" ABC").indentationOffset, 6) } func testOneSpace() { diff --git a/Standard Extensions/Line.swift b/Standard Extensions/Line.swift index 8a8b2a4..c318e24 100644 --- a/Standard Extensions/Line.swift +++ b/Standard Extensions/Line.swift @@ -8,7 +8,7 @@ import Foundation -struct Line { +struct Line: Equatable { var stringValue: String init(_ stringValue: String) { @@ -30,17 +30,22 @@ struct Line { let offsetString = String(repeating: " ", count: offset) stringValue = offsetString + stringValue.trimmingCharacters(in: .whitespacesAndNewlines) } + + mutating func replace(range: Range, with value: String) { + stringValue.replace(range: range, with: value) + } } extension Line: Collection { typealias Index = String.Index - typealias Element = String.Element + typealias Element = Character - subscript(position: String.Index) -> Element { + // Subscript by String Index + subscript(position: String.Index) -> Character { return stringValue[position] } - subscript (position: Int) -> Element { + subscript(position: Int) -> Element { let index = self.index(self.startIndex, offsetBy: position) return self[index] } @@ -52,7 +57,18 @@ extension Line: Collection { var startIndex: Line.Index { return stringValue.startIndex } + var endIndex: Line.Index { return stringValue.endIndex } } + +extension Array where Element == Line { + func joined(separator: String, trimming: CharacterSet) -> Line { + let joinedString = self + .map { $0.stringValue.trimmingCharacters(in: trimming)} + .joined(separator: separator) + + return Line(joinedString) + } +} diff --git a/XcodeKit/TextBuffer+Basic.swift b/XcodeKit/TextBuffer+Basic.swift index 4bb5d01..e626d42 100644 --- a/XcodeKit/TextBuffer+Basic.swift +++ b/XcodeKit/TextBuffer+Basic.swift @@ -13,11 +13,12 @@ typealias TextBuffer = XCSourceTextBuffer extension TextBuffer { - subscript (offset: Int) -> Line { + subscript(offset: Int) -> Line { return Line(lines[offset] as! String) } - subscript (indexSet: IndexSet) -> [Line] { + /// Fetch all lines at index present in indexSet + subscript(indexSet: IndexSet) -> [Line] { return indexSet.map { self[$0] } } @@ -45,14 +46,3 @@ extension TextBuffer { return currentLine[position.column] } } - - - - - - - - - - - From 05e00df919012e3760c720efe294ef4b474359d6 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 14 Jul 2018 19:11:20 +0530 Subject: [PATCH 50/56] Version update --- Line/Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Line/Info.plist b/Line/Info.plist index 2b71a47..faf4a1f 100644 --- a/Line/Info.plist +++ b/Line/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 1.0 + 0.7 CFBundleVersion - 1 + 10 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSExtension From c86a287b2728de705b1cdc18b016c2ced984a946 Mon Sep 17 00:00:00 2001 From: Kaunteya Suryawanshi Date: Sat, 14 Jul 2018 19:13:36 +0530 Subject: [PATCH 51/56] Version update --- Linex/Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linex/Info.plist b/Linex/Info.plist index 95499b4..636b634 100644 --- a/Linex/Info.plist +++ b/Linex/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.6 + 0.7 CFBundleVersion - 7 + 8 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion From b7e93743c94ebde350ea108b0de9cb00347ee9a5 Mon Sep 17 00:00:00 2001 From: James Pamplona Date: Wed, 25 Nov 2020 14:33:11 -0800 Subject: [PATCH 52/56] Upgrade to Swift 5 - Resolve an ambiguous return value build error. --- Linex.xcodeproj/project.pbxproj | 25 ++++++++++++++--------- Standard Extensions/Character+Linex.swift | 4 ++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index c98329a..29d2d42 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -454,6 +454,7 @@ E35942161F55564C009EFA35 = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = KQQ77ZBE5E; + LastSwiftMigration = 1220; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { @@ -464,22 +465,26 @@ E35942271F55564C009EFA35 = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = KQQ77ZBE5E; + LastSwiftMigration = 1220; ProvisioningStyle = Automatic; TestTargetID = E35942161F55564C009EFA35; }; E359423A1F55565E009EFA35 = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = KQQ77ZBE5E; + LastSwiftMigration = 1220; ProvisioningStyle = Automatic; }; E39E226C1F59876A00354A5F = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = KQQ77ZBE5E; + LastSwiftMigration = 1220; ProvisioningStyle = Automatic; }; E3F543921F5A84FC008F426E = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = KQQ77ZBE5E; + LastSwiftMigration = 1220; ProvisioningStyle = Automatic; }; }; @@ -792,7 +797,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -810,7 +815,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -825,7 +830,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.LinexTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Linex.app/Contents/MacOS/Linex"; }; name = Debug; @@ -841,7 +846,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.LinexTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Linex.app/Contents/MacOS/Linex"; }; name = Release; @@ -860,7 +865,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -878,7 +883,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -895,7 +900,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Selection; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -912,7 +917,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Selection; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -929,7 +934,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Convert; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -946,7 +951,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Convert; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Standard Extensions/Character+Linex.swift b/Standard Extensions/Character+Linex.swift index 06e788c..2a2aa22 100644 --- a/Standard Extensions/Character+Linex.swift +++ b/Standard Extensions/Character+Linex.swift @@ -27,11 +27,11 @@ extension Character { var closing: Character { assert(self.isOpening, "Only opening characters can have closing characters") - return ["{":"}", "(":")", "[":"]"][self]! + return Self(["{":"}", "(":")", "[":"]"][self]!) } var opening: Character { assert(self.isClosing, "Only closing characters can have opening characters") - return ["}":"{", ")":"(", "]":"["][self]! + return Self(["}":"{", ")":"(", "]":"["][self]!) } } From 5148a81a807df754708a9acb695feb77ca5c6ee1 Mon Sep 17 00:00:00 2001 From: James Pamplona Date: Wed, 25 Nov 2020 14:56:08 -0800 Subject: [PATCH 53/56] Make compatible with Xcode 12 on macOS 11 Big Sur - Link and embed XcodeKit framework in extension targets. - Fix version mismatches in build and version numbers so that menu items appear and are available. --- Convert/Info.plist | 2 +- Line/Info.plist | 2 +- Linex.xcodeproj/project.pbxproj | 57 +++++++++++++++++++++++ Linex/Info.plist | 4 +- Selection/Info.plist | 82 ++++++++++++++++----------------- 5 files changed, 102 insertions(+), 45 deletions(-) diff --git a/Convert/Info.plist b/Convert/Info.plist index fc4ceb9..109e055 100644 --- a/Convert/Info.plist +++ b/Convert/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.0 CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSExtension diff --git a/Line/Info.plist b/Line/Info.plist index faf4a1f..812dd7f 100644 --- a/Line/Info.plist +++ b/Line/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 0.7 + $(MARKETING_VERSION) CFBundleVersion 10 LSMinimumSystemVersion diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 29d2d42..54c8c18 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -7,6 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + DD60A3FF256F15330053F85C /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD60A3FE256F15330053F85C /* XcodeKit.framework */; }; + DD60A400256F15330053F85C /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD60A3FE256F15330053F85C /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DDD528CB256F162200DF2491 /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD60A3FE256F15330053F85C /* XcodeKit.framework */; }; + DDD528CC256F162200DF2491 /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD60A3FE256F15330053F85C /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DDD528CE256F162900DF2491 /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD60A3FE256F15330053F85C /* XcodeKit.framework */; }; + DDD528CF256F162900DF2491 /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD60A3FE256F15330053F85C /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; E30650FE20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; E30650FF20AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; E306510020AC6E52006B0BBF /* CharacterSet+Linex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */; }; @@ -100,6 +106,39 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + DD60A401256F15330053F85C /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + DD60A400256F15330053F85C /* XcodeKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + DDD528CD256F162200DF2491 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + DDD528CC256F162200DF2491 /* XcodeKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + DDD528D0256F162900DF2491 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + DDD528CF256F162900DF2491 /* XcodeKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; E359424D1F55565E009EFA35 /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -116,6 +155,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + DD60A3FE256F15330053F85C /* XcodeKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XcodeKit.framework; path = Library/Frameworks/XcodeKit.framework; sourceTree = DEVELOPER_DIR; }; E30650FD20AC6E52006B0BBF /* CharacterSet+Linex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Linex.swift"; sourceTree = ""; }; E306510620AEEC48006B0BBF /* TextBuffer+Expand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextBuffer+Expand.swift"; sourceTree = ""; }; E306510A20B0388C006B0BBF /* TextRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRange.swift; sourceTree = ""; }; @@ -181,6 +221,7 @@ buildActionMask = 2147483647; files = ( E359423E1F55565E009EFA35 /* Cocoa.framework in Frameworks */, + DD60A3FF256F15330053F85C /* XcodeKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -189,6 +230,7 @@ buildActionMask = 2147483647; files = ( E39E226E1F59876A00354A5F /* Cocoa.framework in Frameworks */, + DDD528CB256F162200DF2491 /* XcodeKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -197,6 +239,7 @@ buildActionMask = 2147483647; files = ( E3F543941F5A84FC008F426E /* Cocoa.framework in Frameworks */, + DDD528CE256F162900DF2491 /* XcodeKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -285,6 +328,7 @@ E359423C1F55565E009EFA35 /* Frameworks */ = { isa = PBXGroup; children = ( + DD60A3FE256F15330053F85C /* XcodeKit.framework */, E359423D1F55565E009EFA35 /* Cocoa.framework */, ); name = Frameworks; @@ -397,6 +441,7 @@ E35942371F55565E009EFA35 /* Sources */, E35942381F55565E009EFA35 /* Frameworks */, E35942391F55565E009EFA35 /* Resources */, + DD60A401256F15330053F85C /* Embed Frameworks */, ); buildRules = ( ); @@ -414,6 +459,7 @@ E39E22691F59876A00354A5F /* Sources */, E39E226A1F59876A00354A5F /* Frameworks */, E39E226B1F59876A00354A5F /* Resources */, + DDD528CD256F162200DF2491 /* Embed Frameworks */, ); buildRules = ( ); @@ -431,6 +477,7 @@ E3F5438F1F5A84FC008F426E /* Sources */, E3F543901F5A84FC008F426E /* Frameworks */, E3F543911F5A84FC008F426E /* Resources */, + DDD528D0256F162900DF2491 /* Embed Frameworks */, ); buildRules = ( ); @@ -792,8 +839,10 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -810,8 +859,10 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -861,6 +912,7 @@ INFOPLIST_FILE = Line/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; + MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Line; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -879,6 +931,7 @@ INFOPLIST_FILE = Line/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; + MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Line; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -894,6 +947,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Selection/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; @@ -911,6 +965,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Selection/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; @@ -928,6 +983,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Convert/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; @@ -945,6 +1001,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Convert/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; diff --git a/Linex/Info.plist b/Linex/Info.plist index 636b634..f64fd81 100644 --- a/Linex/Info.plist +++ b/Linex/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.7 + $(MARKETING_VERSION) CFBundleVersion - 8 + $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/Selection/Info.plist b/Selection/Info.plist index 857be7b..e694075 100644 --- a/Selection/Info.plist +++ b/Selection/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.0 CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSExtension @@ -28,46 +28,46 @@ XCSourceEditorCommandDefinitions - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).expand - XCSourceEditorCommandName - Select Word - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).selectLine - XCSourceEditorCommandName - Select Line - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).selectLineAbove - XCSourceEditorCommandName - Select Line Up - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).oneSpace - XCSourceEditorCommandName - One Space - - - XCSourceEditorCommandClassName - $(PRODUCT_MODULE_NAME).SourceEditorCommand - XCSourceEditorCommandIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER).align - XCSourceEditorCommandName - Align - + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).expand + XCSourceEditorCommandName + Select Word + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).selectLine + XCSourceEditorCommandName + Select Line + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).selectLineAbove + XCSourceEditorCommandName + Select Line Up + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).oneSpace + XCSourceEditorCommandName + One Space + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).align + XCSourceEditorCommandName + Align + XCSourceEditorExtensionPrincipalClass $(PRODUCT_MODULE_NAME).SourceEditorExtension From 8fda19b1b8d3bc5d10cce74f7c33d91bc7b3d0f7 Mon Sep 17 00:00:00 2001 From: James Pamplona Date: Wed, 25 Nov 2020 15:24:23 -0800 Subject: [PATCH 54/56] Fix warnings about the XcodeKit framework being built for a newer version of macOS than the base deployment target. --- Linex.xcodeproj/project.pbxproj | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 54c8c18..1b33849 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -747,6 +747,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -805,6 +806,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -842,6 +844,7 @@ CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -862,6 +865,7 @@ CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -879,6 +883,7 @@ DEVELOPMENT_TEAM = KQQ77ZBE5E; INFOPLIST_FILE = LinexTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.LinexTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -895,6 +900,7 @@ DEVELOPMENT_TEAM = KQQ77ZBE5E; INFOPLIST_FILE = LinexTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.LinexTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -911,7 +917,7 @@ DEVELOPMENT_TEAM = KQQ77ZBE5E; INFOPLIST_FILE = Line/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Line; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -930,7 +936,7 @@ DEVELOPMENT_TEAM = KQQ77ZBE5E; INFOPLIST_FILE = Line/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Line; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -950,7 +956,7 @@ CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Selection/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Selection; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -968,7 +974,7 @@ CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Selection/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Selection; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -986,7 +992,7 @@ CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Convert/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Convert; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1004,7 +1010,7 @@ CURRENT_PROJECT_VERSION = 10; INFOPLIST_FILE = Convert/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.kaunteya.Linex.Convert; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; From 7e1306e21c9b8a036d9561bc80493c7eee2c2845 Mon Sep 17 00:00:00 2001 From: James Pamplona Date: Wed, 25 Nov 2020 15:28:13 -0800 Subject: [PATCH 55/56] Update to recommended settings. - Enable hardened runtime. - Warn about quoted include. - Update language locale to modern representation. --- Linex.xcodeproj/project.pbxproj | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Linex.xcodeproj/project.pbxproj b/Linex.xcodeproj/project.pbxproj index 1b33849..807a4c5 100644 --- a/Linex.xcodeproj/project.pbxproj +++ b/Linex.xcodeproj/project.pbxproj @@ -495,7 +495,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1220; ORGANIZATIONNAME = "Kaunteya Suryawanshi"; TargetAttributes = { E35942161F55564C009EFA35 = { @@ -538,7 +538,7 @@ }; buildConfigurationList = E35942121F55564C009EFA35 /* Build configuration list for PBXProject "Linex" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -842,6 +842,7 @@ COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; CURRENT_PROJECT_VERSION = 10; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -863,6 +864,7 @@ COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; CURRENT_PROJECT_VERSION = 10; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Linex/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -915,6 +917,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Line/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -934,6 +937,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Line/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -954,6 +958,7 @@ COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; CURRENT_PROJECT_VERSION = 10; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Selection/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -972,6 +977,7 @@ COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; CURRENT_PROJECT_VERSION = 10; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Selection/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -990,6 +996,7 @@ COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; CURRENT_PROJECT_VERSION = 10; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Convert/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; @@ -1008,6 +1015,7 @@ COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = KQQ77ZBE5E; CURRENT_PROJECT_VERSION = 10; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Convert/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.15; From a3f2a839ff1acaf336b253d377092a261ad0a43c Mon Sep 17 00:00:00 2001 From: James Pamplona Date: Wed, 25 Nov 2020 15:38:05 -0800 Subject: [PATCH 56/56] Fix warning about immediate execution of defer statement. --- Line/SourceEditorCommand.swift | 4 +--- Selection/SourceEditorCommand.swift | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Line/SourceEditorCommand.swift b/Line/SourceEditorCommand.swift index e9d7582..e0266dd 100644 --- a/Line/SourceEditorCommand.swift +++ b/Line/SourceEditorCommand.swift @@ -148,8 +148,6 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } } - defer { - completionHandler(nil) - } + completionHandler(nil) } } diff --git a/Selection/SourceEditorCommand.swift b/Selection/SourceEditorCommand.swift index b7d8121..f2fd38c 100644 --- a/Selection/SourceEditorCommand.swift +++ b/Selection/SourceEditorCommand.swift @@ -66,8 +66,6 @@ class SourceEditorCommand: NSObject, XCSourceEditorCommand { } } - defer { - completionHandler(nil) - } - } + completionHandler(nil) + } }