Condense scope arrays in tests

Condense scope arrays in tests

--- spec/language-csound-spec.coffee
+++ spec/language-csound-spec.coffee
@@ -22,50 +22,22 @@
       '''
       tokens = lines[0]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
+      expect(tokens[0]).toEqual value: '/*', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
       tokens = lines[1]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: ' * comment', scopes: [
-        'source.csound'
-        'comment.block.csound'
-      ]
+      expect(tokens[0]).toEqual value: ' * comment', scopes: ['source.csound', 'comment.block.csound']
       tokens = lines[2]
       expect(tokens.length).toBe 2
-      expect(tokens[0]).toEqual value: ' ', scopes: [
-        'source.csound'
-        'comment.block.csound'
-      ]
-      expect(tokens[1]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: ' ', scopes: ['source.csound', 'comment.block.csound']
+      expect(tokens[1]).toEqual value: '*/', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
       tokens = lines[3]
       expect(tokens.length).toBe 2
-      expect(tokens[0]).toEqual value: ';', scopes: [
-        'source.csound'
-        'comment.line.csound'
-        'punctuation.definition.comment.line.csound'
-      ]
-      expect(tokens[1]).toEqual value: ' comment', scopes: [
-        'source.csound'
-        'comment.line.csound'
-      ]
+      expect(tokens[0]).toEqual value: ';', scopes: ['source.csound', 'comment.line.csound', 'punctuation.definition.comment.line.csound']
+      expect(tokens[1]).toEqual value: ' comment', scopes: ['source.csound', 'comment.line.csound']
       tokens = lines[4]
       expect(tokens.length).toBe 2
-      expect(tokens[0]).toEqual value: '//', scopes: [
-        'source.csound'
-        'comment.line.csound'
-        'punctuation.definition.comment.line.csound'
-      ]
-      expect(tokens[1]).toEqual value: ' comment', scopes: [
-        'source.csound'
-        'comment.line.csound'
-      ]
+      expect(tokens[0]).toEqual value: '//', scopes: ['source.csound', 'comment.line.csound', 'punctuation.definition.comment.line.csound']
+      expect(tokens[1]).toEqual value: ' comment', scopes: ['source.csound', 'comment.line.csound']

     it 'tokenizes instrument blocks', ->
       lines = grammar.tokenizeLines '''
@@ -77,151 +49,39 @@

       tokens = lines[0]
       expect(tokens.length).toBe 15
-      expect(tokens[0]).toEqual value: 'instr', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'keyword.function.csound'
-      ]
-      expect(tokens[1]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[2]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
-      expect(tokens[3]).toEqual value: '1', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'entity.name.function.csound'
-      ]
-      expect(tokens[4]).toEqual value: ',', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-      ]
-      expect(tokens[5]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[6]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
-      expect(tokens[7]).toEqual value: 'N_a_M_e_', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'entity.name.function.csound'
-      ]
-      expect(tokens[8]).toEqual value: ',', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-      ]
-      expect(tokens[9]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[10]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
-      expect(tokens[11]).toEqual value: '+', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-      ]
-      expect(tokens[12]).toEqual value: 'Name', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'entity.name.function.csound'
-      ]
-      expect(tokens[13]).toEqual value: '//', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-        'comment.line.csound'
-        'punctuation.definition.comment.line.csound'
-      ]
-      expect(tokens[14]).toEqual value: '', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.instrument-declaration.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'instr', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'keyword.function.csound']
+      expect(tokens[1]).toEqual value: '/*', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[2]).toEqual value: '*/', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+      expect(tokens[3]).toEqual value: '1', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'entity.name.function.csound']
+      expect(tokens[4]).toEqual value: ',', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound']
+      expect(tokens[5]).toEqual value: '/*', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[6]).toEqual value: '*/', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+      expect(tokens[7]).toEqual value: 'N_a_M_e_', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'entity.name.function.csound']
+      expect(tokens[8]).toEqual value: ',', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound']
+      expect(tokens[9]).toEqual value: '/*', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[10]).toEqual value: '*/', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+      expect(tokens[11]).toEqual value: '+', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound']
+      expect(tokens[12]).toEqual value: 'Name', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'entity.name.function.csound']
+      expect(tokens[13]).toEqual value: '//', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound', 'comment.line.csound', 'punctuation.definition.comment.line.csound']
+      expect(tokens[14]).toEqual value: '', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.instrument-declaration.csound']

       tokens = lines[1]
       expect(tokens.length).toBe 2
-      expect(tokens[0]).toEqual value: 'aLabel', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'entity.name.label.csound'
-      ]
-      expect(tokens[1]).toEqual value: ':', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'entity.punctuation.label.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'aLabel', scopes: ['source.csound', 'meta.instrument-block.csound', 'entity.name.label.csound']
+      expect(tokens[1]).toEqual value: ':', scopes: ['source.csound', 'meta.instrument-block.csound', 'entity.punctuation.label.csound']

       tokens = lines[2]
       expect(tokens.length).toBe 7
-      expect(tokens[1]).toEqual value: 'i', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'storage.type.csound'
-      ]
-      expect(tokens[2]).toEqual value: 'Duration', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'meta.other.csound'
-      ]
-      expect(tokens[3]).toEqual value: ' ', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-      ]
-      expect(tokens[4]).toEqual value: '=', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'keyword.operator.csound'
-      ]
-      expect(tokens[5]).toEqual value: ' ', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-      ]
-      expect(tokens[6]).toEqual value: 'p3', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'support.variable.csound'
-      ]
+      expect(tokens[1]).toEqual value: 'i', scopes: ['source.csound', 'meta.instrument-block.csound', 'storage.type.csound']
+      expect(tokens[2]).toEqual value: 'Duration', scopes: ['source.csound', 'meta.instrument-block.csound', 'meta.other.csound']
+      expect(tokens[3]).toEqual value: ' ', scopes: ['source.csound', 'meta.instrument-block.csound']
+      expect(tokens[4]).toEqual value: '=', scopes: ['source.csound', 'meta.instrument-block.csound', 'keyword.operator.csound']
+      expect(tokens[5]).toEqual value: ' ', scopes: ['source.csound', 'meta.instrument-block.csound']
+      expect(tokens[6]).toEqual value: 'p3', scopes: ['source.csound', 'meta.instrument-block.csound', 'support.variable.csound']

       tokens = lines[3]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: 'endin', scopes: [
-        'source.csound'
-        'meta.instrument-block.csound'
-        'keyword.other.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'endin', scopes: ['source.csound', 'meta.instrument-block.csound', 'keyword.other.csound']

     it 'tokenizes user-defined opcodes', ->
       # The Csound grammar relies on the existence of an active text editor to
@@ -236,128 +96,29 @@

           tokens = lines[0]
           expect(tokens.length).toBe 14
-          expect(tokens[0]).toEqual value: 'opcode', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'keyword.function.csound'
-          ]
-          expect(tokens[1]).toEqual value: '/*', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'comment.block.csound'
-            'punctuation.definition.comment.begin.csound'
-          ]
-          expect(tokens[2]).toEqual value: '*/', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'comment.block.csound'
-            'punctuation.definition.comment.end.csound'
-          ]
-          expect(tokens[3]).toEqual value: 'aUDO', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'entity.name.function.opcode.csound'
-          ]
-          expect(tokens[4]).toEqual value: ',', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-          ]
-          expect(tokens[5]).toEqual value: '/*', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'comment.block.csound'
-            'punctuation.definition.comment.begin.csound'
-          ]
-          expect(tokens[6]).toEqual value: '*/', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'comment.block.csound'
-            'punctuation.definition.comment.end.csound'
-          ]
-          expect(tokens[7]).toEqual value: '0', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'meta.opcode-type-signature.csound'
-            'storage.type.csound'
-          ]
-          expect(tokens[8]).toEqual value: ',', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'meta.opcode-type-signature.csound'
-          ]
-          expect(tokens[9]).toEqual value: '/*', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'comment.block.csound'
-            'punctuation.definition.comment.begin.csound'
-          ]
-          expect(tokens[10]).toEqual value: '*/', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'comment.block.csound'
-            'punctuation.definition.comment.end.csound'
-          ]
-          expect(tokens[11]).toEqual value: '0', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'meta.opcode-type-signature.csound'
-            'storage.type.csound'
-          ]
-          expect(tokens[12]).toEqual value: '//', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-            'meta.opcode-details.csound'
-            'meta.opcode-type-signature.csound'
-            'comment.line.csound'
-            'punctuation.definition.comment.line.csound'
-          ]
-          expect(tokens[13]).toEqual value: '', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'meta.opcode-declaration.csound'
-          ]
+          expect(tokens[0]).toEqual value: 'opcode', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'keyword.function.csound']
+          expect(tokens[1]).toEqual value: '/*', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+          expect(tokens[2]).toEqual value: '*/', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+          expect(tokens[3]).toEqual value: 'aUDO', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'entity.name.function.opcode.csound']
+          expect(tokens[4]).toEqual value: ',', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound']
+          expect(tokens[5]).toEqual value: '/*', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+          expect(tokens[6]).toEqual value: '*/', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+          expect(tokens[7]).toEqual value: '0', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'meta.opcode-type-signature.csound', 'storage.type.csound']
+          expect(tokens[8]).toEqual value: ',', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'meta.opcode-type-signature.csound']
+          expect(tokens[9]).toEqual value: '/*', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+          expect(tokens[10]).toEqual value: '*/', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+          expect(tokens[11]).toEqual value: '0', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'meta.opcode-type-signature.csound', 'storage.type.csound']
+          expect(tokens[12]).toEqual value: '//', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound', 'meta.opcode-details.csound', 'meta.opcode-type-signature.csound', 'comment.line.csound', 'punctuation.definition.comment.line.csound']
+          expect(tokens[13]).toEqual value: '', scopes: ['source.csound', 'meta.opcode-definition.csound', 'meta.opcode-declaration.csound']

           tokens = lines[1]
           expect(tokens.length).toBe 2
