-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
6,885 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# TypeScript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
# parcel-bundler cache (https://parceljs.org/) | ||
.cache | ||
|
||
# next.js build output | ||
.next | ||
|
||
# nuxt.js build output | ||
.nuxt | ||
|
||
# vuepress build output | ||
.vuepress/dist | ||
|
||
# Serverless directories | ||
.serverless | ||
|
||
# output for typescript | ||
**/out | ||
|
||
# cache fodler | ||
wlServerCache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Changelog | ||
All notable changes to this project will be documented in this file. | ||
|
||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
||
## [0.1.0] - 2019-01-12 | ||
|
||
### Added | ||
|
||
- A state-less server to handle messages, via TCP socket protocol. | ||
|
||
- Support for the following language features: | ||
|
||
- Hover: Provide definitions for variables with usage message. | ||
|
||
- Completion: for wolfram system names. | ||
|
||
- Completion Resolve: Further information would be provided for the items in | ||
the list. | ||
|
||
- Diagnostics: Syntax error would be underlined. | ||
|
||
- Support for exporting temporary SVG images for the information of the variables. | ||
|
||
- A type system with pattern test. | ||
|
||
- A unit test framework. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,167 @@ | ||
# lsp-wl | ||
# Wolfram Language Server | ||
|
||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) | ||
|
||
![WolframLanguageServerLogo](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/develop/images/wolfram-language-server-logo-clipped.png) | ||
> by [kenkangxgwe](mailto:[email protected]) and [hxianglong](https://github.com/huxianglong) | ||
**Wolfram Language Server (WLServer)** is an implementation of the Microsoft's | ||
[Language Server Protocol | ||
(LSP)](https://microsoft.github.io/language-server-protocol) for [Wolfram | ||
Language](http://www.wolfram.com/language). This server is | ||
implemented in Wolfram Language itself. | ||
|
||
Our current goal is to provide the experience as good as the Mathematica FrontEnd | ||
with addition power from the editor. | ||
|
||
We have provided the client-side code for VS Code in this repo, which is based on some slight | ||
modifications of [Microsoft's LSP | ||
example](https://github.com/Microsoft/vscode-extension-samples/tree/master/lsp-sample). | ||
If you are using other tools supporting LSP, some slight modifications to the | ||
client would certainly work too. | ||
|
||
## Installation | ||
|
||
0. [Wolfram Mathematica](http://www.wolfram.com/mathematica/) (11.2 or | ||
higher<a name="ref1"></a>[<sup>1</sup>](#footnote1)). | ||
|
||
1. Download the [server](https://github.com/kenkangxgwe/lsp-wl) from its | ||
repository. | ||
|
||
``` sh | ||
git clone https://github.com/kenkangxgwe/lsp-wl.git | ||
``` | ||
|
||
2. Install the client. Currently, we provide the VS Code extension on [Visual | ||
Studio Marketplace: Wolfram Language Server](https://marketplace.visualstudio.com/items?itemName=lsp-wl.lsp-wl-client) | ||
|
||
## Run the Server | ||
|
||
Clients can start the server by running the `init.wls` file from Wolfram | ||
Mathematica executables | ||
|
||
``` sh | ||
wolfram -script /path/to/lsp-wl/init.wls [args] | ||
# or | ||
wolframscript -f /path/to/lsp-wl/init.wls [args] | ||
``` | ||
|
||
The posible arguments for the server are | ||
|
||
- `--help, -h` to print help information. | ||
- `--socket=port` to assign the port that the server connect to. (Default: | ||
`6536`) | ||
Socket is the only channel that we currently support. | ||
- `--log=level, -l level` to specify the logging level of the server. | ||
(Levels: `error`, `warn`, `info`, `debug`. Default: `info`) | ||
- `--test, -t` to run the unit test for the server. | ||
|
||
If you want to run the server from Mathematica you can use the following code. | ||
|
||
``` mathematica | ||
initfile = "/path/to/lsp-wl/init.wls"; | ||
args = {}; | ||
Block[{$ScriptCommandLine = Prepend[args, initfile], Quit = Function[{}, Throw[Null]]}, | ||
Catch[<< (initfile)] | ||
]; | ||
``` | ||
|
||
This is a good way to see the results from the unit tests. | ||
|
||
You may also specify the following `initializationOptions`. | ||
|
||
- `"theme": "dark" | "light"` For better typesetting of documentation, SVG | ||
images are used in the popup such as hovering. Since the background is | ||
transparent, this setting is to ensure the text in the images are actually | ||
visible. If you use dark themes, then choose `dark` <a name="ref2"> | ||
</a>[<sup>2</sup>](#footnote2). (Default: `dark`) | ||
|
||
## Features | ||
|
||
- *Hover:* Provide definitions for Wolfram functions and system variables, such | ||
as `String` and `$Path`. | ||
|
||
- *Completion:* The completion is triggered by the client automatically. | ||
Currently, Wolfram functions and system variables would be displayed. | ||
|
||
- *Completion Resolve:* Further information would be provided for the items in | ||
the list. | ||
|
||
- *Diagnostics:* Syntax error would be underlined. However, the specific syntax | ||
error is not supported at the moment. | ||
|
||
This is an early release, so more features are on the way. Syntax highlight is | ||
NOT supported according to the design of LSP, but there are already some good | ||
enough extensions like [Wolfram | ||
Language](https://marketplace.visualstudio.com/items?itemName=flipphillips.wolfram-language). | ||
|
||
Here is a full list of [LSP features](https://microsoft.github.io/language-server-protocol/specification). | ||
|
||
## Contribute | ||
|
||
### Design Principles | ||
|
||
1. The files are located according to its context name. The `init.wls` is the | ||
entry script that parses the commandline arguments, loads packages | ||
and starts the server. | ||
|
||
2. We implemented an stateless server in ``WolframLanguageServer`Server` `` that | ||
will parse and handle the messages. | ||
|
||
3. ``WolframLanguageServer`DataType` `` is a simple type system | ||
that supports pattern test on every field of a class. The operations on the | ||
objects are designed to be immutable. | ||
|
||
4. ``WolframLanguageServer`Test`* `` stores the unit tests for some of | ||
the packages. | ||
|
||
### Todo list | ||
|
||
It will be nice if you want to make a contribution to the following topic. | ||
|
||
* Our server-client communication only supports Socket with TCP protocol. We | ||
tried to use ZMQ_Stream protocol and `SocketListen[]` to enable concurrency, | ||
but it fails to send responses back to the client. | ||
|
||
* It will be helpful to implement a stdio channel, so that the Mathematica | ||
earlier than 11.2 will also be supported. | ||
|
||
* Since we embed SVG image in the `markupContent[]` and VS Code client cannot | ||
resize the popup window according to its size, it is hard to tweak the image | ||
width and the font size on every machine. We are looking for a better solution. | ||
|
||
* More editor clients are needed. You can feel free to open a repository and | ||
create a pull request to add the clients in README.md once your client is released. | ||
|
||
* A scanner/parser might be needed to extract tokens for future usage. We have | ||
investigated serveral implementations in other languages, but we are still | ||
prefer a wolfram language scanner/parser written in wolfram language and can | ||
be easily integrated into this project. | ||
|
||
If you want to help us with this project, feel free to fork and create a pull | ||
request. Do not forget to add unit tests if possible. | ||
|
||
## Donations :dollar: | ||
|
||
If you really like this project, please donate to us! **$5 (or equivalently | ||
¥35)**. A cup of coffee :coffee: would certainly | ||
brighten our day! Your donation would be the motivation for us to move forward, | ||
thanks in advance :smile:. | ||
|
||
- Paypal: [email protected] | ||
- Alipay (With QRCode): 13916018006 | ||
![Alipay | ||
QRCode](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/develop/images/alipay.jpg) | ||
|
||
## Footnotes | ||
|
||
<a name="footnote1"> </a> **[1]** `SocketListen[]` is used for server-client | ||
communication, which is introduced since 11.2. We plan to support stdio for | ||
better compatibility [^](#ref1) | ||
|
||
<a name="footnote2"> </a> **[2]** This reminds me of a joke making fun of | ||
Project Managers. A programmer, who cannot put up with endless unreasonable | ||
requests from his project manager, complained about one stupid task from him | ||
online, which is to automatically change the theme of the app with the conion, 'Add an option for | ||
users to choose when launching the app, what is the color of your cell phone | ||
protector. Then change the them accordingly.' [^](#ref2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
(* ::Package:: *) | ||
|
||
(* Wolfram Language Server Data Type *) | ||
(* Author: kenkangxgwe <kenkangxgwe_at_gmail.com>, | ||
huxianglong <hxianglong_at_gmail.com> | ||
*) | ||
|
||
|
||
BeginPackage["WolframLanguageServer`DataType`"]; | ||
ClearAll[Evaluate[Context[] <> "*"]]; | ||
|
||
DeclareType::usage = "DeclareType[typename, <|key_String -> pattern...|>] declares a type given by its name and an association indicating every field and its pattern in the type. | ||
typename[key] gets access to the corresponding value. | ||
typename[key, default] gets access to the corresponding value. If it is missing, returns the default. | ||
Keys[typename] returns all fields for the type. | ||
KeyPatterns[typename] returns the key-pattern pair of the type."; | ||
|
||
ReplaceKey::usage = "ReplaceKey[object, key -> value] assigns the value to key in given object. | ||
ReplaceKey[object, {key1, key2} -> value] assigns the value to object[key1][key2]. | ||
Replacekey[replaceRule_Rule] is an operator that can be applied to an object."; | ||
|
||
KeyPatterns::usage = "KeyPatterns[typename] returns the key-pattern pair of the type."; | ||
|
||
|
||
TypeCheck[v_?MissingQ, _] := v; | ||
TypeCheck[_, p_?MissingQ] := p; | ||
TypeCheck[val_, pat_] := If[MatchQ[val, pat], val, Missing["PatternMismatch", pat]]; | ||
|
||
ReplaceKey[_, {} -> value_] := value; | ||
ReplaceKey[rule_Rule][obj_] := ReplaceKey[obj, rule]; | ||
|
||
ReplaceKey[list_List, key_Integer -> value_] := | ||
ReplaceKey[list, {key} -> value]; | ||
ReplaceKey[list_List, {key_Integer, keys___} -> value_] := | ||
ReplacePart[list, key -> ReplaceKey[Extract[key][list], {keys} -> value]]; | ||
|
||
ReplaceKey[assoc_Association, key_ -> value_] := | ||
ReplaceKey[assoc, {key} -> value]; | ||
ReplaceKey[assoc_Association, {key_, keys___} -> value_] := | ||
Append[assoc, key -> ReplaceKey[assoc[key], {keys} -> value]]; | ||
|
||
AssociationSameQ[assoc1_Association, assoc2_Association] := Module[ | ||
{ | ||
keylist | ||
}, | ||
|
||
keylist = Keys[assoc1]; | ||
If[!ContainsExactly[keylist][Keys[assoc2]], | ||
Return[False] | ||
]; | ||
|
||
MapThread[If[AssociationQ[#1] && AssociationQ[#2], | ||
AssociationSameQ[#1, #2], | ||
SameQ[#1, #2] | ||
]&, { | ||
assoc1 /@ keylist, | ||
assoc2 /@ keylist | ||
}] // ContainsOnly[{True}] | ||
|
||
]; | ||
|
||
DeclareType[typename_, typekey:<|(_String -> _)...|>] := Module[ | ||
{ | ||
}, | ||
|
||
typename[typedict_Association][key_String] := TypeCheck[typedict[key], typekey[key]]; | ||
typename[typedict_Association][key_String, default_] := With[ | ||
{value = typename[typedict][key]}, | ||
If[MissingQ[value], TypeCheck[default, typekey[key]], value] | ||
]; | ||
Keys[typename] ^= Keys[typekey]; | ||
KeyPatterns[typename] = typekey; | ||
|
||
ReplaceKey[typename[typedict_Association], key_String -> value_] := | ||
ReplaceKey[typename[typedict], {key} -> value]; | ||
ReplaceKey[typename[typedict_Association], {key_String, keys___} -> value_] := | ||
typename[Append[typedict, key -> ReplaceKey[typedict[key], {keys} -> value]]]; | ||
|
||
typename /: SameQ[typename[typedict1_Association], typename[typedict2_Association]] := ( | ||
AssociationSameQ[typedict1, typedict1] | ||
); | ||
]; | ||
|
||
|
||
EndPackage[]; |
Oops, something went wrong.