From 1e0a303ea11ba15675da959a1262dc0ee8d2b47c Mon Sep 17 00:00:00 2001 From: Peter-Schorn Date: Tue, 11 May 2021 21:02:43 -0500 Subject: [PATCH 1/2] Added settings for line length (2). --- CommentWrapper.xcodeproj/project.pbxproj | 24 +++++++ CommentWrapper/Base.lproj/Main.storyboard | 25 ++++---- CommentWrapper/CommentWrapper.entitlements | 12 ++-- .../Settings/SettingsViewController.swift | 53 ++++++++++++++++ .../Settings/SettingsViewController.xib | 63 +++++++++++++++++++ CommentWrapper/ViewController.swift | 8 +++ CommentWrapperExt/CommentWrapper.swift | 9 ++- .../CommentWrapperExt.entitlements | 4 ++ CommentWrapperExt/Info.plist | 2 +- Extensions/Settings.swift | 35 +++++++++++ 10 files changed, 216 insertions(+), 19 deletions(-) create mode 100644 CommentWrapper/Settings/SettingsViewController.swift create mode 100644 CommentWrapper/Settings/SettingsViewController.xib create mode 100644 Extensions/Settings.swift diff --git a/CommentWrapper.xcodeproj/project.pbxproj b/CommentWrapper.xcodeproj/project.pbxproj index 9e3d94b..6ecd7af 100644 --- a/CommentWrapper.xcodeproj/project.pbxproj +++ b/CommentWrapper.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 474458A2264B520000B30C22 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 474458A1264B520000B30C22 /* SettingsViewController.xib */; }; + 474458A4264B54E000B30C22 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474458A3264B54E000B30C22 /* SettingsViewController.swift */; }; + 474458A6264B64EA00B30C22 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474458A5264B64EA00B30C22 /* Settings.swift */; }; + 474458A7264B653700B30C22 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474458A5264B64EA00B30C22 /* Settings.swift */; }; + 474458A8264B653700B30C22 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474458A5264B64EA00B30C22 /* Settings.swift */; }; 670349A92095A7C1002A1E30 /* ExternalLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670349A82095A7C1002A1E30 /* ExternalLinks.swift */; }; 6720E7E2208B7E1200D07850 /* CommentWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A3C0A32078260E00E93876 /* CommentWrapper.swift */; }; 6720E7E3208B7E1700D07850 /* CommentUnwrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A3C0B6207A89F700E93876 /* CommentUnwrapper.swift */; }; @@ -96,6 +101,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 474458A1264B520000B30C22 /* SettingsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsViewController.xib; sourceTree = ""; }; + 474458A3264B54E000B30C22 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; + 474458A5264B64EA00B30C22 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; 670349A82095A7C1002A1E30 /* ExternalLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLinks.swift; sourceTree = ""; }; 6720E7E4208B827C00D07850 /* ContentBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBuilder.swift; sourceTree = ""; }; 6720E7E6208B8B9600D07850 /* AttributedTextViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedTextViewController.swift; sourceTree = ""; }; @@ -165,6 +173,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 4744589E264B509100B30C22 /* Settings */ = { + isa = PBXGroup; + children = ( + 474458A1264B520000B30C22 /* SettingsViewController.xib */, + 474458A3264B54E000B30C22 /* SettingsViewController.swift */, + ); + path = Settings; + sourceTree = ""; + }; 6720E7EA208B8C7B00D07850 /* Content */ = { isa = PBXGroup; children = ( @@ -227,6 +244,7 @@ 6720E7E7208B8B9600D07850 /* AttributedTextViewController.xib */, 672771C8208B4B9D00256933 /* Installation Instructions */, 672771C9208B4BE900256933 /* About */, + 4744589E264B509100B30C22 /* Settings */, 67A3C073207822B000E93876 /* Assets.xcassets */, 67A3C078207822B100E93876 /* Info.plist */, 67A3C079207822B100E93876 /* CommentWrapper.entitlements */, @@ -277,6 +295,7 @@ children = ( 67A3C0B0207A886700E93876 /* Character+Extensions.swift */, 67A3C0A7207A847900E93876 /* String+Extensions.swift */, + 474458A5264B64EA00B30C22 /* Settings.swift */, ); path = Extensions; sourceTree = ""; @@ -408,6 +427,7 @@ buildActionMask = 2147483647; files = ( 6720E7E9208B8B9600D07850 /* AttributedTextViewController.xib in Resources */, + 474458A2264B520000B30C22 /* SettingsViewController.xib in Resources */, 67A3C074207822B000E93876 /* Assets.xcassets in Resources */, 672771C7208B4B8700256933 /* InstallationInstructionsViewController.xib in Resources */, 67A3C077207822B000E93876 /* Main.storyboard in Resources */, @@ -517,7 +537,9 @@ 6720E7EE208B8D7400D07850 /* InstructionsContent.swift in Sources */, 6720E7E8208B8B9600D07850 /* AttributedTextViewController.swift in Sources */, 67A3C070207822B000E93876 /* AppDelegate.swift in Sources */, + 474458A4264B54E000B30C22 /* SettingsViewController.swift in Sources */, 6720E7EC208B8C9000D07850 /* IntroductionContent.swift in Sources */, + 474458A6264B64EA00B30C22 /* Settings.swift in Sources */, 672771CC208B4BFB00256933 /* AboutViewController.swift in Sources */, 6720E7E2208B7E1200D07850 /* CommentWrapper.swift in Sources */, 6720E7E5208B827C00D07850 /* ContentBuilder.swift in Sources */, @@ -532,6 +554,7 @@ files = ( 678F0EE020853DB300D94D9D /* ItemizerTests.swift in Sources */, 67A3C0AF207A855C00E93876 /* String+Extensions.swift in Sources */, + 474458A8264B653700B30C22 /* Settings.swift in Sources */, 67A3C0B3207A88E800E93876 /* Character+ExtensionsTests.swift in Sources */, 67A3C0BE207A8D3E00E93876 /* CommentUnwrapperTests.swift in Sources */, 67A3C0BA207A8AE600E93876 /* Itemizer.swift in Sources */, @@ -551,6 +574,7 @@ files = ( 67A3C0B8207A89F700E93876 /* CommentUnwrapper.swift in Sources */, 67A3C0BB207A8AE600E93876 /* Itemizer.swift in Sources */, + 474458A7264B653700B30C22 /* Settings.swift in Sources */, 67A3C0A8207A847900E93876 /* String+Extensions.swift in Sources */, 67A3C097207822DD00E93876 /* SourceEditorExtension.swift in Sources */, 67A3C0A42078260E00E93876 /* CommentWrapper.swift in Sources */, diff --git a/CommentWrapper/Base.lproj/Main.storyboard b/CommentWrapper/Base.lproj/Main.storyboard index 2bf2c9e..56f0077 100644 --- a/CommentWrapper/Base.lproj/Main.storyboard +++ b/CommentWrapper/Base.lproj/Main.storyboard @@ -1,10 +1,8 @@ - + - - + - @@ -62,7 +60,7 @@ - + @@ -136,7 +134,7 @@ - + @@ -170,7 +168,7 @@ - + @@ -178,20 +176,21 @@ - + - + - - - + + + + @@ -219,7 +218,7 @@ - + diff --git a/CommentWrapper/CommentWrapper.entitlements b/CommentWrapper/CommentWrapper.entitlements index f2ef3ae..57371f2 100644 --- a/CommentWrapper/CommentWrapper.entitlements +++ b/CommentWrapper/CommentWrapper.entitlements @@ -2,9 +2,13 @@ - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - + com.apple.security.app-sandbox + + com.apple.security.application-groups + + group.CommentWrapper + + com.apple.security.files.user-selected.read-only + diff --git a/CommentWrapper/Settings/SettingsViewController.swift b/CommentWrapper/Settings/SettingsViewController.swift new file mode 100644 index 0000000..a326436 --- /dev/null +++ b/CommentWrapper/Settings/SettingsViewController.swift @@ -0,0 +1,53 @@ +// +// SettingsViewController.swift +// Comment Wrapper Host +// +// Created by Peter Schorn on 5/11/21. +// Copyright © 2021 Steve Barnegren. All rights reserved. +// + +import AppKit + +class SettingsViewController: NSViewController { + + @IBOutlet weak var lineLengthPopupButton: NSPopUpButton! + + override func viewDidLoad() { + super.viewDidLoad() + + for option in LineLengthOption.allCases { + self.lineLengthPopupButton.addItem(withTitle: option.rawValue) + } + + switch Settings.lineLength { + case .absolute: + self.lineLengthPopupButton.selectItem(at: 1) + default /* .excludingLeadingIndentation */: + self.lineLengthPopupButton.selectItem(at: 0) + } + + + } + + + @IBAction func selectedLineLengthPopupButton( + _ popupButton: NSPopUpButton + ) { + let lineLength: LineLengthOption + let index = popupButton.indexOfSelectedItem + switch index { + case 0: + lineLength = .excludingLeadingIndentation + case 1: + lineLength = .absolute + default: + print("unexpected index for popup button: \(index)") + return + } + + Settings.lineLength = lineLength + print("set line length to \(lineLength)") + + } + +} diff --git a/CommentWrapper/Settings/SettingsViewController.xib b/CommentWrapper/Settings/SettingsViewController.xib new file mode 100644 index 0000000..0486da3 --- /dev/null +++ b/CommentWrapper/Settings/SettingsViewController.xib @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CommentWrapper/ViewController.swift b/CommentWrapper/ViewController.swift index 3759aa0..2b9ec44 100644 --- a/CommentWrapper/ViewController.swift +++ b/CommentWrapper/ViewController.swift @@ -17,6 +17,7 @@ class ViewController: NSViewController { case introduction case installationInstructions case about + case settings } // MARK: - Properties @@ -46,6 +47,7 @@ class ViewController: NSViewController { case 0: showContent(type: .introduction) case 1: showContent(type: .installationInstructions) case 2: showContent(type: .about) + case 3: showContent(type: .settings) default: fatalError("Unhandled segmented control selection") } } @@ -72,6 +74,12 @@ class ViewController: NSViewController { case .about: let about = AboutViewController(nibName: "AboutViewController", bundle: nil) displayContent(viewController: about) + + case .settings: + let settings = SettingsViewController( + nibName: "SettingsViewController", bundle: nil + ) + displayContent(viewController: settings) } self.contentType = type diff --git a/CommentWrapperExt/CommentWrapper.swift b/CommentWrapperExt/CommentWrapper.swift index f5b99a9..bee0cf7 100644 --- a/CommentWrapperExt/CommentWrapper.swift +++ b/CommentWrapperExt/CommentWrapper.swift @@ -19,7 +19,14 @@ class CommentWrapper { .joined(separator: "\n") let items = Itemizer.itemize(string: unprefixedString) - let wrappedString = wrap(items: items, lineLength: lineLength) + let adjustedLineLength: Int + switch Settings.lineLength { + case .absolute: + adjustedLineLength = lineLength - prefix.count + default: + adjustedLineLength = lineLength + } + let wrappedString = wrap(items: items, lineLength: adjustedLineLength) let wrappedWithPrefix = wrappedString .lines() diff --git a/CommentWrapperExt/CommentWrapperExt.entitlements b/CommentWrapperExt/CommentWrapperExt.entitlements index 852fa1a..1eb84ce 100644 --- a/CommentWrapperExt/CommentWrapperExt.entitlements +++ b/CommentWrapperExt/CommentWrapperExt.entitlements @@ -4,5 +4,9 @@ com.apple.security.app-sandbox + com.apple.security.application-groups + + group.CommentWrapper + diff --git a/CommentWrapperExt/Info.plist b/CommentWrapperExt/Info.plist index 4f0fb02..4f5f6c6 100644 --- a/CommentWrapperExt/Info.plist +++ b/CommentWrapperExt/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - Set at build time + 202104.28.1639 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSExtension diff --git a/Extensions/Settings.swift b/Extensions/Settings.swift new file mode 100644 index 0000000..ec4ade0 --- /dev/null +++ b/Extensions/Settings.swift @@ -0,0 +1,35 @@ +import Foundation + +/// Contains the settings from UserDefaults. +enum Settings { + + private static let userDefaults = UserDefaults( + suiteName: "group.CommentWrapper" + )! + + static var lineLength: LineLengthOption { + get { + Self.userDefaults.string( + forKey: LineLengthOption.lineLengthKey + ) + .flatMap(LineLengthOption.init(rawValue:)) + ?? .excludingLeadingIndentation + } + set { + Self.userDefaults.setValue( + newValue.rawValue, + forKey: LineLengthOption.lineLengthKey + ) + } + } + +} + +enum LineLengthOption: String, CaseIterable { + + /// The `UserDefaults` key used to store this option. + static let lineLengthKey = "line length" + + case excludingLeadingIndentation = "Excluding Leading Indentation" + case absolute = "Absolute" +} From a9a8861db10f6ce419cea6307aba6dcc11b824f3 Mon Sep 17 00:00:00 2001 From: Peter-Schorn Date: Tue, 11 May 2021 22:00:05 -0500 Subject: [PATCH 2/2] Added tests for line length settings --- CommentWrapperTests/CommentWrapperTests.swift | 50 +++++++++++++++++++ CommentWrapperTests/Info.plist | 2 + CommentWrapperTests/TestObserver.swift | 27 ++++++++++ 3 files changed, 79 insertions(+) create mode 100644 CommentWrapperTests/TestObserver.swift diff --git a/CommentWrapperTests/CommentWrapperTests.swift b/CommentWrapperTests/CommentWrapperTests.swift index 8439d08..5fa5f49 100644 --- a/CommentWrapperTests/CommentWrapperTests.swift +++ b/CommentWrapperTests/CommentWrapperTests.swift @@ -253,5 +253,55 @@ class CommentWrapperTests: XCTestCase { XCTAssertEqual(output, expected) } + + func testHandleLineLengthSettings() { + + let previousLineLength = Settings.lineLength + defer { + Settings.lineLength = previousLineLength + } + + // indented by 8 spaces + let input = """ + // The central class in this library. Provides methods for all of the Spotify + // web API endpoints and contains an authorization manager for managing the + // authorization process of your application. + """ + + let expectedAbsolute = """ + // The central class in this + // library. Provides methods for + // all of the Spotify + // web API endpoints and + // contains an authorization + // manager for managing the + // authorization process of your + // application. + """ + + let expectedExlcudingLeadingIndentation = """ + // The central class in this library. + // Provides methods for all of the Spotify + // web API endpoints and contains an + // authorization manager for managing the + // authorization process of your + // application. + """ + + Settings.lineLength = .absolute + let outputAbsolute = CommentWrapper.wrap(string: input, lineLength: 40) + XCTAssertEqual(outputAbsolute, expectedAbsolute) + + Settings.lineLength = .excludingLeadingIndentation + let outputExcludingLeadingIndentation = CommentWrapper.wrap( + string: input, lineLength: 40 + ) + print(outputExcludingLeadingIndentation) + XCTAssertEqual( + outputExcludingLeadingIndentation, + expectedExlcudingLeadingIndentation + ) + + } } diff --git a/CommentWrapperTests/Info.plist b/CommentWrapperTests/Info.plist index 6c40a6c..a0c4266 100644 --- a/CommentWrapperTests/Info.plist +++ b/CommentWrapperTests/Info.plist @@ -2,6 +2,8 @@ + NSPrincipalClass + $(PRODUCT_NAME).TestObserver CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable diff --git a/CommentWrapperTests/TestObserver.swift b/CommentWrapperTests/TestObserver.swift new file mode 100644 index 0000000..94baf5f --- /dev/null +++ b/CommentWrapperTests/TestObserver.swift @@ -0,0 +1,27 @@ +import Foundation +import XCTest + +class TestObserver: NSObject, XCTestObservation { + + static var storedLineLength: LineLengthOption? = nil + + override init() { + super.init() + XCTestObservationCenter.shared.addTestObserver(self) + } + + func testBundleWillStart(_ testBundle: Bundle) { + // Save the line length that is stored in user defaults + Self.storedLineLength = Settings.lineLength + + // Set the line length to the default value so that the tests will pass + Settings.lineLength = .excludingLeadingIndentation + } + + func testBundleDidFinish(_ testBundle: Bundle) { + // Set the line length back to what was stored in user defaults. + Settings.lineLength = Self.storedLineLength ?? + .excludingLeadingIndentation + } + +}