GithubHelp home page GithubHelp logo

cyrusfirheir / twee3-language-tools Goto Github PK

View Code? Open in Web Editor NEW
42.0 8.0 12.0 3.21 MB

[ VSCode extension ] Syntax highlighting and programmatic language tools for Twee 3, and Twine 2 storyformats.

Home Page: https://marketplace.visualstudio.com/items?itemName=cyrusfirheir.twee3-language-tools

License: MIT License

TypeScript 71.36% JavaScript 0.65% HTML 0.34% Vue 27.65%
twee twee3 vscode language-extension grammar harlowe sugarcube twine syntax-highlighting diagnostics

twee3-language-tools's Introduction

Twee 3 Language Tools

Syntax highlighting for HTML and select storyformats (see Features) on top of Twee 3 code.

Made possible feedback from the folks over at the Twine Games Discord Server and through contributions from:

Made with contrib.rocks.


Requirements

The extension relies on a workspace (or a folder) being open. If single files are to be edited, the storyformat must be configured manually.

Supported file extensions:

  • .tw
  • .twee

To set the correct storyformat for the files, a StoryData passage with the storyformat (and version) (see example below) mentioned in it is preferred. If not, the extension provides the option to set the format explictly.)

:: StoryData
{
	"ifid": "<ifid here>",
	"format": "<story format here, i.e. 'SugarCube'>",
	"format-version": "<story format version here, i.e. '2.35.0'>"
}

Features

Twee

  • Syntax highlighting.

  • Snippet to generate the StoryData special passage: start typing StoryData in a Twee document and press Tab when prompted with the snippet. This populates the IFID field with a newly generated one.

  • Command palette tool to generate IFID: open the command palette (Ctrl/Cmd + Shift + P or F1 by default) and search for "IFID".

  • A list of passages for quick jumps (can be grouped by files, folders, or passage tags.) Open from the Twee 3 Language Tools tab on the activity bar (the forking paths logo.)

    Passage List

  • Workspace statistics Status bar item (WIP).

    • Total passage count (includes Story passages, Special passages, and Script/Stylesheet-tagged passages)
    • Story passage count
  • A story-map view that opens inside VSCode (and optionally, in the browser)! Still in early stages. Also accessible from the Twee 3 Language Tools tab on the activity bar.

    • Currently implemented features:

      • Snap to grid (button on top-left.)
      • Arrows to linked passages.
      • Passage position, size, and tags can be edited via a sidebar. Changes are not currently autosaved, and a manual save button is present.
      • Multi-select, and thereby mass editing of position, size, and tags.
      • Ability to move passages across files.
    • Usage:

      • Use the middle-mouse button, or hold down Shift while dragging the mouse to pan the map grid.
      • Scroll the mousewheel or stretch/pinch on trackpad to zoom in/out.
      • Hold Ctrl/Cmd while selecting to add new passages to selection, or remove already added passages from it.

    Story Map

SugarCube

(id: sugarcube-2)

Chapbook

(id: chapbook-1)

  • Syntax highlighting.
    Chapbook syntax

Harlowe

(id: harlowe-3)

  • Syntax highlighting.
    Harlowe syntax

twee-config

Custom Macro definitions for SugarCube

The extension adds diagnostics for erroneous usage of macros in TwineScript for the sugarcube-2 storyformat. By default, only the definitions for the core SugarCube library are present, but custom definitions can be added. The process is as follows:

  1. Add a *.twee-config.yaml (or .yml) OR *.twee-config.json (* represents any valid file name) file to your project folder (or anywhere in the workspace.)
  2. Define custom macros as follows:
    • If using *.twee-config.yaml (indentation is important for YAML files):
       sugarcube-2:
      
         macros:
      
           customMacroName:
             container: true
      
           anotherOne: {}
    • If using *.twee-config.json:
       {
       	"sugarcube-2": {
       		"macros": {
       			"customMacroName": {
       				"container": true
       			},
       			"anotherOne": {}
       		}
       	}
       }