-          expect(tokens[0]).toEqual value: '  ', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-          ]
-          expect(tokens[1]).toEqual value: 'aUDO', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'entity.name.function.opcode.csound'
-          ]
+          expect(tokens[0]).toEqual value: '  ', scopes: ['source.csound', 'meta.opcode-definition.csound']
+          expect(tokens[1]).toEqual value: 'aUDO', scopes: ['source.csound', 'meta.opcode-definition.csound', 'entity.name.function.opcode.csound']

           tokens = lines[2]
           expect(tokens.length).toBe 1
-          expect(tokens[0]).toEqual value: 'endop', scopes: [
-            'source.csound'
-            'meta.opcode-definition.csound'
-            'keyword.other.csound'
-          ]
+          expect(tokens[0]).toEqual value: 'endop', scopes: ['source.csound', 'meta.opcode-definition.csound', 'keyword.other.csound']

     it 'tokenizes numbers', ->
       lines = grammar.tokenizeLines '''
@@ -366,16 +127,10 @@
       '''
       tokens = lines[0]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: '123', scopes: [
-        'source.csound'
-        'constant.numeric.integer.decimal.csound'
-      ]
+      expect(tokens[0]).toEqual value: '123', scopes: ['source.csound', 'constant.numeric.integer.decimal.csound']
       tokens = lines[1]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: '0123456789', scopes: [
-        'source.csound'
-        'constant.numeric.integer.decimal.csound'
-      ]
+      expect(tokens[0]).toEqual value: '0123456789', scopes: ['source.csound', 'constant.numeric.integer.decimal.csound']

       lines = grammar.tokenizeLines '''
         0xabcdef0123456789
@@ -383,24 +138,12 @@
       '''
       tokens = lines[0]
       expect(tokens.length).toBe 2
-      expect(tokens[0]).toEqual value: '0x', scopes: [
-        'source.csound'
-        'storage.type.number.csound'
-      ]
-      expect(tokens[1]).toEqual value: 'abcdef0123456789', scopes: [
-        'source.csound'
-        'constant.numeric.integer.hexadecimal.csound'
-      ]
+      expect(tokens[0]).toEqual value: '0x', scopes: ['source.csound', 'storage.type.number.csound']
+      expect(tokens[1]).toEqual value: 'abcdef0123456789', scopes: ['source.csound', 'constant.numeric.integer.hexadecimal.csound']
       tokens = lines[1]
       expect(tokens.length).toBe 2
