Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Restructuring and Help generator partially done

  • Loading branch information...
commit f22aaf2acf7c2994d4e0b846ff696b34a3361762 1 parent d6d7a3c
Paul Driver authored April 25, 2011
19  LICENSE
... ...
@@ -0,0 +1,19 @@
  1
+Copyright (c) 2011 Paul Driver
  2
+
  3
+Permission is hereby granted, free of charge, to any person obtaining a copy
  4
+of this software and associated documentation files (the "Software"), to deal
  5
+in the Software without restriction, including without limitation the rights
  6
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7
+copies of the Software, and to permit persons to whom the Software is
  8
+furnished to do so, subject to the following conditions:
  9
+
  10
+The above copyright notice and this permission notice shall be included in
  11
+all copies or substantial portions of the Software.
  12
+
  13
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19
+THE SOFTWARE.
189  getopt.coffee
... ...
@@ -1,189 +0,0 @@
1  
-exports[t] = t.toUpperCase() for t in ['flag', 'scalar', 'array', 'object']
2  
-exports.list = exports.array
3  
-exports.hash = exports.object
4  
-exports.bool = exports.flag
5  
-
6  
-exports.BaseError         = class BaseError extends Error
7  
-    constructor: (@desc) ->
8  
-        Error.captureStackTrace(this, this.constructor)
9  
-        @message = @describe()
10  
-
11  
-    toString: () ->
12  
-        'getopt.' + @constructor.name + ': ' + @describe()
13  
-
14  
-    describe: () ->
15  
-        JSON.stringify(@desc)
16  
-
17  
-exports.InternalError     = class InternalError extends BaseError
18  
-exports.UnvalidatedType   = class UnvalidatedType extends InternalError
19  
-
20  
-exports.SpecError         = class SpecError extends BaseError
21  
-exports.InvalidShort      = class InvalidShort extends SpecError
22  
-exports.Conflict          = class Conflict extends SpecError
23  
-exports.NoType            = class NoType extends SpecError
24  
-exports.UnknownType       = class UnknownType extends SpecError
25  
-
26  
-exports.ParseError        = class ParseError extends BaseError
27  
-
28  
-exports.UnknownOption     = class UnknownOption extends ParseError
29  
-    describe: () -> "Unknown option #{ @desc } encountered"
30  
-
31  
-exports.NoValue           = class NoValue extends ParseError
32  
-    describe: () -> @desc + " requires a value, but none was given"
33  
-
34  
-exports.FlagWithValue     = class FlagWithValue extends ParseError
35  
-    describe: () ->
36  
-        "#{ @desc.name } was given \"#{ @desc.value }\", but takes no arguments"
37  
-
38  
-exports.ScalarWithValues  = class ScalarWithValues extends ParseError
39  
-    describe: () -> @desc + " was given more than one value"
40  
-
41  
-exports.RequiredMissing   = class RequiredMissing extends ParseError
42  
-    describe: () -> "Required option #{ @desc } was missing"
43  
-
44  
-class Result
45  
-    constructor: (@parser) ->
46  
-        @argv = []
47  
-
48  
-    # Add a positional argument to the result
49  
-    arg: (blob) -> @argv.push blob
50  
-
51  
-    # Mark a flag by given option name
52  
-    flag: (name) ->
53  
-        throw new NoValue name unless @parser.isFlag name
54  
-        target = @parser.index[name]
55  
-        this[target] = true
56  
-
57  
-    # Mark a param (scalar, array, or object) by name with value.
58  
-    param: (name, value) ->
59  
-        throw new NoValue name unless value
60  
-
61  
-        p      = @parser
62  
-        target = p.index[name]
63  
-        throw new UnknownOption name unless target
64  
-        spec   = p.spec[target]
65  
-
66  
-        switch spec.type
67  
-            when exports.flag
68  
-                throw new FlagWithValue name: name, value: value
69  
-            when exports.scalar
70  
-                if this[target]
71  
-                    throw new ScalarWithValues name
72  
-                this[target] = value
73  
-            when exports.array
74  
-                o = this[target] or= []
75  
-                o.push value
76  
-            when exports.object
77  
-                match = /^([^=]*)(?:=(.+))?$/.exec(value)
78  
-                o = this[target] or= {}
79  
-                o[match[1]] = match[2]
80  
-            else
81  
-                throw new UnvalidatedType(name)
82  
-
83  
-    # Set defaults, throw errors if required parameters weren't seen.
84  
-    finalize: () ->
85  
-        p = @parser
86  
-        for own target, spec of p.spec
87  
-            if (spec.type isnt exports.flag) and not this[target]
88  
-                this[target] = spec.default
89  
-
90  
-            value = this[target]
91  
-            if spec.required and (
92  
-                (spec.type is exports.scalar and not value) or
93  
-                (spec.type is exports.array  and value.length < 1)
94  
-            )
95  
-                throw new RequiredMissing(target)
96  
-
97  
-        return this
98  
-
99  
-exports.Parser = class Parser
100  
-    constructor: (spec) ->
101  
-        @spec  = spec
102  
-        @index = {}
103  
-        for own target, subspec of spec
104  
-
105  
-            # upgrade scalars to arrays
106  
-            longs = subspec.long or [target]
107  
-            longs = [longs] unless Array.isArray longs
108  
-            subspec.long = longs
109  
-
110  
-            shorts = subspec.short or []
111  
-            shorts = [shorts] unless Array.isArray shorts
112  
-            subspec.short = shorts
113  
-
114  
-            alias = ('--' + l for l in longs)
115  
-
116  
-            for s in shorts
117  
-                if s.length isnt 1
118  
-                    throw new InvalidShort(s)
119  
-                alias.push '-' + s
120  
-
121  
-            for a in alias
122  
-                existing = @index[a]
123  
-                throw new Conflict(target, a, existing) if existing
124  
-                @index[a] = target
125  
-
126  
-            t = subspec.type
127  
-            throw new NoType(target) unless t
128  
-
129  
-            if t is exports.array
130  
-                subspec.default or= []
131  
-            else if t is exports.object
132  
-                subspec.default or= {}
133  
-            else if t isnt exports.scalar and t isnt exports.flag
134  
-                throw new UnknownType name: target, type: t
135  
-
136  
-
137  
-    isFlag: (name) ->
138  
-        target = @index[name]
139  
-        throw new UnknownOption(name) unless target
140  
-        @spec[target].type is exports.flag
141  
-
142  
-    parse: (argv) ->
143  
-        result = new Result(this)
144  
-        i = 0
145  
-        while i < argv.length
146  
-            blob = argv[i]
147  
-
148  
-            # special case for single - (usually means stdin)
149  
-            if blob is '-'
150  
-                result.arg blob
151  
-
152  
-            # -- stop processing and treat the rest of argv
153  
-            else if blob is '--'
154  
-                result.arg(a) for a in argv.slice(i+1)
155  
-                break
156  
-
157  
-            # -vax is equivalent to -v -a -x if -v is a flag
158  
-            # -Dfoo is equivalent to -D=foo if -D isn't a flag
159  
-            else if match = /^-(\w.+)$/.exec(blob)
160  
-                name   = match[1]
161  
-                first  = '-' + name.charAt(0)
162  
-
163  
-                if @isFlag first
164  
-                    result.flag('-' + f) for f in name.split('')
165  
-                else
166  
-                    result.param first, name.slice(1)
167  
-
168  
-            # --answer=42 but NOT -answer=42. That will be parsed by
169  
-            # the above rule as -a nswer=42. We're also not supporting -a=42,
170  
-            # since that's not standard at all. That will be parsed as -a =42
171  
-            else if match = /^(--\w+)=(.*)$/.exec(blob)
172  
-                result.param match[1], match[2]
173  
-
174  
-            # -v or --verbose
175  
-            else if match = /^(-\w)$/.exec(blob) or
176  
-                            /^(--\w+)$/.exec(blob)
177  
-                name = match[1]
178  
-                if @isFlag name
179  
-                    result.flag name
180  
-                else
181  
-                    # If it's not a flag, consume the next argument as value
182  
-                    result.param name, argv[++i]
183  
-            else
184  
-                # treat everything else as positional
185  
-                result.arg(blob)
186  
-
187  
-            i += 1
188  
-
189  
-        return result.finalize()
79  lib/Help.coffee
... ...
@@ -0,0 +1,79 @@
  1
