What is vscode-ts-tex
vscode-ts-tex is a vs code plugin for ts-tex. It acts as the intermediary layer between the ts-tex language service and vscode.
ts-tex is a thin layer over the typescript compiler api that provides you with the ability to execute typescript functions out of your latex (or actually any) document and receive language services (intellisense) during writing.
PLEASE NOTE: to activate ts-tex syntax highlighting for your .{tex,latex} files, you might have to choose tex (.tex) from the list of languages on the bottom right pane in vscode or configure the file-association permanently in settings.json.
I also maintain a repository for useful ts-tex modules. If you find any of them useful, feel free to use them or you can use them as a learning resource for ts-tex.
Currently the target group for ts-tex would be developers who like to write LaTeX but are fed up with it's lack of language services and it's complex and inconsistent interface or people who like to write typesafe macros. In the long run (iff anybody uses this) there could be a lot of ts-tex modules and ts-tex could be an easier interface to learn than LaTeX.
This extension is in early developement stage so please look at section Limitations to review current issues and not supported use-cases. vscode-ts-tex can also be used together with LaTeX-Workshop to get additional language services for the normal LaTeX part of your documents.
What does vscode-ts-tex currently provide
Syntax highlighting
i.e. latex highlighting combined with typescript highlighting in your .tex documents. In order for syntax highlighting to work you have to have an extension like LaTeX-Workshop that already defines a .tex grammar. The additions are then injected into the existing grammar.
Diagnostics
Full typescript diagnostics for typescript function calls are provided in the document. ts-tex uses the typescript compiler api internally, so the diagnostics are no different from writing a normal typescript file.
Completion items
Completion items are provided on characters [."]
Signature helps
Signature helps are provided for typescript function calls.
Hovers
Hovering on a typescript function call in your tex document will evaluate the call and display it's result
Definition provider
Upon pressing F12 on typescript function calls in your document, you can jump to the file where your function is defined.
Commands
Commands can be accessed by pressing ctrl+shift+p
- tstex.build: builds your defined root file or lets you choose a file if none is configured
- tstex.rewriteApiFile: regenerates the tstex_modules/_api.ts file, can be used in case it was accidentally edited
- tstex.configureRootFile: configures the current rootFile and saves it to workspace configuration
- tstex.reload: reinitialized the ast
Updates
All .{tex,latex} file indices are updated during editing and diagnostics are updated on the fly. TS Code files (tstex_modules/**/*.ts) are currently more expensive to update, so they are only updated on save. The extension will also keep track of newly created or deleted document or code files.
Configurations
Please look at the Contributes page to find descriptions of the configuration parameters.
ts-tex Quickstart
To activate the extension open a folder in vscode and navigate to a *.{tex,latex} file. Please note that atm workspaces with multiple folders are not supported.
All *.{tex,latex} files in this directory and it's subdirectories are loaded. A special directory tstex_modules will be created (if non-existant). In it you can add .ts files, that will be transpiled and added to your scope on each save. Also a _api.ts file will be created. This file should not be edited by the user, as it specifies the api you can use to add functionality that you can access from your document.
Creating a new module
In any tstex_modules/**/*.ts file you can create a class that implements IModule defined in _api.ts. Classes that implement IModule will be instantiated and added as a property to your scope. Example:
// ./tstex_modules/mymodule.ts
import { IModule } from "./_api.ts";
export class MyModule implements IModule
{
*createTable(table: string[][])
{
//... do some stuff
yield result;
}
}
Now from your document you can access the functionality of this module by
// ./myLatexDoc.tex
\this.myModule.createTable([["asd"],
["test"]]
);
ts-tex has a custom parser that will differentiate between typescript code and non-typescript code. Just like in latex all function-calls into the typescript domain have to start with "\". Your statement will be executed in the context of a scope class, so you will have to write "this." to access functions of your scope.
To fit with javascript property naming style the property name of your module instance on your scope object wll be camel-cased if necessary. Note that only special classes that extend _api.ts interfaces such as IModule will be transpiled and instantiated. Other code such as defined functions or classes won't be transpiled or executed at any time and are therefore not callable from your document or your module code. Please look at the api for more Details.
Build
The result of your function call will be converted to string in a recursive manner and in the built document the function call will be replaced by this string. String conversion happens with these rules:
- value is array: convert all elements to string and join
- value is object: call toString() method
- value is number: convert number to string
- value is boolean: convert boolean to string
- value is string: it stays string
- value is Iterable:, i.e. the function is a generator function -> the generator is iterated over and all results are converted to string and joined
- value is Promise: currently unsupported but I will look into this in the future
Note that by default when building e.g. a file test.tstex will result in a built file .build.test.tstex file. This is due to filenames with a leading . being ignored by vscode-ts-tex's updates. This makes sense, because we don't want to add the build result to the AST as it is not a ts-tex file.
If a function call takes up more than one line in your document but the evaluation results in less lines, ts-tex will add newlines to the result until it matches the line count of the function call. This is useful when compiling your built document with LaTeX the error lines of the built document will match the lines of your document. Because of this I recommend the convention to always yield single line strings out of function calls. This makes sure that your function calls and function results in the built document and working document are always aligned!
Lifecyclehooks
When implementing IModule from your custom module class you can implement the following functions:
_init(resolver: IResolver)
: will be called on construction of your module class (everytime you change your module code and save it, your module instance will be re-instantiated). A resolver is passed to you where you can register or resolve dependencies that you might have added in other module files.
_finalize()
: will be called whenever your module will be unloaded. Note that when you change your module code and save it, this method will be called before the new module will be instantiated.
_prebuild()
: logic that will be executed before building the document
_postbuild()
: logic that will be executed after building the document
Details
For more Details on how ts-tex works and more advanced operations (e.g. extensible CompletionProvider api) please refer to ts-tex.
Error Handling
For extension output you can check the ts-tex output channel in vscode
Limitations
- Workspaces with more than one open folder are currently not supported
- Currently only linux file-endings LF are supported, no CRLF. Atm I see no reason to invest effort into implementing this support but if somebody needs it feel free to patch it yourself or text me.
- TS-Comments are not parsed atm as they are not really usefull in documents (you can comment with normal latex comments with % outside of function calls).
Known Bugs
- Due to a parse issue a ts function call starting in the very first character of a document will be ignored
Security
ts-tex runs code from your document. Currently no security concept (like vms) has been implemented. Be cautious when running 3rd party modules, as they are programs and have access to your filesystem! If I see that a lot of people use ts-tex maybe I will look into implementing a sandboxing mechanism of modules.
Disclaimer
I'm currently writing this software alone and it's in early developement stage so it will still have bugs.
Credits
The following libraries were really helpful for implementing this project