-      expect(tokens[0]).toEqual value: '0X', scopes: [
-        'source.csound'
-        'storage.type.number.csound'
-      ]
-      expect(tokens[1]).toEqual value: 'ABCDEF', scopes: [
-        'source.csound'
-        'constant.numeric.integer.hexadecimal.csound'
-      ]
+      expect(tokens[0]).toEqual value: '0X', scopes: ['source.csound', 'storage.type.number.csound']
+      expect(tokens[1]).toEqual value: 'ABCDEF', scopes: ['source.csound', 'constant.numeric.integer.hexadecimal.csound']

       floats = [
         '1e2'
@@ -417,33 +160,15 @@
       for i in [0...lines.length]
         tokens = lines[i]
         expect(tokens.length).toBe 1
-        expect(tokens[0]).toEqual value: floats[i], scopes: [
-          'source.csound'
-          'constant.numeric.float.csound'
-        ]
+        expect(tokens[0]).toEqual value: floats[i], scopes: ['source.csound', 'constant.numeric.float.csound']

     it 'tokenizes quoted strings', ->
       {tokens} = grammar.tokenizeLine '"characters$MACRO."'
       expect(tokens.length).toBe 4
-      expect(tokens[0]).toEqual value: '"', scopes: [
-        'source.csound'
-        'string.quoted.csound'
-        'punctuation.definition.string.begin.csound'
-      ]
-      expect(tokens[1]).toEqual value: 'characters', scopes: [
-        'source.csound'
-        'string.quoted.csound'
-      ]
-      expect(tokens[2]).toEqual value: '$MACRO.', scopes: [
-        'source.csound'
-        'string.quoted.csound'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[3]).toEqual value: '"', scopes: [
-        'source.csound'
-        'string.quoted.csound'
-        'punctuation.definition.string.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: '"', scopes: ['source.csound', 'string.quoted.csound', 'punctuation.definition.string.begin.csound']
+      expect(tokens[1]).toEqual value: 'characters', scopes: ['source.csound', 'string.quoted.csound']
+      expect(tokens[2]).toEqual value: '$MACRO.', scopes: ['source.csound', 'string.quoted.csound', 'entity.name.function.preprocessor.csound']
+      expect(tokens[3]).toEqual value: '"', scopes: ['source.csound', 'string.quoted.csound', 'punctuation.definition.string.end.csound']

     it 'tokenizes braced strings', ->
       lines = grammar.tokenizeLines '''
@@ -453,22 +178,13 @@
       '''
       tokens = lines[0]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: '{{', scopes: [
-        'source.csound'
-        'string.braced.csound'
-      ]
+      expect(tokens[0]).toEqual value: '{{', scopes: ['source.csound', 'string.braced.csound']
       tokens = lines[1]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: 'characters$MACRO.', scopes: [
-        'source.csound'
-        'string.braced.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'characters$MACRO.', scopes: ['source.csound', 'string.braced.csound']
       tokens = lines[2]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: '}}', scopes: [
-        'source.csound'
-        'string.braced.csound'
-      ]
+      expect(tokens[0]).toEqual value: '}}', scopes: ['source.csound', 'string.braced.csound']

     it 'tokenizes escape sequences', ->
       escapeSequences = [
@@ -485,18 +201,10 @@
       ]
       {tokens} = grammar.tokenizeLine "\"#{escapeSequences.join ''}\""
       for i in [1...tokens.length - 1]
-        expect(tokens[i]).toEqual value: escapeSequences[i - 1], scopes: [
-          'source.csound'
-          'string.quoted.csound'
-          'constant.character.escape.csound'
-        ]
+        expect(tokens[i]).toEqual value: escapeSequences[i - 1], scopes: ['source.csound', 'string.quoted.csound', 'constant.character.escape.csound']
       {tokens} = grammar.tokenizeLine "{{#{escapeSequences.join ''}}}"
       for i in [1...tokens.length - 1]
-        expect(tokens[i]).toEqual value: escapeSequences[i - 1], scopes: [
-          'source.csound'
-          'string.braced.csound'
-          'constant.character.escape.csound'
-        ]
+        expect(tokens[i]).toEqual value: escapeSequences[i - 1], scopes: ['source.csound', 'string.braced.csound', 'constant.character.escape.csound']

     it 'tokenizes operators', ->
       operators = [
@@ -532,10 +240,7 @@
       for i in [0...lines.length]
         tokens = lines[i]
         expect(tokens.length).toBe 1
-        expect(tokens[0]).toEqual value: operators[i], scopes: [
-          'source.csound'
-          'keyword.operator.csound'
-        ]
+        expect(tokens[0]).toEqual value: operators[i], scopes: ['source.csound', 'keyword.operator.csound']

     it 'tokenizes global value identifiers', ->
       globalValueIdentifiers = [
@@ -551,10 +256,7 @@
       for i in [0...lines.length]
         tokens = lines[i]
         expect(tokens.length).toBe 1
-        expect(tokens[0]).toEqual value: globalValueIdentifiers[i], scopes: [
-          'source.csound'
-          'variable.other.readwrite.global.csound'
-        ]
+        expect(tokens[0]).toEqual value: globalValueIdentifiers[i], scopes: ['source.csound', 'variable.other.readwrite.global.csound']

     it 'tokenizes keywords', ->
       keywords = [
@@ -578,10 +280,7 @@
       for i in [0...lines.length]
         tokens = lines[i]
         expect(tokens.length).toBe 1
-        expect(tokens[0]).toEqual value: keywords[i], scopes: [
-          'source.csound'
-          'keyword.control.csound'
-        ]
+        expect(tokens[0]).toEqual value: keywords[i], scopes: ['source.csound', 'keyword.control.csound']

     it 'tokenizes printks and prints escape sequences', ->
       opcodes = [
@@ -610,29 +309,12 @@
       ]
       for opcode in opcodes
         {tokens} = grammar.tokenizeLine "#{opcode} \"#{escapeSequences.join ''}\""
-        expect(tokens[0]).toEqual value: opcode, scopes: [
-          'source.csound'
-          'support.function.csound'
-        ]
-        expect(tokens[1]).toEqual value: ' ', scopes: [
-          'source.csound'
-        ]
-        expect(tokens[2]).toEqual value: '"', scopes: [
-          'source.csound'
-          'string.quoted.csound'
-          'punctuation.definition.string.begin.csound'
-        ]
+        expect(tokens[0]).toEqual value: opcode, scopes: ['source.csound', 'support.function.csound']
+        expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound']
+        expect(tokens[2]).toEqual value: '"', scopes: ['source.csound', 'string.quoted.csound', 'punctuation.definition.string.begin.csound']
         for i in [3...tokens.length - 1]
-          expect(tokens[i]).toEqual value: escapeSequences[i - 3], scopes: [
-            'source.csound'
-            'string.quoted.csound'
-            'constant.character.escape.csound'
-          ]
-        expect(tokens[tokens.length - 1]).toEqual value: '"', scopes: [
-          'source.csound'
-          'string.quoted.csound'
-          'punctuation.definition.string.end.csound'
-        ]
+          expect(tokens[i]).toEqual value: escapeSequences[i - 3], scopes: ['source.csound', 'string.quoted.csound', 'constant.character.escape.csound']
+        expect(tokens[tokens.length - 1]).toEqual value: '"', scopes: ['source.csound', 'string.quoted.csound', 'punctuation.definition.string.end.csound']

     it 'tokenizes goto statements', ->
       keywordsAndOpcodes = [
@@ -661,61 +343,23 @@
       lines = grammar.tokenizeLines(keywordsAndOpcodes.join ' aLabel //\n')
       for i in [0...lines.length - 1]
         tokens = lines[i]
-        expect(tokens[0]).toEqual value: keywordsAndOpcodes[i], scopes: [
-          'source.csound'
-          'keyword.control.csound'
-        ]
-        expect(tokens[1]).toEqual value: ' ', scopes: [
-          'source.csound'
-        ]
-        expect(tokens[2]).toEqual value: 'aLabel', scopes: [
-          'source.csound'
-          'entity.name.label.csound'
-        ]
-        expect(tokens[3]).toEqual value: ' ', scopes: [
-          'source.csound'
-        ]
-        expect(tokens[4]).toEqual value: '//', scopes: [
-          'source.csound'
-          'comment.line.csound'
-          'punctuation.definition.comment.line.csound'
-        ]
+        expect(tokens[0]).toEqual value: keywordsAndOpcodes[i], scopes: ['source.csound', 'keyword.control.csound']
+        expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound']
+        expect(tokens[2]).toEqual value: 'aLabel', scopes: ['source.csound', 'entity.name.label.csound']
+        expect(tokens[3]).toEqual value: ' ', scopes: ['source.csound']
+        expect(tokens[4]).toEqual value: '//', scopes: ['source.csound', 'comment.line.csound', 'punctuation.definition.comment.line.csound']

     it 'tokenizes include directives', ->
       for character in ['"', '|']
         {tokens} = grammar.tokenizeLine "#include/**/#{character}file.udo#{character}"
         expect(tokens.length).toBe 7
-        expect(tokens[0]).toEqual value: '#include', scopes: [
-          'source.csound'
-          'keyword.include.preprocessor.csound'
-        ]
-        expect(tokens[1]).toEqual value: '/*', scopes: [
-          'source.csound'
-          'comment.block.csound'
-          'punctuation.definition.comment.begin.csound'
-        ]
-        expect(tokens[2]).toEqual value: '*/', scopes: [
-          'source.csound'
-          'comment.block.csound'
-          'punctuation.definition.comment.end.csound'
-        ]
-        expect(tokens[3]).toEqual value: character, scopes: [
-          'source.csound'
-          'string.include.csound'
-          'punctuation.definition.string.begin.csound'
-        ]
-        expect(tokens[4]).toEqual value: 'file.udo', scopes: [
-          'source.csound'
-          'string.include.csound'
-        ]
-        expect(tokens[5]).toEqual value: character, scopes: [
-          'source.csound'
-          'string.include.csound'
-          'punctuation.definition.string.end.csound'
-        ]
-        expect(tokens[6]).toEqual value: '', scopes: [
-          'source.csound'
-        ]
+        expect(tokens[0]).toEqual value: '#include', scopes: ['source.csound', 'keyword.include.preprocessor.csound']
+        expect(tokens[1]).toEqual value: '/*', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+        expect(tokens[2]).toEqual value: '*/', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
+        expect(tokens[3]).toEqual value: character, scopes: ['source.csound', 'string.include.csound', 'punctuation.definition.string.begin.csound']
+        expect(tokens[4]).toEqual value: 'file.udo', scopes: ['source.csound', 'string.include.csound']
+        expect(tokens[5]).toEqual value: character, scopes: ['source.csound', 'string.include.csound', 'punctuation.definition.string.end.csound']
+        expect(tokens[6]).toEqual value: '', scopes: ['source.csound']

     it 'tokenizes object-like macro definitions', ->
       lines = grammar.tokenizeLines '''
@@ -728,87 +372,32 @@

       tokens = lines[0]
       expect(tokens.length).toBe 5
-      expect(tokens[0]).toEqual value: '# \tdefine', scopes: [
-        'source.csound'
-        'keyword.define.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: 'MACRO', scopes: [
-        'source.csound'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[2]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.begin.csound'
-      ]
-      expect(tokens[3]).toEqual value: 'macro_body', scopes: [
-        'source.csound'
-        'meta.other.csound'
-      ]
-      expect(tokens[4]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: '# \tdefine', scopes: ['source.csound', 'keyword.define.preprocessor.csound']
+      expect(tokens[1]).toEqual value: 'MACRO', scopes: ['source.csound', 'entity.name.function.preprocessor.csound']
+      expect(tokens[2]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.begin.csound']
+      expect(tokens[3]).toEqual value: 'macro_body', scopes: ['source.csound', 'meta.other.csound']
+      expect(tokens[4]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.end.csound']

       tokens = lines[1]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: '#define', scopes: [
-        'source.csound'
-        'keyword.define.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[2]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: '#define', scopes: ['source.csound', 'keyword.define.preprocessor.csound']
+      expect(tokens[1]).toEqual value: '/*', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[2]).toEqual value: '*/', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
       tokens = lines[2]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: 'MACRO', scopes: [
-        'source.csound'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[2]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'MACRO', scopes: ['source.csound', 'entity.name.function.preprocessor.csound']
+      expect(tokens[1]).toEqual value: '/*', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[2]).toEqual value: '*/', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
       tokens = lines[3]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.begin.csound'
-      ]
-      expect(tokens[1]).toEqual value: '\\#', scopes: [
-        'source.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[2]).toEqual value: 'macro', scopes: [
-        'source.csound'
-        'meta.other.csound'
-      ]
+      expect(tokens[0]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.begin.csound']
+      expect(tokens[1]).toEqual value: '\\#', scopes: ['source.csound', 'constant.character.escape.csound']
+      expect(tokens[2]).toEqual value: 'macro', scopes: ['source.csound', 'meta.other.csound']
       tokens = lines[4]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: 'body', scopes: [
-        'source.csound'
-        'meta.other.csound'
-      ]
-      expect(tokens[1]).toEqual value: '\\#', scopes: [
-        'source.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[2]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'body', scopes: ['source.csound', 'meta.other.csound']
+      expect(tokens[1]).toEqual value: '\\#', scopes: ['source.csound', 'constant.character.escape.csound']
+      expect(tokens[2]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.end.csound']

     it 'tokenizes function-like macro definitions', ->
       lines = grammar.tokenizeLines '''
@@ -821,128 +410,44 @@

       tokens = lines[0]
       expect(tokens.length).toBe 10
-      expect(tokens[0]).toEqual value: '#define', scopes: [
-        'source.csound'
-        'keyword.define.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: 'MACRO', scopes: [
-        'source.csound'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[2]).toEqual value: '(', scopes: [
-        'source.csound'
-      ]
-      expect(tokens[3]).toEqual value: 'ARG1', scopes: [
-        'source.csound'
-        'variable.parameter.preprocessor.csound'
-      ]
-      expect(tokens[4]).toEqual value: '#', scopes: [
-        'source.csound'
-      ]
-      expect(tokens[5]).toEqual value: 'ARG2', scopes: [
-        'source.csound'
-        'variable.parameter.preprocessor.csound'
-      ]
-      expect(tokens[6]).toEqual value: ')', scopes: [
-        'source.csound'
-      ]
-      expect(tokens[7]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.begin.csound'
-      ]
-      expect(tokens[8]).toEqual value: 'macro_body', scopes: [
-        'source.csound'
-        'meta.other.csound'
-      ]
-      expect(tokens[9]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: '#define', scopes: ['source.csound', 'keyword.define.preprocessor.csound']
+      expect(tokens[1]).toEqual value: 'MACRO', scopes: ['source.csound', 'entity.name.function.preprocessor.csound']
+      expect(tokens[2]).toEqual value: '(', scopes: ['source.csound']
+      expect(tokens[3]).toEqual value: 'ARG1', scopes: ['source.csound', 'variable.parameter.preprocessor.csound']
+      expect(tokens[4]).toEqual value: '#', scopes: ['source.csound']
+      expect(tokens[5]).toEqual value: 'ARG2', scopes: ['source.csound', 'variable.parameter.preprocessor.csound']
+      expect(tokens[6]).toEqual value: ')', scopes: ['source.csound']
+      expect(tokens[7]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.begin.csound']
+      expect(tokens[8]).toEqual value: 'macro_body', scopes: ['source.csound', 'meta.other.csound']
+      expect(tokens[9]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.end.csound']

       tokens = lines[1]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: '#define', scopes: [
-        'source.csound'
-        'keyword.define.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[2]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: '#define', scopes: ['source.csound', 'keyword.define.preprocessor.csound']
+      expect(tokens[1]).toEqual value: '/*', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[2]).toEqual value: '*/', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
       tokens = lines[2]
       expect(tokens.length).toBe 10
-      expect(tokens[0]).toEqual value: 'MACRO', scopes: [
-        'source.csound'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: '(', scopes: [
-        'source.csound'
-      ]
-      expect(tokens[2]).toEqual value: 'ARG1', scopes: [
-        'source.csound'
-        'variable.parameter.preprocessor.csound'
-      ]
-      expect(tokens[3]).toEqual value: "'", scopes: [
-        'source.csound'
-      ]
-      expect(tokens[4]).toEqual value: 'ARG2', scopes: [
-        'source.csound'
-        'variable.parameter.preprocessor.csound'
-      ]
-      expect(tokens[5]).toEqual value: "'", scopes: [
-        'source.csound'
-      ]
-      expect(tokens[6]).toEqual value: 'ARG3', scopes: [
-        'source.csound'
-        'variable.parameter.preprocessor.csound'
-      ]
-      expect(tokens[7]).toEqual value: ')', scopes: [
-        'source.csound'
-      ]
-      expect(tokens[8]).toEqual value: '/*', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.begin.csound'
-      ]
-      expect(tokens[9]).toEqual value: '*/', scopes: [
-        'source.csound'
-        'comment.block.csound'
-        'punctuation.definition.comment.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'MACRO', scopes: ['source.csound', 'entity.name.function.preprocessor.csound']
+      expect(tokens[1]).toEqual value: '(', scopes: ['source.csound']
+      expect(tokens[2]).toEqual value: 'ARG1', scopes: ['source.csound', 'variable.parameter.preprocessor.csound']
+      expect(tokens[3]).toEqual value: "'", scopes: ['source.csound']
+      expect(tokens[4]).toEqual value: 'ARG2', scopes: ['source.csound', 'variable.parameter.preprocessor.csound']
+      expect(tokens[5]).toEqual value: "'", scopes: ['source.csound']
+      expect(tokens[6]).toEqual value: 'ARG3', scopes: ['source.csound', 'variable.parameter.preprocessor.csound']
+      expect(tokens[7]).toEqual value: ')', scopes: ['source.csound']
+      expect(tokens[8]).toEqual value: '/*', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.begin.csound']
+      expect(tokens[9]).toEqual value: '*/', scopes: ['source.csound', 'comment.block.csound', 'punctuation.definition.comment.end.csound']
       tokens = lines[3]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.begin.csound'
-      ]
-      expect(tokens[1]).toEqual value: '\\#', scopes: [
-        'source.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[2]).toEqual value: 'macro', scopes: [
-        'source.csound'
-        'meta.other.csound'
-      ]
+      expect(tokens[0]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.begin.csound']
+      expect(tokens[1]).toEqual value: '\\#', scopes: ['source.csound', 'constant.character.escape.csound']
+      expect(tokens[2]).toEqual value: 'macro', scopes: ['source.csound', 'meta.other.csound']
       tokens = lines[4]
       expect(tokens.length).toBe 3
-      expect(tokens[0]).toEqual value: 'body', scopes: [
-        'source.csound'
-        'meta.other.csound'
-      ]
-      expect(tokens[1]).toEqual value: '\\#', scopes: [
-        'source.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[2]).toEqual value: '#', scopes: [
-        'source.csound'
-        'punctuation.definition.macro.end.csound'
-      ]
+      expect(tokens[0]).toEqual value: 'body', scopes: ['source.csound', 'meta.other.csound']
+      expect(tokens[1]).toEqual value: '\\#', scopes: ['source.csound', 'constant.character.escape.csound']
+      expect(tokens[2]).toEqual value: '#', scopes: ['source.csound', 'punctuation.definition.macro.end.csound']

     it 'tokenizes macro preprocessor directives', ->
       preprocessorDirectives = [
@@ -955,20 +460,10 @@
       for i in [0...lines.length - 1]
         tokens = lines[i]
         expect(tokens.length).toBe 4
-        expect(tokens[0]).toEqual value: preprocessorDirectives[i], scopes: [
-          'source.csound'
-          'keyword.preprocessor.csound'
-        ]
-        expect(tokens[1]).toEqual value: ' ', scopes: [
-          'source.csound'
-        ]
-        expect(tokens[2]).toEqual value: 'MACRO', scopes: [
-          'source.csound'
-          'entity.name.function.preprocessor.csound'
-        ]
-        expect(tokens[3]).toEqual value: '', scopes: [
-          'source.csound'
-        ]
+        expect(tokens[0]).toEqual value: preprocessorDirectives[i], scopes: ['source.csound', 'keyword.preprocessor.csound']
+        expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound']
+        expect(tokens[2]).toEqual value: 'MACRO', scopes: ['source.csound', 'entity.name.function.preprocessor.csound']
+        expect(tokens[3]).toEqual value: '', scopes: ['source.csound']

     it 'tokenizes other preprocessor directives', ->
       preprocessorDirectives = [
@@ -981,173 +476,40 @@
       ]
       lines = grammar.tokenizeLines(preprocessorDirectives.join '\n')
       for i in [0...lines.length]
-        expect(lines[i][0]).toEqual value: preprocessorDirectives[i], scopes: [
-          'source.csound'
-          'keyword.preprocessor.csound'
-        ]
+        expect(lines[i][0]).toEqual value: preprocessorDirectives[i], scopes: ['source.csound', 'keyword.preprocessor.csound']

     it 'tokenizes function-like macros', ->
       {tokens} = grammar.tokenizeLine '$MACRO.(((x\\))\' "x)\\)x\\))"# {{x\\))x)\\)}});'
       expect(tokens.length).toBe 29
-      expect(tokens[0]).toEqual value: '$MACRO.', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[1]).toEqual value: '(', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-      ]
-      expect(tokens[2]).toEqual value: '(', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[3]).toEqual value: '(', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[4]).toEqual value: 'x', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'meta.other.csound'
-      ]
-      expect(tokens[5]).toEqual value: '\\)', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[6]).toEqual value: ')', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'meta.macro-parameter-value-parenthetical.csound'
-        'invalid.illegal.csound'
-      ]
-      expect(tokens[7]).toEqual value: "'", scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'punctuation.macro-parameter-separator.csound'
-      ]
-      expect(tokens[8]).toEqual value: ' ', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-      ]
-      expect(tokens[9]).toEqual value: '"', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-        'punctuation.definition.string.begin.csound'
-      ]
-      expect(tokens[10]).toEqual value: 'x', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-      ]
-      expect(tokens[11]).toEqual value: ')', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-        'invalid.illegal.csound'
-      ]
-      expect(tokens[12]).toEqual value: '\\)', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[13]).toEqual value: 'x', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-      ]
-      expect(tokens[14]).toEqual value: '\\)', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[15]).toEqual value: ')', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-        'invalid.illegal.csound'
-      ]
-      expect(tokens[16]).toEqual value: '"', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.quoted.csound'
-        'punctuation.definition.string.end.csound'
-      ]
-      expect(tokens[17]).toEqual value: '#', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'punctuation.macro-parameter-separator.csound'
-      ]
-      expect(tokens[18]).toEqual value: ' ', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-      ]
-      expect(tokens[19]).toEqual value: '{{', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-      ]
-      expect(tokens[20]).toEqual value: 'x', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-      ]
-      expect(tokens[21]).toEqual value: '\\)', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[22]).toEqual value: ')', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-        'invalid.illegal.csound'
-      ]
-      expect(tokens[23]).toEqual value: 'x', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-      ]
-      expect(tokens[24]).toEqual value: ')', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-        'invalid.illegal.csound'
-      ]
-      expect(tokens[25]).toEqual value: '\\)', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-        'constant.character.escape.csound'
-      ]
-      expect(tokens[26]).toEqual value: '}}', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-        'string.braced.csound'
-      ]
-      expect(tokens[27]).toEqual value: ')', scopes: [
-        'source.csound'
-        'meta.function-like-macro-use.csound'
-      ]
-      expect(tokens[28]).toEqual value: ';', scopes: [
-        'source.csound'
-        'comment.line.csound'
-        'punctuation.definition.comment.line.csound'
-      ]
+      expect(tokens[0]).toEqual value: '$MACRO.', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'entity.name.function.preprocessor.csound']
+      expect(tokens[1]).toEqual value: '(', scopes: ['source.csound', 'meta.function-like-macro-use.csound']
+      expect(tokens[2]).toEqual value: '(', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'meta.macro-parameter-value-parenthetical.csound', 'constant.character.escape.csound']
+      expect(tokens[3]).toEqual value: '(', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'meta.macro-parameter-value-parenthetical.csound', 'meta.macro-parameter-value-parenthetical.csound', 'constant.character.escape.csound']
+      expect(tokens[4]).toEqual value: 'x', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'meta.macro-parameter-value-parenthetical.csound', 'meta.macro-parameter-value-parenthetical.csound', 'meta.other.csound']
+      expect(tokens[5]).toEqual value: '\\)', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'meta.macro-parameter-value-parenthetical.csound', 'meta.macro-parameter-value-parenthetical.csound', 'constant.character.escape.csound']
+      expect(tokens[6]).toEqual value: ')', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'meta.macro-parameter-value-parenthetical.csound', 'invalid.illegal.csound']
+      expect(tokens[7]).toEqual value: "'", scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'punctuation.macro-parameter-separator.csound']
+      expect(tokens[8]).toEqual value: ' ', scopes: ['source.csound', 'meta.function-like-macro-use.csound']
+      expect(tokens[9]).toEqual value: '"', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound', 'punctuation.definition.string.begin.csound']
+      expect(tokens[10]).toEqual value: 'x', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound']
+      expect(tokens[11]).toEqual value: ')', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound', 'invalid.illegal.csound']
+      expect(tokens[12]).toEqual value: '\\)', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound', 'constant.character.escape.csound']
+      expect(tokens[13]).toEqual value: 'x', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound']
+      expect(tokens[14]).toEqual value: '\\)', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound', 'constant.character.escape.csound']
+      expect(tokens[15]).toEqual value: ')', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound', 'invalid.illegal.csound']
+      expect(tokens[16]).toEqual value: '"', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.quoted.csound', 'punctuation.definition.string.end.csound']
+      expect(tokens[17]).toEqual value: '#', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'punctuation.macro-parameter-separator.csound']
+      expect(tokens[18]).toEqual value: ' ', scopes: ['source.csound', 'meta.function-like-macro-use.csound']
+      expect(tokens[19]).toEqual value: '{{', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound']
+      expect(tokens[20]).toEqual value: 'x', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound']
+      expect(tokens[21]).toEqual value: '\\)', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound', 'constant.character.escape.csound']
+      expect(tokens[22]).toEqual value: ')', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound', 'invalid.illegal.csound']
+      expect(tokens[23]).toEqual value: 'x', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound']
+      expect(tokens[24]).toEqual value: ')', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound', 'invalid.illegal.csound']
+      expect(tokens[25]).toEqual value: '\\)', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound', 'constant.character.escape.csound']
+      expect(tokens[26]).toEqual value: '}}', scopes: ['source.csound', 'meta.function-like-macro-use.csound', 'string.braced.csound']
+      expect(tokens[27]).toEqual value: ')', scopes: ['source.csound', 'meta.function-like-macro-use.csound']
+      expect(tokens[28]).toEqual value: ';', scopes: ['source.csound', 'comment.line.csound', 'punctuation.definition.comment.line.csound']

   describe 'Csound Score grammar', ->
@@ -1166,61 +528,26 @@
       '''
       tokens = lines[0]
       expect(tokens.length).toBe 4
-      expect(tokens[0]).toEqual value: 'm', scopes: [
-        'source.csound-score'
-        'keyword.mark.preprocessor.csound-score'
-      ]
-      expect(tokens[1]).toEqual value: ' ', scopes: [
-        'source.csound-score'
-      ]
-      expect(tokens[2]).toEqual value: 'mark', scopes: [
-        'source.csound-score'
-        'entity.name.label.csound-score'
-      ]
-      expect(tokens[3]).toEqual value: '', scopes: [
-        'source.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: 'm', scopes: ['source.csound-score', 'keyword.mark.preprocessor.csound-score']
+      expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound-score']
+      expect(tokens[2]).toEqual value: 'mark', scopes: ['source.csound-score', 'entity.name.label.csound-score']
+      expect(tokens[3]).toEqual value: '', scopes: ['source.csound-score']
       tokens = lines[1]
       expect(tokens.length).toBe 4
-      expect(tokens[0]).toEqual value: 'n', scopes: [
-        'source.csound-score'
-        'keyword.repeat-mark.preprocessor.csound-score'
-      ]
-      expect(tokens[1]).toEqual value: ' ', scopes: [
-        'source.csound-score'
-      ]
-      expect(tokens[2]).toEqual value: 'mark', scopes: [
-        'source.csound-score'
-        'entity.name.label.csound-score'
-      ]
-      expect(tokens[3]).toEqual value: '', scopes: [
-        'source.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: 'n', scopes: ['source.csound-score', 'keyword.repeat-mark.preprocessor.csound-score']
+      expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound-score']
+      expect(tokens[2]).toEqual value: 'mark', scopes: ['source.csound-score', 'entity.name.label.csound-score']
+      expect(tokens[3]).toEqual value: '', scopes: ['source.csound-score']

     it 'tokenizes repeat section statements', ->
       {tokens} = grammar.tokenizeLine 'r 1 MACRO\n'
       expect(tokens.length).toBe 6
-      expect(tokens[0]).toEqual value: 'r', scopes: [
-        'source.csound-score'
-        'keyword.repeat-section.preprocessor.csound-score'
-      ]
-      expect(tokens[1]).toEqual value: ' ', scopes: [
-        'source.csound-score'
-      ]
-      expect(tokens[2]).toEqual value: '1', scopes: [
-        'source.csound-score'
-        'constant.numeric.integer.decimal.csound-score'
-      ]
-      expect(tokens[3]).toEqual value: ' ', scopes: [
-        'source.csound-score'
-      ]
-      expect(tokens[4]).toEqual value: 'MACRO', scopes: [
-        'source.csound-score'
-        'entity.name.function.preprocessor.csound'
-      ]
-      expect(tokens[5]).toEqual value: '\n', scopes: [
-        'source.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: 'r', scopes: ['source.csound-score', 'keyword.repeat-section.preprocessor.csound-score']
+      expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound-score']
+      expect(tokens[2]).toEqual value: '1', scopes: ['source.csound-score', 'constant.numeric.integer.decimal.csound-score']
+      expect(tokens[3]).toEqual value: ' ', scopes: ['source.csound-score']
+      expect(tokens[4]).toEqual value: 'MACRO', scopes: ['source.csound-score', 'entity.name.function.preprocessor.csound']
+      expect(tokens[5]).toEqual value: '\n', scopes: ['source.csound-score']

     it 'tokenizes other score statements', ->
       scoreStatements = [
@@ -1241,22 +568,13 @@
       for i in [0...lines.length]
         tokens = lines[i]
         expect(tokens.length).toBe 1
-        expect(tokens[0]).toEqual value: scoreStatements[i], scopes: [
-          'source.csound-score'
-          'keyword.control.csound-score'
-        ]
+        expect(tokens[0]).toEqual value: scoreStatements[i], scopes: ['source.csound-score', 'keyword.control.csound-score']
       {tokens} = grammar.tokenizeLine 'w'
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: 'w', scopes: [
-        'source.csound-score'
-        'invalid.illegal.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: 'w', scopes: ['source.csound-score', 'invalid.illegal.csound-score']
       {tokens} = grammar.tokenizeLine 'z'
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: 'z', scopes: [
-        'source.csound-score'
-        'constant.numeric.language.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: 'z', scopes: ['source.csound-score', 'constant.numeric.language.csound-score']

     it 'tokenizes next-p and previous-p symbols', ->
       scoreStatements = [
@@ -1270,16 +588,8 @@
       for token in ['np', 'nP', 'Np', 'NP']
         {tokens} = grammar.tokenizeLine token + i
         expect(tokens.length).toBe 2
-        expect(tokens[0]).toEqual value: token, scopes: [
-          'source.csound-score'
-          'meta.p-symbol.csound-score'
-          'keyword.control.csound-score'
-        ]
-        expect(tokens[1]).toEqual value: i.toString(), scopes: [
-          'source.csound-score'
-          'meta.p-symbol.csound-score'
-          'constant.numeric.integer.decimal.csound-score'
-        ]
+        expect(tokens[0]).toEqual value: token, scopes: ['source.csound-score', 'meta.p-symbol.csound-score', 'keyword.control.csound-score']
+        expect(tokens[1]).toEqual value: i.toString(), scopes: ['source.csound-score', 'meta.p-symbol.csound-score', 'constant.numeric.integer.decimal.csound-score']
         i++

     it 'tokenizes braced loops', ->
@@ -1289,40 +599,14 @@
       '''
       tokens = lines[0]
       expect(tokens.length).toBe 5