The following properties are currently programmed, even though not all of them are used as of now:

  • name (string) optional: Name of the macro (currently unused in code; the name of the object suffices for now.)
  • description (string) optional: Description of macro. Shown on hover. Supports markdown.
  • container (boolean) optional: If the macro is a container (i.e. requires a closing tag) or not. false by default.
  • selfClose (boolean) optional: If the macro is a self-closable. Requires macro to be a container first. false by default.
  • children (string|child-definition array) optional: If the macro has children, specify their names as an array (currently unused in code.) You still need to define the child macros as their own macro definitions.
  • parents (string array) optional: If the macro is a child macro, specify the names of its parents as an array (currently unused in code.)
  • deprecated (boolean) optional: If the macro is deprecated or not. false by default.
  • deprecatedSuggestions (string array) optional: If the macro is deprecated, specify any alternatives to the macro as an array.
  • parameters (object) optional: Allows for macro argument validation. Read here for more information.
  • decoration (object) optional: Allows for declaring decorations to be displayed on that macro. Uses DecorationRenderOptions' fields. Requires definedMacroDecorations setting to be enabled.

The fields description and parameters allow substituting globally defined values in. Read here for more information.

NOTE: Multiple twee-config files can be present in a workspace. They will stack and add to the macro definitions for the workspace. The recommended strategy is to make separate files for separate macro sets/libraries, e.g. (the following file can also be used as an example):

  • click-to-proceed.twee-config.yaml (Link)

Experimental Stuff

Passage Auto-packer

Uses a simple packing algorithm to space out passages into clusters based on the file they originate from.

To use, search for Pack passages to clusters from the command palette (Ctrl/Cmd + Shift + P or F1 by default).


SugarCube-2: Add All Unrecognized Macros to Definition File

Adds every unrecognized macro to the definition file, instead of doing it one by one.

To use, search for Unrecognized Macros from the command palette (Ctrl/Cmd + Shift + P or F1 by default).

However, it is still recommended to add definitions one at a time.


SugarCube-2: Self-closing macros

NOTE: SugarCube 2 does NOT have a self-closing syntax for container macros, this feature is just to support custom passage processing functions.

Example of such a function which replaces self-closed instances with the actual closing macro tag (i.e. <<macro />> with <<macro>><</macro>>):

Config.passages.onProcess = function(p) {
	const macroNamePattern = `[A-Za-z][\\w-]*|[=-]`;

	const selfCloseMacroRegex = new RegExp(`<<(${macroNamePattern})((?:\\s*)(?:(?:/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/)|(?://.*\\n)|(?:\`(?:\\\\.|[^\`\\\\])*\`)|(?:"(?:\\\\.|[^"\\\\])*")|(?:'(?:\\\\.|[^'\\\\])*')|(?:\\[(?:[<>]?[Ii][Mm][Gg])?\\[[^\\r\\n]*?\\]\\]+)|[^>]|(?:>(?!>)))*?)\\/>>`, 'gm');

	return p.text.replace(selfCloseMacroRegex, "<<$1$2>><</$1>>");
};

The twee3LanguageTools.experimental.sugarcube-2.selfClosingMacros.enable setting enables detection of self-closed macros.


Known issues

Argument validation is still a work in progress. Passage name validation, especially. Shouldn't hinder workflow, however.


Changelog

Changelog here.


twee3-language-tools's People

Contributors

ardigame avatar cyrusfirheir avatar joeyrsp avatar justnoon avatar leahiel avatar minusgix avatar togashikokujin avatar tranberry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twee3-language-tools's Issues

feature for Group: Folder

for now we already have group sorting by File, None and Tag

could you please add group sorting for Folder ? so i can see the passage name and passage tags more easily. thx before

parameter type of `any`

Right now a parameter has to have a distinct type, but I have a case where I have a macro that takes any for one parameter, does internal type checking, and then hands off to my backend. Having an any, that twee3-language-tools simply ignores so long as it is set would be very useful.

Weird error when making a textbox with sugarcube 2 in a .twee file

not quite sure what this is but figured I should post it here if not intentional.
so I am trying to port my game over to use Tweego and this extension is helping out a lot but after moving something over that had a macro to make a textbox VS code threw this error
the text box code ---> Your Name: <<textbox "$name" "" [[GuruIntroduction]]>>
the error it throws ---> Expected literal ('autofocus'), but found: sc2-ex(109)

