Skip to content

Commit

Permalink
🔖 Alpha release 0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
kenkangxgwe committed Feb 5, 2019
2 parents e8717a9 + 302d134 commit 1a17e72
Show file tree
Hide file tree
Showing 20 changed files with 5,961 additions and 4,994 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ 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.1] - 2019-02-05 🧧

### Added

- Markdown text-based document information

### Fixed

- Tail-recursive message handler with no limits

### Deprecated

- SVG image for document information

## [0.1.0] - 2019-01-12

### Added
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 lsp-wl
Copyright (c) 2019 lsp-wl

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
47 changes: 25 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
# Wolfram Language Server

[![Develop with: Wolfram Language](https://img.shields.io/badge/Develop%20with-Wolfram%20Language-%23d81013.svg)](http://www.wolfram.com/language/)
[![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)
![WolframLanguageServerLogo](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/master/images/wolfram-language-server-logo-clipped.png)
> by [kenkangxgwe](mailto:[email protected]) and [hxianglong](https://github.com/huxianglong)
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**

- [Wolfram Language Server](#wolfram-language-server)
- [Installation](#installation)
- [Run the Server](#run-the-server)
- [Features](#features)
- [Contribute](#contribute)
- [Design Principles](#design-principles)
- [Todo list](#todo-list)
- [Donations :dollar:](#donations-dollar)
- [Footnotes](#footnotes)

<!-- markdown-toc end -->

**Wolfram Language Server (WLServer)** is an implementation of the Microsoft's
[Language Server Protocol
(LSP)](https://microsoft.github.io/language-server-protocol) for [Wolfram
Expand Down Expand Up @@ -68,27 +84,25 @@ Block[{$ScriptCommandLine = Prepend[args, initfile], Quit = Function[{}, Throw[N

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`.

![hover](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/develop/images/hover.png)

- *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.

![completion](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/develop/images/completion.png)

- *Diagnostics:* Syntax error would be underlined. However, the specific syntax
error is not supported at the moment.

![diagnostics](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/develop/images/diagnostics.png)

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
Expand Down Expand Up @@ -126,10 +140,6 @@ It will be nice if you want to make a contribution to the following topic.
* 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.

Expand All @@ -151,17 +161,10 @@ thanks in advance :smile:.
- Paypal: [email protected]
- Alipay (With QRCode): 13916018006
![Alipay
QRCode](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/develop/images/alipay.jpg)
QRCode](https://raw.githubusercontent.com/kenkangxgwe/lsp-wl/master/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)
better compatibility. [^](#ref1)
172 changes: 143 additions & 29 deletions WolframLanguageServer/DataType.wl
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,136 @@
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.";

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::usage = Keys::usage <> "\nKeys[typename] gives a list of the keys field_i in type typename.";
KeyPatterns::usage = "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.";

(* ::Section:: *)
(*DeclareType*)


DeclareType[typename_Symbol, typekey:<|(_String -> _)...|>] := Module[
{
},
(* Getter *)
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]
];

ConstructType[parameters_Association, typename] := Module[
{
},

typename[Association[
(# -> ConstructType[parameters[#], typekey[#]]&)
/@ Intersection[Keys[typekey], Keys[parameters]]
]]
];

(* Keys and Patterns *)
Keys[typename] ^= Keys[typekey];
KeyPatterns[typename] = typekey;

(* ReplaceKey *)
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]]];

(* SameQ *)
typename /: SameQ[typename[typedict1_Association], typename[typedict2_Association]] := (
AssociationSameQ[typedict1, typedict1]
);

(* usage *)
Evaluate[typename]::usage = StringJoin[{
ToString[typename, InputForm],
"[<|",
Riffle[KeyValueMap[{#1, " -> ", ToString[#2]}&, typekey], ", "],
"|>]",
Replace[Evaluate[typename]::usage, _MessageName -> "."]
}];
];


(* ::Section:: *)
(*Default Constructor*)


ConstructType[parameters_, pattern_] := If[MatchQ[parameters, pattern], parameters,
Replace[pattern, {
Verbatim[Pattern][_, obj_] :> ConstructType[parameters, obj],
Verbatim[Blank][h_] :> ConstructType[parameters, h],
_ :> Missing["ConstructorNotFound", {parameters, pattern}]
}]
];

ConstructType[parameters_, pattern:Verbatim[Alternatives][ps__]] := (
ConstructTypeAlternatives[parameters, {{ps}, Missing["ConstructorNotFound", {parameters, pattern}]}]
);

ConstructTypeAlternatives[parameters_, {{}, res_}] := res;
ConstructTypeAlternatives[parameters_, {{p_, ps___}, res_}] := ConstructTypeAlternatives[parameters,
ConstructType[parameters, p]
// Replace[{
_Missing -> {{ps}, res},
newres_ :> {{}, newres}
}]
];

ConstructType[parameters_List, pattern:List[(Verbatim[Repeated]|Verbatim[RepeatedNull])[p_]]] := (
ConstructTypeList[p, {parameters, {}}] // Replace[_Missing -> Missing["ConstructorNotFound", {parameters, pattern}]]
);

ConstructType[parameters_List, pattern:List[(Verbatim[BlankSequence]|Verbatim[BlankNullSequence])[p_]]] := (
ConstructTypeList[_p, {parameters, {}}] // Replace[_Missing -> Missing["ConstructorNotFound", {parameters, pattern}]]
);

ConstructTypeList[p_, {{}, res_}] := res;
ConstructTypeList[p_, {{param_, params___}, res_}] := ConstructTypeList[p,
ConstructType[param, p]
// Replace[{
_Missing -> {{}, MissingQ["ConstructorNotFound"]},
curRes_ :> {{params}, Append[res, curRes]}
}]
];

ConstructType[parameters_Association, pattern:Association[(Verbatim[Repeated]|Verbatim[RepeatedNull])[Rule[key_, val_]]]] := (
ConstructType[Keys[parameters], {key...}]
// Replace[{
_Missing -> Missing["ConstructorNotFound", {parameters, pattern}],
res1_ :> (
ConstructType[Values[parameters], {val...}]
// Replace[{
_Missing -> Missing["ConstructorNotFound", {parameters, pattern}],
res2_ :> Association[Thread[res1 -> res2]]
}]
)
}]
);


(* ::Section:: *)
(*TypeCheck*)


TypeCheck[v_?MissingQ, _] := v;
TypeCheck[_, p_?MissingQ] := p;
TypeCheck[val_, pat_] := If[MatchQ[val, pat], val, Missing["PatternMismatch", pat]];
TypeCheck[val_, pat_] := If[MatchQ[val, pat], val, Missing["PatternMismatch", {val, pat}]];


(* ::Section:: *)
(*ReplaceKey*)


ReplaceKey[_, {} -> value_] := value;
ReplaceKey[rule_Rule][obj_] := ReplaceKey[obj, rule];
Expand All @@ -38,7 +152,12 @@ ReplaceKey[assoc_Association, key_ -> value_] :=
ReplaceKey[assoc, {key} -> value];
ReplaceKey[assoc_Association, {key_, keys___} -> value_] :=
Append[assoc, key -> ReplaceKey[assoc[key], {keys} -> value]];



(* ::Section:: *)
(*AssociationSameQ*)


AssociationSameQ[assoc1_Association, assoc2_Association] := Module[
{
keylist
Expand All @@ -59,27 +178,22 @@ AssociationSameQ[assoc1_Association, assoc2_Association] := Module[

];

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]
);
];

(* ::Section:: *)
(*TypeUsage*)


TypeUsage[typename_Symbol, usage_String] := (
Evaluate[typename]::usage = StringJoin[{
Evaluate[typename]::usage
// Replace[{
_MessageName -> "",
s_String :> StringDrop[s, -1]
}],
" ",
usage
}]
);


EndPackage[];
10 changes: 7 additions & 3 deletions WolframLanguageServer/Logger.wl
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ LoggerStart[level_, streams:{_OutputStream..}] := Module[
levelno, head
},

levelno = If[MissingQ[#], Length[LoggingLevels], First @ #]& @ FirstPosition[LoggingLevels, level];
levelno = FirstPosition[LoggingLevels, level]
// Replace[{
_Missing -> Length[LoggingLevels],
{l_} :> l
}];

{LogError, LogWarn, LogInfo, LogDebug} =
(Function[{lvl},
Function[{msg},
Function[{stream}, WriteString[stream,
"[" <> StringPadRight[ToUpperCase[lvl], 5] <> " "
<> DateString["ISODateTime"] <> "] " <> ToString[msg] <> "\n"
Snippet["[" <> StringPadRight[ToUpperCase[lvl], 5] <> " "
<> DateString["ISODateTime"] <> "] " <> ToString[msg], 20] <> "\n"
]] /@ streams; msg
]
(*Echo[#, lvl, ##2]&*)
Expand Down
Loading

0 comments on commit 1a17e72

Please sign in to comment.