Giter Site home page Giter Site logo

guaka's People

Contributors

a2 avatar ainopara avatar dduan avatar glessard avatar goyox86 avatar nsomar avatar ponyboy47 avatar thii avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

guaka's Issues

Inheritable flags. (Feature Request)

I'd really love a way to have child commands inherit flags from their parent.

For instance:

myCli
parentCommand
-c flag
fooCommand understands -c, even though it's defined on parentCommand.

This would be useful for defining common command line params to an entire 'namespace'.
Another example: a 'config' namespace / parent command has a common flag -f for config file that config set and config get could both use.

Implement template engine for help messages

At the moment the help message is generated with a default style.
This task will implement a template with placeholder (similar to mustache) to print help in other styles

Add generation cli to generate commands

Add generation cli application
This application will be able to

  1. generate a new root command guaka new "name"
  2. create new subcommands guaka add "name"
  3. add subcommands to a particular command guaka add "name" -p "parent"
  4. add flags to a command guaka add flag --longname "name" --shortname "name" --type ...

Default Xcode project

It would be nice if the tooling "guaka create" created an Xcode project with a working unit test.

Consider overloading the Flags subscript instead of including types in method names

getInt(name:) and getBool(name:) etc could use overloads instead of unique names to distinguish the types. This impacts usage at the call site in the following ways:

  1. When called nakedly, a type annotation may need used to disambiguate the method.
  2. When the type is able to be inferred, the call site avoids adding redundant type information.

In addition to overloading "get" methods, it seems intuitive to access these via subscript. Below is a little playground snippet exploring this idea and showing some call site usage side by side.

struct Flag {
    var value: Any
}

struct Flags {
    let flagsDict: [String: Flag]

    init(flags: [String: Flag]) {
        self.flagsDict = flags
    }

    public subscript(name: String) -> Flag? {
        return flagsDict[name]
    }

    public subscript(name: String) -> Bool? {
        return flagsDict[name]?.value as? Bool
    }

    public func getBool(name: String) -> Bool? {
        return flagsDict[name]?.value as? Bool
    }
}

func log(_ verbose: Bool?, _ message: String) {
    if verbose ?? false {
        print(message)
    }
}

let flags = Flags(flags: ["verbose": Flag(value: true)])

// type inferred subscript:
_ = {
    let verbose: Bool? = flags["verbose"]
    log(flags["verbose"], "log message")
}()


// compared to:
_ = {
    let verbose = flags.getBool(name: "verbose")
    log(flags.getBool(name: "verbose"), "log message")
}()

Awesome library BTW. :)

Successful tests on Linux - steps need to be done

Hi, it seems that Guaka can be build on Linux, but tests are not working. This needs to happen to get swift test running:

  1. In Tests/LinuxMain.swift you need to change:
@testable import ProcessTests

to

@testable import GuakaTests
  1. All classes *Tests in files of directory Tests/GuakaTests need to have static variable called allTests like this one:
    static var allTests : [(String, (CommandArgumentsTests) -> () throws -> Void)] {
        return [
            ("testEmptySignature", testEmptySignature),
            ("testRequiredArguments", testRequiredArguments),
            ("testOptionalArguments", testOptionalArguments),
            ("testExtraneousArguments", testExtraneousArguments),
            ("testNonTerminalWithRequiredArguments", testNonTerminalWithRequiredArguments),
            ("testNonTerminalWithOptionalArguments", testNonTerminalWithOptionalArguments),
            ("testParameterPlacement", testParameterPlacement),
            ("testCombinedRequiredAndOptionalArguments", testCombinedRequiredAndOptionalArguments),
            ("testEmptyOptionalCollectedParameter", testEmptyOptionalCollectedParameter),
            ("testQuotedArguments", testQuotedArguments)
        ]
    }
  1. When 2. is done, then Tests/LinuxMain.swift needs to have similar definition of XTCMain like this one:
XCTMain([
     testCase(CommandArgumentsTests.allTests),
     testCase(CommandMessageGeneratorTests.allTests),
     testCase(OptionsTests.allTests),
     testCase(RouterTests.allTests),
     testCase(SwiftCLITests.allTests)
])

This all will make sure, that swift test on Linux will run all tests.

I would submit PR for this, but I'm not sure if there is order to those tests if any, so I wouldn't like to mess it up.

PS: Examples taken from similar framework called SwiftCLI: https://github.com/jakeheis/SwiftCLI

Support options being used multiple times

Basically, conditionally conform Array to FlagValue:

extension Array: FlagValue where Element: FlagValue {
    // Implementation...
}

Allow array types to be specified multiple times on the command line, where each time it's specified you just append the item to the array.

This is a pretty common feature used by some video converting tools (ffmpeg, handbrake, etc).

ie: transcode_video supports multiple 'target' options, some for file/encoding size and others for encoding speed. So this is a perfectly valid command:
transcode-video --target big --target quick --output /path/to/output /path/to/file

The --target big option will perform a higher quality encoding, resulting in a larger file size and slower encode. The --target quick option performs other optimizations that speed up the encoding without noticeably reducing the quality and only increasing the file size by a small amount.

