jatoben / commandline Goto Github PK
View Code? Open in Web Editor NEWA pure Swift library for creating command-line interfaces
License: Apache License 2.0
A pure Swift library for creating command-line interfaces
License: Apache License 2.0
Given the following situation: My Tool can do two jobs: A and B. Job A needs parameters a and b, Job B needs parameters c and d.
So if the user wants job A I want parameters a and b required. If he wants job B I want parameters c and d required.
How would I handle theses depending parameters nicely, meaning without lots of if
and custom messages of required parameters.
I was wondering, shouldn’t BoolOption.isSet
not be true by default for consistency with other options? The reason I ask is that it thwarts common patterns for trying to determine which options are set after parsing.
var CLIOptions = [Option]()
// Create options, parse, etc., ...
// This doesn’t currently work because of BoolOption (since its true by default)
let flagsOn = CLIOptions.filter { $0.isSet }
// A work around
let isSetNonBoolOptions = CLIOptions.filter { $0.isSet == true &&
$0 as? BoolOption == nil }
let isSetBoolOptions = CLIOptions.filter { $0 as? BoolOption != nil }
.map { $0 as! BoolOption }
.filter { $0.value == true }
Is there a better way to go about this? Love to hear what you think!
I'm trying to implement a progress indicator - it would be nice if the framework provided a way to write over the current line instead of printing on a new one.
Hi,
thanks for the project! :-)
I would like three cases of flow through my command line app:
--version => output version and end
--help => output help info and end
all others -> normal flow
I've got the all others flow under control based on your examples. :-)
The --help kind of works, since failing will output the help ;-)
The --version I don't know how I should implement
Any suggestions for how I can add different set of valid requirement combinations?
Cheers
Nik
Hi folks,
If you've been watching this repository, you can tell that I haven't had time to work on this for quite a while. I plan to archive it in the near future to avoid any confusion.
If anyone has an active fork and would like to pick up the mantle—@benoit-pereira-da-silva, @beltex, or @pdesantis maybe?—I'd be happy to point to your fork(s) for anyone who's looking for a maintained version.
Thanks to everyone who's contributed!
Hi,
Your module cannot be installed with SPM :
import PackageDescription
let package = Package(
name: "MyProject",
targets: [],
dependencies: [
.Package(url: "https://github.com/jatoben/CommandLine.git",
majorVersion: 2)
]
)
swift package fetch
Fetching https://github.com/jatoben/CommandLine.git
Cloning https://github.com/jatoben/CommandLine.git
Resolving https://github.com/jatoben/CommandLine.git at 2.2.0
error: the directory Tests/CommandLine has an invalid name ('CommandLine'): the name of a test module has no 'Tests' suffix
fix: rename the directory 'Tests/CommandLine' to have a 'Tests' suffix
In order to use CommandLine with Carthage, there must be a tag marking at least one commit with a version number.
programm --files "path/my file.txt"
is getting two files on its options: path/my
and file.txt
as separated files.
But "my file.txt" is only one file named "my file" and I only want this: path/my file.txt
, not this: path/my
and file.txt
.
Unlike the IntOption class, which uses the form
if let val = Int(values[0]) {
DoubleOption uses the toDouble String extension. Were it instead to use the form
if let val = Double(values[0]) {
the code base becomes slightly smaller, since toDouble can be deleted, and (more importantly) it becomes able to parse values in scientific notation.
Is there a reason I'm not seeing why it's this way? I've tried this change on a version prior to the rename to CommandLineKit, and it appears to work fine.
Hello,
I got this code sample:
let cli = CommandLine()
let deploy = StringOption(shortFlag: "d", longFlag: "deploy",
helpMessage: "Deploys a plugin, color scheme or template from given directory. Default: Current Directory.")
cli.addOptions(deploy)
do {
try cli.parse()
} catch {
cli.printUsage(error)
exit(EX_USAGE)
}
if deploy.value {
//TODO: empty path => current dir
print (deploy.value)
}
How can I recognize that the deploy option was called but with an empty value ?
I want to support both : Giving a specific directory or leaving the directory path blank which should result in using the current directory. The only way I can think of is to make two options, one StringOption and one BoolOption.
Is there any better chance to implement this behaviour ?
Thanks,
David
It would be nice if there was a way to specify at least one input file without an option. Here's an example with cp
:
cp someFile.txt copiedFile.txt # Copies someFile.txt to copiedFile.txt
And it would also be helpful to show that in the help text:
Usage:
./example [options] [file] file2 file3
It would also be great if these files could be optional (so, for example, the absence of a file causes the program to read from stdin
).
Wrapping long help lines to the terminal width would make the usage message look much better. Unfortunately the canonical method to get the terminal size is an ioctl(2)
call, and Swift is not compatible with C varargs.
Swift 3's standard library will have its own CommandLine class (renamed from Process): https://github.com/apple/swift/commits/master/stdlib/public/core/CommandLine.swift
What's the plan with respect to the potential name clash?
Swift.CommandLine
and CommandLine.CommandLine
?CommandLine
class to something else, e.g. CommandLineKit
?CommandLine
an extension of Swift.CommandLine
?I'm starting a new project that was prototyped in Python, and one of the differences I noticed between Python's ArgParse and CommandLine is the lack of a default help flag.
To me, at least, having a a help flag included by default would be useful as most applications would benefit from having a simple -h, --help
to provide usage and, for the most part, the what the flag needs to do doesn't change (borrowing from ArgParse's help message): "show this help message and exit".
I made made some modifications to my local repo:
CommandLine.addHelp(option: BoolOption? = nil)
to add a default help option, or override with a custom one. This sets ._helpOption
..parse()
to throw a new .HelpOption
error. This follows my expected behavior where usage info is printed and then exits.CommandLine.description
that is used as the error descriptionI'm still messing around with the updates, but am planning on making a pull request if people think it's a good idea.
My own todo list on this is possibly integrate the description and/ or overriding the default help option into the CommandLine init.
When using recent snapshots (since March).
This is caused by https://bugs.swift.org/browse/SR-1119
It would be interesting for me to have a default stray value not associated with any flag, let's say:
$ readfile --type=pdf ~/Documents/myfile.pdf
Perhaps I am missing something.
Thanks for the awesome tool! :)
It seems the biggest Command Line parser feature that is missing.
Hey guys,
I am author of Laurine, Localization generator that had quite a lot of success over the last months and that makes work with localizations breeze. I am using your library to parse out command line arguments that it then takes to create the output files.
I am in the process of converting everything into swift 3.0, I already reworked whole command line to 3.0 but once I run it, it seems that it does not recognize input properly. Specifically, it always says that for input option it did not find appropriate value:
Invalid value(s) for option -t, --stringsTableName:
Usage: /Users/jiritrecak/Documents/Development/OpenSource/Laurine/Example/Laurine/../../LaurineGenerator.swift [options]
-i, --input:
Required | String | Path to the localization file
...
If you guys would be willing to help with tracking down the issue, that would be amazing - I already spent quite a lot of time debugging it and you are pretty much master of your library :)
Repository with the latest changes and buildable Swift 3.0 version can be found here:
https://github.com/JiriTrecak/Laurine/tree/master-3
You simply download the repository as whole, run xcode project and sh error occurs. It can also be run through command line.
Sincerely and thanks for amazing work you already did,
Jiri
Edit: obviously, you can use any change that I did in Swift 3.0 support for this repo as well, I used latest push from one of your contributors and made it "working" for GM.
Hey, your library is really interesting.
The only problem I found was the README.md
, which lacks an Installation Section
I created this iOS Open source Readme Template so you can take a look on how to easily create an Installation Section
If you want, I can help you to organize the lib.
What are your thoughts? 😄
Now that XCode 7.3 was released with Swift 2.2 shipped by default I'm seeing the following issues when trying to install the latest commit on the master branch:
The following build commands failed:
CompileSwift normal x86_64 /path/to/project/Carthage/Checkouts/CommandLine/CommandLine/StringExtensions.swift
CompileSwift normal x86_64 /path/to/project/Carthage/Checkouts/CommandLine/CommandLineTests/CommandLineTests.swift
CompileSwift normal x86_64 /path/to/project/Carthage/Checkouts/CommandLine/CommandLine/Option.swift
CompileSwift normal x86_64 /path/to/project/Carthage/Checkouts/CommandLine/CommandLineTests/StringExtensionTests.swift
CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
(5 failures)
Can we fix this?
One thing that happens with having shortFlag
be mandatory is that since its only a single character, you quickly get collisions, and thus are forced to use random characters for an option (-y, --check-file
). I think in such a case, it would be better to have the option to specify only a longFlag
. You could make a case for the other direction too of course, thus I'm thinking it be useful to have the ability to exclusively choose a shortFlag
or longFlag
for an Option
.
Hello,
First, thanks for this truly masterful piece of code!
I wanted to know if there is any way how to use those parameters in XCode build phase, if you add your command as a new run script phase. I am able to run it easily from the commandline using swift + parameters, but I am not sure how to run it from the build script. I've used following:
"$LAURINE_PATH" - -i "$SOURCE_PATH" -d "$DELIMITER" > "$OUTPUT_PATH"
And that is buildable, but does not seem to produce any output (command line does). Maybe it is something worth updating in the documentation as well.
Thank you!
Below the title please add badges this help a lot.
If your component is compatible:
Indicated:
You can take inspiration from this template for iOS iOS-readme-template
Hey, How about this: Set class Option
from public
to open
to make custom Options
It's nice to have sub commands support, like git add/commit, pod install etc...
Hi @jatoben,
First off, thanks for the awesome project!
I had a question regarding the project license. On that note, I am not a lawyer, nor am I an expert on this subject matter. :)
I’m working on a command line tool that is soon to be open-sourced under GPLv2.0, which is unfortunately incompatible with the Apache 2.0 license. See here and here. This is due to the patent clause. GPLv3.0 is compatible (see previous links), however I was hoping not to upgrade to it. Thus, would you be open to granting a dual-license, Apache 2.0 & GPLv2.0 (or some other GPLv2.0 compatible license) for the case of use with GPLv2.0 projects?
I totally understand if not, just thought it be worth asking. :)
Sincerely,
beltex
format:
myCLKTool bootstrap --optionsFile options.yml
Would it be possible for this library to provide some support for network or other asynchronous requests so I don't need to manually manage a run loop?
Maybe I am missing something, but is there a way to set default values that are then overridden by the command line? Trying to set the value of any of my options informs me it a get-only s property
I get this error when running:
dyld: Library not loaded: @rpath/libswiftCore.dylib Referenced from: /Users/USERNAME/Library/Developer/Xcode/DerivedData/LocaleShots-CLI-gncnoendtwgqeofpgzeuqazdgxau/Build/Products/Debug/CommandLine.framework/Versions/A/CommandLine Reason: image not found (lldb)
There is some help here: http://stackoverflow.com/a/26383255/2183008
[some output omitted]
$ cd /tmp/
$ git clone https://github.com/jatoben/CommandLine
$ cd CommandLine
$ git checkout v2.2.0 -b 2.2.0
$ swift build
error: the module at Tests/CommandLine has an invalid name ('CommandLine'): the name of a test module has no ‘Tests’ suffix
fix: rename the module at ‘Tests/CommandLine’ to have a ‘Tests’ suffix
Please tag the repo more often; the current head works just fine and deserves a 2.2.1 tag!
Hi,
I’m currently using the swift package manager with your repo as a dependency and it seems that there is no 'Package.swift' file added in your version tags (none in the 3 versions).
Is this a choice or am I missing something?
$ swift build
Cloning https://github.com/jatoben/CommandLine
Using version 2.0.0 of package CommandLine
error: No Package.swift file found at: /home/foo/bar/Packages/CommandLine-2.0.0/Package.swift
Thanks,
Just a nice to have, nothing critical! :)
Have an option for the CommandLine
class to turn on ANSI color. This would apply to error messages (ParseError.description
), which could be in red for example, and to printUsage()
, in which color is applied to shortFlag
, longFlag
, and the helpMessage
(Usage
line too?). Here's an example of what that might look like.
This just requires pre-appending a print statement with an escape code to turn on a particular color, and appending the off code. If there is interest in adding this I'd be happy to submit a pull request.
Program:
import Foundation
let cli = CommandLine()
let file1 = StringOption(longFlag: "file", required: true, helpMessage: "Path to the output file.")
let file2 = StringOption(longFlag: "file", required: true, helpMessage: "Path to the output file.")
cli.addOptions(file1, file2)
do {
try cli.parse()
} catch {
cli.printUsage(error)
exit(EX_USAGE)
}
Result of running:
Missing required options: ["--file", "--file"]
Usage: /Users/d12frosted/Library/Developer/Xcode/DerivedData/Knittens-fsuflsjrrwdnzwaueherzytkigua/Build/Products/Debug/KnittensBot [options]
--file:
Path to the output file.
--file:
Path to the output file.
Program ended with exit code: 64
I expect from CommandLine to show an error in such case.
This error occurs when swift build
is run:
error: the directory Tests/CommandLine has an invalid name ('CommandLine'): the name of a test module has no 'Tests' suffix
fix: rename the directory 'Tests/CommandLine' to have a 'Tests' suffix
The package dependency is defined as follows:
╭─pradeep@home ~/csv2md ‹system›
╰─➤ cat Package.swift 1 ↵
// swift-tools-version:3.1
import PackageDescription
let package = Package(
name: "csv2md",
dependencies: [
.Package(url: "https://github.com/Daniel1of1/CSwiftV", majorVersion: 0),
.Package(url: "https://github.com/jatoben/CommandLine", majorVersion: 2, minor: 2),
.Package(url: "https://github.com/onevcat/Rainbow", majorVersion: 2)
]
)
Me being a newbie to Swift, I might be missing something obvious!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.