Skip to content

Commit

Permalink
Merge pull request #68 from ABridoux/bugfix/65-Lux-json-escaped-quotes
Browse files Browse the repository at this point in the history
[#68] Lux json escaped quotes
  • Loading branch information
ABridoux authored Jul 4, 2020
2 parents 45e7d7b + a558ffc commit 84e8895
Show file tree
Hide file tree
Showing 18 changed files with 578 additions and 334 deletions.
17 changes: 13 additions & 4 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,26 @@
"repositoryURL": "https://github.com/ABridoux/lux",
"state": {
"branch": null,
"revision": "b97bc3f12e516669ab95e05161b91062f7934a64",
"version": "0.2.1"
"revision": "c0b65dceb8e36335874c412c9611fdac021a57af",
"version": "0.3.6"
}
},
{
"package": "Splash",
"repositoryURL": "https://github.com/JohnSundell/Splash",
"state": {
"branch": null,
"revision": "ca9a1b7bff35381fe5ae9fe2ec9333cc5f2a586c",
"version": "0.13.0"
}
},
{
"package": "swift-argument-parser",
"repositoryURL": "https://github.com/apple/swift-argument-parser",
"state": {
"branch": null,
"revision": "3d79b2b5a2e5af52c14e462044702ea7728f5770",
"version": "0.1.0"
"revision": "eb51f949cdd0c9d88abba9ce79d37eb7ea1231d0",
"version": "0.2.0"
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,14 @@ import ArgumentParser
import Scout
import Foundation

private let discussion =
"""
Notes
=====
- All the keys which do not exist in the path will be created
- Enclose the value with slash signs to force the value as a string: /valueAsString/ (Plist, Json)
- Enclose the value with interrogative signs to force the value as a boolean: ?valueToBoolean? (Plist, Json)
- Enclose the value with tilde signs to force the value as a real: ~valueToReal~ (Plist)
- Enclose the value with chevron signs to force the value as a integer: <valueToInteger> (Plist)
- When adding an element in an array , use the index -1 to add the element at the end of the array
Examples
========
Given the following Json (as input stream or file)
{
"people": {
"Tom": {
"height": 175,
"age": 68,
"hobbies": [
"cooking",
"guitar"
]
},
"Arnaud": {
"height": 180,
"age": 23,
"hobbies": [
"video games",
"party",
"tennis"
]
}
}
}
`scout add "people.Franklin.height"=165` will create a new dictionary Franklin and add a height key into it with the value 165
`scout add "people.Tom.hobbies[-1]"="Playing music"` will add the hobby "Playing music" to Tom hobbies at the end of the array
`scout add "people.Arnaud.hobbies[1]"=reading` will insert the hobby "reading" to Arnaud hobbies between the hobby "video games" and "party"
`scout add "people.Franklin.hobbies[0]"=football` will create a new dictionary Franklin, add a hobbies array into it, and insert the value "football" in the array
`scout add "people.Franklin.height"=/165/` will create a new dictionary Franklin and add a height key into it with the String value "165"
`scout add "people.Franklin.height"=~165~` will create a new dictionary Franklin and add a height key into it with the Real value 165 (Plist only)
More
====
You can find more examples here: https://github.com/ABridoux/scout/tree/master/Playground
"""

struct AddCommand: ParsableCommand {
static let configuration = CommandConfiguration(
commandName: "add",
abstract: "Add value at a given path",
discussion: discussion)
discussion: "To find examples and advanced explanations, please type `scout doc add`")

@Argument(help: PathAndValue.help)
var pathsAndValues: [PathAndValue]
var pathsAndValues = [PathAndValue]()

@Option(name: [.short, .customLong("input")], help: "A file path from which to read the data")
var inputFilePath: String?
Expand All @@ -74,8 +20,11 @@ struct AddCommand: ParsableCommand {
@Option(name: [.short, .customLong("modify")], help: "Read and write the data into the same file at the given path")
var modifyFilePath: String?

@Flag(name: [.short, .long], default: false, inversion: .prefixedNo, help: "Output the modified data")
var verbose: Bool
@Flag(name: [.short, .long], inversion: .prefixedNo, help: "Output the modified data")
var verbose = false

@Flag(name: [.long], inversion: .prefixedNo, help: "Colorise the ouput")
var color = true

func run() throws {

Expand All @@ -99,17 +48,17 @@ struct AddCommand: ParsableCommand {
if var json = try? PathExplorerFactory.make(Json.self, from: data) {

try add(pathsAndValues, to: &json)
try ScoutCommand.output(output, dataWith: json, verbose: verbose)
try ScoutCommand.output(output, dataWith: json, verbose: verbose, colorise: color)

} else if var plist = try? PathExplorerFactory.make(Plist.self, from: data) {

try add(pathsAndValues, to: &plist)
try ScoutCommand.output(output, dataWith: plist, verbose: verbose)
try ScoutCommand.output(output, dataWith: plist, verbose: verbose, colorise: color)

} else if var xml = try? PathExplorerFactory.make(Xml.self, from: data) {

try add(pathsAndValues, to: &xml)
try ScoutCommand.output(output, dataWith: xml, verbose: verbose)
try ScoutCommand.output(output, dataWith: xml, verbose: verbose, colorise: color)

} else {
if let filePath = inputFilePath {
Expand Down
72 changes: 72 additions & 0 deletions Sources/ScoutCLT/Add/AddDocumentation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import ArgumentParser
import Lux

struct AddDocumentation: Documentation {
private static let jsonInjector = JSONInjector(type: .terminal)
private static let zshInjector = ZshInjector(type: .terminal)

private static let jsonExample =
"""
{
"people": {
"Tom": {
"height": 175,
"age": 68,
"hobbies": [
"cooking",
"guitar"
]
},
"Arnaud": {
"height": 180,
"age": 23,
"hobbies": [
"video games",
"party",
"tennis"
]
}
}
}
"""

private static let examples = [(#"`scout add "people.Franklin.height=165"`"#, #"will create a new dictionary Franklin and add a height key into it with the value 165"#),
(#"`scout add "people.Tom.hobbies[-1]"="Playing music"`"#, #"will add the hobby "Playing music" to Tom hobbies at the end of the array"#),
(#"`scout add "people.Arnaud.hobbies[1]=reading"`"#, #"will insert the hobby "reading" to Arnaud hobbies between the hobby "video games" and "party""#),
(#"`scout add "people.Franklin.hobbies[0]"=football`"#, """
will create a new dictionary Franklin,
add a hobbies array into it, and insert the value "football" in the array
"""),
(#"`scout add "people.Franklin.height=/165/"`"#, #"will create a new dictionary Franklin and add a height key into it with the String value "165""#),
(#"`scout add "people.Franklin.height=~165~"`"#, #"will create a new dictionary Franklin and add a height key into it with the Real value 165 (Plist only)"#)]

static let text =
"""
Add command
============
Notes
-----
- You can add multiple values in one command
- Specify the \(zshInjector.delegate.inject(.optionNameOrFlag, in: .terminal, "-v")) flag to see the modified data
- Deactivate the output colorization with \(zshInjector.delegate.inject(.optionNameOrFlag, in: .terminal, "--no-color")).
Useful if you encounter slowdowns when dealing with large files although it is not recommended not ouput large files in the terminal.
- All the keys which do not exist in the path will be created
- Enclose the value with slash signs to force the value as a string: /valueAsString/ (Plist, Json)
- Enclose the value with interrogative signs to force the value as a boolean: ?valueToBoolean? (Plist, Json)
- Enclose the value with tilde signs to force the value as a real: ~valueToReal~ (Plist)
- Enclose the value with chevron signs to force the value as a integer: <valueToInteger> (Plist)
- When adding an element in an array, use the index -1 to add the element at the end of the array
Examples
--------
JSON file
\(jsonInjector.inject(in: jsonExample))
\(examplesText(from: examples))
"""
}
10 changes: 6 additions & 4 deletions Sources/ScoutCLT/ColorDelegates/JSONInjectorDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,26 @@ final class JSONInjectorColorDelegate: JSONDelegate {
}

required init() {
fatalError("init() has not been implemented")
colors = JsonColors()
super.init()
}

// MARK: - Functions

override func injection(for category: JSONCategory, type: TextType) -> String {
override func terminalModifier(for category: JSONCategory) -> TerminalModifier {
var colorCode: Int?

// retrieve the color code in the colors plist if any
switch category {
case .punctuation: colorCode = colors.punctuation
case .keyName: colorCode = colors.keyName
case .keyValue: colorCode = colors.keyValue
}

if let code = colorCode {
return String.colorPrefix(code)
return TerminalModifier(colorCode: code)
} else {
return super.injection(for: category, type: type)
return super.terminalModifier(for: category)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ final class PlistInjectorColorDelegate: PlistDelegate {
}

required init() {
fatalError("init() has not been implemented")
colors = PlistColors()
super.init()
}

// MARK: - Functions

override func injection(for category: PlistCategory, type: TextType) -> String {
override func terminalModifier(for category: PlistCategory) -> TerminalModifier {
var colorCode: Int?

switch category {
Expand All @@ -30,9 +31,9 @@ final class PlistInjectorColorDelegate: PlistDelegate {
}

if let code = colorCode {
return String.colorPrefix(code)
return TerminalModifier(colorCode: code)
} else {
return super.injection(for: category, type: type)
return super.terminalModifier(for: category)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ final class XMLInjectorColorDelegate: XMLEnhancedDelegate {
}

required init() {
fatalError("init() has not been implemented")
colors = XmlColors()
super.init()
}

// MARK: - Functions

override func injection(for category: XMLEnhancedCategory, type: TextType) -> String {
override func terminalModifier(for category: XMLEnhancedCategory) -> TerminalModifier {
var colorCode: Int?

switch category {
Expand All @@ -31,9 +32,9 @@ final class XMLInjectorColorDelegate: XMLEnhancedDelegate {
}

if let code = colorCode {
return String.colorPrefix(code)
return TerminalModifier(colorCode: code)
} else {
return super.injection(for: category, type: type)
return super.terminalModifier(for: category)
}
}
}
5 changes: 5 additions & 0 deletions Sources/ScoutCLT/Command.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import ArgumentParser

enum Command: String, ExpressibleByArgument {
case read, set, delete, add
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ struct DeleteCommand: ParsableCommand {
static let configuration = CommandConfiguration(
commandName: "delete",
abstract: "Delete a value at a given path",
discussion: "When accessing an array value by its index, use the index -1 to access to the last element")
discussion: "To find examples and advanced explanations, please type `scout doc delete`")

// MARK: - Properties

@Argument(help: "Paths to indicate the keys to be deleted")
var readingPaths: [Path]
var readingPaths = [Path]()

@Option(name: [.short, .customLong("input")], help: "A file path from which to read the data")
var inputFilePath: String?
Expand All @@ -25,8 +25,11 @@ struct DeleteCommand: ParsableCommand {
@Option(name: [.short, .customLong("modify")], help: "Read and write the data into the same file at the given path")
var modifyFilePath: String?

@Flag(name: [.short, .long], default: false, inversion: .prefixedNo, help: "Output the modified data")
var verbose: Bool
@Flag(name: [.short, .long], inversion: .prefixedNo, help: "Output the modified data")
var verbose = false

@Flag(name: [.long], inversion: .prefixedNo, help: "Colorise the ouput")
var color = true

// MARK: - Functions

Expand All @@ -52,17 +55,17 @@ struct DeleteCommand: ParsableCommand {
if var json = try? PathExplorerFactory.make(Json.self, from: data) {

try readingPaths.forEach { try json.delete($0) }
try ScoutCommand.output(output, dataWith: json, verbose: verbose)
try ScoutCommand.output(output, dataWith: json, verbose: verbose, colorise: color)

} else if var plist = try? PathExplorerFactory.make(Plist.self, from: data) {

try readingPaths.forEach { try plist.delete($0) }
try ScoutCommand.output(output, dataWith: plist, verbose: verbose)
try ScoutCommand.output(output, dataWith: plist, verbose: verbose, colorise: color)

} else if var xml = try? PathExplorerFactory.make(Xml.self, from: data) {

try readingPaths.forEach { try xml.delete($0) }
try ScoutCommand.output(output, dataWith: xml, verbose: verbose)
try ScoutCommand.output(output, dataWith: xml, verbose: verbose, colorise: color)

} else {
if let filePath = inputFilePath {
Expand Down
Loading

0 comments on commit 84e8895

Please sign in to comment.