How to properly fail a command?

The documentation says to fail a command like so:

let printCommand = Command(usage: "print",
                           parent: rootCommand) { _, _ in
    // Error happened
    printCommand.fail(statusCode: 1, errorMessage: "Some error happaned")
}

However this code in my application results in a compilation error:

let checkConfig = Command(usage: "check",
                          shortMessage: "Validate your config",
                          parent: config,
                          aliases: ["validate"]
                         ) { flags, args in
    // validateConfig is a ConditionalRun used before most other commands to ensure the config is valid
    if validateConfig(flags: flags, args: args) {
        print("The config is valid")
    } else {
        // Error: variable used within its own initial value
        checkConfig.fail(statusCode: 1, errorMessage: "The config is not valid")
    }
}

I'm using the version 0.2.0 on Swift 4.2

Api to add commands

The current API works like this:

  • create sub command1
  • create sub command2
  • create super command that contains 1 and 2
  • call execute on this super command

Looks like this:

let show = try! Command(
  name: "show",
  flags: [
    Flag(longName: "foo", value: "-", inheritable: false),
    Flag(longName: "bar", value: "-", inheritable: false),
    Flag(longName: "yy", value: true, inheritable: false),
    ],
  commands: []) { flags, args in
    print("Running git with \(flags) and \(args)")
}

let remote = try! Command(
  name: "remote",
  flags: [
    Flag(longName: "foo", value: "-", inheritable: true),
    Flag(longName: "remote", value: true, inheritable: true),
    Flag(longName: "bar", value: "-", inheritable: false),
    Flag(longName: "xx", value: true, inheritable: false),
    ],
  commands: [show]) { flags, args in
    print("Running git with \(flags) and \(args)")
}

let rebase = try! Command(
  name: "rebase",
  flags: [
    Flag(longName: "varvar", value: false, shortName: "v", inheritable: true),
    ],
  commands: []) { flags, args in
    print("Running git with \(flags) and \(args)")
}

let git = try! Command(
  name: "git",
  flags: [
    Flag(longName: "debug", type: Bool.self, required: true),
    Flag(longName: "verbose", value: false, shortName: "v", inheritable: true),
    Flag(longName: "togge", value: false, shortName: "t", inheritable: false),
    Flag(longName: "root", value: 1, shortName: "r", inheritable: false),
    ],
  commands: [rebase, remote]) { flags, args in
    print("Running git with \(flags) and \(args)")
}

It looks like we need to do the opposite, start from sub, and then implement super, which is opposite of the way of thinking,

The main constraint here is that commands array now its immutable. It has to change to mutable to accomodate the generator process.

Whats your idea on this @goyox86

Documentation

  • dependencies on mac and linux
  • how to install it on mac OS and Linux

Things to document

  • Generate a document website (that contains the help generated with Jazzy)
  • Update the readme.md
  • Landing Page?
  • Document other related projects
  • Wiki?
  • how to use gauaka cli
  • how to statically compile it

Multiple longNames

Not sure if this is part of the POSIX spec or not, but would it be desirable to allow a Flag to have multiple longNames? There are certain abbreviations I use in my scripts for command names, but I like to expose/permit the unabbreviated version as well.
ie: Both --abr value and --average-bit-rate value would be valid

inheritablePreRun is not recursive

Hello,

Let’s say I’m writing the git CLI for example purpose.

I want to handle the --version flag for all commands and subcommands. For this, I will create an inheritablePreRun on the root command git, which will process the --version flag if it is set.

Then, after a little bit of coding, I’ll have to write the git submodule commands (git submodule update, git submodule foreach, etc.).
For each of this commands, I’ll need to read the submodule config file (.gitmodules).
To avoid re-implementing the logic of the parsing and error processing (command failure, etc.), I’ll want to implement an inheritablePreRun on the git submodule command.
However, once I do that, the root inheritablePreRun will be ignored, thus dropping my handling of the --version flag!

I think inheritablePreRuns should be executed recursively from the root to the current command being executed.

Any thoughts?

Add badges

Below the title please add badges this help a lot.

If your component is compatible:

  • with SwiftPM add SwiftPM compatible

Indicated:

  • the Swift version Swift Version
  • Platforms supported Plaforms
  • License License MIT

Improve method of failing a command

Currently, fail(statusCode:errorMessage:) is defined on Command, but the default run signature does not pass the command in, so the only way to actually fail a command is to do something like this:

let command = Command(usage: "foo", run: nil)
command.run = { flags, args in
    command.fail(statusCode: 1, errorMessage: "bar")
}

Ideally it would be nice to do something like:

let command = Command(usage: "foo") { cmd, flags, args in
    cmd.fail(statusCode: 1, errorMessage: "bar")
}

or even to allow the run handler to throw, in which case Guaka would print some error (or even use description if the error is CustomStringConvertible?)

enum FooError: Error, CustomStringConvertible {
    case bar

    var description: String {
        switch self {
        case .bar:
            return "bar"
        }
    }
}

let command = Command(usage: "foo") { flags, args in
    throw FooError.bar
}

Review the type safty of the flags

Make sure that the flags and their types are type safe
Maybe experiment into making the flag a generic? Or add a class that contains all the flags and is then passed to the command.

This class will have methods like getInt(flagName:) getString getBool

License for this project

Hi, this seems to be very good framework for building CLI applications, but I can't find anywhere how it is licensed (LICENSE file is missing). Could you please add it?

Thanks.

Add root command fallback to a subcommand

We need the possibility to let the root command execute a subcommand. In our use case the root command does nothing. So it would be nice that if no subcommand is specified, a default subcommand is used.

Example:
We have a root command called rootCommand with the sub commands foo and bar. foo should be the default.

We want to call:

> rootCommand "Hello World"

instead of:

> rootCommand foo "Hello World"

homebrew install fails with 404 error

$ brew install oarrabi/tap/guaka
==> Installing guaka from oarrabi/tap
==> Downloading https://github.com/oarrabi/Guaka-Generator/releases/download/0.1.1/guaka-generator-0.1.1-darwin-X64.tar.bz2

curl: (22) The requested URL returned error: 404 Not Found
Error: Failed to download resource "guaka"
Download failed: https://github.com/oarrabi/Guaka-Generator/releases/download/0.1.1/guaka-generator-0.1.1-darwin-X64.tar.bz2

The homebrew installation advertised at http://docs.getguaka.com/#getting-started fails with 404 Not Found error (see above)

Other methods of installation, such as the command below, seem to be working:
curl https://raw.githubusercontent.com/oarrabi/Guaka-Generator/master/scripts/install.sh -sSf | bash

Pre-release tasks.

  • Do we have a static build for Linux for Guaka-Generator?
  • Update the site to refer to the Guaka-Generator Github page.
  • Maybe a way of installing in Linux systems like https://github.com/junegunn/fzf? (That one is slick)
  • Create an account on DO with [email protected] and add a droplet move the site there.
  • If we have a installation instruction for Guaka-Generator on the site for MacOS we either remove it or add the Linux one.

//cc @oarrabi

Manually implementing Guaka issue

Followed along with the "Getting Started - Manually implementing Guaka"
But couldn't make it work.
Run ./.build/debug/abc "Hello from cli" then the issue is:

hello: 'Hello from cli' is not a hello command. See 'hello --help'.

Did you mean this?
Hello from cli

From Package.swift

import PackageDescription

let package = Package(name: "abc",
dependencies: [
.Package(url: "https://github.com/oarrabi/Guaka.git", majorVersion: 0),
]
)

From main.swift

import Guaka

let command = Command(usage: "hello") { _, args in
print("You passed (args) to your Guaka app!")
}

command.execute()

After run swift build:

Compile Swift Module 'StringScanner' (5 sources)
Compile Swift Module 'Guaka' (24 sources)
Compile Swift Module 'abc' (1 sources)
Linking ./.build/debug/abc

Escape values

Is there a way to escape a flag?

I wanted to have a command that passes along some arbitrary arguments and flags in a flag to a different script mycommand --args "--flag value", but Guaka complains as it doesn't see "--flag value" as a single string

Async code

Is there a way to run async code?
I want to make a network request but the app exits before the network request returns

Replace usage of the printToConsole method

When building on Swift 4.2, warnings that the printToConsole method should only be used in tests. This should probably be replaced with just print.

.build/checkouts/Guaka.git--3899120711634822110/Sources/Guaka/Command/Command+Execution.swift:149:9: warning: 'printToConsole' is deprecated: This method is for enabling testability and as such should only be used in tests.
        printToConsole(helpGenerator.errorString(forError: error))
        ^
.build/checkouts/Guaka.git--3899120711634822110/Sources/Guaka/Command/Command+Execution.swift:151:9: warning: 'printToConsole' is deprecated: This method is for enabling testability and as such should only be used in tests.
        printToConsole(helpGenerator.errorString(forError: .unknownError))
        ^
.build/checkouts/Guaka.git--3899120711634822110/Sources/Guaka/Command/Command+Execution.swift:155:7: warning: 'printToConsole' is deprecated: This method is for enabling testability and as such should only be used in tests.
      printToConsole(message)
      ^
.build/checkouts/Guaka.git--3899120711634822110/Sources/Guaka/Command/Command+Execution.swift:167:7: warning: 'printToConsole' is deprecated: This method is for enabling testability and as such should only be used in tests.
      printToConsole(deprecationMessage)
      ^
.build/checkouts/Guaka.git--3899120711634822110/Sources/Guaka/Command/Command+Execution.swift:173:18: warning: 'printToConsole' is deprecated: This method is for enabling testability and as such should only be used in tests.
      .forEach { printToConsole($0) }
                 ^
.build/checkouts/Guaka.git--3899120711634822110/Sources/Guaka/Command/Command.swift:386:5: warning: 'printToConsole' is deprecated: This method is for enabling testability and as such should only be used in tests.
    printToConsole(errorMessage ?? helpMessage)
    ^

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.