Commit d45de10a authored by Leon Arnott's avatar Leon Arnott
Browse files

Altered the syntax highlighting to add a dotted line indicating when changers...

Altered the syntax highlighting to add a dotted line indicating when changers and variables will attach to hooks, eliminating whitespace.

This is by no means perfect, but is still, in my mind, better than having no visual indication whatsoever. This also brings along two tooltips related to changer attachment.

Also added some syntax highlighting colours for a few common operators.
parent d2716f3f6368
......@@ -1094,18 +1094,18 @@ define(['jquery', 'macros', 'utils', 'state', 'passages', 'renderer', 'engine',
const makeStyleString = value => {
const clampedSize = max(0, min(1, value / maxValue));
const g = gradient.multiply(maxValue / value);
return `height:100%;background-image:${
return `height:100%;background-repeat:no-repeat;background-image:${
/*
A center-aligned graph consists of two different gradient backgrounds, extending to the left and right
from the centre. This line produces the left extension.
*/
(isCenter ? assign(g, { angle: 270 }).toLinearGradientString() + " no-repeat, " : '')
(isCenter ? assign(g, { angle: 270 }).toLinearGradientString() + ", " : '')
/*
And, this line produces either the right extension, or the entire bar for other alignments.
Note that the gradient angle is reversed for right-alignment (270 rather than 90).
*/
+ assign(g, { angle: isCenter || marginLeft === 0 ? 90 : 270 }).toLinearGradientString()
} no-repeat;background-size:${
};background-size:${
isCenter ? Array(2).fill(clampedSize * 50 + "%") : clampedSize * 100 + "%"
};background-position-x:${
/*
......
......@@ -37,7 +37,11 @@
[name, ...macro.aka].forEach(name => a[name] = macro);
return a;
}, {});
/*
Produce an array holding just Changer or Any macro names, used to determine if the Changer attachment line should be drawn.
*/
const changerMacros = Object.entries(validMacros).filter(([name,macro]) => ["Changer","Any"].includes(macro.returnType)).map(e => e[0]);
/*
The mode is defined herein.
*/
......@@ -283,6 +287,10 @@
return {
pos: 0,
/*
This is used to (somewhat crudely) keep track of possible changer attachment.
*/
attachment: false,
};
},
blankLine(state) {
......@@ -331,11 +339,15 @@
let counts = {};
let ret = '';
for (let i = 0; i < currentBranch.length; i+=1) {
const type = currentBranch[i].type;
// if the name is "verbatim", erase all of the class names before it.
const {type,text} = currentBranch[i];
// If the type is "verbatim", erase all of the class names before it.
if (type === "verbatim") {
ret = '';
}
// If the type is not "escapedLine" or "br", or if it's text that trims to "+", assume the end of changer attachment.
if (i === 0 && state.attachment && (type !== "escapedLine" && type !== "br" && type !== "root" && (type !== "text" || !text.match(/^\s*\+?\s*$/)))) {
state.attachment = false;
}
let name = "harlowe-3-" + type;
counts[name] = (counts[name] || 0) + 1;
// If this name has been used earlier in the chain, suffix
......@@ -348,7 +360,7 @@
It's an error if a text node appears inside a macro, but not inside a code hook.
*/
case "text": {
if (currentBranch[i].text.trim()) {
if (text.trim()) {
const insideMacro = currentBranch.slice(i + 1).reduce((a,t) =>
a === undefined ? t.type === "macro" ? true : t.type === "hook" ? false : a : a,
undefined
......@@ -363,7 +375,7 @@
Use the error style if the macro's name doesn't match the list of
existant Harlowe macros.
*/
case "macroName":
case "macroName": {
const macroName = insensitiveName(currentBranch[i].text.slice(0,-1));
if (!validMacros.hasOwnProperty(macroName)) {
name += " harlowe-3-error";
......@@ -377,9 +389,43 @@
name += "-" + validMacros[macroName].returnType.toLowerCase();
}
break;
}
case "macro": {
/*
If this macro is a Changer or an Any macro, then shakily assume that from here
on begins changer attachment whitespace.
*/
const macroName = insensitiveName(currentBranch[i].children[0].text.slice(0,-1));
if (!changerMacros.includes(macroName)) {
break;
}
}
/* falls through */
case "variable":
case "tempVariable":
/*
For variables, it can only be a shaky presumption that they contain changers. Nevertheless,
it's often vital to show it anyway.
*/
if (i === 0 && state.pos === currentBranch[i].end) {
state.attachment = true;
}
break;
}
ret += name + " ";
}
/*
Finally, put on the changerAttachment class if there's currently changer attachment being speculated.
*/
if (state.attachment === true) {
ret += " harlowe-3-changerAttachment";
/*
In order to enable the tooltips to produce a unique text tooltip for changer attachment lines,
the tree needs to be crudely modified here. All this would be avoided if changer attachment was
part of the lexer, but, alas...
*/
currentToken.changerAttachment = true;
}
return ret;
},
};
......
......@@ -30,9 +30,9 @@
scriptStyleTag: () => tooltipMessages.tag,
tag: "This is a <b>HTML tag</b>. Harlowe supports raw HTML in passage code.",
hook: ({type, name, tagPosition}) => (type === "hook" ? `These square brackets are a <b>hook</b>, enclosing this section of passage code.` : '')
+ ` Changer values can be attached to the front of hooks.`
+ ` Changer values can be attached to the left of hooks.`
+ (name ? `<br>This hook has a <b>nametag</b> on the ${
tagPosition === "prepended" ? "front" : "back"
tagPosition === "prepended" ? "left" : "right"
}. This allows the hook to be referred to in macro calls using the hook name <code>?${
name
}</code>.` : ''),
......@@ -45,7 +45,7 @@
type === "unclosedCollapsed" ? "the remainder of the passage " : 'the <code>{</code> and <code>}</code> marks'
} will be replaced with a single space. You can use this to space out your code and keep your passage readable.<br>To include a line break within this markup that will be preserved, use a HTML <code>&lt;br&gt;</code> tag.`,
escapedLine: `This is an <b>escaped line break</b> mark. This removes the line break before or after it from the displayed passage.`,
twineLink: ({passage}) => `This is a link to the passage "${passage}". Links, like hooks and commands, can have changer values attached to the front.`,
twineLink: ({passage}) => `This is a link to the passage "${passage}". Links, like hooks and commands, can have changer values attached to the left.`,
br: ``, // Display nothing,
url: ``,
variable: `This is a <b>story-wide variable</b>. After this has been set to a data value, it can be used anywhere else in the story. Use these to store data values related to your story's game state, or changers that are commonly used.`,
......@@ -152,7 +152,7 @@
const rt = defs.returnType.toLowerCase();
return `This is a <b>call to the \`(${defs.name}:)\` macro</b>. ${
rt === "instant" || rt === "command" ? `It produces a <span class="cm-harlowe-3-macroName-command">command</span>, so it should appear in passage code without being connected to a hook.` :
rt === "changer" ? `It produces a <span class="cm-harlowe-3-macroName-changer">changer</span>, which can be placed in front of a hook, or combined with other changers.` :
rt === "changer" ? `It produces a <span class="cm-harlowe-3-macroName-changer">changer</span>, which can be placed to the left of a hook or a command (passage links are commands), or combined with other changers.` :
rt === "any" || rt === "string" ? "" :
`Since it produces a <span class="cm-harlowe-3-macroName-${rt}">${rt}</span>, it should be nested inside another macro call that can use ${rt} (or any) data.`
}<code class='harlowe-3-tooltipMacroSignature'>${
......@@ -163,7 +163,17 @@
defs.abstract
}</div>`;
},
text: ({text}, path) => {
text: ({changerAttachment, text}, path) => {
if (changerAttachment) {
if (text.trim() === "+") {
return `If the code to the left and right of this <b>+ sign</b> produces two <span class="cm-harlowe-3-macroName-changer">changer</span> values,`
+ ` then they will be added together (even though this text is outside of a macro call), removing the + sign and the surrounding whitespace.<br><br>`
+ `Note that there needs to be a hook or a command after the rightmost changer, so that the combined changer can attach to it.`;
}
return `If the code on the left produces a <span class="cm-harlowe-3-macroName-changer">changer</span>, and the code on the right is a hook or a <span class="cm-harlowe-3-macroName-command">command</span>`
+ ` (passage links are commands), then the changer will <b>attach</b> to the right, applying its changes and removing this whitespace.<br><br>`
+ `You can place any amount of whitespace, including newlines, between a changer and the hook or command it's attached to.`;
}
if (text.trim()) {
const insideMacro = path.reduce((a,t) =>
a === undefined ? t.type === "macro" ? true : t.type === "hook" ? false : a : a,
......
......@@ -15,7 +15,8 @@ const {min} = Math,
typeColours = require('../js/utils/typecolours'),
toolbarStyles = (execSync('sass ./scripts/toolbar.css --scss --style compressed') + '').replace(/\ufeff/,''),
animations = (execSync('sass ./scss/animations.scss --scss --style compressed') + '').replace(/\ufeff/,'');
animations = (execSync('sass ./scss/animations.scss --scss --style compressed') + '').replace(/\ufeff/,''),
changerAttachmentColour = typeColours.changer.replace('color:','').replace('1.0','0.5');
const versionClass = 'cm-harlowe-3-';
/*
......@@ -78,7 +79,16 @@ const outputFile = {
"^=macro ":
"font-weight:bold;" + typeColours.macro,
comma: typeColours.macro,
"comma, spread": typeColours.macro,
addition:
typeColours.any,
"subtraction, multiplication, division":
typeColours.number,
"is, and, or, not, isNot, contains, doesNotContain, isIn, isA, isNotA, isNotIn, matches, doesNotMatch":
typeColours.boolean,
"bold, strong":
"font-weight:bold;",
......@@ -92,6 +102,9 @@ const outputFile = {
"strike":
"text-decoration: line-through;",
"changerAttachment.text":
"text-decoration: line-through dashed " + changerAttachmentColour + ";" + typeColours.changer,
"verbatim":
"background-color: hsla(0,0%,50%,0.1);",
......
......@@ -201,7 +201,8 @@
border:1px solid hsla(0,0%,50%,0.5);
display:inline-block;
}
.harlowe-3-hideCode ~ * .cm-harlowe-3-root:not(.cm-harlowe-3-text):not(.cm-harlowe-3-string) {
.harlowe-3-hideCode ~ * .cm-harlowe-3-root:not(.cm-harlowe-3-text):not(.cm-harlowe-3-string),
.harlowe-3-hideCode ~ * .cm-harlowe-3-changerAttachment {
opacity:0.25;
}
.harlowe-3-tooltip {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment