diff --git a/.github/CODE_OF_CONDUCT.markdown b/.github/CODE_OF_CONDUCT.markdown new file mode 100644 index 0000000..7706e0e --- /dev/null +++ b/.github/CODE_OF_CONDUCT.markdown @@ -0,0 +1,74 @@ +## Code of Conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at support@geedbla.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/.github/CONTRIBUTING.markdown b/.github/CONTRIBUTING.markdown new file mode 100644 index 0000000..8363e28 --- /dev/null +++ b/.github/CONTRIBUTING.markdown @@ -0,0 +1,26 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a + build. +2. Update the README.md with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. +3. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. + + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..eb7adcc --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [Gary-Ash] diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.markdown b/.github/ISSUE_TEMPLATE/Bug_Report.markdown new file mode 100644 index 0000000..44b8b11 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_Report.markdown @@ -0,0 +1,51 @@ +--- +name: Bug report 🐛 +about: Report errors or unexpected behavior +title: "Bug Report (IF I DO NOT CHANGE THIS THE ISSUE WILL BE CLOSED)" +labels: '' +assignees: '' + +--- + + + + + +# Environment + +```none +Cascadia Code version number: +Application (with version) used to display text: +OS platform and version: +Screen resolution (i.e. 220dpi): + +Any other software? +``` + +# Steps to reproduce + + + +# Expected behavior + + + +# Actual behavior + + diff --git a/.github/ISSUE_TEMPLATE/Documentation_Issue.markdown b/.github/ISSUE_TEMPLATE/Documentation_Issue.markdown new file mode 100644 index 0000000..f4b0849 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Documentation_Issue.markdown @@ -0,0 +1,10 @@ +--- +name: Documentation Issue 📚 +about: Report issues in our documentation +title: "Documentation Issue" +labels: Issue-Docs +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.markdown b/.github/ISSUE_TEMPLATE/Feature_Request.markdown new file mode 100644 index 0000000..c497876 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_Request.markdown @@ -0,0 +1,34 @@ +--- +name: Feature Request/Idea 🚀 +about: Suggest a new feature or improvement (this does not mean you have to implement it) +title: "Feature Request" +labels: Issue-Feature +assignees: '' + +--- + + + +# Description of the new feature/enhancement (with images if possible) + + + +# Proposed technical implementation details (optional) + + diff --git a/.github/PULL_REQUEST_TEMPLATE.markdown b/.github/PULL_REQUEST_TEMPLATE.markdown new file mode 100644 index 0000000..3f2583d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.markdown @@ -0,0 +1,27 @@ + + + + + +##### Checklist + + +- [ ] `make -j4 test` (UNIX), or `vcbuild test` (Windows) passes +- [ ] tests and/or benchmarks are included +- [ ] documentation is changed or added +- [ ] commit message follows [commit guidelines](./doc/guides/contributing/pull-requests.md#commit-message-guidelines) + + + +### Affected core subsystem(s) + + +### Description of change + diff --git a/.github/Screenshot.png b/.github/Screenshot.png new file mode 100644 index 0000000..83a7344 Binary files /dev/null and b/.github/Screenshot.png differ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..8c5133e --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,34 @@ +#***************************************************************************** +# ci.yaml +# +# This file contains the Github actions based CI building and automated +# testing on pushes and pull requests +# +# Author : Gary Ash +# Created : 28-Apr-2024 3:03pm +# Modified : +# +# Copyright © 2024 By Gary Ash All rights reserved. +#***************************************************************************** + +name: CI + +on: + push: + branches: [ "main", "develop" ] + + pull_request: + branches: [ "main", "develop" ] + +jobs: + build: + name: Build and Test default scheme + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Run testing workflow + run: | + sh BuildEnv/ci.sh \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f9398c --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +.DS_Store +.AppleDouble +.LSOverride +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +xcuserdata/ +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +**/xcshareddata/WorkspaceSettings.xcsettings + +*.hmap +*.ipa +*.dSYM.zip +*.dSYM +.swiftpm +.build/ + +CocoaPods + +Pods/ +WeGoal/Pods/ +WeGoal/Pods/ +*/Pods/* +Podfile.lock diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..cb3eff0 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,94 @@ + +excluded: + - Pods + - Carthage +included: + - Source + - Tests +analyzer_rules: + - unused_declaration + - unused_import +line_length: + warning: 200 + ignores_function_declarations: true + ignores_comments: true + ignores_interpolated_strings: true + ignores_urls: true +opt_in_rules: + - anyobject_protocol + - array_init + - attributes + - closure_end_indentation + - closure_spacing + - collection_alignment + - contains_over_filter_count + - contains_over_filter_is_empty + - contains_over_first_not_nil + - contains_over_range_nil_comparison + - discouraged_object_literal + - empty_collection_literal + - empty_count + - empty_string + - empty_xctest_method + - enum_case_associated_values_count + - explicit_init + - extension_access_modifier + - fallthrough + - fatal_error_message + - file_header + - file_name + - first_where + - flatmap_over_map_reduce + - identical_operands + - joined_default_parameter + - legacy_random + - let_var_whitespace + - last_where + - legacy_multiple + - literal_expression_end_indentation + - lower_acl_than_parent + - modifier_order + - nimble_operator + - nslocalizedstring_key + - number_separator + - object_literal + - operator_usage_whitespace + - overridden_super_call + - override_in_extension + - pattern_matching_keywords + - prefer_self_type_over_type_of_self + - private_action + - private_outlet + - prohibited_interface_builder + - prohibited_super_call + - quick_discouraged_call + - quick_discouraged_focused_test + - quick_discouraged_pending_test + - reduce_into + - redundant_nil_coalescing + - redundant_type_annotation + - single_test_class + - sorted_first_last + - sorted_imports + - static_operator + - strong_iboutlet + - toggle_bool + - unavailable_function + - unneeded_parentheses_in_closure_argument + - unowned_variable_capture + - untyped_error_in_catch + - vertical_parameter_alignment_on_call + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - xct_specific_matcher + - yoda_condition + +disabled_rules: + - orphaned_doc_comment + +identifier_name: + excluded: + - id + +number_separator: + minimum_length: 5 diff --git a/BuildEnv/Beta.png b/BuildEnv/Beta.png new file mode 100644 index 0000000..5ca04de Binary files /dev/null and b/BuildEnv/Beta.png differ diff --git a/BuildEnv/ci.sh b/BuildEnv/ci.sh new file mode 100755 index 0000000..7e37cb7 --- /dev/null +++ b/BuildEnv/ci.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env zsh +#***************************************************************************************** +# ci.sh +# +# This script will run iOS and/or macOS tests on GitHub check in +# +# Author : Gary Ash +# Created : 28-Apr-2024 3:03pm +# Modified : +# +# Copyright © 2024 By Gary Ash All rights reserved. +#***************************************************************************************** + +set -o pipefail + +#***************************************************************************************** +# routine to extract a few project settings from the (main) project file +#***************************************************************************************** +getMainProjectSettings() { + projectF=$(find . -name "$Scheme.xcodeproj") + if [[ -n $projectF ]]; then + projectF="$projectF/project.pbxproj" + result=$(grep -m1 -i -e "SUPPORTED_PLATFORMS =" "$projectF") + result=$(echo "$result" | grep -po '".*"') + result=$(echo "$result" | sed 's/^\"\(.*\)\"$/\1/') + echo "$result" + else + echo "Unable to get project settings" + exit 1 + fi +} + +#***************************************************************************************** +# routine to get the macOS build target and compare it against the macOS version of the +# Github action runner +#***************************************************************************************** +getMacVersion() { + projectF=$(find . -name "$Scheme.xcodeproj") + if [[ -n $projectF ]]; then + projectF="$projectF/project.pbxproj" + machineVersion="$(sw_vers -productVersion)" + buildTarget=$(grep -m1 -i -e "MACOSX_DEPLOYMENT_TARGET =" "$projectF") + buildTarget="${buildTarget#*=}" + buildTarget="${buildTarget%;*}" + buildTarget="${buildTarget#"${buildTarget%%[![:space:]]*}"}" + + if [[ $buildTarget < $machineVersion ]]; then + echo "good" + else + echo "no good" + fi + fi +} + +#***************************************************************************************** +# script main-line +#***************************************************************************************** +ProjectFile="$(find . -name '*.xcworkspace' -depth 1)" 2>/dev/null +if [[ -z $ProjectFile ]]; then + ProjectFile="$(find . -name '*.xcodeproj' -depth 1)" 2>/dev/null +fi + +Scheme="$(xcodebuild -list -json | jq -r '.project.schemes[0]')" 2>/dev/null +Simulator=$(xcrun xctrace list devices 2>&1 | grep -oE 'iPhone.*?[^\(]+' | head -1 | awk '{$1=$1;print}' | sed -e "s/ Simulator$//" 2>/dev/null) +Platforms=$(getMainProjectSettings) + +if [[ $ProjectFile =~ .*\.xcworkspace$ ]]; then + ProjectFlag="-workspace" +else + ProjectFlag="-project" +fi + +if [[ $Platforms =~ iphonesimulator ]]; then + destination="platform=iOS Simulator,name=${Simulator}" + xcodebuild build-for-testing -quiet "${ProjectFlag}" "${ProjectFile}" -scheme "${Scheme}" -destination "${destination}" | xcpretty -c + xcodebuild test-without-building -quiet "${ProjectFlag}" "${ProjectFile}" -scheme "${Scheme}" -destination "${destination}" | xcpretty -c +fi + +if [[ $Platforms =~ macosx ]]; then + good=$(getMacVersion) + if [[ $good == "good" ]]; then + destination="platform=macOS" + xcodebuild build-for-testing -quiet "${ProjectFlag}" "${ProjectFile}" -scheme "${Scheme}" -destination "${destination}" | xcpretty -c + xcodebuild test-without-building -quiet "${ProjectFlag}" "${ProjectFile}" -scheme "${Scheme}" -destination "${destination}" | xcpretty -c + fi +fi diff --git a/BuildEnv/increment-build-number.sh b/BuildEnv/increment-build-number.sh new file mode 100644 index 0000000..18d6ff7 --- /dev/null +++ b/BuildEnv/increment-build-number.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +if [ "${CONFIGURATION}" = "Release" ] || [ "${CONFIGURATION}" = "TestFlight" ]; then + cd "${PROJECT_DIR}" + agvtool bump +fi diff --git a/BuildEnv/restore-stamped-icon.sh b/BuildEnv/restore-stamped-icon.sh new file mode 100644 index 0000000..eb06fa5 --- /dev/null +++ b/BuildEnv/restore-stamped-icon.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh +if [ "${CONFIGURATION}" = "TestFlight" ]; then + if [ -f "/opt/homebrew/bin/brew" ]; then + export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" + fi + if which magick >/dev/null; then + iconDir="${SRCROOT}/${PROJECT_NAME}/Assets.xcassets/AppIcon.appiconset/" + cp -rf "${TMPDIR}/${iconDir}" "${iconDir}" + fi +fi diff --git a/BuildEnv/stamp-beta-version.sh b/BuildEnv/stamp-beta-version.sh new file mode 100644 index 0000000..1cb8c23 --- /dev/null +++ b/BuildEnv/stamp-beta-version.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +if [ "${CONFIGURATION}" = "TestFlight" ]; then + if [ -f "/opt/homebrew/bin/brew" ]; then + export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" + fi + + if which magick >/dev/null; then + iconDir="$SRCROOT/$PROJECT_NAME/Assets.xcassets/AppIcon.appiconset" + mkdir -p "${TMPDIR}/${iconDir}" + echo "${TMPDIR}/${iconDir}" + cp -rf "${iconDir}" "${TMPDIR}/${iconDir}" + + for file in $(find "$iconDir" -name "*.png" -type f); do + width=$(magick identify -format %w "$file") + if [ "$width" = 1024 ]; then + largeIcon="$file" + break + fi + done + + version="$MARKETING_VERSION" + build="$CURRENT_PROJECT_VERSION" + caption="v${version}\nBuild: ${build}" + width=$(magick identify -format %w ${largeIcon}) + height=$(magick identify -format %h ${largeIcon}) + band_height=$(((height * 47) / 100)) + band_position=$((height - band_height)) + text_position=$((band_position - 3)) + point_size=$(((13 * width) / 100)) + + magick convert "${largeIcon}" -blur 10x8 /tmp/blurred.png + magick convert "${largeIcon}" -gamma 0 -fill white -draw "rectangle 0,$band_position,$width,$height" /tmp/mask.png + magick convert -size ${width}x${band_height} xc:none -fill 'rgba(0,0,0,0.2)' -draw "rectangle 0,0,$width,$band_height" /tmp/labels-base.png + magick convert -background none -size ${width}x${band_height} -pointsize $point_size -fill white -gravity center -gravity South caption:"$caption" /tmp/labels.png + magick convert "$largeIcon" /tmp/blurred.png /tmp/mask.png -composite /tmp/temp.png + magick convert /tmp/temp.png /tmp/labels-base.png -geometry +0+$band_position -composite /tmp/labels.png -geometry +0+$text_position -geometry +${w}-${h} -composite "$largeIcon" + + #rm -f /tmp/*.png + for file in $(find "$iconDir" -name "*.png" -type f); do + dim=$(magick identify -format "%wx%h" "$file") + if [ "$dim" != "1024x1024" ]; then + magick convert "$largeIcon" -resize "$dim!" "$file" + fi + done + else + echo "warning: Image Magick not installed, brew install imagemagick" + fi +fi +exit 0 diff --git a/BuildEnv/swiftlint-project.sh b/BuildEnv/swiftlint-project.sh new file mode 100644 index 0000000..b03a1d3 --- /dev/null +++ b/BuildEnv/swiftlint-project.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env sh +if [ "${CONFIGURATION}" = "Debug" ]; then + if [[ -f "/opt/homebrew/bin/brew" ]]; then + export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" + fi + + if which swiftlint >/dev/null; then + find "$SRCROOT" -type f -name "*.swift" -print0 | xargs -0 swiftlint --fix --config "$PROJECT_DIR/.swiftlint.yml" --path + else + echo "warning: SwiftLint not installed, brew install SwiftLint" + fi +fi diff --git a/Extension/Constants.swift b/Extension/Constants.swift new file mode 100644 index 0000000..a9b9f4a --- /dev/null +++ b/Extension/Constants.swift @@ -0,0 +1,32 @@ +/***************************************************************************************** + * Constants.swift + * + * + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import Foundation + +let SupportedContentUTIs = [ + "public.swift-source", + "com.apple.dt.playground", + "com.apple.dt.playgroundpage", + "com.apple.dt.swiftpm-package-manifest", + "com.apple.xcode.strings-text", + "public.c-plus-plus-source", + "public.objective-c-source", + "public.objective-c-plus-plus-source", + "public.c-header", + "public.c-source", + "public.precompiled-c-header" +] + +enum CommandError: String, Error { + case notSupported = "Unsupported file type" + case notMine = "Not a Gee Dbl A source file" +} diff --git a/Extension/Extension.entitlements b/Extension/Extension.entitlements new file mode 100755 index 0000000..b754523 --- /dev/null +++ b/Extension/Extension.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + XcodeGeeDblA + + + diff --git a/Extension/Info.plist b/Extension/Info.plist new file mode 100644 index 0000000..267e0fb --- /dev/null +++ b/Extension/Info.plist @@ -0,0 +1,75 @@ + + + + + NSExtension + + NSExtensionAttributes + + XCSourceEditorExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).SourceEditorExtension + XCSourceEditorCommandDefinitions + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).UpdateHeader + XCSourceEditorCommandName + Update File Header + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).SeperatorLine + XCSourceEditorCommandName + Insert Seperator Comment + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).AsteriskBox + XCSourceEditorCommandName + Insert Asterisk Box Comment + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).DashBox + XCSourceEditorCommandName + Insert Dash Box Comment + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).DashBox + XCSourceEditorCommandName + Insert Dash Box Comment + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).AddComment + XCSourceEditorCommandName + Insert Function Trace Comment + + + XCSourceEditorCommandClassName + $(PRODUCT_MODULE_NAME).SourceEditorCommand + XCSourceEditorCommandIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER).RemoveComment + XCSourceEditorCommandName + Remove Function Trace Comment + + + + NSExtensionPointIdentifier + com.apple.dt.Xcode.extension.source-editor + + + diff --git a/Extension/SourceEditorCommand.swift b/Extension/SourceEditorCommand.swift new file mode 100755 index 0000000..144fb55 --- /dev/null +++ b/Extension/SourceEditorCommand.swift @@ -0,0 +1,220 @@ +/***************************************************************************************** + * SourceEditorCommand.swift + * + * This file contains the extension main command entry point + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import Foundation +import XcodeKit + +class SourceEditorCommand: NSObject, XCSourceEditorCommand { + private var copyrightHolders: [String] + private let dateFormatter = DateFormatter() + + override init() { + copyrightHolders = UserDefaults(suiteName: "XcodeGeeDblA")?.array(forKey: "Copyright Holders") as? [String] ?? [] + super.init() + } + + func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { + guard SupportedContentUTIs.contains(invocation.buffer.contentUTI) else { + return completionHandler(nil) + } + + if invocation.commandIdentifier.hasSuffix(".UpdateHeader") { + guard let copyrightRange = invocation.buffer.completeBuffer.range(of: "Copyright © ([0-9 \\*-]*) By (.*) All rights reserved.", options: .regularExpression, range: nil, locale: nil) else { + return completionHandler(nil) + } + if let tightenRange = invocation.buffer.completeBuffer.range(of: "By (.*) All", options: .regularExpression, range: copyrightRange, locale: nil) { + let s = String(invocation.buffer.completeBuffer[tightenRange.lowerBound ... tightenRange.upperBound]) + var company = s.replacingOccurrences(of: "By ", with: "") + company = company.replacingOccurrences(of: " All", with: "") + company = company.trimmingCharacters(in: .whitespacesAndNewlines) + + for c in copyrightHolders { + if c == company { + updateHeaderComment(&invocation.buffer.completeBuffer) + break + } + } + return completionHandler(nil) + } + updateHeaderComment(&invocation.buffer.completeBuffer) + } else if invocation.commandIdentifier.hasSuffix(".SeperatorLine") { + seperatorLine(invocation) + } else if invocation.commandIdentifier.hasSuffix(".AsteriskBox") { + boxComment(invocation, decoratorChar: "*") + } else if invocation.commandIdentifier.hasSuffix(".DashBox") { + boxComment(invocation, decoratorChar: "-") + } else if invocation.commandIdentifier.hasSuffix(".EqualsBox") { + boxComment(invocation, decoratorChar: "=") + } else if invocation.commandIdentifier.hasSuffix(".AddComment") { + addComments(invocation) + } else if invocation.commandIdentifier.hasSuffix(".RemoveComment") { + removeComments(invocation) + } + completionHandler(nil) + } + + private func boxComment(_ invocation: XCSourceEditorCommandInvocation, decoratorChar: String) { + for range in invocation.buffer.selections { + let r = range as! XCSourceTextRange + if r.start.line == r.end.line, r.start.column == r.end.column { + var numberOfDecorationCharacters = 88 - getColumnNumber(invocation, column: r.start.column) + if numberOfDecorationCharacters < 1 { + numberOfDecorationCharacters = 3 + } + let comment1 = addSpaces(invocation, numberSpaces: r.start.column) + "/*" + String(repeating: decoratorChar, count: numberOfDecorationCharacters) + let comment2 = addSpaces(invocation, numberSpaces: r.start.column) + " *" + let comment3 = addSpaces(invocation, numberSpaces: r.start.column) + " *" + String(repeating: decoratorChar, count: numberOfDecorationCharacters - 2) + "*/" + + if r.start.column > 0 { + invocation.buffer.lines.insert(comment1, at: r.start.line) + invocation.buffer.lines.insert(comment2, at: r.start.line) + invocation.buffer.lines.insert(comment3, at: r.start.line) + setCursor(invocation, line: r.start.line - 2, column: r.start.column + 3) + } else { + invocation.buffer.lines.insert(comment1, at: r.start.line) + invocation.buffer.lines.insert(comment2, at: r.start.line + 1) + invocation.buffer.lines.insert(comment3, at: r.start.line + 2) + setCursor(invocation, line: r.start.line + 1, column: r.start.column + 3) + } + } + } + } + + private func seperatorLine(_ invocation: XCSourceEditorCommandInvocation) { + for range in invocation.buffer.selections { + let r = range as! XCSourceTextRange + if r.start.line == r.end.line, r.start.column == r.end.column { + var numberDashes = 86 - getColumnNumber(invocation, column: r.start.column) + if numberDashes < 1 { + numberDashes = 1 + } + let comment = addSpaces(invocation, numberSpaces: r.start.column) + "/*" + String(repeating: "-", count: numberDashes) + "*/\n" + invocation.buffer.lines.insert(comment, at: r.start.line) + setCursor(invocation, line: r.start.line + 1, column: r.start.column) + } + } + } + + private func updateHeaderComment(_ buffer: inout String) { + if let range = buffer.range(of: "Modified : + let currentDate = Date() + + let modifiedOn = "Modified : + buffer.removeSubrange(range) + buffer.insert(contentsOf: modifiedOn, at: range.lowerBound) + } + + if let range = buffer.range(of: "Created : 28-Apr-2024 3:03pm + if let dateRange = buffer.range(of: "\\d+-.*", options: .regularExpression, range: range, locale: nil) { + let startIndex = dateRange.lowerBound + let endIndex = dateRange.upperBound + let dateSubstring = String(buffer[startIndex ..< endIndex]) + + dateFormatter.dateFormat = "d-MMM-yyyy h:mma" + if let date = dateFormatter.date(from: dateSubstring) { + let creaatedOn = "Created : 28-Apr-2024 3:03pm + buffer.removeSubrange(range) + buffer.insert(contentsOf: creaatedOn, at: range.lowerBound) + } + } + } + + if let range = buffer.range(of: "Copyright © ([0-9 \\*-]*) By (.*) All rights reserved", options: .regularExpression, range: nil, locale: nil) { + if let yearRange = buffer.range(of: "20[0-9]*", options: .regularExpression, range: range, locale: nil) { + let startIndex = yearRange.lowerBound + let endIndex = yearRange.upperBound + let yearSubstring = String(buffer[startIndex ..< endIndex]) + + let year = Int(yearSubstring) + let currentDate = Date() + let components = Calendar.current.dateComponents([.year], from: currentDate) + + if year != components.year! { + if let dateRange = buffer.range(of: "20[0-9]* - 20[0-9]*", options: .regularExpression, range: range, locale: nil) { + buffer.removeSubrange(dateRange) + } else { + buffer.removeSubrange(yearRange) + } + let copyright = "\(year!) - \(components.year!)" + buffer.insert(contentsOf: copyright, at: yearRange.lowerBound) + } + } + } + } + + private func setCursor(_ invocation: XCSourceEditorCommandInvocation, line: Int, column: Int) { + var col = column + if invocation.buffer.usesTabsForIndentation { + col = invocation.buffer.indentationWidth * column + } + let p = XCSourceTextPosition(line: line, column: col) + invocation.buffer.selections.removeAllObjects() + invocation.buffer.selections[0] = XCSourceTextRange(start: p, end: p) + } + + private func getColumnNumber(_ invocation: XCSourceEditorCommandInvocation, column: Int) -> Int { + if invocation.buffer.usesTabsForIndentation { + return invocation.buffer.indentationWidth * column + } + return column + 1 + } + + private func addSpaces(_ invocation: XCSourceEditorCommandInvocation, numberSpaces: Int) -> String { + return String(repeating: " ", count: getColumnNumber(invocation, column: numberSpaces)) + } + + private func stringFromDate(_ date: Date) -> String { + var output = "" + let components = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: date) + dateFormatter.amSymbol = "am" + dateFormatter.pmSymbol = "pm" + dateFormatter.dateFormat = "d-MMM-yyyy" + + if let day = components.day { + if day < 10 { + output = " " + } + } + output += dateFormatter.string(from: date) + if let hour = components.hour { + let h = (hour > 12) ? hour - 12 : hour + if h > 9 { + output += " " + } else { + output += " " + } + + dateFormatter.dateFormat = "h:mma" + output += dateFormatter.string(from: date) + } + return output + } + + private func addComments(_ invocation: XCSourceEditorCommandInvocation) { + let extraIndent: String + + if invocation.buffer.usesTabsForIndentation { + extraIndent = "\t" + } else { + extraIndent = String(repeatElement(" ", count: invocation.buffer.indentationWidth)) + } + + guard let regex = try? NSRegularExpression(pattern: "([ \\t]*)(.*func )([^(]+)(.*?\n)", options: .caseInsensitive) else { return } + invocation.buffer.completeBuffer = regex.stringByReplacingMatches(in: invocation.buffer.completeBuffer, options: [], range: NSRange(location: 0, length: invocation.buffer.completeBuffer.utf16.count), withTemplate: "$1$2$3$4$1\(extraIndent)print(\"# Gee Dbl A: Entering $3()\")\n") + } + + private func removeComments(_ invocation: XCSourceEditorCommandInvocation) { + guard let regex = try? NSRegularExpression(pattern: "(.*# Gee Dbl A: Entering.*\n)", options: .caseInsensitive) else { return } + invocation.buffer.completeBuffer = regex.stringByReplacingMatches(in: invocation.buffer.completeBuffer, options: [], range: NSRange(location: 0, length: invocation.buffer.completeBuffer.utf16.count), withTemplate: "") + } + +} diff --git a/Extension/SourceEditorExtension.swift b/Extension/SourceEditorExtension.swift new file mode 100755 index 0000000..6353fdc --- /dev/null +++ b/Extension/SourceEditorExtension.swift @@ -0,0 +1,19 @@ +/***************************************************************************************** + * SourceEditorExtension.swift + * + * This file contains extension boilerplate + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import Foundation +import XcodeKit + +class SourceEditorExtension: NSObject, XCSourceEditorExtension { + func extensionDidFinishLaunching() { + } +} diff --git a/LICENSE.markdown b/LICENSE.markdown new file mode 100644 index 0000000..4402ef2 --- /dev/null +++ b/LICENSE.markdown @@ -0,0 +1,21 @@ +MIT License + +Copyright © 2024 By Gary Ash All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..fabe5f9 --- /dev/null +++ b/README.markdown @@ -0,0 +1,8 @@ +### Gee Dbl A’s Xcode Extension. +This project is simple test of the Xcode source extension system. Please ensure that the extension is enabled in your System Preference/Settings. + +![Screen Shot](.github/Screenshot.png) + + + +All this does right now is update the modified time stamp of the file header comment that I commonly use in my projects. \ No newline at end of file diff --git a/XcodeFormatOnSave.workflow/.gitkeep b/XcodeFormatOnSave.workflow/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XcodeFormatOnSave.workflow/Contents/Info.plist b/XcodeFormatOnSave.workflow/Contents/Info.plist new file mode 100644 index 0000000..1d2c0d5 --- /dev/null +++ b/XcodeFormatOnSave.workflow/Contents/Info.plist @@ -0,0 +1,27 @@ + + + + + NSServices + + + NSBackgroundColorName + background + NSIconName + NSActionTemplate + NSMenuItem + + default + XcodeFormatOnSave + + NSMessage + runWorkflowAsService + NSRequiredContext + + NSApplicationIdentifier + com.apple.dt.Xcode + + + + + diff --git a/XcodeFormatOnSave.workflow/Contents/document.wflow b/XcodeFormatOnSave.workflow/Contents/document.wflow new file mode 100644 index 0000000..9d7323f --- /dev/null +++ b/XcodeFormatOnSave.workflow/Contents/document.wflow @@ -0,0 +1,159 @@ + + + + + AMApplicationBuild + 523 + AMApplicationVersion + 2.10 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0.2 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run AppleScript.action + ActionName + Run AppleScript + ActionParameters + + source + tell application "System Events" tell process "Xcode" set frontmost to true if menu item "Update File Header" of menu of menu item "GeeDblA Xcode Extension" of menu "Editor" of menu bar 1 exists then click menu item "Update File Header" of menu of menu item "GeeDblA Xcode Extension" of menu "Editor" of menu bar 1 if menu item "Format File" of menu of menu item "SwiftFormat" of menu "Editor" of menu bar 1 exists then click menu item "Format File" of menu of menu item "SwiftFormat" of menu "Editor" of menu bar 1 end if end if click menu item "Save" of menu "File" of menu bar 1 end tell end tell + + BundleIdentifier + com.apple.Automator.RunScript + CFBundleVersion + 1.0.2 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunScriptAction + InputUUID + 389952C6-ABE0-4EBC-819C-9E85FA159C85 + Keywords + + Run + + OutputUUID + C806C8EA-9D98-476A-AEC8-D9B2421EC6F7 + UUID + EEC3527D-CE33-44D1-A391-1EA0B9A72E41 + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + on run {input, parameters} + + (* Your script goes here *) + + return input +end run + name + source + required + 0 + type + 0 + uuid + 0 + + + isViewVisible + 1 + location + 601.500000:1064.000000 + nibPath + /System/Library/Automator/Run AppleScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + 1 + + + connectors + + workflowMetaData + + applicationBundleID + com.apple.dt.Xcode + applicationBundleIDsByPath + + /Applications/Xcode.app + com.apple.dt.Xcode + + applicationPath + /Applications/Xcode.app + applicationPaths + + /Applications/Xcode.app + + inputTypeIdentifier + com.apple.Automator.nothing + outputTypeIdentifier + com.apple.Automator.nothing + presentationMode + 11 + processesInput + + serviceApplicationBundleID + com.apple.dt.Xcode + serviceApplicationPath + /Applications/Xcode.app + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + + systemImageName + NSActionTemplate + useAutomaticInputType + + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/XcodeGeeDblA.xcodeproj/project.pbxproj b/XcodeGeeDblA.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6f9947f --- /dev/null +++ b/XcodeGeeDblA.xcodeproj/project.pbxproj @@ -0,0 +1,1100 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + AB0266AA28F9F88A00B107D4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0266A928F9F88A00B107D4 /* Cocoa.framework */; }; + AB0266AF28F9F88A00B107D4 /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB0266AE28F9F88A00B107D4 /* SourceEditorExtension.swift */; }; + AB0266B128F9F88A00B107D4 /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB0266B028F9F88A00B107D4 /* SourceEditorCommand.swift */; }; + AB0266B628F9F88A00B107D4 /* GeeDblA Xcode Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = AB0266A728F9F88A00B107D4 /* GeeDblA Xcode Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + AB0266BD28F9FCEF00B107D4 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB0266BC28F9FCEF00B107D4 /* Constants.swift */; }; + AB2024D628F758A7002A8481 /* XcodeGeeDblAApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB2024D528F758A7002A8481 /* XcodeGeeDblAApp.swift */; }; + AB2024D828F758A7002A8481 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB2024D728F758A7002A8481 /* ContentView.swift */; }; + AB2024E828F758A8002A8481 /* XcodeGeeDblATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB2024E728F758A8002A8481 /* XcodeGeeDblATests.swift */; }; + AB2024F228F758A8002A8481 /* XcodeGeeDblAUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB2024F128F758A8002A8481 /* XcodeGeeDblAUITests.swift */; }; + AB2024F428F758A8002A8481 /* XcodeGeeDblAUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB2024F328F758A8002A8481 /* XcodeGeeDblAUITestsLaunchTests.swift */; }; + AB56AB9128F87A3900A2B9D5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AB56AB8428F87A3900A2B9D5 /* Assets.xcassets */; }; + AB56AB9228F87A3900A2B9D5 /* Main.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB56AB8628F87A3900A2B9D5 /* Main.strings */; }; + AB56AB9328F87A3900A2B9D5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB56AB8828F87A3900A2B9D5 /* Main.storyboard */; }; + AB56AB9428F87A3900A2B9D5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB56AB8A28F87A3900A2B9D5 /* Localizable.strings */; }; + AB56AB9528F87A3900A2B9D5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB56AB8C28F87A3900A2B9D5 /* InfoPlist.strings */; }; + AB56AB9628F87A3900A2B9D5 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = AB56AB8E28F87A3900A2B9D5 /* Localizable.stringsdict */; }; + AB611E4228FE14F4008F0FB3 /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0266AB28F9F88A00B107D4 /* XcodeKit.framework */; }; + AB611E4328FE14F4008F0FB3 /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AB0266AB28F9F88A00B107D4 /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + ABB1B1C128F76132002CCBB5 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ABB1B1C028F76132002CCBB5 /* Preview Assets.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + AB0266B428F9F88A00B107D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AB2024CA28F758A7002A8481 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AB0266A628F9F88A00B107D4; + remoteInfo = Extension; + }; + AB2024E428F758A8002A8481 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AB2024CA28F758A7002A8481 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AB2024D128F758A7002A8481; + remoteInfo = XcodeGeeDblA; + }; + AB2024EE28F758A8002A8481 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AB2024CA28F758A7002A8481 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AB2024D128F758A7002A8481; + remoteInfo = XcodeGeeDblA; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + AB0266B728F9F88A00B107D4 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + AB0266B628F9F88A00B107D4 /* GeeDblA Xcode Extension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + AB611E4428FE14F4008F0FB3 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + AB611E4328FE14F4008F0FB3 /* XcodeKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + AB0266A728F9F88A00B107D4 /* GeeDblA Xcode Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "GeeDblA Xcode Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + AB0266A928F9F88A00B107D4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + AB0266AB28F9F88A00B107D4 /* XcodeKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XcodeKit.framework; path = Library/Frameworks/XcodeKit.framework; sourceTree = DEVELOPER_DIR; }; + AB0266AE28F9F88A00B107D4 /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; + AB0266B028F9F88A00B107D4 /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; + AB0266B228F9F88A00B107D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + AB0266B328F9F88A00B107D4 /* Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Extension.entitlements; sourceTree = ""; }; + AB0266BC28F9FCEF00B107D4 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + AB2024D228F758A7002A8481 /* XcodeGeeDblA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XcodeGeeDblA.app; sourceTree = BUILT_PRODUCTS_DIR; }; + AB2024D528F758A7002A8481 /* XcodeGeeDblAApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeGeeDblAApp.swift; sourceTree = ""; }; + AB2024D728F758A7002A8481 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + AB2024E328F758A8002A8481 /* XcodeGeeDblATests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XcodeGeeDblATests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + AB2024E728F758A8002A8481 /* XcodeGeeDblATests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeGeeDblATests.swift; sourceTree = ""; }; + AB2024ED28F758A8002A8481 /* XcodeGeeDblAUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XcodeGeeDblAUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + AB2024F128F758A8002A8481 /* XcodeGeeDblAUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeGeeDblAUITests.swift; sourceTree = ""; }; + AB2024F328F758A8002A8481 /* XcodeGeeDblAUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeGeeDblAUITestsLaunchTests.swift; sourceTree = ""; }; + AB56AB8428F87A3900A2B9D5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + AB56AB8728F87A3900A2B9D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Main.strings; sourceTree = ""; }; + AB56AB8928F87A3900A2B9D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + AB56AB8B28F87A3900A2B9D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + AB56AB8D28F87A3900A2B9D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = ""; }; + AB56AB8F28F87A3900A2B9D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = Base; path = Base.lproj/Localizable.stringsdict; sourceTree = ""; }; + AB56AB9028F87A3900A2B9D5 /* XcodeGeeDblA.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = XcodeGeeDblA.entitlements; sourceTree = ""; }; + ABB1B1C028F76132002CCBB5 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + AB0266A428F9F88A00B107D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AB0266AA28F9F88A00B107D4 /* Cocoa.framework in Frameworks */, + AB611E4228FE14F4008F0FB3 /* XcodeKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024CF28F758A7002A8481 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024E028F758A8002A8481 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024EA28F758A8002A8481 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + AB0266A828F9F88A00B107D4 /* Frameworks */ = { + isa = PBXGroup; + children = ( + AB0266A928F9F88A00B107D4 /* Cocoa.framework */, + AB0266AB28F9F88A00B107D4 /* XcodeKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + AB0266AD28F9F88A00B107D4 /* Extension */ = { + isa = PBXGroup; + children = ( + AB0266B328F9F88A00B107D4 /* Extension.entitlements */, + AB0266B228F9F88A00B107D4 /* Info.plist */, + AB0266BC28F9FCEF00B107D4 /* Constants.swift */, + AB0266B028F9F88A00B107D4 /* SourceEditorCommand.swift */, + AB0266AE28F9F88A00B107D4 /* SourceEditorExtension.swift */, + ); + path = Extension; + sourceTree = ""; + }; + AB2024C928F758A7002A8481 = { + isa = PBXGroup; + children = ( + AB2024D428F758A7002A8481 /* XcodeGeeDblA */, + AB2024E628F758A8002A8481 /* XcodeGeeDblATests */, + AB2024F028F758A8002A8481 /* XcodeGeeDblAUITests */, + ABB1B1BF28F76132002CCBB5 /* Preview Content */, + AB0266AD28F9F88A00B107D4 /* Extension */, + AB0266A828F9F88A00B107D4 /* Frameworks */, + AB2024D328F758A7002A8481 /* Products */, + ); + sourceTree = ""; + }; + AB2024D328F758A7002A8481 /* Products */ = { + isa = PBXGroup; + children = ( + AB2024D228F758A7002A8481 /* XcodeGeeDblA.app */, + AB2024E328F758A8002A8481 /* XcodeGeeDblATests.xctest */, + AB2024ED28F758A8002A8481 /* XcodeGeeDblAUITests.xctest */, + AB0266A728F9F88A00B107D4 /* GeeDblA Xcode Extension.appex */, + ); + name = Products; + sourceTree = ""; + }; + AB2024D428F758A7002A8481 /* XcodeGeeDblA */ = { + isa = PBXGroup; + children = ( + AB56AB8428F87A3900A2B9D5 /* Assets.xcassets */, + AB2024D728F758A7002A8481 /* ContentView.swift */, + AB2024D528F758A7002A8481 /* XcodeGeeDblAApp.swift */, + AB56AB8528F87A3900A2B9D5 /* Resources */, + ); + path = XcodeGeeDblA; + sourceTree = ""; + }; + AB2024E628F758A8002A8481 /* XcodeGeeDblATests */ = { + isa = PBXGroup; + children = ( + AB2024E728F758A8002A8481 /* XcodeGeeDblATests.swift */, + ); + path = XcodeGeeDblATests; + sourceTree = ""; + }; + AB2024F028F758A8002A8481 /* XcodeGeeDblAUITests */ = { + isa = PBXGroup; + children = ( + AB2024F128F758A8002A8481 /* XcodeGeeDblAUITests.swift */, + AB2024F328F758A8002A8481 /* XcodeGeeDblAUITestsLaunchTests.swift */, + ); + path = XcodeGeeDblAUITests; + sourceTree = ""; + }; + AB56AB8528F87A3900A2B9D5 /* Resources */ = { + isa = PBXGroup; + children = ( + AB56AB8628F87A3900A2B9D5 /* Main.strings */, + AB56AB8828F87A3900A2B9D5 /* Main.storyboard */, + AB56AB8A28F87A3900A2B9D5 /* Localizable.strings */, + AB56AB8C28F87A3900A2B9D5 /* InfoPlist.strings */, + AB56AB8E28F87A3900A2B9D5 /* Localizable.stringsdict */, + AB56AB9028F87A3900A2B9D5 /* XcodeGeeDblA.entitlements */, + ); + path = Resources; + sourceTree = ""; + }; + ABB1B1BF28F76132002CCBB5 /* Preview Content */ = { + isa = PBXGroup; + children = ( + ABB1B1C028F76132002CCBB5 /* Preview Assets.xcassets */, + ); + name = "Preview Content"; + path = "XcodeGeeDblA/Preview Content"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + AB0266A628F9F88A00B107D4 /* GeeDblA Xcode Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = AB0266BB28F9F88A00B107D4 /* Build configuration list for PBXNativeTarget "GeeDblA Xcode Extension" */; + buildPhases = ( + AB0266A328F9F88A00B107D4 /* Sources */, + AB0266A428F9F88A00B107D4 /* Frameworks */, + AB0266A528F9F88A00B107D4 /* Resources */, + AB611E4428FE14F4008F0FB3 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "GeeDblA Xcode Extension"; + productName = Extension; + productReference = AB0266A728F9F88A00B107D4 /* GeeDblA Xcode Extension.appex */; + productType = "com.apple.product-type.xcode-extension"; + }; + AB2024D128F758A7002A8481 /* XcodeGeeDblA */ = { + isa = PBXNativeTarget; + buildConfigurationList = AB2024F728F758A8002A8481 /* Build configuration list for PBXNativeTarget "XcodeGeeDblA" */; + buildPhases = ( + ABB1B1C228F76374002CCBB5 /* Swift Lint */, + AB2024CE28F758A7002A8481 /* Sources */, + AB2024CF28F758A7002A8481 /* Frameworks */, + ABB1B1C428F76B27002CCBB5 /* Overlay Build Info On Icon */, + AB2024D028F758A7002A8481 /* Resources */, + ABB1B1C528F76D9A002CCBB5 /* Reset App Icon */, + AB0266B728F9F88A00B107D4 /* Embed Foundation Extensions */, + ); + buildRules = ( + ); + dependencies = ( + AB0266B528F9F88A00B107D4 /* PBXTargetDependency */, + ); + name = XcodeGeeDblA; + productName = XcodeGeeDblA; + productReference = AB2024D228F758A7002A8481 /* XcodeGeeDblA.app */; + productType = "com.apple.product-type.application"; + }; + AB2024E228F758A8002A8481 /* XcodeGeeDblATests */ = { + isa = PBXNativeTarget; + buildConfigurationList = AB2024FA28F758A8002A8481 /* Build configuration list for PBXNativeTarget "XcodeGeeDblATests" */; + buildPhases = ( + AB2024DF28F758A8002A8481 /* Sources */, + AB2024E028F758A8002A8481 /* Frameworks */, + AB2024E128F758A8002A8481 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + AB2024E528F758A8002A8481 /* PBXTargetDependency */, + ); + name = XcodeGeeDblATests; + productName = XcodeGeeDblATests; + productReference = AB2024E328F758A8002A8481 /* XcodeGeeDblATests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + AB2024EC28F758A8002A8481 /* XcodeGeeDblAUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = AB2024FD28F758A8002A8481 /* Build configuration list for PBXNativeTarget "XcodeGeeDblAUITests" */; + buildPhases = ( + AB2024E928F758A8002A8481 /* Sources */, + AB2024EA28F758A8002A8481 /* Frameworks */, + AB2024EB28F758A8002A8481 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + AB2024EF28F758A8002A8481 /* PBXTargetDependency */, + ); + name = XcodeGeeDblAUITests; + productName = XcodeGeeDblAUITests; + productReference = AB2024ED28F758A8002A8481 /* XcodeGeeDblAUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + AB2024CA28F758A7002A8481 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1400; + LastUpgradeCheck = 1410; + ORGANIZATIONNAME = "Gee Dbl A"; + TargetAttributes = { + AB0266A628F9F88A00B107D4 = { + CreatedOnToolsVersion = 14.0.1; + }; + AB2024D128F758A7002A8481 = { + CreatedOnToolsVersion = 14.0.1; + }; + AB2024E228F758A8002A8481 = { + CreatedOnToolsVersion = 14.0.1; + TestTargetID = AB2024D128F758A7002A8481; + }; + AB2024EC28F758A8002A8481 = { + CreatedOnToolsVersion = 14.0.1; + TestTargetID = AB2024D128F758A7002A8481; + }; + }; + }; + buildConfigurationList = AB2024CD28F758A7002A8481 /* Build configuration list for PBXProject "XcodeGeeDblA" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = AB2024C928F758A7002A8481; + productRefGroup = AB2024D328F758A7002A8481 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + AB2024D128F758A7002A8481 /* XcodeGeeDblA */, + AB2024E228F758A8002A8481 /* XcodeGeeDblATests */, + AB2024EC28F758A8002A8481 /* XcodeGeeDblAUITests */, + AB0266A628F9F88A00B107D4 /* GeeDblA Xcode Extension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + AB0266A528F9F88A00B107D4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024D028F758A7002A8481 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB56AB9428F87A3900A2B9D5 /* Localizable.strings in Resources */, + AB56AB9528F87A3900A2B9D5 /* InfoPlist.strings in Resources */, + AB56AB9228F87A3900A2B9D5 /* Main.strings in Resources */, + AB56AB9128F87A3900A2B9D5 /* Assets.xcassets in Resources */, + ABB1B1C128F76132002CCBB5 /* Preview Assets.xcassets in Resources */, + AB56AB9328F87A3900A2B9D5 /* Main.storyboard in Resources */, + AB56AB9628F87A3900A2B9D5 /* Localizable.stringsdict in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024E128F758A8002A8481 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024EB28F758A8002A8481 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + ABB1B1C228F76374002CCBB5 /* Swift Lint */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Swift Lint"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/usr/bin/env sh\nif [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n\tif [[ -f \"/opt/homebrew/bin/brew\" ]]; then\n\t\texport PATH=\"/opt/homebrew/bin:/opt/homebrew/sbin:$PATH\"\n\tfi\n\n if which swiftlint >/dev/null; then\n\t\t find \"$SRCROOT\" -type f -name \"*.swift\" -print0 | xargs -0 swiftlint --fix --config \"$PROJECT_DIR/.swiftlint.yml\"\n else\n echo \"warning: SwiftLint not installed, brew install SwiftLint\"\n fi\nfi\n"; + }; + ABB1B1C428F76B27002CCBB5 /* Overlay Build Info On Icon */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Overlay Build Info On Icon"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/usr/bin/env sh\nif [ \"${CONFIGURATION}\" = \"TestFlight\" ]; then\n\tif [ -f \"/opt/homebrew/bin/brew\" ]; then\n\t\texport PATH=\"/opt/homebrew/bin:/opt/homebrew/sbin:$PATH\"\n\tfi\n\n\tif which magick >/dev/null; then\n\t\ticonDir=\"$SRCROOT/$PROJECT_NAME/Assets.xcassets/AppIcon.appiconset\"\n\t\tmkdir -p \"${TMPDIR}/${iconDir}\"\n\t\techo \"${TMPDIR}/${iconDir}\"\n\t\tcp -rf \"${iconDir}\" \"${TMPDIR}/${iconDir}\"\n\n\t\tfor file in $(find \"$iconDir\" -name \"*.png\" -type f); do\n\t\t\twidth=$(magick identify -format %w \"$file\")\n\t\t\tif [ \"$width\" = 1024 ]; then\n\t\t\t\tlargeIcon=\"$file\"\n\t\t\t\tbreak\n\t\t\tfi\n\t\tdone\n\n\t\tversion=\"$MARKETING_VERSION\"\n\t\tbuild=\"$CURRENT_PROJECT_VERSION\"\n\t\tcaption=\"v${version}\\nBuild: ${build}\"\n\t\twidth=$(magick identify -format %w ${largeIcon})\n\t\theight=$(magick identify -format %h ${largeIcon})\n\t\tband_height=$((($height * 47) / 100))\n\t\tband_position=$(($height - $band_height))\n\t\ttext_position=$(($band_position - 3))\n\t\tpoint_size=$(((13 * $width) / 100))\n\n\t\tmagick convert \"${largeIcon}\" -blur 10x8 /tmp/blurred.png\n \tmagick convert \"${largeIcon}\" -gamma 0 -fill white -draw \"rectangle 0,$band_position,$width,$height\" /tmp/mask.png\n \tmagick convert -size ${width}x${band_height} xc:none -fill 'rgba(0,0,0,0.2)' -draw \"rectangle 0,0,$width,$band_height\" /tmp/labels-base.png\n \tmagick convert -background none -size ${width}x${band_height} -pointsize $point_size -fill white -gravity center -gravity South caption:\"$caption\" /tmp/labels.png\n \tmagick convert \"$largeIcon\" /tmp/blurred.png /tmp/mask.png -composite /tmp/temp.png\n \tmagick convert /tmp/temp.png /tmp/labels-base.png -geometry +0+$band_position -composite /tmp/labels.png -geometry +0+$text_position -geometry +${w}-${h} -composite \"$largeIcon\"\n\n\t\t#rm -f /tmp/*.png\n\t\tfor file in $(find \"$iconDir\" -name \"*.png\" -type f); do\n\t\t\tdim=$(magick identify -format \"%wx%h\" \"$file\")\n\t\t\tif [ \"$dim\" != \"1024x1024\" ]; then\n\t\t\t\tmagick convert \"$largeIcon\" -resize \"$dim!\" \"$file\"\n\t\t\tfi\n\t\tdone\n\telse\n\t echo \"warning: Image Magick not installed, brew install imagemagick\"\n\tfi\nfi\nexit 0\n\n"; + }; + ABB1B1C528F76D9A002CCBB5 /* Reset App Icon */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Reset App Icon"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + AB0266A328F9F88A00B107D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB0266AF28F9F88A00B107D4 /* SourceEditorExtension.swift in Sources */, + AB0266B128F9F88A00B107D4 /* SourceEditorCommand.swift in Sources */, + AB0266BD28F9FCEF00B107D4 /* Constants.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024CE28F758A7002A8481 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2024D828F758A7002A8481 /* ContentView.swift in Sources */, + AB2024D628F758A7002A8481 /* XcodeGeeDblAApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024DF28F758A8002A8481 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2024E828F758A8002A8481 /* XcodeGeeDblATests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AB2024E928F758A8002A8481 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2024F228F758A8002A8481 /* XcodeGeeDblAUITests.swift in Sources */, + AB2024F428F758A8002A8481 /* XcodeGeeDblAUITestsLaunchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + AB0266B528F9F88A00B107D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AB0266A628F9F88A00B107D4 /* GeeDblA Xcode Extension */; + targetProxy = AB0266B428F9F88A00B107D4 /* PBXContainerItemProxy */; + }; + AB2024E528F758A8002A8481 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AB2024D128F758A7002A8481 /* XcodeGeeDblA */; + targetProxy = AB2024E428F758A8002A8481 /* PBXContainerItemProxy */; + }; + AB2024EF28F758A8002A8481 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AB2024D128F758A7002A8481 /* XcodeGeeDblA */; + targetProxy = AB2024EE28F758A8002A8481 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + AB56AB8628F87A3900A2B9D5 /* Main.strings */ = { + isa = PBXVariantGroup; + children = ( + AB56AB8728F87A3900A2B9D5 /* Base */, + ); + name = Main.strings; + sourceTree = ""; + }; + AB56AB8828F87A3900A2B9D5 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + AB56AB8928F87A3900A2B9D5 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + AB56AB8A28F87A3900A2B9D5 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + AB56AB8B28F87A3900A2B9D5 /* Base */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + AB56AB8C28F87A3900A2B9D5 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + AB56AB8D28F87A3900A2B9D5 /* Base */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + AB56AB8E28F87A3900A2B9D5 /* Localizable.stringsdict */ = { + isa = PBXVariantGroup; + children = ( + AB56AB8F28F87A3900A2B9D5 /* Base */, + ); + name = Localizable.stringsdict; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + AB0266B828F9F88A00B107D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Extension/Extension.entitlements; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + ENABLE_HARDENED_RUNTIME = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Extension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Gee Dbl A's Xcode Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 By Gary Ash All rights reserved. + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblA.Extension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + AB0266B928F9F88A00B107D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Extension/Extension.entitlements; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + ENABLE_HARDENED_RUNTIME = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Extension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Gee Dbl A's Xcode Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 By Gary Ash All rights reserved. + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblA.Extension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + AB0266BA28F9F88A00B107D4 /* TestFlight */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Extension/Extension.entitlements; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + ENABLE_HARDENED_RUNTIME = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Extension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Gee Dbl A's Xcode Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 By Gary Ash All rights reserved. + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblA.Extension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = TestFlight; + }; + AB2024F528F758A8002A8481 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + 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; + CLANG_WARN_ENUM_CONVERSION = YES; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + AB2024F628F758A8002A8481 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + 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; + CLANG_WARN_ENUM_CONVERSION = YES; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + AB2024F828F758A8002A8481 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = XcodeGeeDblA/Resources/XcodeGeeDblA.entitlements; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_ASSET_PATHS = "\"XcodeGeeDblA/Preview Content\""; + DEVELOPMENT_TEAM = H46K66JBHS; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "Gee Dbl A's Xcode Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblA; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + AB2024F928F758A8002A8481 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = XcodeGeeDblA/Resources/XcodeGeeDblA.entitlements; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEPLOYMENT_POSTPROCESSING = YES; + DEVELOPMENT_ASSET_PATHS = "\"XcodeGeeDblA/Preview Content\""; + DEVELOPMENT_TEAM = H46K66JBHS; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "Gee Dbl A's Xcode Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblA; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIPFLAGS = "-rSTx"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + AB2024FB28F758A8002A8481 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblATests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XcodeGeeDblA.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/XcodeGeeDblA"; + }; + name = Debug; + }; + AB2024FC28F758A8002A8481 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblATests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XcodeGeeDblA.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/XcodeGeeDblA"; + }; + name = Release; + }; + AB2024FE28F758A8002A8481 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblAUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = XcodeGeeDblA; + }; + name = Debug; + }; + AB2024FF28F758A8002A8481 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblAUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = XcodeGeeDblA; + }; + name = Release; + }; + ABD11BBA28F75EDC008AF08B /* TestFlight */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + 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; + CLANG_WARN_ENUM_CONVERSION = YES; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = TestFlight; + }; + ABD11BBB28F75EDC008AF08B /* TestFlight */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = XcodeGeeDblA/Resources/XcodeGeeDblA.entitlements; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEPLOYMENT_POSTPROCESSING = YES; + DEVELOPMENT_ASSET_PATHS = "\"XcodeGeeDblA/Preview Content\""; + DEVELOPMENT_TEAM = H46K66JBHS; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "Gee Dbl A's Xcode Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblA; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIPFLAGS = "-rSTx"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = TestFlight; + }; + ABD11BBC28F75EDC008AF08B /* TestFlight */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblATests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XcodeGeeDblA.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/XcodeGeeDblA"; + }; + name = TestFlight; + }; + ABD11BBD28F75EDC008AF08B /* TestFlight */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = H46K66JBHS; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.geedbla.XcodeGeeDblAUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = XcodeGeeDblA; + }; + name = TestFlight; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + AB0266BB28F9F88A00B107D4 /* Build configuration list for PBXNativeTarget "GeeDblA Xcode Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB0266B828F9F88A00B107D4 /* Debug */, + AB0266B928F9F88A00B107D4 /* Release */, + AB0266BA28F9F88A00B107D4 /* TestFlight */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AB2024CD28F758A7002A8481 /* Build configuration list for PBXProject "XcodeGeeDblA" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB2024F528F758A8002A8481 /* Debug */, + AB2024F628F758A8002A8481 /* Release */, + ABD11BBA28F75EDC008AF08B /* TestFlight */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AB2024F728F758A8002A8481 /* Build configuration list for PBXNativeTarget "XcodeGeeDblA" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB2024F828F758A8002A8481 /* Debug */, + AB2024F928F758A8002A8481 /* Release */, + ABD11BBB28F75EDC008AF08B /* TestFlight */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AB2024FA28F758A8002A8481 /* Build configuration list for PBXNativeTarget "XcodeGeeDblATests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB2024FB28F758A8002A8481 /* Debug */, + AB2024FC28F758A8002A8481 /* Release */, + ABD11BBC28F75EDC008AF08B /* TestFlight */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AB2024FD28F758A8002A8481 /* Build configuration list for PBXNativeTarget "XcodeGeeDblAUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB2024FE28F758A8002A8481 /* Debug */, + AB2024FF28F758A8002A8481 /* Release */, + ABD11BBD28F75EDC008AF08B /* TestFlight */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = AB2024CA28F758A7002A8481 /* Project object */; +} diff --git a/XcodeGeeDblA.xcodeproj/xcshareddata/.gitkeep b/XcodeGeeDblA.xcodeproj/xcshareddata/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/Extension.xcscheme b/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/Extension.xcscheme new file mode 100644 index 0000000..d5e74a1 --- /dev/null +++ b/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/Extension.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/TestFlight.xcscheme b/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/TestFlight.xcscheme new file mode 100644 index 0000000..d443d3e --- /dev/null +++ b/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/TestFlight.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/XcodeGeeDblA.xcscheme b/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/XcodeGeeDblA.xcscheme new file mode 100644 index 0000000..d582675 --- /dev/null +++ b/XcodeGeeDblA.xcodeproj/xcshareddata/xcschemes/XcodeGeeDblA.xcscheme @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XcodeGeeDblA/Assets.xcassets/AccentColor.colorset/Contents.json b/XcodeGeeDblA/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..6112869 --- /dev/null +++ b/XcodeGeeDblA/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,15 @@ +{ + "colors" : [ + { + "color" : { + "platform" : "universal", + "reference" : "systemBlueColor" + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/Contents.json b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..30cf2f6 --- /dev/null +++ b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "filename" : "icon_16x16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "icon_16x16@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "icon_32x32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "icon_32x32@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "icon_128x128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "icon_128x128@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "icon_256x256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "icon_512x512.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "icon_512x512 1.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "icon_512x512@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_128x128.png new file mode 100644 index 0000000..bf31f54 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_128x128.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png new file mode 100644 index 0000000..073a1c7 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_16x16.png new file mode 100644 index 0000000..4c74ed5 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_16x16.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png new file mode 100644 index 0000000..3e3bca7 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_256x256.png new file mode 100644 index 0000000..073a1c7 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_256x256.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_32x32.png new file mode 100644 index 0000000..3e3bca7 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_32x32.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png new file mode 100644 index 0000000..2fbd03d Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512 1.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512 1.png new file mode 100644 index 0000000..51db7c3 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512 1.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512.png new file mode 100644 index 0000000..51db7c3 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png new file mode 100644 index 0000000..09d0ed3 Binary files /dev/null and b/XcodeGeeDblA/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png differ diff --git a/XcodeGeeDblA/Assets.xcassets/Contents.json b/XcodeGeeDblA/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/XcodeGeeDblA/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XcodeGeeDblA/ContentView.swift b/XcodeGeeDblA/ContentView.swift new file mode 100644 index 0000000..2fe28fc --- /dev/null +++ b/XcodeGeeDblA/ContentView.swift @@ -0,0 +1,64 @@ +/***************************************************************************************** + * ContentView.swift + * + * This file contains the implementation of the copyright's list editor. + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import SwiftUI + +struct ContentView: View { + @State private var selection: String? + @State private var copyrightHolder = "" + @State var copyrightHolders: [String] + + var body: some View { + VStack { + VStack { + Text("copyright.holders") + .font(.title) + HStack(spacing: 10) { + TextField("copyright holder", text: $copyrightHolder) + .overlay(RoundedRectangle(cornerRadius: 3.0).strokeBorder(Color.blue, style: StrokeStyle(lineWidth: 1.0))) + .padding() + + Button("add") { + copyrightHolder = copyrightHolder.trimmingCharacters(in: .whitespacesAndNewlines) + copyrightHolders.append(copyrightHolder) + copyrightHolders.sort() + UserDefaults(suiteName: "XcodeGeeDblA")?.set(copyrightHolders, forKey: "Copyright Holders") + copyrightHolder = "" + } + } + Spacer() + } + List(selection: $selection) { + ForEach(copyrightHolders, id: \.self) { company in + Text(company) + } + .onDelete { + copyrightHolders.remove(atOffsets: $0) + UserDefaults(suiteName: "XcodeGeeDblA")?.set(copyrightHolders, forKey: "Copyright Holders") + } + } + } + .padding(20) + } + + init() { + var temp = UserDefaults(suiteName: "XcodeGeeDblA")?.array(forKey: "Copyright Holders") as? [String] ?? [] + temp.sort() + copyrightHolders = temp + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/XcodeGeeDblA/Preview Content/.gitkeep b/XcodeGeeDblA/Preview Content/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XcodeGeeDblA/Preview Content/Preview Assets.xcassets/Contents.json b/XcodeGeeDblA/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/XcodeGeeDblA/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XcodeGeeDblA/Resources/Base.lproj/InfoPlist.strings b/XcodeGeeDblA/Resources/Base.lproj/InfoPlist.strings new file mode 100644 index 0000000..788cbd7 --- /dev/null +++ b/XcodeGeeDblA/Resources/Base.lproj/InfoPlist.strings @@ -0,0 +1,11 @@ +/***************************************************************************************** + * InfoPlist.strings + * + * + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ \ No newline at end of file diff --git a/XcodeGeeDblA/Resources/Base.lproj/Localizable.strings b/XcodeGeeDblA/Resources/Base.lproj/Localizable.strings new file mode 100644 index 0000000..dc3fa7a --- /dev/null +++ b/XcodeGeeDblA/Resources/Base.lproj/Localizable.strings @@ -0,0 +1,14 @@ +/***************************************************************************************** + * Localizable.strings + * + * + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ +"copyright holder" = "Copyright Holder"; +"copyright.holders" = "Copyright Holders"; +"add" = "Add"; diff --git a/XcodeGeeDblA/Resources/Base.lproj/Localizable.stringsdict b/XcodeGeeDblA/Resources/Base.lproj/Localizable.stringsdict new file mode 100644 index 0000000..006d3e9 --- /dev/null +++ b/XcodeGeeDblA/Resources/Base.lproj/Localizable.stringsdict @@ -0,0 +1,30 @@ + + + + + StringKey + + NSStringLocalizedFormatKey + %#@VARIABLE@ + VARIABLE + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + + zero + + one + + two + + few + + many + + other + + + + + diff --git a/XcodeGeeDblA/Resources/Base.lproj/Main.storyboard b/XcodeGeeDblA/Resources/Base.lproj/Main.storyboard new file mode 100644 index 0000000..7cc234c --- /dev/null +++ b/XcodeGeeDblA/Resources/Base.lproj/Main.storyboard @@ -0,0 +1,717 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XcodeGeeDblA/Resources/Base.lproj/Main.strings b/XcodeGeeDblA/Resources/Base.lproj/Main.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/XcodeGeeDblA/Resources/Base.lproj/Main.strings @@ -0,0 +1 @@ + diff --git a/XcodeGeeDblA/Resources/XcodeGeeDblA.entitlements b/XcodeGeeDblA/Resources/XcodeGeeDblA.entitlements new file mode 100644 index 0000000..af3dc88 --- /dev/null +++ b/XcodeGeeDblA/Resources/XcodeGeeDblA.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.security.application-groups + + XcodeGeeDblA + + + diff --git a/XcodeGeeDblA/XcodeGeeDblAApp.swift b/XcodeGeeDblA/XcodeGeeDblAApp.swift new file mode 100644 index 0000000..4b487d7 --- /dev/null +++ b/XcodeGeeDblA/XcodeGeeDblAApp.swift @@ -0,0 +1,22 @@ +/***************************************************************************************** + * XcodeGeeDblAApp.swift + * + * This file implements the application object + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import SwiftUI + +@main +struct XcodeGeeDblAApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/XcodeGeeDblATests/XcodeGeeDblATests.swift b/XcodeGeeDblATests/XcodeGeeDblATests.swift new file mode 100644 index 0000000..efa6a55 --- /dev/null +++ b/XcodeGeeDblATests/XcodeGeeDblATests.swift @@ -0,0 +1,39 @@ +/***************************************************************************************** + * XcodeGeeDblATests.swift + * + * + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +@testable import XcodeGeeDblA +import XCTest + +final class XcodeGeeDblATests: XCTestCase { + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } +} diff --git a/XcodeGeeDblAUITests/XcodeGeeDblAUITests.swift b/XcodeGeeDblAUITests/XcodeGeeDblAUITests.swift new file mode 100644 index 0000000..0de4e28 --- /dev/null +++ b/XcodeGeeDblAUITests/XcodeGeeDblAUITests.swift @@ -0,0 +1,45 @@ +/***************************************************************************************** + * XcodeGeeDblAUITests.swift + * + * + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import XCTest + +final class XcodeGeeDblAUITests: XCTestCase { + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/XcodeGeeDblAUITests/XcodeGeeDblAUITestsLaunchTests.swift b/XcodeGeeDblAUITests/XcodeGeeDblAUITestsLaunchTests.swift new file mode 100644 index 0000000..b33713a --- /dev/null +++ b/XcodeGeeDblAUITests/XcodeGeeDblAUITestsLaunchTests.swift @@ -0,0 +1,36 @@ +/***************************************************************************************** + * XcodeGeeDblAUITestsLaunchTests.swift + * + * + * + * Author : Gary Ash + * Created : 28-Apr-2024 3:03pm + * Modified : + * + * Copyright © 2024 By Gary Ash All rights reserved. + ****************************************************************************************/ + +import XCTest + +final class XcodeGeeDblAUITestsLaunchTests: XCTestCase { + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +}