Language server for MiniScript
npm install miniscript-languageserverminiscript-languageserver is a Language Server for MiniScript that offers a variety of features, including:
miniscript-languageserver supports the following language server protocol (LSP) features:
bash
npm install -g miniscript-languageserver
`
Usage
`bash
miniscript-languageserver
`
Configuration
`ts
{
fileExtensions: string; // default: "ms"
formatter: boolean; // default: true
autocomplete: boolean; // default: true
hoverdocs: boolean; // default: true
diagnostic: boolean; // default: true
transpiler: {
beautify: {
keepParentheses: boolean; // default: true
indentation: "Tab" | "Whitespace"; // default: "Tab"
indentationSpaces: number; // default: 2
};
};
typeAnalyzer: {
strategy: "Dependency" | "Workspace"; // default: "Dependency"
exclude?: string; // default: undefined
};
}
`
Example Implementations
This section provides a collection of IDEs that implement the miniscript-languageserver.
- VSCode: Visual Studio Code setup for miniscript-languageserver.
- Sublime Text: Instructions for integrating with Sublime Text.
- IntelliJ: Guide for using miniscript-languageserver with IntelliJ.
- Neovim (nvim): Configuration for Neovim users.
- Visual Studio: Learn how to set up a Visual Studio extension using LSP to add support for the MiniScript language in Visual Studio.
Any other IDEs that follow the LSP standards should also work with miniscript-languageserver.
#### VSCode
1. Create language client file.
`ts
import * as path from 'path';
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
TransportKind
} from 'vscode-languageclient/node';
const serverModule = context.asAbsolutePath(
path.join('node_modules', 'miniscript-languageserver', 'index.js')
);
const serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc }
};
const clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'miniscript' }],
synchronize: {
fileEvents: workspace.createFileSystemWatcher('*/')
},
diagnosticCollectionName: 'miniscript'
};
const client = new LanguageClient(
'languageServerExample',
'Language Server Example',
serverOptions,
clientOptions
);
client.registerProposedFeatures();
client.start();
`
#### Sublime
1. Install the LSP Package from the Sublime Text Package Control.
2. Create the following LSP client configuration in your Sublime settings:
`json
{
"show_diagnostics_panel_on_save": 0,
"clients": {
"miniscript": {
"enabled": true,
"command": ["miniscript-languageserver", "--stdio"],
"selector": "source.miniscript"
}
},
"semantic_highlighting": true
}
`
3. Create a Sublime syntax file for miniscript. The highlighting will be provided via the semantic provider, so there's no need to add additional patterns here. Use the following configuration:
`yaml
%YAML 1.2
---
name: miniscript
file_extensions:
- src
scope: source.miniscript
contexts:
main:
- match: '.+'
scope: text.miniscript
`
#### IntelliJ
To set up miniscript-languageserver in IntelliJ, follow these steps:
1. Install miniscript-languageserver.
2. Install the LSP4IJ plugin from the JetBrains Plugin Marketplace.
3. Go to Languages & Frameworks > Language Servers.
4. Click the "+" icon to add a new language server configuration.
5. In the Name field, enter miniscript.
6. In the Command field, enter miniscript-languageserver --stdio.
7. In the Filename Patterns section:
- Set File Name Pattern to *.src.
- Set Language Id to miniscript.
8. Restart IntelliJ.
You should now have miniscript-languageserver set up and ready to use with IntelliJ.
#### nvim
1. Add the following configuration to your init.vim:
`vim
" Install vim-plug if it's not already installed
call plug#begin('~/.vim/plugged')
" Install LSP config plugin
Plug 'neovim/nvim-lspconfig'
call plug#end()
" LSP configuration for miniscript-languageserver
lua < local configs = require'lspconfig.configs'
local lspconfig = require'lspconfig'
-- Enable debug-level logging
vim.lsp.set_log_level("debug")
if not configs.miniscript then
configs.miniscript = {
default_config = {
cmd = { "miniscript-languageserver", "--stdio" },
filetypes = { "miniscript" },
root_dir = lspconfig.util.root_pattern(".git", vim.fn.getcwd()),
settings = {},
on_attach = function(client, bufnr) -- Optional on_attach function
-- Set up hover keybinding here
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', 'lua vim.lsp.buf.hover()', { noremap = true, silent = true })
end,
},
}
end
-- Register and start the miniscript LSP
lspconfig.miniscript.setup{}
EOF
autocmd BufRead,BufNewFile *.src set filetype=miniscript
`
2. Don't forget to run :PlugInstall to install the necessary plugins.
This configuration ensures that miniscript-languageserver will be properly integrated into Neovim, and that .src files will be recognized with the correct syntax highlighting and LSP features.
#### Visual Studio
1. Begin by following the official Visual Studio Extensibility Tutorial to create a new Visual Studio extension. This will set up the basic structure for the extension project.
2. In this step, we define a custom content type for the language we are adding (e.g., MiniScript). This will help Visual Studio identify files based on their extension or content type. Create a new class called ContentTypeDefinitions.cs:
`csharp
using Microsoft.VisualStudio.LanguageServer.Client;
using Microsoft.VisualStudio.Utilities;
using System.ComponentModel.Composition;
namespace MiniScript
{
internal static class MiniScriptContentDefinition
{
[Export]
[Name("miniscript")]
[BaseDefinition(CodeRemoteContentDefinition.CodeRemoteContentTypeName)]
public static ContentTypeDefinition MiniScriptContentTypeDefinition;
[Export]
[FileExtension(".ms")]
[ContentType("miniscript")]
public static FileExtensionToContentTypeDefinition MiniScriptFileExtensionDefinition;
}
}
`
3. Next, you will create the LanguageClient.cs class that connects Visual Studio to the language server. This class implements ILanguageClient, which is essential for interacting with the LSP. Create a new file called LanguageClient.cs:
`csharp
using Microsoft.VisualStudio.LanguageServer.Client;
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudio.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace MiniScript
{
[Export(typeof(ILanguageClient))]
[ContentType("miniscript")]
[RunOnContext(RunningContext.RunOnHost)]
public class MiniScriptLanguageClient : ILanguageClient
{
public event AsyncEventHandler StartAsync;
public event AsyncEventHandler StopAsync;
public object InitializationOptions => null;
public IEnumerable FilesToWatch => null;
public bool ShowNotificationOnInitializeFailed => true;
public string Name => "MiniScript Language Client";
public IEnumerable ConfigurationSections => new[] { "miniscript" };
public Task ActivateAsync(CancellationToken token)
{
var info = new ProcessStartInfo
{
FileName = @"C:\Users\myUser\AppData\Roaming\npm\miniscript-languageserver.cmd",
Arguments = "--stdio",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
var process = new Process { StartInfo = info };
if (process.Start())
{
Debug.WriteLine("Language server started successfully.");
return Task.FromResult(new Connection(process.StandardOutput.BaseStream, process.StandardInput.BaseStream));
}
Debug.WriteLine("Failed to start language server.");
return Task.FromResult(null);
}
public async Task OnLoadedAsync()
{
if (StartAsync != null)
{
await StartAsync.InvokeAsync(this, EventArgs.Empty);
}
}
public async Task StopServerAsync()
{
if (StopAsync != null)
{
await StopAsync.InvokeAsync(this, EventArgs.Empty);
}
}
public Task OnServerInitializedAsync()
{
return Task.CompletedTask;
}
public Task OnServerInitializeFailedAsync(ILanguageClientInitializationInfo initializationState)
{
string message = "MiniScript failed to activate, now we can't test LSP! :(";
string exception = initializationState.InitializationException?.ToString() ?? string.Empty;
message = $"{message}\n {exception}";
var failureContext = new InitializationFailureContext()
{
FailureMessage = message,
};
return Task.FromResult(failureContext);
}
}
}
`
4. At this point, you have a basic framework for integrating a custom language server into Visual Studio. You can customize the content type, server activation, or extend the language client.
How to Add Tooltips
Tooltips in miniscript-languageserver can help provide additional context, such as method descriptions, to users. You can contribute your own tooltips by following this workflow:
1. Fork and create a pull request (PR) with your changes to the miniscript-meta repository, where the meta descriptions are stored.
2. Once your changes are merged, create a separate PR in this repository to update the version of miniscript-languageserver to include the new meta descriptions.
Additionally, you can define method-specific tooltips directly in the code using comments. This allows for quick, tooltips for individual methods.
`js
// @type Bar
// @property {string} virtualMoo
Bar = {}
Bar.moo = ""
// Hello world
// I am bold
// @description Alternative description
// @example test("title", 123)
// @param {string} test - The title of the book.
// @param {string|number} abc - The author of the book.
// @return {Bar} - Some info about return
Bar.test = function(test, abc)
print "test"
return self
end function
// @type Foo
Foo = new Bar
// @return {Foo}
Foo.New = function(message)
result = new Foo
return result
end function
myVar = Foo.New
myVar.test // shows defined signature of Bar.test on hover
myVar.virtualMoo // shows virtual property of type string on hover
``