+specification = require './specification'
  2
+type          = require './types'
  3
+
  4
+leftCol = (spec, alias, long) ->
  5
+    prefix = if long then '--' else '-'
  6
+    str = prefix + alias
  7
+
  8
+    if spec.type isnt type.flag
  9
+        if spec.type is type.object
  10
+            str += ' KEY=VAL'
  11
+        else if long
  12
+            str += '=VAL'
  13
+        else
  14
+            str += ' VAL'
  15
+
  16
+    str
  17
+
  18
+rank = {}
  19
+rank[type[t]] = i for t, i in ['flag', 'scalar', 'array', 'object']
  20
+
  21
+exports.Help = class Help
  22
+    tw: 78
  23
+
  24
+    constructor: (@spec) ->
  25
+        specification.index(@spec)
  26
+
  27
+    toString: () ->
  28
+        lines = []
  29
+        for own target, sub of @spec
  30
+            line = { rank: rank[sub.type] }
  31
+            left = (leftCol(sub, s, false) for s in sub.short.slice(0).sort())
  32
+            left.push leftCol(sub, s, true) for s in sub.long.slice(0).sort()
  33
+
  34
+            line.left  = left
  35
+            line.fl    = left[0]
  36
+            line.ll    = left[left.length-1]
  37
+            line.right = sub.description.trim()
  38
