Skip to content

Commit

Permalink
add fountain support and default to fountain syntax highlighting for …
Browse files Browse the repository at this point in the history
…script editor
  • Loading branch information
lalalune committed Aug 14, 2024
1 parent 3635e59 commit cdedae6
Showing 1 changed file with 68 additions and 1 deletion.
69 changes: 68 additions & 1 deletion src/components/editors/ScriptEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function ScriptEditor() {
const publish = useScriptEditor((s) => s.publish)
const onDidScrollChange = useScriptEditor((s) => s.onDidScrollChange)
const jumpCursorOnLineClick = useScriptEditor((s) => s.jumpCursorOnLineClick)
const highlightElements = useScriptEditor((s) => s.highlightElements)

const scrollHeight = useScriptEditor((s) => s.scrollHeight)

Expand All @@ -36,7 +37,9 @@ export function ScriptEditor() {
if (!standaloneCodeEditor) {
return
}

// let's do something basic for now: we disable the

// timeline-to-editor scroll sync when the user is
// hovering the editor
if (useScriptEditor.getState().mouseIsInside) {
Expand All @@ -48,6 +51,7 @@ export function ScriptEditor() {
scrollTop: horizontalTimelineRatio,
})
}

// various things we can do here!
// move the scroll:
// editor.setScrollPosition({ scrollTop: horizontalTimelineRatio })
Expand Down Expand Up @@ -105,6 +109,7 @@ export function ScriptEditor() {
}
)
*/
highlightElements()
}

const setMonaco = useScriptEditor((s) => s.setMonaco)
Expand All @@ -125,6 +130,14 @@ export function ScriptEditor() {
inherit: true, // Inherit the default rules
rules: [
// You can define token-specific styles here if needed
{ token: 'scene.int', foreground: '#4EC9B0' },
{ token: 'scene.ext', foreground: '#9CDCFE' },
{ token: 'character', foreground: '#DCDCAA' },
{ token: 'dialog', foreground: '#D4D4D4' },
{ token: 'parenthetical', foreground: '#B5CEA8' },
{ token: 'transition', foreground: '#C586C0' },
{ token: 'shot', foreground: '#CE9178' },
{ token: 'action', foreground: '#D4D4D4' },
],
colors: {
'editor.background':
Expand All @@ -149,9 +162,60 @@ export function ScriptEditor() {

const textModel: MonacoEditor.editor.ITextModel = monaco.editor.createModel(
current || '',
'plaintext'
'fountain'
)
setTextModel(textModel)

// Register fountain language
monaco.languages.register({ id: 'fountain' })
monaco.languages.setMonarchTokensProvider('fountain', {
tokenizer: {
root: [
[/^(INT|I\/E)(.+)/, 'scene.int'],
[/^(EXT)(.+)/, 'scene.ext'],
[/^[A-Z][A-Z\s]+$/, 'character'],
[/^\(.+\)$/, 'parenthetical'],
[/^>.+<$/, 'transition'],
[/^(?:FADE (?:IN|OUT|TO)|CUT TO:)$/, 'transition'],
[/^(?:ANGLE ON|CLOSE ON|PAN|TRACKING|MOVING):.+$/, 'shot'],
[/^(?![A-Z]+$|\(|\>).+/, 'action'],
],
},
})

// Setup code folding
monaco.languages.registerFoldingRangeProvider('fountain', {
provideFoldingRanges: function (model, context, token) {
const lines = model.getLinesContent()
const ranges = []
let sceneStart = -1

for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim()
if (/^(INT|EXT|I\/E)/.test(line)) {
if (sceneStart !== -1) {
ranges.push({
start: sceneStart + 1,
end: i,
kind: monaco.languages.FoldingRangeKind.Region,
})
}
sceneStart = i
}
}

// Add the last scene if there is one
if (sceneStart !== -1 && sceneStart < lines.length - 1) {
ranges.push({
start: sceneStart + 1,
end: lines.length,
kind: monaco.languages.FoldingRangeKind.Region,
})
}

return ranges
},
})
}

return (
Expand All @@ -169,6 +233,9 @@ export function ScriptEditor() {
onChange={setCurrent}
options={{
fontSize: editorFontSize,
language: 'fountain',
folding: true,
foldingStrategy: 'auto',
}}
/>
</div>
Expand Down

0 comments on commit cdedae6

Please sign in to comment.