Skip to content

Commit 56dffb2

Browse files
committed
Various fixes related to multiline text
1 parent 31a4d55 commit 56dffb2

File tree

6 files changed

+67
-9
lines changed

6 files changed

+67
-9
lines changed

README.md

+26
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Loreline is an open-source scripting language for writing interactive fictions.
44

5+
![Screenshot of the Loreline extension for VSCode](/vscode-screenshot.png)
6+
57
Here's a most basic example of Loreline script:
68

79
```lor
@@ -379,3 +381,27 @@ Loreline.play(
379381
```
380382

381383
You can also take a look at [Cli.hx](/cli/loreline/Cli.hx) source code as another reference using Loreline.
384+
385+
## License
386+
387+
MIT License
388+
389+
Copyright (c) 2025 Jérémy Faivre
390+
391+
Permission is hereby granted, free of charge, to any person obtaining a copy
392+
of this software and associated documentation files (the "Software"), to deal
393+
in the Software without restriction, including without limitation the rights
394+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
395+
copies of the Software, and to permit persons to whom the Software is
396+
furnished to do so, subject to the following conditions:
397+
398+
The above copyright notice and this permission notice shall be included in all
399+
copies or substantial portions of the Software.
400+
401+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
402+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
403+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
404+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
405+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
406+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
407+
SOFTWARE.

run.n

-47.9 KB
Binary file not shown.

src/loreline/Interpreter.hx