it is of note that this does in fact work just fine in the twine editor

Does not allow you to add or remove passages in the visual story map editor

The ability to add new passages does not seem possible. I am "selecting while holding control" and it does nothing. I've also attempted to use Ctrl + FN to see if that is needed, and FN, Alt, Shift, but none of those do anything.

Nothing I do actually adds any passages on that map screen, and the same applies to removing them. This makes it impractical to use the tool at all, as being unable to write more passages in kinda defeats the purpose.

Variable Validation (for SugarCube)

It would be nice to let users who want extra validity checking to specify valid variables and their types.
This issue is more of me spilling out ideas, since this is a bit complex and would require adding a good bit of code to handle this properly.

Valid Variables

Simply specifying the name of valid variables was in part the goal of #61. In the simple case of just saying what variable names are valid, it is less complex but still runs into issues.

Parsing all uses of variables, just in the Twee files, is probably not possible.

Supporting this for normal macros which use the argument parsing isn't too hard. The arguments parsing provides the information of whether it is a variable or not pretty easily, and that can be checked even in cases where we are unsure about their parameter types. We would simply check if it was in the valid variable list, and warn if it wasn't. Setup/Settings offers some challenges here, but not too rough.
The main issue comes from more complex macros. This being the ones that are really useful to check, that being macros like <<set>> and <<if>>. There's a few others as well.
The issue with these is that they can essentially be arbitrary TwineScript (JavaScript with some modifications like to being equivalent to =).
Yet, I think it is still feasible to provide useful information for those, even if we do not want to embed a full on Javascript parser (though that is feasible, since these aren't that complex of codes in the blocks, and so aren't awful to parse, but I would want some more aggressive caching. It would also be complex to use.).
The common cases, of course, are <<set $name to 42>>, <<set $name to "text">>, <<set $name to $thing>>, <<set $name to $thing and $thing2>>, etc. We could probably get a useful portion of the way there just with handling cases like these. Nontrivial, yes, but we are primarily just trying to extract variable names ($thing, _thing, setup.Thing, settings.Thing) from it, and that is easier than general parsing.
Infact, it would probably be possible to capture a lot of it with a regex. It would probably be more open to false positives, but it might be good enough, without being super complex.

Types

Having a list of types in variables is useful, especially in avoiding typos, but it could be made better.
Obviously, with types.
Currently, parameter parsing has the big hole in it that it can't verify the types of variables. <<textbox $name>> can't tell whether $name is a variable holding a receiver, or perhaps the user intended to write "$name". This is an issue anywhere. <<goto $thing>> does not have any sense of whether $thing is remotely applicable. Perhaps the user meant to use <<goto $thing_passage>>, because they're related?
Basic type declarations could help this a lot. Ex:

variables:
    $name: receiver
    $thing: string
    $thing_passage: passage

So the types are simply declared.
There is some ambiguity, however.
string could be a valid passage name, but also not. I'd rule on you having to specify the more concrete passage type in order to use it.
However, this also likely needs more and different types than the parameter parsing receives. unknown should be a type here (probably not any since that might become special in parameter parsing), which acts like variables do now where the type could be anything.
This would likely have the issue of wanting to assure T3LT that the variable in that position is right, even if the types disagree. That would require a comment on it.
It might also be beneficial to allow declaration of it holding multiple types, but I'm unsure of the best way to handle that. It would essentially have to be saying that it could be used anywhere that requires one of those types. Because we aren't Typescript, so we can't simply add syntax that narrows the type down, and comments are probably pretty bad for that.

Extra (Per Passage Validation)

We might also want per-passage validation.
The obvious use-case is for temporary variables. Declaring them as valid everywhere would be.. unfortunate.
Being able to declare where they can be used would be better. Not as good as actually noticing that the user calls <<set _tmp to random(0, 100)>> and only allowing it to be used after that line in the passage, but better than nothing.
Especially since the user might reuse temporary variables with different types (aka _tmp).
This would also be extended to normal variables. It would probably be less useful than the tmp variables, but would be more useful than the normal variables.

Usability