+            line.right += '.' unless line.right.match(/\.$/)
  39
+            line.right += ' Required.' if sub.required
  40
+
  41
+            if sub.default
  42
+                line.right += ' Default: ' + JSON.stringify(sub.default)
  43
+
  44
+            lines.push line
  45
+
  46
+        # Right-justify the left sides
  47
+        lengths = (l.ll.length for l in lines)
  48
+        max     = Math.max.apply(Math, lengths)
  49
+        for line in lines
  50
+            for l, i in line.left
  51
+                pad = max - l.length
  52
+                l = ' ' + l for [1..pad] if pad
  53
+                line.left[i] = l + '  '
  54
+
  55
+        # Left-justify the right sides two spaces away
  56
+
  57
+        remaining = @tw - max - 2
  58
+        sep = "\n"
  59
+        sep += ' ' for [1..max+2]
  60
+
  61
+
  62
+        for l, i in lines
  63
+            words = (w.trim() for w in l.right.split /\s/)
  64
+            words = (w for w in words if w.length > 0)
  65
+            all   = ''
  66
+            cur   = words.shift()
  67
+            while words.length > 0
  68
+                w = words.shift()
  69
+                if w.length + cur.length < remaining
  70
+                    cur += ' ' + w
  71
+                else
  72
+                    all += cur + sep
  73
+                    cur = w
  74
+            lines[i].right = all + cur
  75
+
  76
+        lines.sort (a, b) -> (a.rank - b.rank) or a.fl.localeCompare(b.fl)
  77
+        out = (l.left.join("\n") + l.right for l in lines).join "\n\n"
  78
+        console.log out
  79
+        out
116  lib/Parser.coffee
... ...
@@ -0,0 +1,116 @@
  1
+ex            = require './exceptions'
  2
+type          = require './types'
  3
+specification = require './specification'
  4
+
  5
+class Result
  6
+    constructor: (@parser) ->
  7
+        @argv = []
  8
+
  9
+    # Add a positional argument to the result
  10
+    arg: (blob) -> @argv.push blob
  11
+
  12
+    # Mark a flag by given option name
  13
+    flag: (name) ->
  14
+        throw new ex.NoValue name unless @parser.isFlag name
  15
+        target = @parser.index[name]
  16
+        this[target] = true
  17
+
  18
+    # Mark a param (scalar, array, or object) by name with value.
  19
+    param: (name, value) ->
  20
+        throw new ex.NoValue name unless value
  21
+
  22
+        p      = @parser
  23
+        target = p.index[name]
  24
+        throw new ex.UnknownOption name unless target
  25
+        spec   = p.spec[target]
  26
+
  27
+        switch spec.type
  28
+            when type.flag
  29
+                throw new ex.FlagWithValue name: name, value: value
  30
+            when type.scalar
  31
+                if this[target]
  32
+                    throw new ex.ScalarWithValues name
  33
+                this[target] = value
  34
+            when type.array
  35
+                o = this[target] or= []
  36
+                o.push value
  37
+            when type.object
  38
+                match = /^([^=]*)(?:=(.+))?$/.exec(value)
  39
