Skip to content

Commit

Permalink
drafting arguments parser adoption
Browse files Browse the repository at this point in the history
  • Loading branch information
elfenlaid committed Jun 15, 2020
1 parent fddc941 commit 7da9a23
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
"version": "0.9.0"
}
},
{
"package": "swift-argument-parser",
"repositoryURL": "https://github.com/apple/swift-argument-parser",
"state": {
"branch": null,
"revision": "3d79b2b5a2e5af52c14e462044702ea7728f5770",
"version": "0.1.0"
}
},
{
"package": "SwiftCLI",
"repositoryURL": "https://github.com/jakeheis/SwiftCLI",
Expand Down
10 changes: 9 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,22 @@ let package = Package(
.package(
url: "https://github.com/kylef/PathKit",
from: "1.0.0"
),
.package(
url: "https://github.com/apple/swift-argument-parser",
from: "0.1.0"
)
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "Badgy",
dependencies: ["SwiftCLI", "PathKit"]),
dependencies: [
"SwiftCLI",
"PathKit",
.product(name: "ArgumentParser", package: "swift-argument-parser")
]),
.testTarget(
name: "BadgyTests",
dependencies: ["Badgy"]),
Expand Down
143 changes: 143 additions & 0 deletions Sources/Badgy/Commands/Badgy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//
// Badgy
//

import Foundation
import ArgumentParser
import PathKit

struct Badgy: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "A command-line tool to add labels to your app icon",
version: "0.1.4",
subcommands: [Long.self, Small.self],
defaultSubcommand: Long.self
)
}

extension Badgy {
struct Options: ParsableArguments {
@Argument(help :"Specify badge text")
var label: String

@Argument(help :"Specify path to icon with format .png | .jpg | .appiconset", transform: IconPath.init(path:))
var icon: IconPath

@Option(help: "Position on which to place the badge")
var position: Position?

@Option(help: "Specify badge color with a hexadecimal color code format '#rrbbgg' | '#rrbbggaa'")
var color: HexColor?

@Option(help: "Specify badge text/tint color with a hexadecimal color code format '#rrbbgg' | '#rrbbggaa'")
var tintColor: HexColor?

@Flag(help: "Indicates Badgy should replace the input icon")
var replace: Bool

@Flag(help: "Log tech details for nerds")
var verbose: Bool

func validate() throws {
guard DependencyManager().areDependenciesInstalled() else {
throw ValidationError("Missing dependencies. Run: 'brew install imagemagick'")
}
}
}
}

extension Badgy {
struct Long: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "Add rectangular label to app icon"
)

@OptionGroup()
var options: Badgy.Options

@Option(help: "Rotation angle of the badge")
var angle: Int?

func validate() throws {
guard options.label.count <= 4 else {
throw ValidationError("Label should contain maximum 4 characters")
}

if let position = options.position {
let supportedPositions: [Position] = [
.top, .left, .bottom, .right, .center
]
guard supportedPositions.contains(position) else {
let formatted = supportedPositions
.map { $0.rawValue }
.joined(separator: " | ")

throw ValidationError("Invalid provided position, supported positions are: \(formatted)")
}
}

let validAngleRange = -180...180
if let angle = angle {
guard validAngleRange.contains(angle) else {
throw ValidationError("Angle should be within range: \(validAngleRange)")
}
}
}
}
}

extension Badgy {
struct Small: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "Add small square label to app icon"
)

@OptionGroup()
var options: Badgy.Options

func validate() throws {
guard options.label.count <= 1 else {
throw ValidationError("Label should contain maximum 1 characters")
}
}
}
}

extension Position: ExpressibleByArgument { }

struct HexColor: ExpressibleByArgument {
let value: String

init?(argument: String) {
guard NSRegularExpression.hexColorCode.matches(argument) else {
return nil
}

value = argument
}
}

struct IconPath {
static let supportedFormats = Set([
".png", ".jpg", ".jpeg", ".appiconset"
])

let path: Path

init(path: String) throws {
let path = Path(path)

guard path.exists else {
throw ValidationError("Input file doesn't exist")
}

let isSupportedFormat = IconPath.supportedFormats.contains {
path.lastComponent.contains($0)
}
guard isSupportedFormat else {
throw ValidationError("Input file doesn't have a valid format")
}

self.path = path
}
}
2 changes: 1 addition & 1 deletion Sources/Badgy/Helpers/Validation+HexColor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension Validation where T == String {
}
}

private extension NSRegularExpression {
extension NSRegularExpression {
/// `^` asserts position at start of a line
/// `#` matches the character # literally
///
Expand Down

0 comments on commit 7da9a23

Please sign in to comment.