We want this to be nice for the user. Writing a passage and having to swap back to your config file to specify the types is a pain. There would of course be a Quick-Fix for adding unknown variables to it quickly, which would help.
The problem, however, is that they would be unknown. This might be fine for writing it out, but the point of types is to encourage the users that enable it to get good error-checking.
There's four non-exclusive options that can be taken (I think all of them would be good, but one is better than none):

  • Separate quick-fix option that lets you specify the type in a vscode dialog (like the dropdown-from-the-top style dialog).
  • Basic inference. It could scan the current passage for usages and acts of setting the variable. If it sees <<set $name to "blah">> then it can likely infer that it is a string. This would be more a collection of rules to infer things, which could be expanded. It would probably be beneficial to also have more error-prone ones toggleable in settings, since fixing the type isn't that hard.
  • A setting to warn on any usage of a variable with an unknown type. This might be somewhat noisy without the other features.
  • A setting to warn in the config file of an unknown type. This keeps that warning alive, but more out of the way. The issue with this is that I don't think we currently get a span from the yaml/json parsing. So we'd either have to get a better parsing library for that, or just put them at the top of the file.

In Passage Validation

This is either an extension of the passage specific validation, or an alternative.
It would probably be nicer, at least for temporary variables, to specify the type in the passage at which they're declared. Unless you're using the same temp variable name across multiple passages with the same type (which does happen, and should be done if you're not wanting that data to be saved!), the temp is pretty much for the single passage.
The idea is to essentially have a special comment that declares the type of the temp variable.

/* t3lt-var-type: _rng: number */
<<set _rng = random(0, 100)>>

This would scope that to this single passage.
As an extra potential that makes this an attractive option to implement is that it would allow erroring if the variable was used before/after a certain point, since we're told where it is created.

/* an error */
<<if _rng == 0>>

<</if>>
/* t3lt-var-type: _rng: number */
<<set _rng = random(0, 100)>>

Theoretically this also allows checking actual scopes and flow based on that:

<<if $some_condition>>
  /* t3lt-var-type: _thing: number */
  <<set _thing = 5>>
<</if>>
/* an error, because it isn't defined in all branches */
You have _thing things.

However, that is notably more complex, and so it out of scope for this document.

Usability (TypeScript)

Some users use Typescript with SugarCube. If so, they likely have something like this (at least for variables they want to access in code):

declare module "twine-sugarcube" {
    export interface SugarCubeStoryVariables {
        name: string;
        lname: string;
        age: number;
        hair_color: HairColor;
    }
}

It is unfortunate to force the user to redeclare the same variables in another file. This isn't major but it does increase friction.
Sadly, I don't think there's a good way for our extension to ask the inbuilt Typescript extension about what types it has modified. If there is, it becomes a possibility to actually automatically use those definitions.

Nonexistent Passage warning Quickfix

It would be nice to use some existing simple text similarity algorithm to make so if the user types an incorrect passage, we can provide an option to correct it to what they probably meant.
Ex: User writes <<goto "island">> when what they meant was to use their passage named "Island". This case is simple case insensitive checking and would be easier to implement.
But typos are also common, so I think a text similarity library should be used to provide the best results. Possibly allow multiple results, if possible, though I'd limit it to like three or so.
This would make using it better, since then they don't have to scan for where in the name they made the error, and just use ctrl + . and correct it.
This would probably be unique to sugarcube-2, but it would be nice to make it generic enough to work for Harlowe and other formats if we ever properly add passage validity checking to them.

Passage File Splitter

A function to split a single .tw(ee) file with multiple passages into separate files, each with their own passage.

I realize there's a few things that need to be done before this is possible, specifically #38. I'm just putting it here as a todo. Might tackle this myself at some point.

Variable-receiver type for better verification

There are several macros which use the receiver pattern, where it simple takes the name of a variable that it should store/read the value from, such as textbox. Currently these are just accepted as text, but a custom type would allow for greater verification.
If there was a custom type, perhaps textvar or receiver or some other name, then that would allow checking when a string literal is written (which is quite common) to see if it is a good variable name.
Ex: <<textbox "name">> is invalid (at least for textbox, this results in a runtime error of it lacking a sigil), but since it is written into the macro, it would be possible to check the value for it and provide a warning/error.
This obviously would not be possible in all cases, but would still be useful.

Bug: There is no error/warning if you use two <<else>>'s in the same <<if>> statement

It's nice how the if statement goes red if you are missing a closing tag. I just noticed this doesn't happen if you use more than one <<else>>' in the same <<if>> statement. If you render such an if statement at runtime, it gives this error:

Error: <<if>>: <<else>> must be the final clause

It would be nice if the first else had a red underline with a tooltip with the same message.

Example code with the problem:

          <<if conditional>>
            ...
          <<else>>
          <<else>>
            ...
          <</if>>

Collapsible passages

This is a clone of the issue over here: MxAshUp/vscode-twee2-syntax#7

In summary, it would be nice to have passages detected as folding regions so they can be collapsed. This cannot be solved with the folding regions option in a grammar file, but instead needs to be implemented in the language server.

Let passage titles appear in Outline

This is a duplication of an issue from the extension I've been managing over here: MxAshUp/vscode-twee2-syntax#8

Considering the amount of effort already put into this extension, it may be simpler to implement this feature here instead!

For reference, the outline is located beneath the file explorer and look like this currently with twee extension enabled:
Screenshot from 2020-08-17 14-00-09

This functionality has already been implemented with the passage list feature. Would there be any benefit to having this in the outline instead, or in addition to?

As far as I understand the outline pane, symbols would need to be described in the language server for passage titles, and these would be recognized for the outline hierarchy.

Restrict usage of macros to specific passages / files

There is a pattern where utility macros are defined for common things that are performed in a certain area of the game, but aren't intended to ever be used elsewhere.
It would be useful to provide a way for macros to specify that they can only be used inside specific passages or specific files, with the extension warning if it is used outside those.
A quick fix could be provided to autoadd that passage/file to the list.
This would help guard against misusing those macros elsewhere.

[SugarCube 2] Apostrophes trigger string highlighting in <<actions>>

Sorry for the false alarm yesterday, but this time I have an actual issue 😛

When two apostrophes appear within <<actions>> links, the text within is highlighted as a string even though SugarCube doesn't treat them that way.

This occurs both when the apostrophes are in the same link:
image

Or in separate links:
image

Verify setup variables

It would be useful to let the user specify the names of their setup variables to allow checking them for validity. It isn't uncommon for the access to be written out specifically and so it can be checked against the list to avoid typos.
I believe setup is already parsed as some form of variable access and so checking for if it has a literal-word after the dot access should be relatively easy.
This could presumably be enabled by default if it also comes with a feature to easily add the setup definition to the twee-config file.

Go to Definition for Macros that are Widgets

It would be entirely possible to recognize the definitions for macros in widget tagged passages, so then one can use the typical F12 / 'Go to Definition' commands to, well, go to where they're defined.
It would probably be a relatively simple matter of checking (perhaps in updateDiagnostics? or add a function that is called in many of the same times?) if the macro is the <<widget>> macro, getting the name of it, checking if that is in the definitions, and adding that as a runtime-computed field to the macroDef. It might need to be copied over when the macro file is re-read.

Word count

From the discord.

Since you're parsing macro code anyway, you could probably remove that and passage headings and get a decent count.

Start rocket incorrectly assigned

Dear Cycy,

Recently I scrolled through my list of passage, only to find out the start rocket was placed on the wrong passage.

Example:
:: StoryData {} { "ifid": "#", "format": "SugarCube", "format-version": "2.34.1", "start": "SplashScreen", }

image

Expected behavior where the rocket should be:
image

I have no fix for this, so that's why I opened an issue, I am thinking it might have to do with the fact the passage is named "Start", but later converted to "Splashscreen" as the true starting passage.

  • Redsea

Ask if user wants to add all unknown macros

When opening a normal Twine project without definitions (such as extracting their own with TweeGo so they can use the files), they may see many warnings about unknown macros. We have a quick-fix option on each macro which can fix this, but is obviously rather slow when you have many.
That said, there is also a command (Ctrl + P -> Add All Unrecognized Macros to Definition File) which adds them all. This is useful, but is obscure, especially for new users.
It would be a good idea for if there approximately >5 (or more?) macros that are unrecognized at once, that it asks the user if they want to add all of them to the definition file. This perhaps should only occur on startup and when the user adds files to the workspace (aka because they extracted their project in the the current folder in vscode's terminal).

Add Warning for Widgets in Passages

A macro like widget can only be used (properly) within a passage with a specific tag, that of [widget], and so giving an warning if it is used outside of it would be a good idea. Doing this is probably not too hard, just an extra check when processing the macros.

Exit Checking

It would be useful to check if all paths in a passage left to another passage. This would help avoid issues of soft-locks.
The issue with this is that it requires some conception of macros which leave, and control flow.
Adding info about macros that leave the current scene is easy, simply adding a field to their definition like "leaves": true or perhaps "toPassage": true. There could even be information that it leaves to a specific passage, or reference a parameter, which would potentially allow for multipassage exit analysis (ensuring you don't have an unexpected infinite loop), but that won't be covered too much here.
The main issue is really control flow. Currently we don't really have any mechanisms to follow or declare control flow, since everything is technically just a macro.
However, I believe that it is representable to some degree in the config declaration syntax.

"if": {
		"name": "if",
		"children": [
			"else",
			"elseif"
		],
                "becomes": ["if", "else", "elseif"],
		"container": true,
		"description": "..",
		"skipArgs": true
	},

could maybe work... it is rather rough, though. This would essentially declare that it becomes the content within one of those nodes, where it is unknown. The parsing is probably common enough for this to be fine.
This would then allow us to 'simply' check inside of the if's branches for if there is a call to a passage-exiting macro, such as <<goto>>.
This would be simpler for macros like linkreplace, which can only become one thing. I would likely have it use something like "becomes": "payload", so that there's an obvious distinction between the weird submacro's referring to if and referring to the entirety of its content.
It then simply does the checks inside of that macro.

There would of course need to be a comment which signifies that it exits, because we cannot detect every scenario. Ex: <<run blah()>> which calls Engine.play("Hi");.

It may also be good to make so that the 'does leave passage' properties can also have a value other than true and false. Let's go with "maybe", for now. This would allow representing things like a custom macro which only sometimes goes to another passage, like <<ifgoto $condition "CoolPassage">>. This wouldn't be perfect, but it would further enhance the checking.

There is another issue in whether this should be enabled by default. The ideas detailed above will likely cause warnings on current existing projects that are just fine. Such as if they simply call a function that transitions away. Thus, perhaps leaving it off by default would be for the best. Theoretically, there is a minimal subset that can assure itself that it will always be correct in its warnings, but that requires not having any arbitrary twinescript (expressions, set, run, etc.), no custom macros (well, widgets might be fine), and probably some other minor ones that just make it probably not worth the effort of implementing for that warning.
Another point in favor of not having it on by default is that it might be annoying seeing the warning while in the middle of writing the passage.

Slow typing in large file in large project

Hi, when I use this extension to help me with writing it shows significant slowdowns when typing in a large file. The file is approximately 1000 lines long, but the slowdown occurs at a couple hundred lines too. This happens specifically in a very large project, with about 7700 passages. When all the passages are loaded, the performance is horrible, but when the passages are still loading and only about 100 are loaded, the performance is great. Therefore I think it has something to do with the amount of loaded passages. Is there anything that can be done about this?

I use Linux kernel 5.15.13-arch1-1 using Arch Linux.
I run KDE Plasma 5.23.5 on X11 (not sure if that's important at all).
I run VSCode version 1.63.2 from the visual-studio-code-bin package from the AUR.
This is happening on a Lenovo ThinkPad L15 G2 AMD, which has a Ryzen 7 Pro 5850U and 16GB of RAM.

I don't know what more information to provide right now. Do not hesitate to ask me for any more information. Thanks for developing this awesome project!

Let the user supply a list of valid templates for error-checking

SugarCube-2 Templates aren't that common, but they are common enough for some verification of valid templates to be useful.
I think this could/should work like macros. Unrecognized templates have a warning, and have a quick-action to add them to the configuration file. Though, this may have some false-positives, if having ?He without a template named He just writes ?He to the output rather than erroring (which I imagine it does for backwards compatibility, but I haven't checked).
The main issue for this feature is really just parsing and collecting them from the file. Need to find where they can be used, and so on.

Bug regarding "Argument is not text"

Hello, there is some bug regarding "Argument is not text". I have a listbox with an option and that option value is "undefined"(without the quotes) but it says that the argument is not a text, this doesn't happen if you put null instead of undefined.

Code example:

<<listbox "$selectedrecipe" autoselect>>
     <<option "Select a recipe" undefined>>
     <<optionsfrom $learnedrecipes>>
<</listbox>>

Extension forces space after `::` in passage title

While this maybe a better code style, it's just a stylistic choice, and it would be great to have the ability to customize this behavior in extenson options. Especially since the extension doesn't fix this automatically and the users are forced to manual find/replace.

rename "Pack passages..." command with Twee3 prefix

Thanks for the great tool!

Could we rename the "Pack passages to clusters (Experimental)" command to "Twee3 Language Tools: Pack passages to clusters (Experimental)"?

That way it would be discoverable when we type "twee3" in the command palette seach.

Custom style markup proper usage

Dear Cycy,

When typing some code I added in for example: @@.lovecycy;Python is awesome!@@
Its expected output would be neon grey-colored text. Which of course works.

However if one types @@.lovecycy;Python is awesome!@
It doesn't work, because of course, it's missing the second @.

Jokes aside, will there be a possibility you add a check which looks for possible improper closed custom style markup? Since the current version doesn't check it, I have spent too much time searching for that accidental unclosed span.

Yours sincerely,
Sjoerd Hekking

Cache macroList output

The macroList function currently does not cache the files.
Since it is called by collect (which is called by SugarCube diagnostics and hover), it can be called pretty often. While not often enough to likely cause notable/visible input lag it is still reads the file and parses it quite often.
Solution: Use https://code.visualstudio.com/api/references/vscode-api#workspace.createFileSystemWatcher with the current glob for json/yaml/yml files, and keep a global variable (exported or not? I'd say no) of the last parsed result. Then macroList simple checks if it already exists. On a file edit/creation/deletion, all it has to do is perform the parsing again.

I can implement this.

Installed, but not working

I'm not sure where else to put this, but I am not seeing syntax highlighting when I am trying to use this extension. VSC shows it's installed but passage listing is turned off and I can't enable it, and the buttons in the passage listing side pane pop errors "Command 'twee3LanguageTools.passage.list' not found" and "Command 'twee3LanguageTools.storyMap.show' not found"

Sort macro definitions

Currently we simply write out the macro definitions to the config file in whatever order it decides, but it would be nice for readability to have the option (perhaps on by default) to write them out in alphabetical order.
Though, this would require using YAML/JSON libraries that allow that level of control about the iteration order.

Checking if temporary variables are defined

Since temporary variables are locally used within the same passage or <<include "passage">> it might be useful to have a sanity check whether or not the temporary variable has been set. Consider the following code:
<<set _tempVar to "python">> <<if _temp is "python">> Python is amazing! <</if>>
Of course, this wouldn't play, but since these are used locally defined, T3LT could check against whether or not it exists. Since a safety net could've helped me spend an hour less on finding why my code didn't function as expected.

Yours sincerely,
Sjoerd Hekking

SugarCube 2 parameters parsing error

I want to add a definition for a macro that takes either a single or three parameters. This exact case is covered in the wiki page (a |+ b&+ c). However, given the following definition:

NPC:
    name: NPC
    parameters:
        - string |+ string &+ string

and the code <<NPC "Captain">>, the extension complains "Expected type 'string' but there was no argumentsc2-ex(109)".

A workaround

parameters:
          - string
          - string &+ string &+ string

works fine.

Missing passages quickfix

From the Discord:

suggestion!
when someone types [[]] and only inputs a name, without | or -> or <- then create a new story .tw file with that passage if that passage does not already exists.
and if there is a | or -> or <- then wait till it's done and then create it if it didn't exist prior with the appropriate passage part :3
probably best to have it optional tho so you can turn it on/off ^^
maybe also with the option to either insert it into the same file or add a new file for it.

Why not make this one of those fancy lightbulb options?
Like how an undefined macro can be added to the config, make it so undefined passages (in link markup or elsewhere) can be added.

a Quick fix would be the besht, yus
the extension already detects missing passages
so i could allow for a quickfix which promts the user to enter a (relative) filepath to append the new passage to. Leaving blank could append to the current file... If file dun exist, shall be created
>.<

Passage Autocomplete in Macros

Currently, macros don't provide autocomplete for passage names (like link syntax does). It would be beneficial to users if we could provide that.
The sc2 arguments parsing already allows incomplete parsing, but it may need some modifications since I'm unsure if it would provide the partially typed string that the user had typed. As well, this would need to use the parameter types information to know that you are probably trying to type a passage name.
Overall, though, I think most of the pieces for this are already in the code. It would just take a bit of work to implement.

Story Map "Snap to Grid" button hover error

The Story Map's Snap to Grid button is showing element.text (On) or element.text (Off) (respectively) on hover. I'm not 100% sure what it's supposed to show, but this seems incorrect.

Large Files and Performance

Currently, with large files (such as this 30,000 line one), the extension can slow down quite a bit. Sometimes even becoming unresponsive (it became unresponsive on that file for 6 seconds, but whether that was because it finally finished or vscode stopped it, dunno).
This was without argument parsing enabled (or parameter validation), and would only be worse with those enabled.

Improving performance on large files would be useful:

  • Cache collect. If we can tell whether a file has changed since we last saw it, we don't need to redo this (but this does mean that we have to keep the data around). This would be very good for performance I believe, since it is called very often. While even large twine files are usually only on the order of megabytes rather than gigabytes, Javascript will use up a good amount of memory for data and so care might need to be taken. I think there is an inbuilt vscode feature for having a unique-id/incrementing-id to keep track of file changes which could be used.
    • But of course, just a cache on the file wouldn't be the greatest for large files if you're editing them at all. Theoretically could try tracking where edits occur (in passages within the file to make it saner and simpler to implement?) then somehow only update the collect results for the edited passage.
  • Cache argument parsing (and parameter validation once the PR is done). I already have some ideas on this which are somewhat detailed in the PR for parameter validation.

Gracefully Handling it: Important as well, since there will be inputs which we can't manage, is that of gracefully handling it.
The largest files we'll get are probably from those who want to switch their Twine project to use Twee, decompile it to a single file, then check it out. If they see lag and weirdness, they're less likely to stay with it.
I'm uncertain of the best way to do this. Time checking so if an operation takes longer than a certain amount of time it alerts the user that the file is very large? Automatic notifying the user when they open a large file that it works better in smaller files? Does vscode provide any utilities to automatically do this?

Horizontal Note: Adding support for breaking apart the passages in a Twine archive into separate files to Tweego would help with this automagically, since we'd be less likely to get really large files. Though, it is written in Golang, and while I'd be able to manage learning it, I haven't used it barely any.

Thoughts on exposing twee passages as functions?

Love having a VS code plugin!

Would it make sense to model twee passages as functions (not sure the right word for vs.code extension eco system - function or symbol or?? ).

If passages were functions you could use the outline view, find references, find unused functions, find functions that don't point to anything, etc.

Thoughts on this approach?

Quote marks are being treated as strings

Single quote marks are being highlighted as strings, in Harlowe 3.

Example:

It's not fair. I wasn't doing anything.

Will highight in blue everything between the apostraphys: s not fair. I wasn

Optional warning for usage of variable in receiver location

It is a common mistake to write a textbox like <<textbox $name "default">> where in fact, the author meant to write <<textbox "$name" "default">> so as to have the value stored in the variable $name.
Yet, this cannot simply be errored upon, because it isn't uncommon for users to do something like:

<<if $cond>>
    <<set $target = "$player_name">>
<<else>>
    <<set $target = "$npc_name">>
<</if>>
<<textbox $target "default">>

(especially in things like widgets, where you will be accepting a receiver yourself!)
But, for users where this isn't something that they want to do, it could be beneficial to be able to know that they'll avoid mistyping and using a variable directly rather than a string version of it.
Theoretically, this way of writing textbox seems to work: <<textbox '$target' "default">> (assume the single quotes are tilde, for the expression syntax), and so the warning could encourage the user to write out variables which hold references (like $target) with the expression syntax instead. Not perfect, but if it was an optional warning, then that would give an out for those who want to avoid the potential common bug while still using the feature.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.