Export 1-dimension arrays and dicts to Zsh
Export arrays to Zsh arrays and dictionaries to Zsh associate arrays.
This commit is contained in:
parent
8132bcbe0b
commit
2912e48c86
|
@ -98,7 +98,7 @@ public extension ExplorerError {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func mismatchingType<T>(_ type: T.Type, value: ExplorerValue) -> Self {
|
static func mismatchingType<T>(_ type: T.Type, value: ExplorerValue) -> Self {
|
||||||
ExplorerError(description: "ExplorerValue \(value) cannot be represented as \(T.self)")
|
ExplorerError(description: "ExplorerValue '\(value)' cannot be represented as \(T.self)")
|
||||||
}
|
}
|
||||||
|
|
||||||
static func predicateNotEvaluatable(_ predicate: String, description: String) -> Self {
|
static func predicateNotEvaluatable(_ predicate: String, description: String) -> Self {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
import Scout
|
import Scout
|
||||||
import ScoutCLTCore
|
import ScoutCLTCore
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct AddCommand: SADCommand {
|
struct AddCommand: SADCommand {
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ struct AddCommand: SADCommand {
|
||||||
var csvSeparator: String?
|
var csvSeparator: String?
|
||||||
|
|
||||||
@Option(name: .export, help: .export)
|
@Option(name: .export, help: .export)
|
||||||
var exportFormat: Scout.DataFormat?
|
var exportFormat: ExportFormat?
|
||||||
|
|
||||||
// MARK: - Functions
|
// MARK: - Functions
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
import Scout
|
import Scout
|
||||||
import Foundation
|
import ScoutCLTCore
|
||||||
|
|
||||||
struct DeleteCommand: SADCommand {
|
struct DeleteCommand: SADCommand {
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ struct DeleteCommand: SADCommand {
|
||||||
var csvSeparator: String?
|
var csvSeparator: String?
|
||||||
|
|
||||||
@Option(name: .export, help: .export)
|
@Option(name: .export, help: .export)
|
||||||
var exportFormat: Scout.DataFormat?
|
var exportFormat: ExportFormat?
|
||||||
|
|
||||||
// MARK: - Functions
|
// MARK: - Functions
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// Copyright (c) 2020-present Alexis Bridoux
|
// Copyright (c) 2020-present Alexis Bridoux
|
||||||
// MIT license, see LICENSE file for details
|
// MIT license, see LICENSE file for details
|
||||||
|
|
||||||
import Foundation
|
import ScoutCLTCore
|
||||||
import Scout
|
import Scout
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ struct DeleteKeyCommand: SADCommand {
|
||||||
var csvSeparator: String?
|
var csvSeparator: String?
|
||||||
|
|
||||||
@Option(name: [.short, .customLong("export")], help: "Convert the data to the specified format")
|
@Option(name: [.short, .customLong("export")], help: "Convert the data to the specified format")
|
||||||
var exportFormat: Scout.DataFormat?
|
var exportFormat: ExportFormat?
|
||||||
|
|
||||||
// MARK: - Functions
|
// MARK: - Functions
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Foundation
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
import Scout
|
import Scout
|
||||||
import Lux
|
import Lux
|
||||||
|
import ScoutCLTCore
|
||||||
|
|
||||||
extension ParsableCommand {
|
extension ParsableCommand {
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ protocol PathExplorerInputCommand: ParsableCommand {
|
||||||
/// A file path from which to read and write the data
|
/// A file path from which to read and write the data
|
||||||
var modifyFilePath: String? { get }
|
var modifyFilePath: String? { get }
|
||||||
|
|
||||||
|
/// The data format to use to read the data
|
||||||
var dataFormat: Scout.DataFormat { get }
|
var dataFormat: Scout.DataFormat { get }
|
||||||
|
|
||||||
/// Called with the correct `PathExplorer` when `inferPathExplorer(from:in:)` completes
|
/// Called with the correct `PathExplorer` when `inferPathExplorer(from:in:)` completes
|
||||||
|
|
|
@ -49,7 +49,7 @@ extension SADCommand {
|
||||||
|
|
||||||
extension SADCommand {
|
extension SADCommand {
|
||||||
|
|
||||||
/// Print the data from the path explorer and colorize it if specified
|
/// Print the data from the path explorer and highlight it if specified
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - outputFilePath: A file path to a file where to write the data
|
/// - outputFilePath: A file path to a file where to write the data
|
||||||
/// - pathExplorer: The path explorer to use to get the data
|
/// - pathExplorer: The path explorer to use to get the data
|
||||||
|
@ -84,6 +84,26 @@ extension SADCommand {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case .array:
|
||||||
|
do {
|
||||||
|
let array = try pathExplorer.array(of: GroupExportValue.self).map(\.value).joined(separator: " ")
|
||||||
|
print("\(array)")
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
throw RuntimeError.custom("Unable to represent the value as an array of single elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
case .dictionary:
|
||||||
|
do {
|
||||||
|
let dict = try pathExplorer.dictionary(of: GroupExportValue.self)
|
||||||
|
.map { "\($0.key) \($0.value.value)" }
|
||||||
|
.joined(separator: " ")
|
||||||
|
print("\(dict)")
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
throw RuntimeError.custom("Unable to represent the value as a dictionary of single elements")
|
||||||
|
}
|
||||||
|
|
||||||
case .noExport:
|
case .noExport:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct ReadCommand: PathExplorerInputCommand, ExportCommand {
|
||||||
var csvSeparator: String?
|
var csvSeparator: String?
|
||||||
|
|
||||||
@Option(name: .export, help: .export)
|
@Option(name: .export, help: .export)
|
||||||
var exportFormat: Scout.DataFormat?
|
var exportFormat: ExportFormat?
|
||||||
|
|
||||||
// MARK: - Functions
|
// MARK: - Functions
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ struct ReadCommand: PathExplorerInputCommand, ExportCommand {
|
||||||
let readingPath = self.readingPath ?? Path()
|
let readingPath = self.readingPath ?? Path()
|
||||||
var explorer = try pathExplorer.get(readingPath)
|
var explorer = try pathExplorer.get(readingPath)
|
||||||
let value = try getValue(from: &explorer)
|
let value = try getValue(from: &explorer)
|
||||||
let colorInjector = try self.colorInjector(for: exportFormat ?? P.format)
|
|
||||||
|
|
||||||
if value == "" {
|
if value == "" {
|
||||||
throw RuntimeError.noValueAt(path: readingPath.description)
|
throw RuntimeError.noValueAt(path: readingPath.description)
|
||||||
|
@ -71,8 +70,15 @@ struct ReadCommand: PathExplorerInputCommand, ExportCommand {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = colorise ? colorInjector.inject(in: value) : value
|
switch try exportOption() {
|
||||||
print(output)
|
case .array, .dictionary, .noExport, .csv: // cases already handled in getValue()
|
||||||
|
print(value)
|
||||||
|
|
||||||
|
case .dataFormat(let format):
|
||||||
|
let colorInjector = try self.colorInjector(for: format)
|
||||||
|
let output = colorInjector.inject(in: value)
|
||||||
|
print(output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getValue<Explorer: SerializablePathExplorer>(from explorer: inout Explorer) throws -> String {
|
func getValue<Explorer: SerializablePathExplorer>(from explorer: inout Explorer) throws -> String {
|
||||||
|
@ -85,6 +91,26 @@ struct ReadCommand: PathExplorerInputCommand, ExportCommand {
|
||||||
case .dataFormat(let format):
|
case .dataFormat(let format):
|
||||||
return try explorer.exportString(to: format, rootName: fileName(of: inputFilePath))
|
return try explorer.exportString(to: format, rootName: fileName(of: inputFilePath))
|
||||||
|
|
||||||
|
case .array:
|
||||||
|
do {
|
||||||
|
let array = try explorer.array(of: GroupExportValue.self).map(\.value).joined(separator: " ")
|
||||||
|
return "\(array)"
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
throw RuntimeError.custom("Unable to represent the value as an array of single elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
case .dictionary:
|
||||||
|
do {
|
||||||
|
let dict = try explorer.dictionary(of: GroupExportValue.self)
|
||||||
|
.map { "\($0.key) \($0.value.value)" }
|
||||||
|
.joined(separator: " ")
|
||||||
|
return "\(dict)"
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
throw RuntimeError.custom("Unable to represent the value as an array of single elements")
|
||||||
|
}
|
||||||
|
|
||||||
case .noExport:
|
case .noExport:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct SetCommand: SADCommand {
|
||||||
var csvSeparator: String?
|
var csvSeparator: String?
|
||||||
|
|
||||||
@Option(name: .export, help: .export)
|
@Option(name: .export, help: .export)
|
||||||
var exportFormat: Scout.DataFormat?
|
var exportFormat: ExportFormat?
|
||||||
|
|
||||||
// MARK: - Functions
|
// MARK: - Functions
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,14 @@ import Scout
|
||||||
public enum Export: Equatable {
|
public enum Export: Equatable {
|
||||||
case noExport
|
case noExport
|
||||||
case csv(separator: String)
|
case csv(separator: String)
|
||||||
case dataFormat(format: Scout.DataFormat)
|
case dataFormat(format: DataFormat)
|
||||||
|
case array
|
||||||
|
case dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol ExportCommand {
|
public protocol ExportCommand {
|
||||||
var csvSeparator: String? { get }
|
var csvSeparator: String? { get }
|
||||||
var exportFormat: DataFormat? { get }
|
var exportFormat: ExportFormat? { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension ExportCommand {
|
public extension ExportCommand {
|
||||||
|
@ -22,7 +24,15 @@ public extension ExportCommand {
|
||||||
func exportOption() throws -> Export {
|
func exportOption() throws -> Export {
|
||||||
switch (csvSeparator, exportFormat) {
|
switch (csvSeparator, exportFormat) {
|
||||||
case (let separator?, nil): return .csv(separator: separator)
|
case (let separator?, nil): return .csv(separator: separator)
|
||||||
case (nil, let format?): return .dataFormat(format: format)
|
case (nil, let format?):
|
||||||
|
switch format {
|
||||||
|
case .array: return .array
|
||||||
|
case .dict: return .dictionary
|
||||||
|
case .json: return .dataFormat(format: .json)
|
||||||
|
case .plist: return .dataFormat(format: .plist)
|
||||||
|
case .yaml: return .dataFormat(format: .yaml)
|
||||||
|
case .xml: return .dataFormat(format: .xml)
|
||||||
|
}
|
||||||
case (nil, nil): return .noExport
|
case (nil, nil): return .noExport
|
||||||
case (.some, .some): throw CLTCoreError.exportConflict
|
case (.some, .some): throw CLTCoreError.exportConflict
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// Scout
|
||||||
|
// Copyright (c) 2020-present Alexis Bridoux
|
||||||
|
// MIT license, see LICENSE file for details
|
||||||
|
|
||||||
|
import ArgumentParser
|
||||||
|
import Scout
|
||||||
|
|
||||||
|
/// Models the value the export process can take
|
||||||
|
public enum ExportFormat: String, CaseIterable, ExpressibleByArgument, Equatable {
|
||||||
|
case json, plist, yaml, xml, array, dict
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// Scout
|
||||||
|
// Copyright (c) 2020-present Alexis Bridoux
|
||||||
|
// MIT license, see LICENSE file for details
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Scout
|
||||||
|
|
||||||
|
/// Type serving only the purpose to map dictionaries or arrays
|
||||||
|
/// returned by a `PathExplorer` to a `String` value.
|
||||||
|
///
|
||||||
|
/// Init throws if the value is not single.
|
||||||
|
public struct GroupExportValue: ExplorerValueCreatable {
|
||||||
|
|
||||||
|
public let value: String
|
||||||
|
|
||||||
|
public init(from explorerValue: ExplorerValue) throws {
|
||||||
|
switch explorerValue {
|
||||||
|
case .string(let string): value = string
|
||||||
|
case .int(let int): value = int.description
|
||||||
|
case .double(let double): value = double.description
|
||||||
|
case .bool(let bool): value = bool.description
|
||||||
|
case .data(let data): value = data.base64EncodedString()
|
||||||
|
case .date(let date): value = date.description
|
||||||
|
case .dictionary: throw CLTCoreError.wrongUsage("Trying to export a dictionary of values that are not single")
|
||||||
|
case .array: throw CLTCoreError.wrongUsage("Trying to export an array of values that are not single")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue