From 48e5c1b7d568088e0e47bbe23035960572f105d6 Mon Sep 17 00:00:00 2001 From: Thomas Rasch Date: Wed, 14 Aug 2024 15:08:24 +0200 Subject: [PATCH] Code cleanup --- Sources/MVTCLI/CLI.swift | 16 +++++++++---- Sources/MVTCLI/Dump.swift | 19 +++++++++++---- Sources/MVTCLI/Export.swift | 28 ++++++++++++++++------ Sources/MVTCLI/Import.swift | 28 ++++++++++++++++------ Sources/MVTCLI/Info.swift | 7 +++--- Sources/MVTCLI/Merge.swift | 46 +++++++++++++++++++++++++------------ Sources/MVTCLI/Query.swift | 32 +++++++++++++++++++------- 7 files changed, 127 insertions(+), 49 deletions(-) diff --git a/Sources/MVTCLI/CLI.swift b/Sources/MVTCLI/CLI.swift index f75d955..5360667 100644 --- a/Sources/MVTCLI/CLI.swift +++ b/Sources/MVTCLI/CLI.swift @@ -43,13 +43,19 @@ struct CLIError: LocalizedError { struct XYZOptions: ParsableArguments { - @Option(name: .short, help: "Tile x coordinate, if it can't be extracted from the path.") + @Option( + name: .short, + help: "Tile x coordinate, if it can't be extracted from the path.") var x: Int? - @Option(name: .short, help: "Tile y coordinate, if it can't be extracted from the path.") + @Option( + name: .short, + help: "Tile y coordinate, if it can't be extracted from the path.") var y: Int? - @Option(name: .short, help: "Tile zoom level, if it can't be extracted from the path.") + @Option( + name: .short, + help: "Tile zoom level, if it can't be extracted from the path.") var z: Int? /// Try to extract x, y and z tile coordinates from some file paths or URLs, @@ -109,7 +115,9 @@ struct XYZOptions: ParsableArguments { struct Options: ParsableArguments { - @Flag(name: .shortAndLong, help: "Print some debug info.") + @Flag( + name: .shortAndLong, + help: "Print some debug info.") var verbose = false func parseUrl( diff --git a/Sources/MVTCLI/Dump.swift b/Sources/MVTCLI/Dump.swift index 36d1b25..d2f5ddc 100644 --- a/Sources/MVTCLI/Dump.swift +++ b/Sources/MVTCLI/Dump.swift @@ -6,18 +6,27 @@ extension CLI { struct Dump: AsyncParsableCommand { - static let configuration = CommandConfiguration(abstract: "Print the input file (MVT or GeoJSON) as pretty-printed GeoJSON to the console") + static let configuration = CommandConfiguration( + abstract: "Print the input file (MVT or GeoJSON) as pretty-printed GeoJSON to the console") - @Option(name: .shortAndLong, help: "Dump only the specified layer (can be repeated).") + @Option( + name: .shortAndLong, + help: "Dump only the specified layer (can be repeated).") var layer: [String] = [] - @Option(name: [.customShort("P"), .long], help: "Feature property to use for the layer name in input and output GeoJSONs.") + @Option( + name: [.customShort("P"), .long], + help: "Feature property to use for the layer name in input and output GeoJSONs.") var propertyName: String = VectorTile.defaultLayerPropertyName - @Flag(name: [.customLong("Di", withSingleDash: true), .long], help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs. Might speed up GeoJSON parsing considerably.") + @Flag( + name: [.customLong("Di", withSingleDash: true), .long], + help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs. Might speed up GeoJSON parsing considerably.") var disableInputLayerProperty: Bool = false - @Flag(name: [.customLong("Do", withSingleDash: true), .long], help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") + @Flag( + name: [.customLong("Do", withSingleDash: true), .long], + help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") var disableOutputLayerProperty: Bool = false @OptionGroup diff --git a/Sources/MVTCLI/Export.swift b/Sources/MVTCLI/Export.swift index c925a20..265fdc3 100644 --- a/Sources/MVTCLI/Export.swift +++ b/Sources/MVTCLI/Export.swift @@ -6,24 +6,38 @@ extension CLI { struct Export: AsyncParsableCommand { - static let configuration = CommandConfiguration(abstract: "Export a vector tile as GeoJSON to a file") + static let configuration = CommandConfiguration( + abstract: "Export a vector tile as GeoJSON to a file") - @Option(name: [.short, .customLong("output")], help: "Output GeoJSON file.") + @Option( + name: [.short, .customLong("output")], + help: "Output GeoJSON file.", + completion: .file(extensions: ["geojson", "json"])) var outputFile: String - @Flag(name: .shortAndLong, help: "Overwrite existing files.") + @Flag( + name: .shortAndLong, + help: "Overwrite existing files.") var forceOverwrite = false - @Option(name: .shortAndLong, help: "Export only the specified layer (can be repeated).") + @Option( + name: .shortAndLong, + help: "Export only the specified layer (can be repeated).") var layer: [String] = [] - @Option(name: [.customShort("P"), .long], help: "Feature property to use for the layer name in the output GeoJSON.") + @Option( + name: [.customShort("P"), .long], + help: "Feature property to use for the layer name in the output GeoJSON.") var propertyName: String = VectorTile.defaultLayerPropertyName - @Flag(name: [.customLong("Do", withSingleDash: true), .long], help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") + @Flag( + name: [.customLong("Do", withSingleDash: true), .long], + help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") var disableOutputLayerProperty: Bool = false - @Flag(name: .shortAndLong, help: "Pretty-print the output GeoJSON.") + @Flag( + name: .shortAndLong, + help: "Pretty-print the output GeoJSON.") var prettyPrint = false @OptionGroup diff --git a/Sources/MVTCLI/Import.swift b/Sources/MVTCLI/Import.swift index 27abb89..4207a8c 100644 --- a/Sources/MVTCLI/Import.swift +++ b/Sources/MVTCLI/Import.swift @@ -7,24 +7,38 @@ extension CLI { struct Import: AsyncParsableCommand { - static let configuration = CommandConfiguration(abstract: "Import some GeoJSONs into a vector tile") + static let configuration = CommandConfiguration( + abstract: "Import some GeoJSONs into a vector tile") - @Option(name: [.short, .customLong("output")], help: "Output MVT file.") + @Option( + name: [.short, .customLong("output")], + help: "Output MVT file.", + completion: .file(extensions: ["pbf", "mvt"])) var outputFile: String - @Flag(name: .shortAndLong, help: "Overwrite an existing 'output' file.") + @Flag( + name: .shortAndLong, + help: "Overwrite an existing 'output' file.") var forceOverwrite = false - @Flag(name: .shortAndLong, help: "Append to an existing 'output' file.") + @Flag( + name: .shortAndLong, + help: "Append to an existing 'output' file.") var append = false - @Option(name: [.customShort("L"), .long], help: "Layer name in the vector tile for the imported GeoJSON. Can be used with 'property-name' as a fallback name.") + @Option( + name: [.customShort("L"), .long], + help: "Layer name in the vector tile for the imported GeoJSON. Can be used with 'property-name' as a fallback name.") var layerName: String? - @Option(name: [.customShort("P"), .long], help: "Feature property to use for the layer name in input GeoJSONs. Fallback to 'layer-name' or a default if the property is not present.") + @Option( + name: [.customShort("P"), .long], + help: "Feature property to use for the layer name in input GeoJSONs. Fallback to 'layer-name' or a default if the property is not present.") var propertyName: String = VectorTile.defaultLayerPropertyName - @Flag(name: [.customLong("Di", withSingleDash: true), .long], help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs, just use 'layer-name' or a default. Might speed up GeoJSON parsing considerably.") + @Flag( + name: [.customLong("Di", withSingleDash: true), .long], + help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs, just use 'layer-name' or a default. Might speed up GeoJSON parsing considerably.") var disableInputLayerProperty: Bool = false @OptionGroup diff --git a/Sources/MVTCLI/Info.swift b/Sources/MVTCLI/Info.swift index fc2be14..86ff04b 100644 --- a/Sources/MVTCLI/Info.swift +++ b/Sources/MVTCLI/Info.swift @@ -21,9 +21,10 @@ extension CLI { input file. """) - @Option(name: .shortAndLong, - help: "The tables to print, comma separated list of '\(InfoTables.allCases.map(\.rawValue).joined(separator: ","))'.", - transform: { $0.components(separatedBy: ",").compactMap(InfoTables.init(rawValue:)) }) + @Option( + name: .shortAndLong, + help: "The tables to print, comma separated list of '\(InfoTables.allCases.map(\.rawValue).joined(separator: ","))'.", + transform: { $0.components(separatedBy: ",").compactMap(InfoTables.init(rawValue:)) }) var infoTables: [InfoTables] = [.features, .properties] @OptionGroup diff --git a/Sources/MVTCLI/Merge.swift b/Sources/MVTCLI/Merge.swift index 3bedef0..21bf634 100644 --- a/Sources/MVTCLI/Merge.swift +++ b/Sources/MVTCLI/Merge.swift @@ -16,31 +16,50 @@ extension CLI { abstract: "Merge any number of MVTs or GeoJSONs", discussion: "Note: Vector tiles should all have the same tile coordinate or strange things will happen.") - @Option(name: [.short, .customLong("output")], help: "Output file (optional, default is console).") + @Option( + name: [.short, .customLong("output")], + help: "Output file (optional, default is console).", + completion: .file(extensions: ["pbf", "mvt", "json", "geojson"])) var outputFile: String? - @Option(name: [.customShort("O"), .long], help: "Output file format (optional, one of 'auto', 'geojson', 'mvt').") + @Option( + name: [.customShort("O"), .long], + help: "Output file format (optional, one of 'auto', 'geojson', 'mvt').") var outputFormat: OutputFormat = .auto - @Flag(name: .shortAndLong, help: "Force overwrite an existing 'output' file.") + @Flag( + name: .shortAndLong, + help: "Force overwrite an existing 'output' file.") var forceOverwrite = false - @Flag(name: .shortAndLong, help: "Append to an existing 'output' file.") + @Flag( + name: .shortAndLong, + help: "Append to an existing 'output' file.") var append = false - @Option(name: .shortAndLong, help: "Merge only the specified layers (can be repeated).") + @Option( + name: .shortAndLong, + help: "Merge only the specified layers (can be repeated).") var layer: [String] = [] - @Option(name: [.customShort("P"), .long], help: "Feature property to use for the layer name in input and output GeoJSONs.") + @Option( + name: [.customShort("P"), .long], + help: "Feature property to use for the layer name in input and output GeoJSONs.") var propertyName: String = VectorTile.defaultLayerPropertyName - @Flag(name: [.customLong("Di", withSingleDash: true), .long], help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs. Might speed up GeoJSON parsing considerably.") + @Flag( + name: [.customLong("Di", withSingleDash: true), .long], + help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs. Might speed up GeoJSON parsing considerably.") var disableInputLayerProperty: Bool = false - @Flag(name: [.customLong("Do", withSingleDash: true), .long], help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") + @Flag( + name: [.customLong("Do", withSingleDash: true), .long], + help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") var disableOutputLayerProperty: Bool = false - @Flag(name: .shortAndLong, help: "Pretty-print the output GeoJSON.") + @Flag( + name: .shortAndLong, + help: "Pretty-print the output GeoJSON.") var prettyPrint = false @OptionGroup @@ -96,7 +115,7 @@ extension CLI { tile = mvtTile if outputFormatToUse == .geojson, !forceOverwrite { - throw CLIError("Existing file is MVT, but selected output format is GeoJSON (use --force-overwrite to overwrite existing files)") + throw CLIError("Existing file is 'mvt', but selected output format is 'geojson' (use --force-overwrite to overwrite existing files)") } if outputFormatToUse == .auto { outputFormatToUse = .mvt @@ -110,7 +129,7 @@ extension CLI { tile = geoJsonTile if outputFormatToUse == .mvt, !forceOverwrite { - throw CLIError("Existing file is GeoJSON, but selected output format is MVT (use --force-overwrite to overwrite existing files)") + throw CLIError("Existing file is 'geojson', but selected output format is 'mvt' (use --force-overwrite to overwrite existing files)") } if outputFormatToUse == .auto { outputFormatToUse = .geojson @@ -130,10 +149,6 @@ extension CLI { // Assume geoJson if we don't have tile coordinates here if x == nil || y == nil || z == nil { outputFormatToUse = .geojson - - if options.verbose { - print("Warning: Assuming geoJson output format because tile coordinates were not provided") - } } } @@ -150,6 +165,7 @@ extension CLI { if let layerAllowlist { print("Layers: '\(layerAllowlist.joined(separator: ","))'") } + print("Output format: \(outputFormatToUse)") } for path in other { diff --git a/Sources/MVTCLI/Query.swift b/Sources/MVTCLI/Query.swift index 139bb32..9c7a549 100644 --- a/Sources/MVTCLI/Query.swift +++ b/Sources/MVTCLI/Query.swift @@ -10,27 +10,43 @@ extension CLI { struct Query: AsyncParsableCommand { - static let configuration = CommandConfiguration(abstract: "Query the features in the input file (MVT or GeoJSON)") + static let configuration = CommandConfiguration( + abstract: "Query the features in the input file (MVT or GeoJSON)") - @Option(name: [.short, .customLong("output")], help: "Output GeoJSON file (optional, default is console).") + @Option( + name: [.short, .customLong("output")], + help: "Output GeoJSON file (optional, default is console).", + completion: .file(extensions: ["geojson", "json"])) var outputFile: String? - @Flag(name: .shortAndLong, help: "Overwrite existing files.") + @Flag( + name: .shortAndLong, + help: "Overwrite existing files.") var forceOverwrite = false - @Option(name: .shortAndLong, help: "Search only in this layer (can be repeated).") + @Option( + name: .shortAndLong, + help: "Search only in this layer (can be repeated).") var layer: [String] = [] - @Option(name: [.customShort("P"), .long], help: "Feature property to use for the layer name in input and output GeoJSONs.") + @Option( + name: [.customShort("P"), .long], + help: "Feature property to use for the layer name in input and output GeoJSONs.") var propertyName: String = VectorTile.defaultLayerPropertyName - @Flag(name: [.customLong("Di", withSingleDash: true), .long], help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs. Might speed up GeoJSON parsing considerably.") + @Flag( + name: [.customLong("Di", withSingleDash: true), .long], + help: "Don't parse the layer name (option 'property-name') from Feature properties in the input GeoJSONs. Might speed up GeoJSON parsing considerably.") var disableInputLayerProperty: Bool = false - @Flag(name: [.customLong("Do", withSingleDash: true), .long], help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") + @Flag( + name: [.customLong("Do", withSingleDash: true), .long], + help: "Don't add the layer name (option 'property-name') as a Feature property in the output GeoJSONs.") var disableOutputLayerProperty: Bool = false - @Flag(name: .shortAndLong, help: "Pretty-print the output GeoJSON.") + @Flag( + name: .shortAndLong, + help: "Pretty-print the output GeoJSON.") var prettyPrint = false @OptionGroup