docopt.swift icon indicating copy to clipboard operation
docopt.swift copied to clipboard

Use with Codable would be fantastic use case for this library

Open kdawgwilk opened this issue 7 years ago • 13 comments

Being able to parse args in a type safe way using Codable would be amazing.

kdawgwilk avatar Feb 09 '18 06:02 kdawgwilk

Could you please elaborate on this? I'm not sure how exactly this would look like.

kovpas avatar Feb 09 '18 07:02 kovpas

Yeah sorry I was working on a CLI in go and found this Swift version and thought adding support for decoding the args into a struct using the new Codable APIs like go does would be awesome and keep things type safe. https://github.com/docopt/docopt.go/blob/master/README.md#api

I will try to get a prototype posted here in the next few days to give more detail

kdawgwilk avatar Feb 09 '18 09:02 kdawgwilk

let doc : String = """
Naval Fate.

Usage:
  naval_fate ship new <name>...
  naval_fate ship <name> move <x> <y> [--speed=<kn>]
  naval_fate ship shoot <x> <y>
  naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate -h | --help
  naval_fate --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.
"""

struct CommandArgs: Codable {
    enum CodingKeys: String, CodingKey {
        case name = "<name>"
        case x = "<x>"
        case y = "<y>"
        case knots = "<kn>"
        case moored = "--moored"
        case drifting = "--drifting"
    }
    let name: String
    let x: Int
    let y: Int
    let knots: Int
    let moored: Bool
    let drifting: Bool
}

var args = Process.arguments
args.removeAtIndex(0) // arguments[0] is always the program_name
let result = Docopt.decode(CommandArgs.self, args, help: true, version: "1.0")

kdawgwilk avatar Feb 12 '18 18:02 kdawgwilk

Hmmm, this looks super-interesting. Let me think how to implement this. Please let me know if you already have ideas.

kovpas avatar Feb 12 '18 18:02 kovpas

The best way would prob be to create a DocoptDecoder similar to how Foundation provides a JSONDecoder

let decoder = DocoptDecoder()
let result = decoder.decode(CommandArgs.self, usageString)

kdawgwilk avatar Feb 12 '18 18:02 kdawgwilk

I don't have much experience with that, and most of the examples I found are using standard JSONDecoder. I've got a feeling, that decoding a Dictionary into a custom struct should be something more or less standard, but couldn't find anything yet. I'll take some time over the weekend and have a look if such a decoder is easy to implement.

Also - if you have some time and thoughts on how to do that, I'd highly appreciate any input :)

kovpas avatar Feb 12 '18 19:02 kovpas

Some examples:

https://github.com/ShawnMoore/XMLParsing

https://github.com/RockfordWei/Perfect-INI

kdawgwilk avatar Feb 12 '18 19:02 kdawgwilk

You could achieve this fairly easily with DictionaryCoding.

Adding the ability to docopt itself would mean adding a dependency, but you could just import it and DictionaryCoding to your client project and then hook them up.

samdeane avatar Mar 08 '18 17:03 samdeane

Wow, that is something new, thanks a lot, @samdeane! I wouldn't mind having a dependency on DictionaryCoding. One thing that stops me is that Docopt supports cocoapods, while DictionaryCoding doesn't... Copying the source altogether might be a solution, but I'd rather not to do that since updating it would be a pain.

kovpas avatar Mar 09 '18 21:03 kovpas

Why does docopt support CocoaPods? I can’t think of a case where you would need to parse CLI arguments in an app. SPM seems like the only one that should be needed

kdawgwilk avatar Mar 09 '18 22:03 kdawgwilk

@kdawgwilk cocoapods is just a way of managing dependencies and creating a project with those dependencies. You can use it for OS X apps as well. When I wrote this library, SPM didn't exist, so cocoapods was the easiest way of adding docopt.swift into projects.

kovpas avatar Mar 10 '18 09:03 kovpas

I've added myself an issue to add pods support to DictionaryCoding (elegantchaos/DictionaryCoding#9). I've never used it myself, but it shouldn't be too tricky by the look of things...

samdeane avatar Mar 10 '18 13:03 samdeane

Thanks, @samdeane! It is fairly straightforward indeed.

kovpas avatar Mar 11 '18 09:03 kovpas