-      expect(tokens[0]).toEqual value: '{', scopes: [
-        'source.csound-score'
-        'meta.braced-loop.csound-score'
-        'punctuation.csound-score'
-      ]
-      expect(tokens[1]).toEqual value: ' ', scopes: [
-        'source.csound-score'
-        'meta.braced-loop.csound-score'
-      ]
-      expect(tokens[2]).toEqual value: '10', scopes: [
-        'source.csound-score'
-        'meta.braced-loop.csound-score'
-        'meta.braced-loop-details.csound-score'
-        'constant.numeric.integer.decimal.csound-score'
-      ]
-      expect(tokens[3]).toEqual value: ' ', scopes: [
-        'source.csound-score'
-        'meta.braced-loop.csound-score'
-        'meta.braced-loop-details.csound-score'
-      ]
-      expect(tokens[4]).toEqual value: 'I', scopes: [
-        'source.csound-score'
-        'meta.braced-loop.csound-score'
-        'meta.braced-loop-details.csound-score'
-        'meta.braced-loop-macro-name.csound-score'
-        'entity.name.function.preprocessor.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: '{', scopes: ['source.csound-score', 'meta.braced-loop.csound-score', 'punctuation.csound-score']
+      expect(tokens[1]).toEqual value: ' ', scopes: ['source.csound-score', 'meta.braced-loop.csound-score']
+      expect(tokens[2]).toEqual value: '10', scopes: ['source.csound-score', 'meta.braced-loop.csound-score', 'meta.braced-loop-details.csound-score', 'constant.numeric.integer.decimal.csound-score']
+      expect(tokens[3]).toEqual value: ' ', scopes: ['source.csound-score', 'meta.braced-loop.csound-score', 'meta.braced-loop-details.csound-score']
+      expect(tokens[4]).toEqual value: 'I', scopes: ['source.csound-score', 'meta.braced-loop.csound-score', 'meta.braced-loop-details.csound-score', 'meta.braced-loop-macro-name.csound-score', 'entity.name.function.preprocessor.csound-score']
       tokens = lines[1]
       expect(tokens.length).toBe 1
-      expect(tokens[0]).toEqual value: '}', scopes: [
-        'source.csound-score'
-        'meta.braced-loop.csound-score'
-        'punctuation.csound-score'
-      ]
+      expect(tokens[0]).toEqual value: '}', scopes: ['source.csound-score', 'meta.braced-loop.csound-score', 'punctuation.csound-score']

   describe 'Csound Document grammar', ->
@@ -1362,11 +646,7 @@
       )
       expect(lines.length - 2).toBe widgetTypes.length
       for i in [1...lines.length - 1]
-        expect(lines[i][0]).toEqual value: widgetTypes[i - 1], scopes: [
-          'source.csound-document'
-          'meta.cabbage-gui.csound-document'
-          'keyword.widget-type.cabbage-gui.csound-document'
-        ]
+        expect(lines[i][0]).toEqual value: widgetTypes[i - 1], scopes: ['source.csound-document', 'meta.cabbage-gui.csound-document', 'keyword.widget-type.cabbage-gui.csound-document']
       lines = grammar.tokenizeLines(
         '<Cabbage>\n' +
         (deprecatedWidgetTypes.join '\n') +
@@ -1374,11 +654,7 @@
       )
       expect(lines.length - 2).toBe deprecatedWidgetTypes.length
       for i in [1...lines.length - 1]
-        expect(lines[i][0]).toEqual value: deprecatedWidgetTypes[i - 1], scopes: [
-          'source.csound-document'
-          'meta.cabbage-gui.csound-document'
-          'invalid.deprecated.cabbage-gui.csound-document'
-        ]
+        expect(lines[i][0]).toEqual value: deprecatedWidgetTypes[i - 1], scopes: ['source.csound-document', 'meta.cabbage-gui.csound-document', 'invalid.deprecated.cabbage-gui.csound-document']

       # https://github.com/rorywalsh/cabaiste/search?q=CabbageLayoutWidgetStrings+path%3ASource+filename%3ACabbageIds.h
       widgetTypes = [
@@ -1428,11 +704,7 @@
       )
       expect(lines.length - 2).toBe widgetTypes.length
       for i in [1...lines.length - 1]
-        expect(lines[i][0]).toEqual value: widgetTypes[i - 1], scopes: [
-          'source.csound-document'
-          'meta.cabbage-gui.csound-document'
-          'keyword.widget-type.cabbage-gui.csound-document'
-        ]
+        expect(lines[i][0]).toEqual value: widgetTypes[i - 1], scopes: ['source.csound-document', 'meta.cabbage-gui.csound-document', 'keyword.widget-type.cabbage-gui.csound-document']
       lines = grammar.tokenizeLines(
         '<Cabbage>\n' +
         (deprecatedWidgetTypes.join '\n') +
@@ -1440,11 +712,7 @@
       )
       expect(lines.length - 2).toBe deprecatedWidgetTypes.length
       for i in [1...lines.length - 1]
-        expect(lines[i][0]).toEqual value: deprecatedWidgetTypes[i - 1], scopes: [
-          'source.csound-document'
-          'meta.cabbage-gui.csound-document'
-          'invalid.deprecated.cabbage-gui.csound-document'
-        ]
+        expect(lines[i][0]).toEqual value: deprecatedWidgetTypes[i - 1], scopes: ['source.csound-document', 'meta.cabbage-gui.csound-document', 'invalid.deprecated.cabbage-gui.csound-document']

     it 'tokenizes Cabbage widget identifiers', ->
       # https://github.com/rorywalsh/cabaiste/search?q=CabbageIdentifierStrings+path%3ASource+filename%3ACabbageIds.h
@@ -1567,11 +835,7 @@
       )
       expect(lines.length - 2).toBe widgetIdentifiers.length
       for i in [1...lines.length - 1]
