From 059e114a2ef473b538b02f0d3aff7d5b70286c55 Mon Sep 17 00:00:00 2001 From: Cake <65981767+CakeVR@users.noreply.github.com> Date: Thu, 7 Dec 2023 10:30:09 +0100 Subject: [PATCH] Add Timeline Syntax Highlighting (#29) --- documentation/timeline-text-syntax.md | 248 +++++++++++++------------- theme/ayu-highlight.css | 2 +- theme/highlight.js | 97 ++++++++++ 3 files changed, 222 insertions(+), 125 deletions(-) diff --git a/documentation/timeline-text-syntax.md b/documentation/timeline-text-syntax.md index 3709908..f03474f 100644 --- a/documentation/timeline-text-syntax.md +++ b/documentation/timeline-text-syntax.md @@ -1,124 +1,124 @@ -![header_text_syntax](media/headers/text_syntax.png) - -Timelines are saved in a text format, which means that you can use any text-editing software to edit and create them. The built in text editor provides useful autocompletion and syntax highlighting. -📜 -*Info: For dialogic to register your timeline file, it has to use the `.dtl` extension!* - -
-📜 Content - -- [About shortcode events](#about-shortcode-events) - -- [About special events](#about-special-events) - -- [About Indentation](#about-indentation) - -- [Example Timeline](#Example-timeline) - -
- -## About shortcode events - -Most events follow a shortcodes-like style: - -``` -[background path="res://icon.png" fade="1.0"] -``` - -The order of the parameters does not matter, but they have to be separated by at least one space. All parameters regardless of type have to be contained in double quotation marks. - -To find all of the parameters you can use on each event, check out their documentation by searching for their class in the godot help or this documentation. - -## About special events - -Some events have a custom syntax, to make writing them easier. This includes: - -- Character event: - - - `join Emilio (happy) 3 [animation="Bounce In"]` - - `leave Emilio [animation="Bounce Out" length="0.3"]` - - `update Emilio (excited) 4 [animation="Tada" wait="true" repeat="3" move_time="0.3"]` - -- Text event:  - - - `A wonderful text event, said by noone in particular.` - - `Emilio (excited): Hello and welcome!` - - Ending a text event with \ will make it include the next line as well. - -- Choice event: - - - `- I don't know about that` - - `- Yes [if {John.Relationship} > 23]` - - `- Sure, I'm the great wizard [if {Stats.Charisma} > 10] [else="disable" alt_text="I'm the great wizard [to insecure]"]` - -- Condition event: - - - `if {Player.Wisdom} > 3:` - - `elif {Player.Health} <= 10:` - - `else:` - -- Set Variable event: - - - `set {MyVariable} += 10` - - Supported Operators are =, += , -= , *=, /= - -- Comment event: - - - `# Todo: Finnish this!!!!` - -- Label event: - - - `label MyLabelName` - -- Jump event: - - - `jump MyLabelName` - - `jump TimelineName/` # the slash is mandatory to clarify this is a timeline not a label - - `jump TimelineName/LabelName` - -- Return event: - - - `return` - -## About indentation - -Timelines use TAB indentation to know what events belong to a choice or condition block. Only changes in indentation are considered, so it doesn't really matter how much you indent as long as you are consistent within one block. - -## Example timeline - -``` -[background path="res://assets/backgroudns/dialogic_factory.png"] - -join Jowan 4 -jowan (exited): Hello and welcome to[portrait=confused]...[pause=0.5] Wait? What is this? - -Join Emilio (happy) 1 -Emilio: Well, this is is the example timeline. - -Jowan: I thought this was a cool new feature? - -Emilio: Nah, sorry. - -Jowan (sad): It's okay. - -# Some choices jump back to this -label WhatAbout - -Jowan (default): So what should this example be about? -- How to bake cookies -    Emilio (confused): Wait that hasn't to do with dialogic?! -    jump WhatAbout - -- How to reach the moon [if {Player.Name} == "NASA"] -    Jowan (angry): NASA! It's you again. This is for making dialogs!\ -    Please ask someone else about the moon!. -     -    jump WhatAbout - -- How to write timelines in text format -    Jowan: Oh, well it's pretty intuitive.[pause= 0.2][portrait=questioning] I hope. -     -    Emilio: Let's hope it's easy as well. - -[end_timeline] -``` +![header_text_syntax](media/headers/text_syntax.png) + +Timelines are saved in a text format, which means that you can use any text-editing software to edit and create them. The built in text editor provides useful autocompletion and syntax highlighting. +📜 +*Info: For dialogic to register your timeline file, it has to use the `.dtl` extension!* + +
+📜 Content + +- [About shortcode events](#about-shortcode-events) + +- [About special events](#about-special-events) + +- [About Indentation](#about-indentation) + +- [Example Timeline](#Example-timeline) + +
+ +## About shortcode events + +Most events follow a shortcodes-like style: + +```dtl +[background path="res://icon.png" fade="1.0"] +``` + +The order of the parameters does not matter, but they have to be separated by at least one space. All parameters regardless of type have to be contained in double quotation marks. + +To find all of the parameters you can use on each event, check out their documentation by searching for their class in the godot help or this documentation. + +## About special events + +Some events have a custom syntax, to make writing them easier. This includes: + +- Character event: + + - `join Emilio (happy) 3 [animation="Bounce In"]` + - `leave Emilio [animation="Bounce Out" length="0.3"]` + - `update Emilio (excited) 4 [animation="Tada" wait="true" repeat="3" move_time="0.3"]` + +- Text event:  + + - `A wonderful text event, said by noone in particular.` + - `Emilio (excited): Hello and welcome!` + - Ending a text event with \ will make it include the next line as well. + +- Choice event: + + - `- I don't know about that` + - `- Yes [if {John.Relationship} > 23]` + - `- Sure, I'm the great wizard [if {Stats.Charisma} > 10] [else="disable" alt_text="I'm the great wizard [to insecure]"]` + +- Condition event: + + - `if {Player.Wisdom} > 3:` + - `elif {Player.Health} <= 10:` + - `else:` + +- Set Variable event: + + - `set {MyVariable} += 10` + - Supported Operators are =, += , -= , *=, /= + +- Comment event: + + - `# Todo: Finnish this!!!!` + +- Label event: + + - `label MyLabelName` + +- Jump event: + + - `jump MyLabelName` + - `jump TimelineName/` # the slash is mandatory to clarify this is a timeline not a label + - `jump TimelineName/LabelName` + +- Return event: + + - `return` + +## About indentation + +Timelines use TAB indentation to know what events belong to a choice or condition block. Only changes in indentation are considered, so it doesn't really matter how much you indent as long as you are consistent within one block. + +## Example timeline + +```dtl +[background path="res://assets/backgroudns/dialogic_factory.png"] + +join Jowan 4 +jowan (exited): Hello and welcome to[portrait=confused]...[pause=0.5] Wait? What is this? + +join Emilio (happy) 1 +Emilio: Well, this is is the example timeline. + +Jowan: I thought this was a cool new feature? + +Emilio: Nah, sorry. + +Jowan (sad): It's okay. + +# Some choices jump back to this +label WhatAbout + +Jowan (default): So what should this example be about? +- How to bake cookies +    Emilio (confused): Wait that hasn't to do with dialogic?! +    jump WhatAbout + +- How to reach the moon [if {Player.Name} == "NASA"] +    Jowan (angry): NASA! It's you again. This is for making dialogs!\ +    Please ask someone else about the moon!. +     +    jump WhatAbout + +- How to write timelines in text format +    Jowan: Oh, well it's pretty intuitive.[pause= 0.2][portrait=questioning] I hope. +     +    Emilio: Let's hope it's easy as well. + +[end_timeline] +``` diff --git a/theme/ayu-highlight.css b/theme/ayu-highlight.css index ea55f8d..577ae51 100644 --- a/theme/ayu-highlight.css +++ b/theme/ayu-highlight.css @@ -37,7 +37,7 @@ code.hljs .hljs-keyword { color: var(--keyword-color); } code.hljs .hljs-control_flow_keyword { color: var(--control_flow_keyword-color); } -code.hljs .hljs-base_type { color: var(--base_type-color); } +code.hljs .hljs-base_type, .hljs-built_in { color: var(--base_type-color); } code.hljs .hljs-engine_type { color: var(--engine_type-color); } diff --git a/theme/highlight.js b/theme/highlight.js index fe37f4c..bab5902 100644 --- a/theme/highlight.js +++ b/theme/highlight.js @@ -79,4 +79,101 @@ function hljsDefineGDScript(hljs) { }; } + +/* + Function returns a highlight definition for GDScript. +*/ +function hljsDefineDialogicTimeline(hljs) { + var KEYWORDS = { + /* General keywords */ + keyword: + 'join leave update set jump label background set call ' + + 'music voice sound style clear history end_timeline ', + + /* Keywords altering the code flow. */ + control_flow_keyword: + 'if and elif else for match while break continue pass return ', + + /* Improves the Dialogic Autoload's visual clarity. */ + dialogic_keyword: + '', + + /* Built-in types in GDScript. */ + built_in: + '', + + literal: + 'true false null' + }; + + var SPEAKER_NAME = { + className: 'dialogic_keyword', + begin: '\\b[A-Za-z]+\\b(?=\\s*(\\([^)]+\\)|:))' + }; + + var SPEAKER_TEXT = { + className: 'string', + begin: ':', + end: '$', + relevance: 0, + contains: [] + }; + + var SPEAKER_EXPRESSION = { + className: 'built_in', + begin: '\\([^)]+\\)' + }; + + var SPEAKER_ARGUMENT = { + className: 'dialogic_keyword', + begin: '(?<=\\b(?:join|leave|jump|label|update)\\s)\\b[A-Za-z]+\\b' + }; + + var SPEAKER_EXPRESSION = { + className: 'built_in', + begin: '\\([^)]+\\)' + }; + + var EVENT_PROPERTY = { + className: 'built_in', + begin: '\\b[A-Za-z]+\\b(?=\\s*=)' + }; + + return { + aliases: ['dtl', 'timeline'], + keywords: KEYWORDS, + contains: [ + SPEAKER_NAME, + SPEAKER_TEXT, + SPEAKER_EXPRESSION, + EVENT_PROPERTY, + SPEAKER_ARGUMENT, + hljs.NUMBER_MODE, + hljs.HASH_COMMENT_MODE, + { + className: 'comment', + begin: /"""/, end: /"""/ + }, + hljs.QUOTE_STRING_MODE, + { + variants: [ + { + className: 'function', + beginKeywords: 'func' + }, + { + className: 'class', + beginKeywords: 'class' + } + ], + end: /:/, + contains: [ + hljs.UNDERSCORE_TITLE_MODE + ] + }, + ] + }; +} + hljs.registerLanguage('gdscript', hljsDefineGDScript); +hljs.registerLanguage('dialogic-timeline', hljsDefineDialogicTimeline);