+                o = this[target] or= {}
  40
+                o[match[1]] = match[2]
  41
+            else
  42
+                throw new ex.UnvalidatedType(name)
  43
+
  44
+    # Set defaults, throw errors if required parameters weren't seen.
  45
+    finalize: () ->
  46
+        p = @parser
  47
+        for own target, spec of p.spec
  48
+            if (spec.type isnt type.flag) and not this[target]
  49
+                this[target] = spec.default
  50
+
  51
+            value = this[target]
  52
+            if spec.required and (
  53
+                (spec.type is type.scalar and not value) or
  54
+                (spec.type is type.array  and value.length < 1)
  55
+            )
  56
+                throw new ex.RequiredMissing(target)
  57
+
  58
+        return this
  59
+
  60
+exports.Parser = class Parser
  61
+    constructor: (@spec) ->
  62
+        @index = specification.index(@spec)
  63
+
  64
+    isFlag: (name) ->
  65
+        target = @index[name]
  66
+        throw new ex.UnknownOption(name) unless target
  67
+        @spec[target].type is type.flag
  68
+
  69
+    parse: (argv) ->
  70
+        result = new Result(this)
  71
+        i = 0
  72
+        while i < argv.length
  73
+            blob = argv[i]
  74
+
  75
+            # special case for single - (usually means stdin)
  76
+            if blob is '-'
  77
+                result.arg blob
  78
+
  79
+            # -- stop processing and treat the rest of argv
  80
+            else if blob is '--'
  81
+                result.arg(a) for a in argv.slice(i+1)
  82
+                break
  83
+
  84
+            # -vax is equivalent to -v -a -x if -v is a flag
  85
+            # -Dfoo is equivalent to -D=foo if -D isn't a flag
  86
+            else if match = /^-(\w.+)$/.exec(blob)
  87
+                name   = match[1]
  88
+                first  = '-' + name.charAt(0)
  89
+
  90
+                if @isFlag first
  91
+                    result.flag('-' + f) for f in name.split('')
  92
+                else
  93
+                    result.param first, name.slice(1)
  94
+
  95
+            # --answer=42 but NOT -answer=42. That will be parsed by
  96
+            # the above rule as -a nswer=42. We're also not supporting -a=42,
  97
+            # since that's not standard at all. That will be parsed as -a =42
  98
+            else if match = /^(--\w+)=(.*)$/.exec(blob)
  99
+                result.param match[1], match[2]
  100
+
  101
+            # -v or --verbose
  102
+            else if match = /^(-\w)$/.exec(blob) or
  103
+                            /^(--\w+)$/.exec(blob)
  104
+                name = match[1]
  105
+                if @isFlag name
  106
+                    result.flag name
  107
+                else
  108
+                    # If it's not a flag, consume the next argument as value
  109
+                    result.param name, argv[++i]
  110
+            else
  111
+                # treat everything else as positional
  112
+                result.arg(blob)
  113
+
  114
+            i += 1
  115
+
  116
+        return result.finalize()
37  lib/exceptions.coffee
... ...
@@ -0,0 +1,37 @@
  1
+exports.BaseError         = class BaseError extends Error
  2
+    constructor: (@desc) ->
  3
+        Error.captureStackTrace(this, this.constructor)
  4
+        @message = @describe()
  5
+
  6
+    toString: () ->
  7
+        'getopt.' + @constructor.name + ': ' + @describe()
  8
+
  9
+    describe: () ->
  10
+        JSON.stringify(@desc)
  11
+
  12
+exports.InternalError     = class InternalError extends BaseError
  13
+exports.UnvalidatedType   = class UnvalidatedType extends InternalError
  14
+
  15
+exports.SpecError         = class SpecError extends BaseError
  16
+exports.InvalidShort      = class InvalidShort extends SpecError
  17
+exports.Conflict          = class Conflict extends SpecError
  18
+exports.NoType            = class NoType extends SpecError
  19
+exports.UnknownType       = class UnknownType extends SpecError
  20
+
  21
+exports.ParseError        = class ParseError extends BaseError
  22
+
  23
+exports.UnknownOption     = class UnknownOption extends ParseError
  24
+    describe: () -> "Unknown option #{ @desc } encountered"
  25
+
  26
+exports.NoValue           = class NoValue extends ParseError
  27
