Skip to content

Commit 53cf6c7

Browse files
authored
Merge pull request #5 from oarrabi/oarrabi/adding-colors
Working on the output strings
2 parents d39927b + 0b44e37 commit 53cf6c7

30 files changed

+1316
-49
lines changed

Makefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ build-linux-docker:
7272
docker-compose run -w /work swift
7373
@echo "\nLinux version built at bin/linux/guaka\n"
7474

75-
build-all-local: clean build-linux-docker build-project-darwin
75+
build-all-local: clone-swiftline clean build-linux-docker build-project-darwin
7676
@echo "Binaries built at bin/\n"
7777

7878
release-local:
@@ -93,6 +93,15 @@ release-publish-local:
9393
make release-local
9494
make publish-local
9595

96+
clone-swiftline:
97+
@echo "Removing old Swiftline"
98+
@echo ""
99+
rm -rf SwiftLineTemp
100+
101+
@echo "Clone new Swiftline from oarrabi/linux! branch"
102+
git clone -b oarrabi/linux! https://github.com/oarrabi/Swiftline.git SwiftLineTemp
103+
mv SwiftLineTemp/Sources/*.* Sources/Swiftline/
104+
rm -rf SwiftLineTemp
96105

97106
release-and-deploy:
98107
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make build-project-darwin release-darwin VERSION=${TRAVIS_TAG} GITHUB_TOKEN=${GITHUB_TOKEN} ; fi

Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ let package = Package(
44
name: "guaka-cli",
55
targets: [
66
Target(name: "guaka-cli", dependencies: ["GuakaClILib"]),
7-
Target(name: "GuakaClILib"),
7+
Target(name: "Swiftline"),
8+
Target(name: "GuakaClILib", dependencies: ["Swiftline"]),
89
],
910
dependencies: [
1011
.Package(url: "https://github.com/oarrabi/Guaka.git", majorVersion: 0),

Sources/GuakaClILib/GeneratorParts.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public enum GeneratorParts {
2929
generatedComment,
3030
"func setupCommands() {",
3131
comamndAddingPlaceholder,
32-
"}"
32+
"}",
33+
""
3334
].joined(separator: "\n")
3435
}
3536

@@ -41,6 +42,7 @@ public enum GeneratorParts {
4142
"setupCommands()",
4243
"",
4344
"rootCommand.execute()",
45+
""
4446
].joined(separator: "\n")
4547
}
4648

@@ -66,6 +68,7 @@ public enum GeneratorParts {
6668
" // Execute code here",
6769
" print(\"\(commandName) called\")",
6870
"}",
71+
""
6972
].joined(separator: "\n")
7073
}
7174

@@ -77,7 +80,8 @@ public enum GeneratorParts {
7780
" dependencies: [",
7881
" .Package(url: \"\(guakaURL)\", majorVersion: \(guakaVersion)),",
7982
" ]",
80-
")"
83+
")",
84+
""
8185
].joined(separator: "\n")
8286
}
8387

Sources/GuakaClILib/MiscTypes.swift

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// Created by Omar Abdelhafith on 27/11/2016.
66
//
77
//
8+
import Swiftline
9+
810

911
public struct GuakaCliConfig {
1012
public static var dir: DirectoryType.Type = FileSystemDirectory.self
@@ -20,35 +22,53 @@ public enum GuakaError: Error {
2022
case cannotReadFile(String)
2123
case setupFileAltered
2224
case notAGuakaProject
25+
case commandAlreadyExist(String, String)
2326
case missingCommandName
2427
case tooManyArgsPassed
2528
case wrongCommandNameFormat(String)
2629

2730
public var error: String {
2831
switch self {
2932
case .wrongDirectoryGiven(let path):
30-
return "The path given cannot be used \(path)"
33+
return [
34+
"Wrong path given:",
35+
" \(path)",
36+
"The path must be an empty directory"
37+
].joined(separator: "\n").f.red
38+
3139
case .triedToCreateProjectInNonEmptyDirectory(let path):
32-
return "Cannot create project in non empty directory \(path)\n"
40+
return "Cannot create project in non empty directory: \(path)\n".f.red
41+
3342
case .failedCreatingFolder(let path):
34-
return "Failed creating directory \(path)"
43+
return "Failed creating directory \(path)".f.red
44+
3545
case .cannotCreateFile (let name):
36-
return "Cannot generate \(name) file"
46+
return "Cannot generate \(name) file".f.red
47+
3748
case .cannotReadFile(let path):
38-
return "Cannot read contents of file \(path)"
49+
return "Cannot read contents of file \(path)".f.red
50+
3951
case .setupFileAltered:
40-
return "Guaka setup.swift file has been altered.\nThe placeholder used to insert commands cannot be found \(GeneratorParts.comamndAddingPlaceholder).\nYou can try to add it yourself by updating `setup.swift` to look like\n\n\(GeneratorParts.setupFileContent())\n\nAdding command wont be possible."
52+
return "Guaka setup.swift file has been altered.\nThe placeholder used to insert commands cannot be found \(GeneratorParts.comamndAddingPlaceholder).\nYou can try to add it yourself by updating `setup.swift` to look like\n\n\(GeneratorParts.setupFileContent())\n\nAdding command won't be possible.".f.red
53+
4154
case .notAGuakaProject:
42-
return "This command can only be executed in a Guaka project.\nThe following directory does not contain guaka files"
55+
return "This command can only be executed inside a Guaka project.".f.red
56+
4357
case .missingCommandName:
4458
return [
45-
"`guaka add` requires a command that was not given.",
59+
"Missing CommandName for `guaka add`.".f.red,
60+
"",
4661
"Call `guaka add CommandName` to create a new command.",
4762
""
4863
].joined(separator: "\n")
4964

65+
case .commandAlreadyExist(let name, let path):
66+
return [ "The command `\(name)` already exist:".f.red,
67+
" \(path)".f.red,
68+
"Please use a differnt command name"].joined(separator: "\n")
69+
5070
case .wrongCommandNameFormat(let name):
51-
return [ "The command name passed `\(name)` is incorrect.",
71+
return [ "The command name passed `\(name)` is incorrect.".f.red,
5272
"Please use only letters, numbers, underscodes and dashes.",
5373
"",
5474
"Valid examples:",
@@ -57,8 +77,10 @@ public enum GuakaError: Error {
5777
" guaka new my-command",
5878
" guaka new my_command",
5979
" guaka new myCommand"].joined(separator: "\n")
80+
6081
case .tooManyArgsPassed:
61-
return "Too many arguments passed to command."
82+
return "Too many arguments passed to command.".f.red
83+
6284
}
6385

6486
}

Sources/GuakaClILib/Paths.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,9 @@ public struct Paths {
5151

5252
return false
5353
}
54+
55+
public func isNewCommand(commandName: String) -> Bool {
56+
return GuakaCliConfig.file.exists(atPath: path(forSwiftFile: commandName)) == false
57+
}
5458

5559
}

Sources/Swiftline/Agree.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// Agree.swift
3+
// Agree
4+
//
5+
// Created by Omar Abdelhafith on 03/11/2015.
6+
// Copyright © 2015 Omar Abdelhafith. All rights reserved.
7+
//
8+
9+
/**
10+
Displays a yes/no prompt to the user
11+
12+
- parameter prompt: The prompt to display
13+
- returns: the user decision
14+
*/
15+
public func agree(_ prompt: String) -> Bool {
16+
PromptSettings.print(prompt, terminator: " ")
17+
let value = readStringOrEmpty()
18+
19+
let settings = AgreeSettings(prompt: prompt)
20+
let validatedValue = askForValidatedItem(originalValue: value, validator: settings)
21+
22+
return settings.isPositive(validatedValue)
23+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// AgreeSettings.swift
3+
// AgreeSettings
4+
//
5+
// Created by Omar Abdelhafith on 03/11/2015.
6+
// Copyright © 2015 Omar Abdelhafith. All rights reserved.
7+
//
8+
9+
10+
class AgreeSettings: AskerValidator {
11+
12+
let positiveValues = ["Yes", "yes", "Y", "y"]
13+
let negativeValues = ["No", "no", "N", "n"]
14+
15+
let prompt: String
16+
17+
init(prompt: String) {
18+
self.prompt = prompt
19+
}
20+
21+
func validatedItem(forString string: String) -> String {
22+
return string
23+
}
24+
25+
func invalidItemMessage(_ string: String?) -> String? {
26+
if let message = string , positiveValues.contains(message) || negativeValues.contains(message) {
27+
return nil
28+
}
29+
30+
return "Please enter \"yes\" or \"no\"."
31+
}
32+
33+
func newItemPromptMessage() -> String {
34+
return "\(prompt) "
35+
}
36+
37+
func isPositive(_ item: String) -> Bool {
38+
return positiveValues.contains(item)
39+
}
40+
41+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// ArgConvertible.swift
3+
// ArgConvertible
4+
//
5+
// Created by Omar Abdelhafith on 02/11/2015.
6+
// Copyright © 2015 Omar Abdelhafith. All rights reserved.
7+
//
8+
9+
10+
/**
11+
* Any type that extends ArgConvertibleType can be used in ask and choose
12+
*/
13+
public protocol ArgConvertibleType {
14+
15+
/// Create an instance out of a string
16+
static func fromString(_ string: String) -> Self?
17+
18+
/// Return the display name of a type
19+
static func typeName() -> String
20+
}
21+
22+
23+
extension Int: ArgConvertibleType {
24+
public static func fromString(_ string: String) -> Int? {
25+
return Int(string)
26+
}
27+
28+
public static func typeName() -> String {
29+
return "Integer"
30+
}
31+
}
32+
33+
34+
extension Double: ArgConvertibleType {
35+
public static func fromString(_ string: String) -> Double? {
36+
return Double(string)
37+
}
38+
39+
public static func typeName() -> String {
40+
return "Double"
41+
}
42+
}
43+
44+
extension Float: ArgConvertibleType {
45+
public static func fromString(_ string: String) -> Float? {
46+
return Float(string)
47+
}
48+
49+
public static func typeName() -> String {
50+
return "Float"
51+
}
52+
}
53+
54+
55+
extension String: ArgConvertibleType {
56+
public static func fromString(_ string: String) -> String? {
57+
return string
58+
}
59+
60+
public static func typeName() -> String {
61+
return "String"
62+
}
63+
}

Sources/Swiftline/Args.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//
2+
// Args.swift
3+
// Swiftline
4+
//
5+
// Created by Omar Abdelhafith on 25/11/2015.
6+
// Copyright © 2015 Omar Abdelhafith. All rights reserved.
7+
//
8+
9+
10+
/// Return the command line arguments passed to the script
11+
public class Args {
12+
13+
/// Return the list of arguments passed to the script
14+
public static var all: [String] {
15+
return CommandLine.arguments
16+
}
17+
18+
static var cachedResults: ParsedArgs?
19+
20+
/// Return a parsed list of arguments containing the flags and the parameters passed to the scripts
21+
/// The flags are recognized as short flags `-f` or long flags `--force`
22+
/// The flag value will be the argument that follows the flag
23+
/// `--` is used to mark the terminatin of the flags
24+
public static var parsed: ParsedArgs {
25+
let result = parse(argumens: all, cachedResults: cachedResults)
26+
cachedResults = result
27+
return result
28+
}
29+
30+
static func parse(argumens: [String], cachedResults: ParsedArgs?) -> ParsedArgs {
31+
if let result = cachedResults {
32+
return result
33+
}
34+
35+
var parsedFlags = [String: String]()
36+
let parsedArgs = ArgsParser.parseFlags(argumens)
37+
38+
parsedArgs.0.forEach {
39+
parsedFlags[$0.argument.name] = $0.value ?? ""
40+
}
41+
42+
var arguments = parsedArgs.1
43+
44+
// the first argument is always the executable's name
45+
var commandName = ""
46+
if let firstArgument = arguments.first { // just in case!
47+
commandName = firstArgument
48+
arguments.removeFirst(1)
49+
}
50+
51+
return ParsedArgs(command: commandName, flags: parsedFlags, parameters: arguments)
52+
}
53+
54+
}
55+
56+
57+
public struct ParsedArgs {
58+
/// The name of the executable that was invoked from the command line
59+
public let command: String
60+
61+
/// Parsed flags will be prepred in a dictionary, the key is the flag and the value is the flag value
62+
public let flags: [String: String]
63+
64+
/// List of parameters passed to the script
65+
public let parameters: [String]
66+
}

0 commit comments

Comments
 (0)