Skip to content

Commit

Permalink
🔖 Alpha release 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kenkangxgwe committed Jan 13, 2019
2 parents a9efbee + 4dc2e85 commit e8717a9
Show file tree
Hide file tree
Showing 31 changed files with 6,885 additions and 1 deletion.
79 changes: 79 additions & 0 deletions .gitignore
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/
28 changes: 28 additions & 0 deletions CHANGELOG.md
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.
168 changes: 167 additions & 1 deletion README.md
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)
85 changes: 85 additions & 0 deletions WolframLanguageServer/DataType.wl
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[];
Loading

0 comments on commit e8717a9

Please sign in to comment.