+    describe: () -> @desc + " requires a value, but none was given"
  28
+
  29
+exports.FlagWithValue     = class FlagWithValue extends ParseError
  30
+    describe: () ->
  31
+        "#{ @desc.name } was given \"#{ @desc.value }\", but takes no arguments"
  32
+
  33
+exports.ScalarWithValues  = class ScalarWithValues extends ParseError
  34
+    describe: () -> @desc + " was given more than one value"
  35
+
  36
+exports.RequiredMissing   = class RequiredMissing extends ParseError
  37
+    describe: () -> "Required option #{ @desc } was missing"
10  lib/getopt.coffee
... ...
@@ -0,0 +1,10 @@
  1
+reexport = (module) ->
  2
+    m = require module
  3
+    exports[key] = val for own key, val of m
  4
+
  5
+reexport m for m in [
  6
+    './types'
  7
+    './exceptions'
  8
+    './Parser'
  9
+    './Help'
  10
+]
38  lib/specification.coffee
... ...
@@ -0,0 +1,38 @@
  1
+ex   = require './exceptions'
  2
+type = require './types'
  3
+
  4
+exports.index = (spec) ->
  5
+    index = {}
  6
+    for own target, sub of spec
  7
+        # upgrade scalars to arrays
  8
+        longs = sub.long or [target]
  9
+        longs = [longs] unless Array.isArray longs
  10
+        sub.long = longs
  11
+
  12
+        shorts = sub.short or []
  13
+        shorts = [shorts] unless Array.isArray shorts
  14
+        sub.short = shorts
  15
+
  16
+        alias = ('--' + l for l in longs)
  17
+
  18
+        for s in shorts
  19
+            if s.length isnt 1
  20
+                throw new ex.InvalidShort(s)
  21
+            alias.push '-' + s
  22
+
  23
+        for a in alias
  24
+            existing = index[a]
  25
+            throw new ex.Conflict(target, a, existing) if existing
  26
+            index[a] = target
  27
+
  28
+        t = sub.type
  29
+        throw new ex.NoType(target) unless t
  30
+
  31
+        if t is type.array
  32
+            sub.default or= []
  33
+        else if t is type.object
  34
+            sub.default or= {}
  35
+        else if t isnt type.scalar and t isnt type.flag
  36
+            throw new ex.UnknownType name: target, type: t
  37
+
  38
+    index
7  lib/types.coffee
... ...
@@ -0,0 +1,7 @@
  1
+exports[t] = t.toUpperCase() for t in ['flag', 'scalar', 'array', 'object']
  2
+
  3
+exports[key] = exports[val] for own key, val of {
  4
+    list: 'array'
  5
+    hash: 'object'
  6
+    bool: 'flag'
  7
+}
30  package.json
... ...
@@ -0,0 +1,30 @@
  1
+{
  2
+    "name" : "getopt",
  3
+    "description" : "fixme",
  4
+    "version" : "0.1.0",
  5
+    "bugs" : "mailto:frodwith@gmail.com",
  6
+    "keywords" : [ "option", "parse", "commandline", "command", "line" ],
  7
+    "main" : "./lib/getopt.js",
  8
+    "directories" : {
  9
+        "lib" : "./lib",
  10
+        "test" : "./test"
  11
+    },
  12
+    "maintainers" : [
  13
+        { name: "Paul Drvier", email: "frodwith@gmail.com" }
  14
+    ],
  15
+    "contributors" : [
  16
+        { name: "Paul Drvier", email: "frodwith@gmail.com" }
  17
+    ],
  18
+    "licences" : [
  19
+        {
  20
+            "type" : "MIT License",
  21
+            "url"  : "http://www.opensource.org/licenses/mit-license"
  22
+        }
  23
+    ],
  24
+    "repositories" : [
  25
+        {
  26
+            "type" : "git",
  27
+            "url" : "http://github.com/frodwith/node-getopt"
  28
+        }
  29
+    ]
  30
+}
50  test/help.coffee
... ...
@@ -0,0 +1,50 @@
  1
+getopt = require '../lib/getopt'
  2
+
  3
+exports.basic = (t) ->
  4
+    t.expect 1
  5
+    spec =
  6
+        verbose:
  7
+            type: getopt.flag
  8
+            short: 'v'
  9