+8-1
Original file line numberDiff line numberDiff line change
@@ -2295,16 +2295,23 @@ class InterpreterOptions {
22952295
var offset = 0;
22962296

22972297
var keepWhitespace = (str.quotes != Unquoted);
2298+
var keepIndents = (str.quotes != Unquoted);
2299+
var keepComments = (str.quotes != Unquoted);
22982300

22992301
for (i in 0...str.parts.length) {
23002302
final part = str.parts[i];
23012303

23022304
switch (part.partType) {
23032305
case Raw(text):
23042306
if (!keepWhitespace) {
2305-
text = stripStringIndent(text);
2307+
text = text.ltrim();
2308+
}
2309+
if (!keepComments) {
23062310
text = stripStringComments(text);
23072311
}
2312+
if (!keepIndents) {
2313+
text = stripStringIndent(text);
2314+
}
23082315
final len = text.uLength();
23092316
if (len > 0) keepWhitespace = true;
23102317
var prevIsDollar:Bool = false;

src/loreline/Lexer.hx

+8-1
Original file line numberDiff line numberDiff line change
@@ -2446,17 +2446,24 @@ class Token {
24462446
// Only valid if the indentation is identical
24472447
final followingText = tryReadUnquotedString();
24482448
if (followingText != null) {
2449+
final between = input.uSubstring(savedPos - rtrimmedOffset, afterWhitespaceAndCommentsPos);
24492450
switch followingText.type {
24502451
case LString(_, s_, attachments_):
24512452
if (attachments_ != null) {
24522453
for (attachment in attachments_) {
24532454
attachments.push(attachment);
24542455
}
24552456
}
2456-
content += input.uSubstring(savedPos - rtrimmedOffset, afterWhitespaceAndCommentsPos);
2457+
content += between;
24572458
content += s_;
24582459
case _:
24592460
}
2461+
rtrimmedOffset = 0;
2462+
var n = pos - 1;
2463+
while (n >= 0 && input.uCharCodeAt(n) == " ".code || input.uCharCodeAt(n) == "\t".code) {
2464+
rtrimmedOffset++;
2465+
n--;
2466+
}
24602467
}
24612468
else {
24622469
line = savedLine;

src/loreline/cli/Cli.hx

+9-1
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ class Cli {
260260

261261
if (character != null) {
262262

263+
final multiline = text.contains("\n");
264+
263265
character = interpreter.getCharacterField(character, 'name') ?? character;
264266

265267
var tagItems = [];
@@ -270,7 +272,13 @@ class Cli {
270272
}
271273
var tagItemsText = "";
272274
if (tagItems.length > 0) {
273-
tagItemsText = tagItems.join("") + " ";
275+
tagItemsText = tagItems.join("");
276+
if (!multiline) {
277+
tagItemsText += " ";
278+
}
279+
}
280+
if (multiline) {
281+
text = "\n " + text.replace("\n", "\n ").rtrim();
274282
}
275283
type(
276284
" " + (character + ":").cyan().bold() + " " + tagItemsText + text.green()

src/loreline/lsp/Server.hx

+16-6
Original file line numberDiff line numberDiff line change
@@ -1238,13 +1238,23 @@ class Server {
12381238

12391239
function makeRawTextHover(cursorLorelinePos:loreline.Position, title:String, description:Array<String>, content:String, part:NStringPart, ?pos:loreline.Position):Hover {
12401240

1241+
var spaceOffset = 0;
1242+
if (pos == null) {
1243+
pos = part.pos;
1244+
}
1245+
else {
1246+
spaceOffset = pos.offset - part.pos.offset;
1247+
}
1248+
12411249
switch part.partType {
12421250
case Raw(text):
1243-
final offset = cursorLorelinePos.offset - part.pos.offset;
1251+
final offset = cursorLorelinePos.offset - pos.offset;
1252+
var first = true;
12441253
for (sub in extractTextSectionsExcludingComments(text)) {
1245-
if (offset >= sub.offset && offset < sub.offset + sub.length) {
1246-
return makeHover(title, description, content, part, part.pos.withOffset(content, sub.offset, sub.length));
1254+
if (offset >= sub.offset && offset < sub.offset + sub.length - (first ? spaceOffset : 0)) {
1255+
return makeHover(title, description, content, part, pos.withOffset(content, sub.offset - (first ? 0 : spaceOffset), sub.length - (first ? spaceOffset : 0)));
12471256
}
1257+
first = false;
12481258
}
12491259
return null;
12501260
case _:
@@ -1444,23 +1454,23 @@ class Server {
14441454
if (literal.parts.length == 1) {
14451455
switch literal.parts[0].partType {
14461456
case Raw(text):
1447-
return makeRawTextHover(lorelinePos, hoverTitle('Text'), hoverDescriptionForNode(literal.parts[0]), content, stringPart, stringPart.pos.withOffset(content, -1, stringPart.pos.length + 2));
1457+
return makeHover(hoverTitle('Text'), hoverDescriptionForNode(literal.parts[0]), content, stringPart, stringPart.pos.withOffset(content, -1, stringPart.pos.length + 2));
14481458
case Expr(expr):
14491459
case Tag(closing, expr):
14501460
}
14511461
}
14521462
else if (partIndex == 0) {
14531463
switch literal.parts[0].partType {
14541464
case Raw(text):
1455-
return makeRawTextHover(lorelinePos, hoverTitle('Text'), hoverDescriptionForNode(literal.parts[0]), content, stringPart, stringPart.pos.withOffset(content, -1, stringPart.pos.length + 1));
1465+
return makeHover(hoverTitle('Text'), hoverDescriptionForNode(literal.parts[0]), content, stringPart, stringPart.pos.withOffset(content, -1, stringPart.pos.length + 1));
14561466
case Expr(expr):
14571467
case Tag(closing, expr):
14581468
}
14591469
}
14601470
else if (partIndex == literal.parts.length - 1) {
14611471
switch literal.parts[literal.parts.length - 1].partType {
14621472
case Raw(text):
1463-
return makeRawTextHover(lorelinePos, hoverTitle('Text'), hoverDescriptionForNode(literal.parts[literal.parts.length - 1]), content, stringPart, stringPart.pos.withOffset(content, 0, stringPart.pos.length + 1));
1473+
return makeHover(hoverTitle('Text'), hoverDescriptionForNode(literal.parts[literal.parts.length - 1]), content, stringPart, stringPart.pos.withOffset(content, 0, stringPart.pos.length + 1));
14641474
case Expr(expr):
14651475
case Tag(closing, expr):
14661476
}

0 commit comments

Comments
 (0)