-        expect(lines[i][0]).toEqual value: widgetIdentifiers[i - 1], scopes: [
-          'source.csound-document'
-          'meta.cabbage-gui.csound-document'
-          'support.function.widget-identifier.cabbage-gui.csound-document'
-        ]
+        expect(lines[i][0]).toEqual value: widgetIdentifiers[i - 1], scopes: ['source.csound-document', 'meta.cabbage-gui.csound-document', 'support.function.widget-identifier.cabbage-gui.csound-document']
       lines = grammar.tokenizeLines(
         '<Cabbage>\n' +
         (deprecatedWidgetIdentifiers.join '\n') +
@@ -1579,8 +843,4 @@
       )
       expect(lines.length - 2).toBe deprecatedWidgetIdentifiers.length
       for i in [1...lines.length - 1]
-        expect(lines[i][0]).toEqual value: deprecatedWidgetIdentifiers[i - 1], scopes: [
-          'source.csound-document'
-          'meta.cabbage-gui.csound-document'
-          'invalid.deprecated.cabbage-gui.csound-document'
-        ]
+        expect(lines[i][0]).toEqual value: deprecatedWidgetIdentifiers[i - 1], scopes: ['source.csound-document', 'meta.cabbage-gui.csound-document', 'invalid.deprecated.cabbage-gui.csound-document']


updated kerb script with functionality for getting traders on future dates

--- scripts/kerb.coffee
+++ scripts/kerb.coffee
@@ -8,9 +8,57 @@
 #
 # Commands:
 #   hubot what's on kerb
+#   hubot what's on kerb tomorrow
+#   hubot what's on kerb on wednesday
+#   hubot what's on kerb next tuesday
 #   hubot kerb trader <trader name>

 jsdom = require "jsdom"
+
+days_of_week = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
+
+getDate = (next_week, day_of_week_str) ->
+  today = new Date()
+  day_of_week = today.getDay()
+
+  days_to_add = 0
+  if next_week then days_to_add = 7
+
+  day_index = days_of_week.indexOf(day_of_week_str)
+  days_until_date = (day_index - day_of_week) + days_to_add
+  new_date = new Date()
+  new_date.setDate(today.getDate() + days_until_date)
+  return new_date
+
+formatDate = (d) ->
+  day = d.getDate()
+  if day < 10 then day = '0' + day
+  month  = (d.getMonth() + 1)
+  if month < 10 then month = '0' + month
+  formatted_date = d.getFullYear() + "-" + month + "-" + day
+  return formatted_date
+
+tradersOnDate = (msg, formatted_date) ->
+  url = "http://www.kerbfood.com/kings-cross/"
+  jsdom.env url, [ "http://code.jquery.com/jquery-1.5.min.js" ], (errors, window) ->
+    traders = window.$("#date-"+formatted_date+" ul li div.rota_content")
+    message_str = "Traders for " + formatted_date + "\n"
+    traders.each (index, element) =>
+      trader_link = window.$(element).children("h4").children("a").attr('href').split("/")[2];
+      trader_name = window.$(element).children("h4").text()
+      trader_desc = window.$(element).children("p").text() + " ("+trader_link+")"
+
+      message_str += trader_name + "\n"
+      message_str += "  " + trader_desc + "\n"
+
+    if message_str is "Traders for " + formatted_date + "\n"
+      message_str = 'No traders found for ' + formatted_date + ', you might have to risk the canteen :('
+
+    msg.send message_str
+
+displayTradersForDay = (msg, next_week, day_of_week) ->
+  date = getDate(next_week, day_of_week)
+  tradersOnDate(msg, formatDate(date))

 module.exports = (robot) ->
   robot.respond /kerb trader (.*)/i, (msg) ->
@@ -19,25 +67,17 @@
       trader_panel = window.$(".panel")[1]
       msg.send window.$(trader_panel).children("p").text()