+            description: 'Print debugging messages'
  10
+        output:
  11
+            type: getopt.scalar
  12
+            short: 'o'
  13
+            description: 'Filename (- for stdout) to write output to.'
  14
+            default: '-'
  15
+        input:
  16
+            type: getopt.list
  17
+            short: 'i'
  18
+            description: 'Filename(s) (- for stdin) to read input from'
  19
+            default: ['-']
  20
+        password:
  21
+            type: getopt.scalar
  22
+            short: 'p'
  23
+            description: 'Secret string to use when connecting to server. This description is going to be ridiculously long so that we can test the line breaking a bit'
  24
+            required: true
  25
+        symbols:
  26
+            type: getopt.hash
  27
+            short: 'D',
  28
+            long: 'define'
  29
+            description: 'Symbols to define during processing'
  30
+    u = new getopt.Help spec
  31
+    t.equals u.toString(), '''
  32
+-v
  33
+--verbose         Print debugging messages.
  34
+
  35
+-o VAL
  36
+--output=VAL      Filename (- for stdout) to write output to. default: -
  37
+
  38
+--password=VAL    Secret string to use when connecting to server. This
  39
+                  description is going to be ridiculously long so that we can
  40
+                  test the line breaking a bit. Required.
  41
+ 
  42
+-i VAL
  43
+--input=VAL       Filename(s) (- for stdin) to read input from. Can be 
  44
+                  specified multiple times.
  45
+
  46
+-D KEY=VAL
  47
+--define KEY=VAL  Symbols to define during processing. Can be specified 
  48
+                  multiple times.
  49
+'''
  50
+    t.done()
2  test/parse.coffee
... ...
@@ -1,4 +1,4 @@
1  
-getopt = require('getopt')
  1
+getopt = require '../lib/getopt'
2 2
 
3 3
 exports.flag = (t) ->
4 4
     t.expect 6
59  test/spec.coffee
... ...
@@ -0,0 +1,59 @@
  1
+spec = require '../lib/specification'
  2
+ex   = require '../lib/exceptions'
  3
+type = require '../lib/types'
  4
+
  5
+exports.type = (t) ->
  6
+    t.expect 2
  7
+    t.throws (() -> spec.index { foo: { short: 'f' }}), ex.NoType
  8
+    t.throws (() -> spec.index { foo: { type: 'none'}}), ex.UnknownType
  9
+    t.done()
  10
+
  11
+exports.short = (t) ->
  12
+    t.expect 4
  13
+    short = (err, val) ->
  14
+        cons = () ->
  15
+            spec.index
  16
+                foo:
  17
+                    type:  type.flag
  18
+                    short: val
  19
+        tfn  = if err then t.throws else t.doesNotThrow
  20
+        tfn.call t, cons, ex.InvalidShort
  21
+
  22
+    short true, 'foo'
  23
+    short true, 'ab'
  24
+    short false, 'a'
  25
+    short false, 'b'
  26
+    t.done()
  27
+
  28
+exports.conflicts = (t) ->
  29
+    t.expect 6
  30
+
  31
+    conflict = (err, fn) ->
  32
+        s =
  33
+            foo: { type: type.flag }
  34
+            bar: { type: type.flag }
  35
+        fn s
  36
+        tfn  = if err then t.throws else t.doesNotThrow
  37
+        cons = () -> spec.index s
  38
+        tfn.call t, cons, ex.Conflict
  39
+
  40
+    conflict true, (s) -> s.bar.long = 'foo'
  41
+    conflict true, (s) -> s.foo.long = ['foo', 'bar', 'baz']
  42
+
  43
+    conflict true, (s) ->
  44
+        s.foo.long = 'different'
  45
+        s.bar.long = 'different'
  46
+
  47
+    conflict true, (s) ->
  48
+        s.foo.short = 's'
  49
+        s.bar.short = ['q', 'r', 's']
  50
+
  51
+    conflict false, (s) ->
  52
+        s.foo.long  = 's'
  53
+        s.bar.short = 's'
  54
+
  55
+    conflict false, (s) ->
  56
+        s.foo.short = 'a'
  57
+        s.bar.long  = ['a', 'abstruse']
  58
+
  59
+    t.done()

0 notes on commit f22aaf2

Please sign in to comment.
Something went wrong with that request. Please try again.