diff --git a/scripts/interface/Interface.js b/scripts/interface/Interface.js index 84abbe3..20480c5 100644 --- a/scripts/interface/Interface.js +++ b/scripts/interface/Interface.js @@ -37,6 +37,7 @@ define([ } }); code = code.replace(/[{}]/g, ''); + code = 'headers fade\nterminators fade\n' + code; return code; } diff --git a/scripts/main.js b/scripts/main.js index f5d703e..b8cc12f 100644 --- a/scripts/main.js +++ b/scripts/main.js @@ -176,12 +176,12 @@ { title: 'Title', code: 'title {Title}', - preview: 'title Title\nA -> B', + preview: 'headers box\ntitle Title\nA -> B', }, { title: 'Chunky theme', code: 'theme chunky', - preview: 'theme chunky\nA -> B', + preview: 'headers box\ntheme chunky\nA -> B', }, { title: 'Cross terminators', diff --git a/scripts/sequence/CodeMirrorMode.js b/scripts/sequence/CodeMirrorMode.js index 7a16b40..4112413 100644 --- a/scripts/sequence/CodeMirrorMode.js +++ b/scripts/sequence/CodeMirrorMode.js @@ -138,6 +138,13 @@ define(['core/ArrayUtilities'], (array) => { }, }, }}, + 'headers': {type: 'keyword', suggest: true, then: { + 'none': {type: 'keyword', suggest: true, then: {}}, + 'cross': {type: 'keyword', suggest: true, then: {}}, + 'box': {type: 'keyword', suggest: true, then: {}}, + 'fade': {type: 'keyword', suggest: true, then: {}}, + 'bar': {type: 'keyword', suggest: true, then: {}}, + }}, 'terminators': {type: 'keyword', suggest: true, then: { 'none': {type: 'keyword', suggest: true, then: {}}, 'cross': {type: 'keyword', suggest: true, then: {}}, diff --git a/scripts/sequence/Generator.js b/scripts/sequence/Generator.js index fc7dc02..48be6b3 100644 --- a/scripts/sequence/Generator.js +++ b/scripts/sequence/Generator.js @@ -146,6 +146,32 @@ define(['core/ArrayUtilities'], (array) => { } } + function swapBegin(stage, mode) { + if(stage.type === 'agent begin') { + stage.mode = mode; + return true; + } + if(stage.type === 'parallel') { + let any = false; + stage.stages.forEach((subStage) => { + if(subStage.type === 'agent begin') { + subStage.mode = mode; + any = true; + } + }); + return any; + } + return false; + } + + function swapFirstBegin(stages, mode) { + for(let i = 0; i < stages.length; ++ i) { + if(swapBegin(stages[i], mode)) { + break; + } + } + } + function addBounds(target, agentL, agentR, involvedAgents = null) { array.remove(target, agentL, agentEqCheck); array.remove(target, agentR, agentEqCheck); @@ -585,6 +611,7 @@ define(['core/ArrayUtilities'], (array) => { this.currentNest.rightAgent ); optimiseStages(globals.stages); + swapFirstBegin(globals.stages, meta.headers || 'box'); return { meta: { diff --git a/scripts/sequence/Generator_spec.js b/scripts/sequence/Generator_spec.js index c957fbe..23f5081 100644 --- a/scripts/sequence/Generator_spec.js +++ b/scripts/sequence/Generator_spec.js @@ -490,6 +490,25 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => { ]); }); + it('uses the header theme for the topmost begin statement', () => { + const sequence = generator.generate({ + meta: { + headers: 'foo', + }, + stages: [ + PARSED.connect(['A', 'B']), + PARSED.connect(['B', 'C']), + ], + }); + expect(sequence.stages).toEqual([ + GENERATED.beginAgents(['A', 'B'], {mode: 'foo'}), + jasmine.anything(), + GENERATED.beginAgents(['C'], {mode: 'box'}), + jasmine.anything(), + jasmine.anything(), + ]); + }); + it('removes duplicate end agents', () => { const sequence = generator.generate({stages: [ PARSED.beginAgents(['A']), diff --git a/scripts/sequence/Parser.js b/scripts/sequence/Parser.js index cb3422d..c29194d 100644 --- a/scripts/sequence/Parser.js +++ b/scripts/sequence/Parser.js @@ -262,6 +262,19 @@ define([ return true; }, + (line, meta) => { // headers + if(tokenKeyword(line[0]) !== 'headers') { + return null; + } + + const type = tokenKeyword(line[1]); + if(TERMINATOR_TYPES.indexOf(type) === -1) { + throw makeError('Unknown header "' + type + '"', line[1]); + } + meta.headers = type; + return true; + }, + (line) => { // autolabel if(tokenKeyword(line[0]) !== 'autolabel') { return null; @@ -439,6 +452,7 @@ define([ title: '', theme: '', terminators: 'none', + headers: 'box', }, stages: [], }; diff --git a/scripts/sequence/Parser_spec.js b/scripts/sequence/Parser_spec.js index 9224627..06614fd 100644 --- a/scripts/sequence/Parser_spec.js +++ b/scripts/sequence/Parser_spec.js @@ -72,6 +72,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => { title: '', theme: '', terminators: 'none', + headers: 'box', }, stages: [], }); @@ -92,6 +93,11 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => { expect(parsed.meta.terminators).toEqual('bar'); }); + it('reads headers metadata', () => { + const parsed = parser.parse('headers bar'); + expect(parsed.meta.headers).toEqual('bar'); + }); + it('reads multiple tokens as one when reading values', () => { const parsed = parser.parse('title foo bar'); expect(parsed.meta.title).toEqual('foo bar'); @@ -524,6 +530,12 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => { )); }); + it('rejects invalid headers', () => { + expect(() => parser.parse('headers foo')).toThrow(new Error( + 'Unknown header "foo" at line 1, character 8' + )); + }); + it('rejects malformed notes', () => { expect(() => parser.parse('note over A hello')).toThrow(); });