-  robot.respond /what\'s on kerb/i, (msg) ->
-    url = "http://www.kerbfood.com/kings-cross/"
+  robot.respond /what(\')?s on kerb (on|next)?(.*)/i, (msg) ->
+    if msg.match[3] is 'tomorrow'
+      today = new Date()
+      day_of_week = days_of_week[today.getDay() + 1]
+      displayTradersForDay(msg, false, day_of_week)
+    else
+      next_week = msg.match[2] == 'next'
+      day_of_week = msg.match[3].replace(' ','')
+      day_of_week = day_of_week.charAt(0).toUpperCase() + day_of_week.slice(1)
+      displayTradersForDay(msg, next_week, day_of_week)

-    jsdom.env url, [ "http://code.jquery.com/jquery-1.5.min.js" ], (errors, window) ->
-      d = new Date();
-      day = d.getDate()
-      if day < 10 then day = '0' + day
-      month  = (d.getMonth() + 1)
-      if month < 10 then month = '0' + month
-      formatted_date = d.getFullYear() + "-" + month + "-" + day
-
-      traders = window.$("#date-"+formatted_date+" ul li div.rota_content")
-      message_str = ""
-      traders.each (index, element) =>
-        trader_link = window.$(element).children("h4").children("a").attr('href').split("/")[2];
-        trader_name = window.$(element).children("h4").text()
-        trader_desc = window.$(element).children("p").text() + " ("+trader_link+")"
-
-        message_str += trader_name + "\n"
-        message_str += "  " + trader_desc + "\n"
-
-      msg.send message_str+  robot.respond /what(\')?s on kerb$/i, (msg) ->
+    formatted_date = formatDate(new Date())
+    tradersOnDate(msg, formatted_date)


refactor

refactor

--- src/Bacon.JQuery.Bindings.coffee
+++ src/Bacon.JQuery.Bindings.coffee
@@ -23,26 +23,29 @@

   $.fn.asEventStream = Bacon.$.asEventStream
   Bacon.$.textFieldValue = (element, initValue) ->
-      current = -> element.val()
-      inputs = element.asEventStream("keyup").map(current)
-      if initValue?
-        element.val(initValue)
-      else
-        initValue = current()
-      binding = Bacon.Binding(initValue)
-      externalChanges = binding.addSource(inputs)
-      externalChanges.assign(element, "val")
-      binding
+    Bacon.$.domBinding {
+      initValue,
+      currentFromDom: -> element.val(),
+      domEvents: element.asEventStream("keyup"),
+      setToDom: (value) -> element.val(value)
+    }
   Bacon.$.checkBoxValue = (element, initValue) ->
-    current = -> !!element.attr("checked")
-    inputs = element.asEventStream("change").map(current)
+    Bacon.$.domBinding {
+      initValue,
+      currentFromDom: -> !!element.attr("checked"),
+      domEvents: element.asEventStream("change"),
+      setToDom: (value) -> element.attr "checked", value
+    }
+
+  Bacon.$.domBinding = ({ initValue, currentFromDom, domEvents, setToDom}) ->
+    inputs = domEvents.map(currentFromDom)
     if initValue?
-      element.attr "checked", initValue
+      setToDom(initValue)
     else
-      initValue = current()
+      initValue = currentFromDom()
     binding = Bacon.Binding(initValue)
     externalChanges = binding.addSource(inputs)
-    externalChanges.assign(element, "attr", "checked")
+    externalChanges.assign(setToDom)
     binding

   Bacon.$


Conditionally preventDefault

Conditionally preventDefault

--- source/javascripts/stagehand.js.coffee
+++ source/javascripts/stagehand.js.coffee
@@ -136,7 +136,7 @@
       @$controls.find('> ul').append(@stages[name].$el)
     @stages[name]
   changeScene: (e) ->
-    e.preventDefault()
+    if e then e.preventDefault()
     scene = $(e.target).closest('li').data('scene')
     scene.stage.toggleScene(scene.name)
     for name, stage of @stages
@@ -160,7 +160,7 @@
       for stage_name in $actor.attr('data-stage').split(',')
         @addStage(stage_name).addEls($actor)
   toggleControls: (e) ->
-    e.preventDefault()
+    if e then e.preventDefault()
     $(document.body).toggleClass('stagehand-active')
     @saveState()
     false


Use correct textmate package names

Use correct textmate package names

--- spec/markdown-preview-view-spec.coffee
+++ spec/markdown-preview-view-spec.coffee
@@ -8,7 +8,7 @@
   beforeEach ->
     project.setPath(project.resolve('markdown'))
     buffer = project.bufferForPath('file.markdown')
-    atom.activatePackage('ruby.tmbundle', sync: true)
+    atom.activatePackage('ruby-tmbundle', sync: true)
     preview = new MarkdownPreviewView(buffer)

   afterEach ->


Add some type definitions

Add some type definitions

--- readme.coffee
+++ readme.coffee
@@ -148,7 +148,7 @@

 doc.subsection "Creating streams"

-doc.fn "$.asEventStream(\"click\")", """
+doc.fn "$.asEventStream(eventName : String)", """
 creates an EventStream from events on a
 jQuery or Zepto.js object. You can pass optional arguments to add a
 jQuery live selector and/or a function that processes the jQuery
@@ -161,13 +161,13 @@
 ```
 """

-doc.fn "Bacon.fromPromise(promise [, abort])", """
+doc.fn "Bacon.fromPromise(promise : Promise[A] [, abort : boolean]) : EventStream[A]", """
 creates an EventStream from a Promise object such as JQuery Ajax.
 This stream will contain a single value or an error, followed immediately by stream end.  You can use the optional abort flag (i.e. ´fromPromise(p, true)´ to have the `abort` method of the given promise be called when all subscribers have been removed from the created stream.
 Check out this [example](https://github.com/raimohanska/baconjs-examples/blob/master/resources/public/index.html).
 """

-doc.fn "Bacon.fromEventTarget(target, eventName [, eventTransformer])", """
+doc.fn "Bacon.fromEventTarget(target : EventTarget | EventEmitter, eventName : String [, eventTransformer]) : EventStream", """
 creates an EventStream from events
 on a DOM EventTarget or Node.JS EventEmitter object. You can also pass an optional function that transforms the emitted
 events' parameters.
@@ -177,8 +177,8 @@
 ```
 """

-doc.fn "Bacon.fromCallback(f [, args...])", """
-creates an Event stream from a function that
+doc.fn "Bacon.fromCallback(f : (A -> void) -> void [, args...]) : EventStream[A]", """
+creates an EventStream from a function that
 accepts a callback. The function is supposed to call its callback just
 once. For example:

@@ -206,11 +206,11 @@
 ```
 """

-doc.fnOverload "Bacon.fromCallback(object, methodName [, args...])", "object", """
+doc.fnOverload "Bacon.fromCallback(object, methodName [, args...]) : EventStream[A]", "object", """
 a variant of fromCallback which calls the named method of a given object.
 """

-doc.fn "Bacon.fromNodeCallback(f [, args...])", """
+doc.fn "Bacon.fromNodeCallback(f : (E -> A -> void) -> void [, args...]) : EventStream[A]", """
 behaves the same way as [`Bacon.fromCallback`](#bacon-fromcallback),
 except that it expects the callback to be called in the Node.js convention:
 `callback(error, data)`, where error is null if everything is fine. For example:
@@ -228,20 +228,20 @@
 a variant of fromNodeCallback which calls the named method of a given object.
 """

-doc.fn "Bacon.fromPoll(interval, f)", """polls given function with given interval.
-Function should return Events: either [Bacon.Next](#bacon-next) or [Bacon.End](#bacon-end). Polling occurs only
+doc.fn "Bacon.fromPoll(interval : Number, f : -> Event[A]) : EventStream[A]", """polls given function with given interval.
+Function should return Events: either `Bacon.Next` or `Bacon.End`. Polling occurs only
 when there are subscribers to the stream. Polling ends permanently when
-`f` returns [Bacon.End](#bacon_end)
-"""
-
-doc.fn "Bacon.once(value)", """
+`f` returns `Bacon.End`.
+"""
+
+doc.fn "Bacon.once(value : Event[A] | A) : EventStream[A]", """
 creates an EventStream that delivers the given
 single value for the first subscriber. The stream will end immediately
 after this value. You can also send send an `Bacon.Error` event instead of a
 value: `Bacon.once(new Bacon.Error("fail"))`.
 """

-doc.fn "Bacon.fromArray(values)", """
+doc.fn "Bacon.fromArray(values : Array[Event[A] | A]) : EventStream[A]", """
 creates an EventStream that delivers the given
 series of values (given as array) to the first subscriber. The stream ends after these
 values have been delivered. You can also send `Bacon.Error` events, or
@@ -249,27 +249,27 @@
 `Bacon.fromArray([1, new Bacon.Error()])
 """

-doc.fn "Bacon.interval(interval, value)", """
+doc.fn "Bacon.interval(interval : Number, value : A) : EventStream[A]", """
 repeats the single element
 indefinitely with the given interval (in milliseconds)
 """

-doc.fn "Bacon.sequentially(interval, values)", """
+doc.fn "Bacon.sequentially(interval : Number, values : Array[A]) : EventStream[A]", """
 creates a stream containing given
 values (given as array). Delivered with given interval in milliseconds.
 """

-doc.fn "Bacon.repeatedly(interval, values)", """
+doc.fn "Bacon.repeatedly(interval : Number, values : Array[A]) : EventStream[A]", """
 repeats given elements indefinitely
-with given interval in milliseconds. For example, repeatedly(10, [1,2,3])
-would lead to 1,2,3,1,2,3... to be repeated indefinitely.
-"""
-
-doc.fn "Bacon.never()", """
+with given interval in milliseconds. For example, `repeatedly(10, [1,2,3])`
+would lead to `1,2,3,1,2,3...` to be repeated indefinitely.
+"""
+
+doc.fn "Bacon.never() : EventStream", """
 creates an EventStream that immediately ends.
 """

-doc.fn "Bacon.later(delay, value)", """
+doc.fn "Bacon.later(delay : Number, value : A) : EventStream[A]", """
 creates a single-element stream that
 produces given value after given delay (milliseconds).
 """
@@ -279,11 +279,11 @@
 """

 doc.text """
-[`property.changes()`](#property-changes) creates a stream of changes to the `Property`. The stream *does not* include
+`property.changes` creates a stream of changes to the `Property`. The stream *does not* include
 an event for the current value of the Property at the time this method was called.
 """

-doc.fn "property.toEventStream()", """creates an EventStream based on this Property. The stream contains also an event for the current
+doc.fn "property.toEventStream(@ : Property[A]) : EventStream[A]", """creates an EventStream based on this Property. The stream contains also an event for the current
 value of this Property at the time this method was called.
 """

@@ -386,7 +386,7 @@
 will be called for each error in the stream.
 """

-doc.fn "observable.onEnd(f)", """
+doc.fn "observable.onEnd(f : -> void) : Unsubscriber", """
 subscribes a callback to stream end. The function will
 be called when the stream ends. Just like `subscribe`, this method returns a function for unsubscribing.
 """
@@ -941,7 +941,7 @@
 array) as function arguments to `f`
 """

-doc.fn "property.assign(obj, method, [param...])", """
+doc.fn "property.assign(obj, method [, param...])", """
 calls the method of the given
 object with each value of this Property. You can optionally supply
 arguments which will be used as the first arguments of the method call.
@@ -1028,7 +1028,7 @@
 a Property and then combined with the other properties.
 """

-doc.fnOverload "Bacon.combineAsArray(s1, s2, ...)", "multiple-streams", """
+doc.fnOverload "Bacon.combineAsArray(s1, s2...)", "multiple-streams", """
 just like above, but with streams
 provided as a list of arguments as opposed to a single array.

@@ -1118,7 +1118,7 @@
 ```
 """

-doc.fnOverload "Bacon.zipAsArray(stream1, stream2, ..)", "stream1", """
+doc.fnOverload "Bacon.zipAsArray(stream1, stream2...)", "multiple-streams", """
 just like above, but with streams
 provided as a list of arguments as opposed to a single array.
 """


Fix feature handling, more debugging

Fix feature handling, more debugging

--- src/01_tinycpu/features/feature.coffee
+++ src/01_tinycpu/features/feature.coffee
@@ -25,11 +25,13 @@

 	handle_read: (loc, cpu, real_read) ->
 		# Dummy implementation. Reads that value from cpu memory
-		real_read loc
+		#console.log("handle_read(", [loc].join(', '), "): Feature dummy implementation")
+		real_read.call cpu, loc

 	handle_write: (loc, value, cpu, real_write) ->
 		# Dummy implementation. Writes that value to loc on cpu memory
-		real_write loc, value
+		console.log("handle_write(", [loc, value].join(', '), "): Feature dummy implementation")
+		real_write.call cpu, loc, value

 	handle_interrupt: (num, cpu) ->
 		# Dummy implementation. Does nothing.
@@ -41,8 +43,8 @@
 		((instance, feature) ->
 			((read, write) ->
 				if !instance[CPU_FEATURE_VAR]?
-					instance.read = (loc) -> feature.read loc, instance, read
-					instance.write = (loc, value) -> feature.write loc, value, instance, write
+					instance.read = (loc) -> feature.handle_read loc, instance, read
+					instance.write = (loc, value) -> feature.handle_write loc, value, instance, write
 					instance.interrupt = (num) -> feature.interrupt num, instance
 					instance[CPU_FEATURE_VAR] = {}
 				instance[CPU_FEATURE_VAR][name] = feature


OHM-79: Added test for server restart

OHM-79: Added test for server restart

--- test/integration/restartAPITests.coffee
+++ test/integration/restartAPITests.coffee
@@ -1,4 +1,5 @@
 should = require "should"
+sinon = require "sinon"
 request = require "supertest"
 Transaction = require("../../lib/model/transactions").Transaction
 Channel = require("../../lib/model/channels").Channel
@@ -88,59 +89,34 @@

     describe "*restart()", ->

-      i = 0
-      while i < 10
-        i++
+      it "should successfully send API request to restart the server", (done) ->
+        spy = sinon.spy server, 'startRestartServerAgenda'
+        request("https://localhost:8080")
+          .post("/restart")
+          .set("auth-username", testUtils.rootUser.email)
+          .set("auth-ts", authDetails.authTS)
+          .set("auth-salt", authDetails.authSalt)
+          .set("auth-token", authDetails.authToken)
+          .send()
+          .expect(200)
+          .end (err, res) ->
+            if err
+              done err
+            else
+              spy.calledOnce.should.be.true
+              done()

-        # send request to restart server
-        if i is 5
-          it "should successfully send API request to restart the server", (done) ->
-            request("https://localhost:8080")
-              .post("/restart")
-              .set("auth-username", testUtils.rootUser.email)
-              .set("auth-ts", authDetails.authTS)
-              .set("auth-salt", authDetails.authSalt)
-              .set("auth-token", authDetails.authToken)
-              .send()
-              .expect(200)
-              .end (err, res) ->
-                if err
-                  done err
-                else
-                  done()
-
-        it "should successfully create transaction " + i, (done) ->
-          request("https://localhost:8080")
-            .post("/transactions")
-            .set("auth-username", testUtils.rootUser.email)
+      it "should not allow non admin user to restart the server", (done) ->
+        request("https://localhost:8080")
+            .post("/restart")
+            .set("auth-username", testUtils.nonRootUser.email)
             .set("auth-ts", authDetails.authTS)
             .set("auth-salt", authDetails.authSalt)
             .set("auth-token", authDetails.authToken)
-            .send(transactionData)
-            .expect(201)
+            .send()
+            .expect(403)
             .end (err, res) ->
               if err
                 done err
               else
-                done()
-
-
-
-      it "should call getTransactions ", (done) ->
-        Transaction.count {}, (err, countBefore) ->
-          tx = new Transaction transactionData
-          tx.save (error, result) ->
-            should.not.exist (error)
-            request("https://localhost:8080")
-              .get("/transactions?filterPage=0&filterLimit=10")
-              .set("auth-username", testUtils.rootUser.email)
-              .set("auth-ts", authDetails.authTS)
-              .set("auth-salt", authDetails.authSalt)
-              .set("auth-token", authDetails.authToken)
-              .expect(200)
-              .end (err, res) ->
-                if err
-                  done err
-                else
-                  res.body.length.should.equal 10
-                  done()+                done()


#2 store sms id in Messages

#2 store sms id in Messages

--- server/nexmo.coffee
+++ server/nexmo.coffee
@@ -14,6 +14,7 @@
     Messages.insert
       text: sms_data.text
       datetime: new Date()
+      sms_id: sms_data.messageId
     @response.end JSON.stringify sms_data
   ,
     where: 'server'


Removed useless code from Pump.run method

The buffers will be empty, that is a condition for finishing the pump.

--- src/Pump.coffee
+++ src/Pump.coffee
@@ -221,9 +221,3 @@

   run: ->
     @start().whenFinished()
-      .then =>
-        result = {}
-        for name, buffer of @_buffers
-          result[name] = buffer.getContent()
-
-        return result


Exit when compile completed

Exit when compile completed

--- lib/command.coffee
+++ lib/command.coffee
@@ -37,6 +37,7 @@
   run: (args...) ->
     try
       runFiles.apply this, args
+      process.exit 0

     catch e
       throw e  unless e.constructor in [UnsupportedError, SyntaxError]


remember removed functions to include in results

--- lib/control.coffee
+++ lib/control.coffee
@@ -72,6 +72,11 @@

         # remove the function and remember it for an emit
         fn = @_array.splice @_index, 1
+
+        # let's store the removal into context (the eventual return result)
+        @removed ?= []
+        # unwrap it from the array splice() puts it in
+        @removed.push fn[0]

         # emit the removal
         @_chain.emit 'remove', result:true, removed:fn, reason:reason


Updated error configuration compass-mixins

Updated error configuration compass-mixins

--- brunch-config.coffee
+++ brunch-config.coffee
@@ -4,7 +4,7 @@
             sass:
                 mode:'native'
                 options:
-                    includePaths: :["bower_components/compass-mixins/lib/"]
+                    includePaths: ["bower_components/compass-mixins/lib/"]

         conventions:
                 assets: /^app\/assets\//


Fix cross-thread linking via coauthor:...

--- lib/formats.coffee
+++ lib/formats.coffee
@@ -197,14 +197,11 @@
         match
   .replace ///(<a\s[^<>]*href\s*=\s*['"])#{coauthorLinkRe}///ig,
     (match, p1, p2) ->
-      msg = Messages.findOne p2
-      if msg?
-        p1 + pathFor 'message',
-          group: msg.group
-          message: msg._id
-      else
-        console.warn "Couldn't find group for message #{p2} (likely subscription issue)"
-        match
+      ## xxx Could add msg.title, when available, to hover text...
+      #msg = Messages.findOne p2
+      p1 + pathFor 'message',
+        group: msg.group
+        message: msg._id

 katex = require 'katex'


pretify Guesture

pretify Guesture

--- lib/gesture.coffee
+++ lib/gesture.coffee
@@ -8,9 +8,6 @@
     right : {}
   on : {}

-  #@on.left =  (event) ->
-  #@on.right
-  #same for right
   constructor: (options) ->
     {@on,@space,@minActivate} = options
     @addEventListener()
@@ -33,40 +30,23 @@
   mouseDown: (e) =>
     @checkDown 'left', e
     @checkDown 'right', e
-    # if event.left <= @space and @on.left?
-    #   @move.left.start = event.left
-    # else if event.right <= @space and @on.right?
-    #   @move.right.start = event.right
   checkDown: (direction,event) ->
     if event[direction] <= @space and @on[direction]?
       @move[direction].start = event[direction]
+
   mouseMove: (e) =>
     @checkMove 'left', e
     @checkMove 'right', e
-    # @move.left.activate = true if event.diff.left >= @minActivate
-    # @move.right.activate = true if event.diff.right >= @minActivate
-    # if @on.left? and @move.left.activate?
-    #   @on.left event
-    # else if @on.left? and @move.right.activate?
-    #   @on.right event
   checkMove: (direction,event) ->
     @move[direction].activate = true if event.diff[direction] >= @minActivate
     if @on[direction]? and @move[direction].activate?
       @on[direction] event
+
   mouseUp: (e) =>
     e.end = true
     @checkUp 'left', e
     @checkUp 'right', e
-    # if @move.left.activate
-    #   @on.left event
-    #   @stopMove 'left'
-    # if @move.right.activate
-    #   @on.right event
-    #   @stopMove 'right'
   checkUp: (direction,event) ->
     if @move[direction].activate
       @on[direction] event
       @move[direction] = {}
-
-  stopMove: (name) ->
-    @move[name] = {}


Release 0.07.01

Release 0.07.01

--- source/atoms.coffee
+++ source/atoms.coffee
@@ -1,6 +1,6 @@
 # Globals
 Atoms = @Atoms =
-  version   : "0.06.23b"
+  version   : "0.07.01"
   Core      : {}
   Class     : {}


Release 0.04.26

Release 0.04.26

--- source/atoms.coffee
+++ source/atoms.coffee
@@ -1,6 +1,6 @@
 # Globals
 Atoms = @Atoms =
-  version   : "0.04.24"
+  version   : "0.04.26"
   Core      : {}
   Class     : {}


Add comments to previous commit

Add comments to previous commit

--- src/coffee/model/lib/Grid.coffee
+++ src/coffee/model/lib/Grid.coffee
@@ -17,12 +17,14 @@
     if hex
       return hex

+  #Returns a new grid with hex changed if possible to value
   grid.prototype.take = (hex, val) ->
     g = this.clone()
     if g.state[hex.x][hex.y].value is 'neutral'
       g.state[hex.x][hex.y].value = val
     return g

+  #Returns a new grid with hex changed to value
   grid.prototype.set = (hex, val) ->
     g = this.clone()
     g.state[hex.x][hex.y].value = val


MER-41: Add methods to resolve product references.

--- src/coffee/product-import.coffee
+++ src/coffee/product-import.coffee
@@ -9,6 +9,7 @@
   constructor: (@logger, options = {}) ->
     @sync = new ProductSync
     @client = new SphereClient options
+    @_cache = {}

   _resetSummary: ->
     @_summary =
@@ -85,7 +86,48 @@
     debug 'About to send %s requests', _.size(posts)
     Promise.all(posts)

+  _prepareNewProduct: (product) ->
+    Promise.all [
+
+    ]
+
+  _resolveProductTypeReference: (productTypeRef) ->
+    new Promise (resolve, reject) =>
+      if not productTypeRef?
+        reject("Product type reference is undefined")
+      if @_cache.productType[productTypeRef.id]
+        resolve(@_cache.productType[productTypeRef.id])
+      else
+        @client.productTypes.where("name=\"#{productTypeRef.id}\"").fetch()
+        .then(result) =>
+          # Todo: Handle multiple response, currently taking first response.
+          @_cache.productType[productTypeRef.id] = result.results[0]
+          resolve(result.results[0])

+  _resolveCategoriesReference: (categoryRef) ->
+    new Promise (resolve, reject) =>
+      if not categoryRef?
+        reject("Product category is undefined")
+      if @_cache.productCategory[categoryRef.id]
+        resolve(@_cache.productCategory[categoryRef.id])
+      else
+        @client.categories.where("externalId=\"#{categoryRef.id}\"").fetch()
+        .then(result) =>
+          @_cache.productCategory[categoryRef.id] = result.results[0]
+          resolve(result.results[0])
+
+
+  _resolveTaxCategoryReference: (taxCategoryRef) ->
+    new Promise (resolve, reject) =>
+      if not taxCategoryRef?
+        reject("Tax category is undefined")
+      if @_cache.taxCategory[taxCategoryRef.id]
+        resolve(@_cache.taxCategory[taxCategoryRef.id])
+      else
+        @client.taxCategories.where("name=\"#{taxCategoryRef.id}\"").fetch()
+        .then(result) =>
+          @_cache.taxCategory[taxCategoryRef.id] = result.results[0]
+          resolve(result.results[0])

 module.exports = ProductImport


colours

colours

--- source/floor.coffee
+++ source/floor.coffee
@@ -4,7 +4,7 @@
       floorcontainer = new THREE.Object3D()

       geometry = new THREE.BoxGeometry(Game.state.levelWidth*10, 10, Game.state.levelHeight*10)
-      material = new THREE.MeshPhongMaterial({color: 0x00ff00})
+      material = new THREE.MeshPhongMaterial({color: 0xadbeef})
       floor   = new THREE.Mesh(geometry, material)
       floor.position.x = Game.state.levelWidth * 5
       floor.position.y = -5
@@ -38,8 +38,9 @@
     y = Math.floor((data.point.z + Game.state.levelHeight*5)/10)

     if x < Game.state.levelWidth and y < Game.state.levelHeight
+
       this.tileClicked(x, y)

+
   tileClicked: (x, y) ->
-    console.log('Tile (',x,',',y,') clicked.')
     new SmallDesk(x, y)


fix package.json require

fix package.json require

--- src/controllers/main-controller.coffee
+++ src/controllers/main-controller.coffee
@@ -3,7 +3,7 @@
 angular.module 'gateblu-ui'
   .controller 'MainController', ($scope, GatebluService, LogService, UpdateService, GatebluBackendInstallerService) ->
     LogService.add 'Starting up!'
-    version = require('../package.json').version
+    version = require('./package.json').version
     colors = ['green', 'yellow', 'blue', 'darkBlue', 'deepBlue', 'purple', 'lightPurple', 'red', 'pink']
     robotUrls = [
       './images/robot1.png'