Skip to content

Linux Build #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
language: objective-c
osx_image: xcode9
install:
- gem install xcpretty
script:
- xcodebuild -scheme 'Docopt' clean build test | xcpretty -c
matrix:
include:
- os: linux
language: generic
dist: trusty
sudo: required
env:
- SWIFT_BRANCH=swift-4.1-branch
- SWIFT_VERSION=swift-4.1-DEVELOPMENT-SNAPSHOT-2018-03-09-a
install:
- sudo apt-get install clang libicu-dev
- mkdir swift
- curl https://swift.org/builds/$SWIFT_BRANCH/ubuntu1404/$SWIFT_VERSION/$SWIFT_VERSION-ubuntu14.04.tar.gz -s | tar xz -C swift &> /dev/null
- export PATH=$(pwd)/swift/$SWIFT_VERSION-ubuntu14.04/usr/bin:$PATH
- swift package update
script:
- swift test

- os: osx
language: objective-c
osx_image: xcode9
install:
- gem install xcpretty
script:
- xcodebuild -scheme 'Docopt' clean build test | xcpretty -c


notifications:
email: false
13 changes: 4 additions & 9 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,9 @@ let package = Package(
targets: [
.target(
name: "Docopt",
path: "Sources"
)
// Commented out until SPM supports resources
//,
// .testTarget(
// name: "DocoptTests",
// dependencies: ["Docopt"],
// path: "DocoptTests"
// )
dependencies: []),
.testTarget(
name: "DocoptTests",
dependencies: ["Docopt"])
]
)
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion Sources/Command.swift → Sources/Docopt/Command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal class Command: Argument {
let pattern = left[i]
if pattern is Argument {
if pattern.value as? String == self.name {
return (i, Command(self.name, value: true as AnyObject))
return (i, Command(self.name, value: true))
}
}
}
Expand Down
File renamed without changes.
95 changes: 46 additions & 49 deletions Sources/Docopt.swift → Sources/Docopt/Docopt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,25 @@
//

import Foundation
import Darwin

@objc
open class Docopt : NSObject {
fileprivate(set) open var result: [String: AnyObject]!
open class Docopt {
fileprivate(set) open var result: [String: Any]!
fileprivate let doc: String
fileprivate let version: String?
fileprivate let help: Bool
fileprivate let optionsFirst: Bool
fileprivate let arguments: [String]
@objc open static func parse(_ doc: String, argv: [String], help: Bool = false, version: String? = nil, optionsFirst: Bool = false) -> [String: AnyObject] {

open static func parse(_ doc: String, argv: [String], help: Bool = false, version: String? = nil, optionsFirst: Bool = false) -> [String: Any] {
return Docopt(doc, argv: argv, help: help, version: version, optionsFirst: optionsFirst).result
}

internal init(_ doc: String, argv: [String]? = nil, help: Bool = false, version: String? = nil, optionsFirst: Bool = false) {
self.doc = doc
self.version = version
self.help = help
self.optionsFirst = optionsFirst

var args: [String]
if argv == nil {
if CommandLine.argc > 1 {
Expand All @@ -39,45 +37,44 @@ open class Docopt : NSObject {
} else {
args = argv!
}

arguments = args.filter { $0 != "" }
super.init()
result = parse(optionsFirst)
}
fileprivate func parse(_ optionsFirst: Bool) -> [String: AnyObject] {

fileprivate func parse(_ optionsFirst: Bool) -> [String: Any] {
let usageSections = Docopt.parseSection("usage:", source: doc)

if usageSections.count == 0 {
DocoptLanguageError("\"usage:\" (case-insensitive) not found.").raise()
} else if usageSections.count > 1 {
DocoptLanguageError("More than one \"usage:\" (case-insensitive).").raise()
}

DocoptExit.usage = usageSections[0]

var options = Docopt.parseDefaults(doc)
let pattern = Docopt.parsePattern(Docopt.formalUsage(DocoptExit.usage), options: &options)
let argv = Docopt.parseArgv(Tokens(arguments), options: &options, optionsFirst: optionsFirst)
let patternOptions = Set(pattern.flat(Option.self))

for optionsShortcut in pattern.flat(OptionsShortcut.self) {
let docOptions = Set(Docopt.parseDefaults(doc))
optionsShortcut.children = Array(docOptions.subtracting(patternOptions))
}

Docopt.extras(help, version: version, options: argv, doc: doc)

let (matched, left, collected) = pattern.fix().match(argv)
var result = [String: AnyObject]()

var result = [String: Any]()

if matched && left.isEmpty {
let collectedLeafs = collected as! [LeafPattern]
let flatPattern = pattern.flat().filter { pattern in
(collectedLeafs.filter {$0.name == pattern.name}).isEmpty
} + collectedLeafs

for leafChild: LeafPattern in flatPattern {
result[leafChild.name!] = leafChild.value ?? NSNull()
}
Expand All @@ -87,7 +84,7 @@ open class Docopt : NSObject {
DocoptExit().raise()
return result
}

static fileprivate func extras(_ help: Bool, version: String?, options: [LeafPattern], doc: String) {
let helpOption = options.filter { $0.name == "--help" || $0.name == "-h" }
if help && !(helpOption.isEmpty) {
Expand All @@ -100,11 +97,11 @@ open class Docopt : NSObject {
exit(0)
}
}

static internal func parseSection(_ name: String, source: String) -> [String] {
return source.findAll("^([^\n]*\(name)[^\n]*\n?(?:[ \t].*?(?:\n|$))*)", flags: [.caseInsensitive, .anchorsMatchLines] )
}

static internal func parseDefaults(_ doc: String) -> [Option] {
var defaults = [Option]()
let optionsSection = parseSection("options:", source: doc)
Expand All @@ -122,14 +119,14 @@ open class Docopt : NSObject {
}
return defaults
}

static internal func parseLong(_ tokens: Tokens, options: inout [Option]) -> [Option] {
let (long, eq, val) = tokens.move()!.partition("=")
assert(long.hasPrefix("--"))

var value: String? = eq != "" || val != "" ? val : nil
var similar = options.filter {$0.long == long}

if tokens.error is DocoptExit && similar.isEmpty { // if no exact match
similar = options.filter {$0.long?.hasPrefix(long) ?? false}
}
Expand All @@ -144,7 +141,7 @@ open class Docopt : NSObject {
o = Option(nil, long: long, argCount: argCount)
options.append(o)
if tokens.error is DocoptExit {
o = Option(nil, long: long, argCount: argCount, value: (argCount > 0) ? value as AnyObject : true as AnyObject)
o = Option(nil, long: long, argCount: argCount, value: (argCount > 0) ? value : true)
}
} else {
o = Option(similar[0])
Expand All @@ -162,12 +159,12 @@ open class Docopt : NSObject {
}
}
if tokens.error is DocoptExit {
o.value = value as AnyObject? ?? true as AnyObject
o.value = value ?? true
}
}
return [o]
}

static internal func parseShorts(_ tokens: Tokens, options: inout [Option]) -> [Option] {
let token = tokens.move()!
assert(token.hasPrefix("-") && !token.hasPrefix("--"))
Expand All @@ -178,15 +175,15 @@ open class Docopt : NSObject {
let similar = options.filter {$0.short == short}
var o: Option
left = left[1..<left.count]

if similar.count > 1 {
tokens.error.raise("\(short) is specified ambiguously \(similar.count) times")
return []
} else if similar.count < 1 {
o = Option(short)
options.append(o)
if tokens.error is DocoptExit {
o = Option(short, value: true as AnyObject)
o = Option(short, value: true)
}
} else {
var value: String? = nil
Expand All @@ -202,19 +199,19 @@ open class Docopt : NSObject {
left = ""
}
if tokens.error is DocoptExit {
o.value = true as AnyObject
o.value = true
if let val = value
{
o.value = val as AnyObject
o.value = val
}
}
}

parsed.append(o)
}
return parsed
}

static internal func parseAtom(_ tokens: Tokens, options: inout [Option]) -> [Pattern] {
let token = tokens.current()!
if ["(", "["].contains(token) {
Expand All @@ -223,14 +220,14 @@ open class Docopt : NSObject {
let (matching, result): (String, [BranchPattern]) = (token == "(")
? (")", [Required(u)])
: ("]", [Optional(u)])

if tokens.move() != matching {
tokens.error.raise("unmatched '\(token)'")
}

return result
}

if token == "options" {
_ = tokens.move()
return [OptionsShortcut()]
Expand All @@ -244,7 +241,7 @@ open class Docopt : NSObject {
if (token.hasPrefix("<") && token.hasSuffix(">")) || token.isupper() {
return [Argument(tokens.move()!)]
}

return [Command(tokens.move()!)]
}

Expand All @@ -261,20 +258,20 @@ open class Docopt : NSObject {

return result
}

static internal func parseExpr(_ tokens: Tokens, options: inout [Option]) -> [Pattern] {
var seq = parseSeq(tokens, options: &options)
if tokens.current() != "|" {
return seq
}

var result = seq.count > 1 ? [Required(seq)] : seq
while tokens.current() == "|" {
_ = tokens.move()
seq = parseSeq(tokens, options: &options)
result += seq.count > 1 ? [Required(seq)] : seq
}

return result.count > 1 ? [Either(result)] : result
}

Expand All @@ -291,7 +288,7 @@ open class Docopt : NSObject {
while let current = tokens.current() {
if tokens.current() == "--" {
while let token = tokens.move() {
parsed.append(Argument(nil, value: token as AnyObject))
parsed.append(Argument(nil, value: token))
}
return parsed
} else if current.hasPrefix("--") {
Expand All @@ -304,27 +301,27 @@ open class Docopt : NSObject {
}
} else if optionsFirst {
while let token = tokens.move() {
parsed.append(Argument(nil, value: token as AnyObject))
parsed.append(Argument(nil, value: token))
}
return parsed
} else {
parsed.append(Command(nil, value: tokens.move() as AnyObject))
parsed.append(Command(nil, value: tokens.move()))
}
}
return parsed
}

static internal func parsePattern(_ source: String, options: inout [Option]) -> Pattern {
let tokens: Tokens = Tokens.fromPattern(source)
let result: [Pattern] = parseExpr(tokens, options: &options)

if tokens.current() != nil {
tokens.error.raise("unexpected ending: \(tokens)")
}

return Required(result)
}

static internal func formalUsage(_ section: String) -> String {
let (_, _, s) = section.partition(":") // drop "usage:"
let pu = s.split()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//

import Foundation
import Darwin

internal class DocoptError {
var message: String
Expand Down
File renamed without changes.
File renamed without changes.
Loading