Initial Commit
This commit is contained in:
commit
639b0f451d
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
out/
|
30
.vscode/launch.json
vendored
Normal file
30
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"name": "Launch Client",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceRoot}"],
|
||||
"outFiles": ["${workspaceRoot}/client/out/**/*.js"],
|
||||
"preLaunchTask": {
|
||||
"type": "npm",
|
||||
"script": "watch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Language Server E2E Test",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}",
|
||||
"--extensionTestsPath=${workspaceRoot}/client/out/test/index",
|
||||
"${workspaceRoot}/client/testFixture"
|
||||
],
|
||||
"outFiles": ["${workspaceRoot}/client/out/test/**/*.js"]
|
||||
}
|
||||
]
|
||||
}
|
2
.vscode/settings.json
vendored
Normal file
2
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
33
.vscode/tasks.json
vendored
Normal file
33
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "compile",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"isBackground": true,
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
4
.vscodeignore
Normal file
4
.vscodeignore
Normal file
|
@ -0,0 +1,4 @@
|
|||
.vscode/**
|
||||
.vscode-test/**
|
||||
.gitignore
|
||||
vsc-extension-quickstart.md
|
28
CHANGELOG.md
Normal file
28
CHANGELOG.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to the "openquest" extension will be documented in this file.
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- Initial release
|
||||
|
||||
|
||||
## Release Notes
|
||||
|
||||
Users appreciate release notes as you update your extension.
|
||||
|
||||
### 1.0.0
|
||||
|
||||
Initial release of ...
|
||||
|
||||
### 1.0.1
|
||||
|
||||
Fixed issue #.
|
||||
|
||||
### 1.1.0
|
||||
|
||||
Added features X, Y, and Z.
|
||||
|
||||
---
|
29
README.md
Normal file
29
README.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# OpenQuest
|
||||
A Language extension for the Quest language, a DSL for mission scripting (Metin2)
|
||||
|
||||
|
||||
## Features
|
||||
Supports mostly all known tipical features like:
|
||||
- Quest Language Highlighting and formatting
|
||||
- Lua Language embedded in respective Quest scopes
|
||||
- [OpenQuest Language Server support](https://github.com/oridevteam/openquest-rs)
|
||||
- Language Server connections (local and remote)
|
||||
|
||||
|
||||
Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
|
||||
|
||||
For example if there is an image subfolder under your extension project workspace:
|
||||
|
||||
\!\[feature X\]\(images/feature-x.png\)
|
||||
|
||||
> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
|
||||
|
||||
|
||||
## Requirements
|
||||
The extension is able to provide everything necessary by itself,
|
||||
however you can check its Settings for things you might want to change to your own
|
||||
|
||||
|
||||
## Known Issues
|
||||
Nothing quite yet
|
||||
|
23
client/package.json
Normal file
23
client/package.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "openquest-lsp-client",
|
||||
"description": "OpenQuest VSC LSP CLient",
|
||||
"author": "openquest",
|
||||
"license": "MIT",
|
||||
"version": "0.0.1",
|
||||
"publisher": "vscode",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-extension-samples"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.75.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageclient": "^8.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.2.5",
|
||||
"@types/vscode": "^1.75.1",
|
||||
"@vscode/test-electron": "^2.2.3"
|
||||
}
|
||||
}
|
354
client/pnpm-lock.yaml
Normal file
354
client/pnpm-lock.yaml
Normal file
|
@ -0,0 +1,354 @@
|
|||
lockfileVersion: '6.1'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
vscode-languageclient:
|
||||
specifier: ^8.1.0
|
||||
version: 8.1.0
|
||||
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.2.5
|
||||
version: 20.2.5
|
||||
'@types/vscode':
|
||||
specifier: ^1.75.1
|
||||
version: 1.75.1
|
||||
'@vscode/test-electron':
|
||||
specifier: ^2.2.3
|
||||
version: 2.2.3
|
||||
|
||||
packages:
|
||||
|
||||
/@tootallnate/once@1.1.2:
|
||||
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/@types/node@20.2.5:
|
||||
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
|
||||
dev: true
|
||||
|
||||
/@types/vscode@1.75.1:
|
||||
resolution: {integrity: sha512-emg7wdsTFzdi+elvoyoA+Q8keEautdQHyY5LNmHVM4PTpY8JgOTVADrGVyXGepJ6dVW2OS5/xnLUWh+nZxvdiA==}
|
||||
dev: true
|
||||
|
||||
/@vscode/test-electron@2.2.3:
|
||||
resolution: {integrity: sha512-7DmdGYQTqRNaLHKG3j56buc9DkstriY4aV0S3Zj32u0U9/T0L8vwWAC9QGCh1meu1VXDEla1ze27TkqysHGP0Q==}
|
||||
engines: {node: '>=16'}
|
||||
dependencies:
|
||||
http-proxy-agent: 4.0.1
|
||||
https-proxy-agent: 5.0.1
|
||||
rimraf: 3.0.2
|
||||
unzipper: 0.10.14
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/agent-base@6.0.2:
|
||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
/big-integer@1.6.51:
|
||||
resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==}
|
||||
engines: {node: '>=0.6'}
|
||||
dev: true
|
||||
|
||||
/binary@0.3.0:
|
||||
resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==}
|
||||
dependencies:
|
||||
buffers: 0.1.1
|
||||
chainsaw: 0.1.0
|
||||
dev: true
|
||||
|
||||
/bluebird@3.4.7:
|
||||
resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==}
|
||||
dev: true
|
||||
|
||||
/brace-expansion@1.1.11:
|
||||
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
concat-map: 0.0.1
|
||||
dev: true
|
||||
|
||||
/brace-expansion@2.0.1:
|
||||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
dev: false
|
||||
|
||||
/buffer-indexof-polyfill@1.0.2:
|
||||
resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==}
|
||||
engines: {node: '>=0.10'}
|
||||
dev: true
|
||||
|
||||
/buffers@0.1.1:
|
||||
resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==}
|
||||
engines: {node: '>=0.2.0'}
|
||||
dev: true
|
||||
|
||||
/chainsaw@0.1.0:
|
||||
resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==}
|
||||
dependencies:
|
||||
traverse: 0.3.9
|
||||
dev: true
|
||||
|
||||
/concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
dev: true
|
||||
|
||||
/core-util-is@1.0.3:
|
||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||
dev: true
|
||||
|
||||
/debug@4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
dev: true
|
||||
|
||||
/duplexer2@0.1.4:
|
||||
resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
|
||||
dependencies:
|
||||
readable-stream: 2.3.8
|
||||
dev: true
|
||||
|
||||
/fs.realpath@1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
dev: true
|
||||
|
||||
/fstream@1.0.12:
|
||||
resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==}
|
||||
engines: {node: '>=0.6'}
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
inherits: 2.0.4
|
||||
mkdirp: 0.5.6
|
||||
rimraf: 2.7.1
|
||||
dev: true
|
||||
|
||||
/glob@7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
dev: true
|
||||
|
||||
/graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
dev: true
|
||||
|
||||
/http-proxy-agent@4.0.1:
|
||||
resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
'@tootallnate/once': 1.1.2
|
||||
agent-base: 6.0.2
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/https-proxy-agent@5.0.1:
|
||||
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
agent-base: 6.0.2
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/inflight@1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
dev: true
|
||||
|
||||
/isarray@1.0.0:
|
||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||
dev: true
|
||||
|
||||
/listenercount@1.0.1:
|
||||
resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==}
|
||||
dev: true
|
||||
|
||||
/lru-cache@6.0.0:
|
||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
dependencies:
|
||||
brace-expansion: 1.1.11
|
||||
dev: true
|
||||
|
||||
/minimatch@5.1.6:
|
||||
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
brace-expansion: 2.0.1
|
||||
dev: false
|
||||
|
||||
/minimist@1.2.8:
|
||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||
dev: true
|
||||
|
||||
/mkdirp@0.5.6:
|
||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
minimist: 1.2.8
|
||||
dev: true
|
||||
|
||||
/ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
dev: true
|
||||
|
||||
/once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/path-is-absolute@1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/process-nextick-args@2.0.1:
|
||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
dev: true
|
||||
|
||||
/readable-stream@2.3.8:
|
||||
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
|
||||
dependencies:
|
||||
core-util-is: 1.0.3
|
||||
inherits: 2.0.4
|
||||
isarray: 1.0.0
|
||||
process-nextick-args: 2.0.1
|
||||
safe-buffer: 5.1.2
|
||||
string_decoder: 1.1.1
|
||||
util-deprecate: 1.0.2
|
||||
dev: true
|
||||
|
||||
/rimraf@2.7.1:
|
||||
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rimraf@3.0.2:
|
||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/safe-buffer@5.1.2:
|
||||
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
|
||||
dev: true
|
||||
|
||||
/semver@7.5.1:
|
||||
resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
lru-cache: 6.0.0
|
||||
dev: false
|
||||
|
||||
/setimmediate@1.0.5:
|
||||
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
|
||||
dev: true
|
||||
|
||||
/string_decoder@1.1.1:
|
||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||
dependencies:
|
||||
safe-buffer: 5.1.2
|
||||
dev: true
|
||||
|
||||
/traverse@0.3.9:
|
||||
resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==}
|
||||
dev: true
|
||||
|
||||
/unzipper@0.10.14:
|
||||
resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==}
|
||||
dependencies:
|
||||
big-integer: 1.6.51
|
||||
binary: 0.3.0
|
||||
bluebird: 3.4.7
|
||||
buffer-indexof-polyfill: 1.0.2
|
||||
duplexer2: 0.1.4
|
||||
fstream: 1.0.12
|
||||
graceful-fs: 4.2.11
|
||||
listenercount: 1.0.1
|
||||
readable-stream: 2.3.8
|
||||
setimmediate: 1.0.5
|
||||
dev: true
|
||||
|
||||
/util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
dev: true
|
||||
|
||||
/vscode-jsonrpc@8.1.0:
|
||||
resolution: {integrity: sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: false
|
||||
|
||||
/vscode-languageclient@8.1.0:
|
||||
resolution: {integrity: sha512-GL4QdbYUF/XxQlAsvYWZRV3V34kOkpRlvV60/72ghHfsYFnS/v2MANZ9P6sHmxFcZKOse8O+L9G7Czg0NUWing==}
|
||||
engines: {vscode: ^1.67.0}
|
||||
dependencies:
|
||||
minimatch: 5.1.6
|
||||
semver: 7.5.1
|
||||
vscode-languageserver-protocol: 3.17.3
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver-protocol@3.17.3:
|
||||
resolution: {integrity: sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==}
|
||||
dependencies:
|
||||
vscode-jsonrpc: 8.1.0
|
||||
vscode-languageserver-types: 3.17.3
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver-types@3.17.3:
|
||||
resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==}
|
||||
dev: false
|
||||
|
||||
/wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
dev: true
|
||||
|
||||
/yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: false
|
275
client/src/client_handler.ts
Normal file
275
client/src/client_handler.ts
Normal file
|
@ -0,0 +1,275 @@
|
|||
// Local Imports
|
||||
import constants = require("./constants");
|
||||
import { clients, outputChannel } from "./extension";
|
||||
import * as server_binary from "./server_binary";
|
||||
|
||||
// External Imports
|
||||
import { Duplex } from "stream";
|
||||
import WebSocket, { createWebSocketStream } from 'ws';
|
||||
import {
|
||||
ExtensionContext, RelativePattern, WorkspaceFolder,
|
||||
WorkspaceFoldersChangeEvent, workspace
|
||||
} from "vscode";
|
||||
import * as vscode from "vscode";
|
||||
import { LanguageClient, StreamInfo, integer } from "vscode-languageclient/node";
|
||||
import { ServerOptions } from 'vscode-languageclient/node';
|
||||
import { TextDocument, Uri } from 'vscode';
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
async function openDocument(uri: Uri) {
|
||||
const uriMatch = (d: TextDocument) => d.uri.toString() === uri.toString();
|
||||
const doc = vscode.workspace.textDocuments.find(uriMatch);
|
||||
|
||||
if (doc === undefined) await vscode.workspace.openTextDocument(uri);
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
async function openPestFilesInFolder(folder: Uri) {
|
||||
const pattern = filesInFolderPattern(folder);
|
||||
const uris = await workspace.findFiles(pattern);
|
||||
|
||||
return Promise.all(uris.map(openDocument));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function filesInFolderPattern(folder: Uri) {
|
||||
return new RelativePattern(folder, constants.DOCUMENT_EXTENSION_PATTERN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export async function startClientsForFolder(folder: WorkspaceFolder, ctx: ExtensionContext) {
|
||||
// Settings on how to setup and connect the server
|
||||
let serverOptions = await makeServerOptions();
|
||||
|
||||
if (!serverOptions) {
|
||||
outputChannel.appendLine("[ERROR] Aborting server start.");
|
||||
|
||||
/*
|
||||
await window.showErrorMessage(
|
||||
"Not starting Pest Language Server as a suitable binary was not found."
|
||||
);
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const root = folder.uri;
|
||||
|
||||
const deleteWatcher = workspace.createFileSystemWatcher(
|
||||
filesInFolderPattern(root),
|
||||
true, // ignoreCreateEvents
|
||||
true, // ignoreChangeEvents
|
||||
false // ignoreDeleteEvents
|
||||
);
|
||||
|
||||
const createChangeWatcher = workspace.createFileSystemWatcher(
|
||||
filesInFolderPattern(root),
|
||||
false, // ignoreCreateEvents
|
||||
false, // ignoreChangeEvents
|
||||
true // ignoreDeleteEvents
|
||||
);
|
||||
|
||||
ctx.subscriptions.push(deleteWatcher);
|
||||
ctx.subscriptions.push(createChangeWatcher);
|
||||
|
||||
const client = new LanguageClient(
|
||||
constants.EXTENSION_NAME,
|
||||
serverOptions,
|
||||
{
|
||||
documentSelector: [
|
||||
{
|
||||
language: constants.LANGUAGE_ID,
|
||||
pattern: `${root.fsPath}/${constants.DOCUMENT_EXTENSION_PATTERN}`
|
||||
},
|
||||
],
|
||||
synchronize: { fileEvents: deleteWatcher },
|
||||
diagnosticCollectionName: constants.EXTENSION_NAME,
|
||||
workspaceFolder: folder,
|
||||
outputChannel,
|
||||
}
|
||||
);
|
||||
|
||||
client.start(); // ctx.subscriptions.push(client.start());
|
||||
ctx.subscriptions.push(createChangeWatcher.onDidCreate(openDocument));
|
||||
ctx.subscriptions.push(createChangeWatcher.onDidChange(openDocument));
|
||||
|
||||
const openedFiles = await openPestFilesInFolder(root);
|
||||
const pestFiles: Set<string> = new Set();
|
||||
|
||||
openedFiles.forEach(f => pestFiles.add(f.toString()));
|
||||
clients.set(root.toString(), client);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes Language Server options based on workspace settings, it might:
|
||||
* - Try to find where a executable path is in package managers install paths
|
||||
* - Find a given executable by path in given workspace settings
|
||||
* - Connect to an existing language server websocket on an address
|
||||
*/
|
||||
async function makeServerOptions(): Promise<ServerOptions | undefined> {
|
||||
const workspaceConfig = vscode.workspace.getConfiguration(constants.SETTINGS_NAMESPACE);
|
||||
const customArgs = workspaceConfig.get("serverArguments") as string[];
|
||||
|
||||
// Make either a configuration to spawn a server locally
|
||||
// or connect to an existing local or remote one
|
||||
switch (workspaceConfig.get("handlingMode")) {
|
||||
// Tries to find a language server executable from known package managers
|
||||
// and spawns it
|
||||
case "Automatic (Package Manager)":
|
||||
const serverPath = await server_binary.findLanguageServerPath();
|
||||
const automaticOptions: ServerOptions = {
|
||||
command: serverPath, args: customArgs
|
||||
};
|
||||
|
||||
return automaticOptions;
|
||||
|
||||
// Finds specified language server in path and spawns it
|
||||
case "Local Path":
|
||||
const command: string = workspaceConfig.get("serverBinaryPath");
|
||||
|
||||
let serverOptions: ServerOptions = {
|
||||
command, args: customArgs
|
||||
};
|
||||
|
||||
return serverOptions;
|
||||
|
||||
// Connect to a websocket by specified address in settings
|
||||
case "Remote/Local Connection":
|
||||
const addr: string = workspaceConfig.get("serverAddress");
|
||||
|
||||
return websocketServerOptions(addr);
|
||||
|
||||
default:
|
||||
vscode.window.showErrorMessage("[ERROR] Something that shouldn't error, errored!")
|
||||
break;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function ipcSocketServerOptions(pid: number) {
|
||||
var child_process = require("child_process");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pid
|
||||
* @returns
|
||||
*/
|
||||
function pipeLanguageServer(pid: number): StreamInfo {
|
||||
var child_process = require("child_process");
|
||||
|
||||
// Obtain the stdin and stdout streams of the preexisting process using its PID
|
||||
const languageServerProcess = child_process.spawn('sh', ['-c', `exec ${pid}>&0 <&${pid} 2>&1`], {
|
||||
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
|
||||
// Create a StreamInfo object with the input/output streams of the language server process
|
||||
const streamInfo: StreamInfo = {
|
||||
writer: languageServerProcess.stdin,
|
||||
reader: languageServerProcess.stdout
|
||||
};
|
||||
|
||||
return streamInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generaters server options with a websocket ready connection
|
||||
* @param address
|
||||
*/
|
||||
function websocketServerOptions(address: string): ServerOptions {
|
||||
function connectToServer(hostname: string): Duplex {
|
||||
const socket = new WebSocket(`ws://${hostname}/`);
|
||||
|
||||
const stream = createWebSocketStream(socket);
|
||||
|
||||
stream.on('error', (e) => {
|
||||
outputChannel.appendLine(`[WS] Could not connect: ${e.message}`);
|
||||
});
|
||||
stream.on('open', (e) => outputChannel.appendLine(`[WS] Connected: ${e.message}`))
|
||||
stream.on("data", function (chunk) {
|
||||
console.log(new TextDecoder().decode(chunk));
|
||||
});
|
||||
|
||||
if (socket && (socket.readyState === WebSocket.CONNECTING)) {
|
||||
// TODO: Delay execution while socket is connecting for a bit
|
||||
}
|
||||
|
||||
if (socket && (socket.readyState === WebSocket.CONNECTING || socket.readyState === WebSocket.CLOSING)) {
|
||||
outputChannel.append("[WS] Not connected:")
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
let connection = connectToServer(address);
|
||||
|
||||
return () => Promise.resolve({
|
||||
reader: connection,
|
||||
writer: connection,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client
|
||||
* @returns
|
||||
*/
|
||||
export function stopClient(client: LanguageClient) {
|
||||
client.diagnostics?.clear();
|
||||
return client.stop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param workspaceFolder
|
||||
*/
|
||||
export async function stopClientsForFolder(workspaceFolder: string) {
|
||||
const client = clients.get(workspaceFolder);
|
||||
if (client) {
|
||||
await stopClient(client);
|
||||
}
|
||||
|
||||
clients.delete(workspaceFolder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function updateClients(context: ExtensionContext) {
|
||||
return async function ({ added, removed }: WorkspaceFoldersChangeEvent) {
|
||||
for (const folder of removed) {
|
||||
await stopClientsForFolder(folder.uri.toString());
|
||||
}
|
||||
|
||||
for (const folder of added) {
|
||||
await startClientsForFolder(folder, context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
67
client/src/client_handler_other.ts
Normal file
67
client/src/client_handler_other.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
|
||||
|
||||
|
||||
/*
|
||||
function connectToServer(hostname: string, path: string): Duplex {
|
||||
const ws = new WebSocket(`ws://${hostname}/${path}`);
|
||||
return WebSocket.createWebSocketStream(ws);
|
||||
}
|
||||
*/
|
||||
|
||||
////function makeClient() {
|
||||
// // Options to control the language client
|
||||
// const clientOptions: LanguageClientOptions = {
|
||||
// // Register the server for plain text documents
|
||||
// documentSelector: [{ scheme: 'file', language: 'plaintext' }],
|
||||
// synchronize: {
|
||||
// // Notify the server about file changes to '.clientrc files contained in the workspace
|
||||
// fileEvents: workspace.createFileSystemWatcher('**/.clientrc')
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // The server is implemented in node
|
||||
// const serverModule = context.asAbsolutePath(
|
||||
// path.join('server', 'out', 'server.js')
|
||||
// );
|
||||
//
|
||||
// // Create the language client and start it
|
||||
// client = new LanguageClient(
|
||||
// 'OpenQuestLSP',
|
||||
// 'OpenQuest Language Server',
|
||||
// serverOptionsGenerator(),
|
||||
// clientOptions
|
||||
// );
|
||||
//
|
||||
// // The client will either connect or launch the language server, depending
|
||||
// // on the workspace settings
|
||||
// client.start();
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
///**
|
||||
// * Make server options based on the workspace configuration
|
||||
// */
|
||||
//function serverOptionsGenerator(): ServerOptions {
|
||||
// if (vscode.workspace.getConfiguration(constants.SETTINGS_NAMESPACE).get("serverAddress") !== null) {
|
||||
// // If the extension is launched in debug mode then the debug server options are used
|
||||
// // Otherwise the run options are used
|
||||
// return {
|
||||
// run: { module: serverModule, transport: TransportKind.ipc },
|
||||
// debug: {
|
||||
// module: serverModule,
|
||||
// transport: TransportKind.ipc,
|
||||
// }
|
||||
// };
|
||||
// } else {
|
||||
// return {
|
||||
// run: { module: serverModule, transport: TransportKind.ipc },
|
||||
// debug: {
|
||||
// module: serverModule,
|
||||
// transport: TransportKind.ipc,
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
//}
|
||||
//*/
|
18
client/src/constants.ts
Normal file
18
client/src/constants.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// TODO: Check if some of these things can be accessed trough legacy code
|
||||
// since they are in `package.json`, which could be accessible somehow
|
||||
|
||||
|
||||
/** Name of the VSCode extension namespace */
|
||||
export const DISPLAY_NAME: string = "OpenQuest"
|
||||
export const EXTENSION_NAME: string = "openquest"
|
||||
export const LANGUAGE_ID: string = "quest"
|
||||
|
||||
export const SETTINGS_NAMESPACE: string = EXTENSION_NAME
|
||||
|
||||
export const SUPPORTED_EXTENSIONS = {
|
||||
|
||||
};
|
||||
|
||||
export const DOCUMENT_EXTENSION_PATTERN = "**/*.quest";
|
||||
export const documentsPerExtensionInPath = (path) => `${path}/${DOCUMENT_EXTENSION_PATTERN}`;
|
||||
|
87
client/src/extension.ts
Normal file
87
client/src/extension.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Local Imports
|
||||
import constants = require('./constants');
|
||||
import * as client_handler from "./client_handler"
|
||||
|
||||
|
||||
// External Imports
|
||||
import { workspace, ExtensionContext } from 'vscode';
|
||||
import * as vscode from "vscode";
|
||||
import { LanguageClient } from 'vscode-languageclient/node';
|
||||
import { startClientsForFolder } from './client_handler';
|
||||
|
||||
|
||||
// Common and Persistent variables
|
||||
export const outputChannel = vscode.window.createOutputChannel(
|
||||
constants.DISPLAY_NAME, constants.LANGUAGE_ID
|
||||
);
|
||||
|
||||
export const clients: Map<string, LanguageClient> = new Map();
|
||||
|
||||
|
||||
/**
|
||||
* This function gets called when the extension is activated,
|
||||
* depending on what is the trigger configuration on `package.json#activationEvents
|
||||
*/
|
||||
export function activate(context: ExtensionContext) {
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
outputChannel.appendLine('[INFO] Extension is now active, good deving and have fun !');
|
||||
|
||||
// Commands (these are defined in `package.json#contributes.configurations`)
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand(`${constants.SETTINGS_NAMESPACE}.reload_server`, () => {
|
||||
// The code placed here will be executed every time this command is ran
|
||||
vscode.window.showInformationMessage(`[INFO] Reloading Language Server`);
|
||||
})
|
||||
);
|
||||
|
||||
// Start Language Clients for each folder in the workspace
|
||||
for (const folder of workspace.workspaceFolders || []) {
|
||||
startClientsForFolder(folder, context);
|
||||
}
|
||||
|
||||
// Client to Server synchronization
|
||||
context.subscriptions.push(
|
||||
workspace.onDidChangeWorkspaceFolders(client_handler.updateClients(context))
|
||||
);
|
||||
|
||||
// Refresh client and server settings when changes happen
|
||||
context.subscriptions.push(workspace.onDidChangeConfiguration(
|
||||
(event) => refreshSettings(event, context))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
await Promise.all([...clients.values()].map(client_handler.stopClient));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks what changes were made in workspace and user settings and acts
|
||||
* accordingly, like reconnecting/relaunching language servers
|
||||
*/
|
||||
async function refreshSettings(event: vscode.ConfigurationChangeEvent, context: ExtensionContext) {
|
||||
// Check if changes to language server paths were made
|
||||
if (event.affectsConfiguration(`${constants.SETTINGS_NAMESPACE}.serverPath`)) {
|
||||
for (const client of clients.values()) {
|
||||
const folder = client.clientOptions.workspaceFolder;
|
||||
await client_handler.stopClient(client);
|
||||
|
||||
if (folder) {
|
||||
await startClientsForFolder(folder, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
else {
|
||||
for (const client of clients.values()) {
|
||||
client.sendNotification("workspace/didChangeConfiguration", {
|
||||
settings: {
|
||||
...workspace.getConfiguration(constants.SETTINGS_NAMESPACE),
|
||||
checkForUpdates: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
154
client/src/server_binary.ts
Normal file
154
client/src/server_binary.ts
Normal file
|
@ -0,0 +1,154 @@
|
|||
// Local Imports
|
||||
import constants = require('./constants');
|
||||
import { outputChannel } from './extension';
|
||||
|
||||
|
||||
// External Imports
|
||||
import * as path from 'path';
|
||||
import { stat } from "fs/promises";
|
||||
import * as vscode from "vscode";
|
||||
|
||||
|
||||
/**
|
||||
* Tries to find a language server executable in the following places:
|
||||
* - $PATH or $HOME directory
|
||||
* - The open project's VSCode workspace settings
|
||||
* - Near the unicorns (joking, this one isn't real, just like the unicorns)
|
||||
*/
|
||||
export async function findLanguageServerPath(): Promise<string | undefined> {
|
||||
let customPath = getCustomLanguageServerPath();
|
||||
|
||||
if (customPath !== undefined) { return customPath }
|
||||
|
||||
// TODO: Think if we should also prompt and do updates
|
||||
if (promptInstallLanguageServerExecutable()) {
|
||||
if (installLanguageServerExecutable()) {
|
||||
return searchInstalledLanguageServer();
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for a custom language server binary set in the Workspace or User settings
|
||||
*/
|
||||
function getCustomLanguageServerPath(): string | undefined {
|
||||
const workspaceConfig = vscode.workspace.getConfiguration(constants.EXTENSION_NAME);
|
||||
|
||||
// Check for custom language server path
|
||||
if (workspaceConfig.get("serverBinaryPath") && vscode.workspace.workspaceFolders !== undefined) {
|
||||
outputChannel.appendLine(
|
||||
path.resolve(
|
||||
vscode.workspace.workspaceFolders[0].uri.fsPath,
|
||||
workspaceConfig.get("serverBinaryPath") as string
|
||||
)
|
||||
);
|
||||
|
||||
return path.resolve(
|
||||
vscode.workspace.workspaceFolders[0].uri.fsPath,
|
||||
workspaceConfig.get("serverBinaryPath") as string
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prompt the user about installing the language server from a known origin
|
||||
* and installs it if agreed
|
||||
*/
|
||||
async function promptInstallLanguageServerExecutable(): Promise<boolean> {
|
||||
const choice = await vscode.window.showWarningMessage(
|
||||
"Could not find a language server binary.\
|
||||
Would you like to install one using `cargo install`?",
|
||||
{},
|
||||
"Yes"
|
||||
);
|
||||
// TODO: The prompt could also say what places we tried to look into
|
||||
// and consequentially a better message on from where we are getting it
|
||||
// and to where it is being installed
|
||||
|
||||
if (!choice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Download language server executable from mirrors defined in `package.json`
|
||||
* and put them
|
||||
* @returns
|
||||
*/
|
||||
async function installLanguageServerExecutable(): Promise<boolean> {
|
||||
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks in known paths like HOME(Linux, Windows, Unix) and UserProfile(Windows)
|
||||
*/
|
||||
function searchInstalledLanguageServer() {
|
||||
let base = process.env["HOME"];
|
||||
|
||||
if (process.platform === "win32") {
|
||||
base = process.env["USERPROFILE"];
|
||||
}
|
||||
|
||||
if (!base) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks for the cargo binary path in HOME
|
||||
* @returns Path of the executables directory for cargo
|
||||
*/
|
||||
function lookForCargoBinPath() {
|
||||
let base = process.env["HOME"];
|
||||
|
||||
if (!base) { return undefined}
|
||||
|
||||
const cargoInstallRoot = process.env["CARGO_INSTALL_ROOT"];
|
||||
if (cargoInstallRoot) {
|
||||
return cargoInstallRoot;
|
||||
}
|
||||
|
||||
const cargoHome = process.env["CARGO_HOME"];
|
||||
|
||||
if (cargoHome) {
|
||||
return path.join(cargoHome, "bin");
|
||||
}
|
||||
return path.join(base, ".cargo", "bin");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives language server binary name based on current environment
|
||||
*/
|
||||
function getBinaryName(): string {
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
return "openquest-ls.exe"
|
||||
case "linux":
|
||||
return "openquest-ls"
|
||||
default:
|
||||
return "openquest-ls"
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks if a given path exists */
|
||||
async function checkPathValidity(path: string): Promise<boolean> {
|
||||
try {
|
||||
await stat(path)
|
||||
return true
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
0
client/testFixture/completion.txt
Normal file
0
client/testFixture/completion.txt
Normal file
1
client/testFixture/diagnostics.txt
Normal file
1
client/testFixture/diagnostics.txt
Normal file
|
@ -0,0 +1 @@
|
|||
ANY browsers, ANY OS.
|
7
client/testWorkspace/.vscode/settings.json
vendored
Normal file
7
client/testWorkspace/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
// "openquest.handlingMode": "Remote/Local Connection",
|
||||
// "openquest.serverAddress": "localhost:4000"
|
||||
"openquest.handlingMode": "Local Path",
|
||||
"openquest.serverBinaryPath": "/run/media/nibunta/OMTRON/Projectos/Metin_Projects/General Projects/openquest/openquest-rs/target/debug/openquest-lsp",
|
||||
"openquest.serverArguments": ["--transport", "stdio"]
|
||||
}
|
5
client/testWorkspace/test.lua
Normal file
5
client/testWorkspace/test.lua
Normal file
|
@ -0,0 +1,5 @@
|
|||
local thing = 10
|
||||
|
||||
function test()
|
||||
end
|
||||
|
7
client/testWorkspace/test.quest
Normal file
7
client/testWorkspace/test.quest
Normal file
|
@ -0,0 +1,7 @@
|
|||
define thing 10
|
||||
define some 100
|
||||
|
||||
quest some with thing begin
|
||||
state start begin
|
||||
end
|
||||
end
|
1
client/testWorkspace/test.txt
Normal file
1
client/testWorkspace/test.txt
Normal file
|
@ -0,0 +1 @@
|
|||
#10
|
13
client/tsconfig.json
Normal file
13
client/tsconfig.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2020",
|
||||
"lib": ["es2020"],
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", ".vscode-test"]
|
||||
}
|
30
language-configuration.json
Normal file
30
language-configuration.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"comments": {
|
||||
// symbol used for single line comment. Remove this entry if your language does not support line comments
|
||||
"lineComment": "--",
|
||||
// symbols used for start and end a block comment. Remove this entry if your language does not support block comments
|
||||
"blockComment": [ "--[[", "]]--" ]
|
||||
},
|
||||
// symbols used as brackets
|
||||
"brackets": [
|
||||
["begin", "end"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
],
|
||||
// symbols that are auto closed when typing
|
||||
"autoClosingPairs": [
|
||||
["begin", "end"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
],
|
||||
// symbols that can be used to surround a selection
|
||||
"surroundingPairs": [
|
||||
["begin", "end"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
]
|
||||
}
|
5236
package-lock.json
generated
Normal file
5236
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
103
package.json
Normal file
103
package.json
Normal file
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"name": "openquest",
|
||||
"displayName": "OpenQuest",
|
||||
"description": "Support for the Quest language, a DSL for mission scripting (Metin2)",
|
||||
"version": "0.0.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/OriDevTeam/openquest-rs\""
|
||||
},
|
||||
"license": "Apache2",
|
||||
"publisher": "OriDevTeam",
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"keywords": [
|
||||
"quest",
|
||||
"language"
|
||||
],
|
||||
"engines": {
|
||||
"vscode": "^1.78.0"
|
||||
},
|
||||
"main": "./client/out/extension",
|
||||
"contributes": {
|
||||
"languages": [
|
||||
{
|
||||
"id": "quest",
|
||||
"aliases": [
|
||||
"Quest",
|
||||
"quest"
|
||||
],
|
||||
"extensions": [
|
||||
".quest"
|
||||
],
|
||||
"configuration": "./language-configuration.json",
|
||||
"embeddedLanguages": { "meta.embedded.block.lua": "lua" }
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "quest",
|
||||
"scopeName": "source.quest",
|
||||
"path": "./syntaxes/quest.tmLanguage.json"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": "OpenQuest",
|
||||
"properties": {
|
||||
"openquest.handlingMode": {
|
||||
"scope": "window",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Automatic (Package Manager)",
|
||||
"Local Path",
|
||||
"Remote/Local Connection"
|
||||
],
|
||||
"default": "Automatic (Package Manager)",
|
||||
"description": "Where and how to connect to a language server, or spawn a new process of one"
|
||||
},
|
||||
"openquest.serverAddress": {
|
||||
"scope": "window",
|
||||
"type": "string",
|
||||
"markdownDescription": "Language Server address to connect to (**Example:** localhost:5050)"
|
||||
},
|
||||
"openquest.serverArguments": {
|
||||
"scope": "window",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"description": "Arguments to pass when initializing language server"
|
||||
},
|
||||
"openquest.serverBinaryPath": {
|
||||
"scope": "window",
|
||||
"type": "string",
|
||||
"markdownDescription": "Path of the language server executable (if not given, it will look in $PATH and consequentially $HOME)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "pnpm run compile",
|
||||
"compile": "tsc -b",
|
||||
"postinstall": "cd client && pnpm install && cd ..",
|
||||
"watch": "tsc -b -w",
|
||||
"lint": "eslint ./client/src ./server/src --ext .ts,.tsx",
|
||||
"test": "sh ./scripts/e2e.sh",
|
||||
"package-y2j": "js-yaml package.yaml > package.json",
|
||||
"grammar-y2j": "js-yaml syntaxes/quest.tmGrammar.yaml > syntaxes/quest.tmGrammar.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"generator-code": "^1.7.7",
|
||||
"js-yaml": "^4.1.0",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "^16.18.34",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
||||
"@typescript-eslint/parser": "^5.59.9",
|
||||
"@types/ws": "^8.5.5",
|
||||
"eslint": "^8.42.0",
|
||||
"mocha": "^9.2.2",
|
||||
"typescript": "^5.1.3"
|
||||
}
|
||||
}
|
80
packagee.yaml
Normal file
80
packagee.yaml
Normal file
|
@ -0,0 +1,80 @@
|
|||
name: openquest
|
||||
displayName: OpenQuest
|
||||
description: Support for the Quest language, a DSL for mission scripting (Metin2)
|
||||
version: 0.0.1
|
||||
repository:
|
||||
type: git
|
||||
url: https://github.com/OriDevTeam/openquest-rs"
|
||||
license: Apache2
|
||||
publisher: OriDevTeam
|
||||
categories:
|
||||
- Programming Languages
|
||||
keywords:
|
||||
- quest
|
||||
- language
|
||||
engines: {vscode: ^1.78.0}
|
||||
main: ./client/out/extension
|
||||
contributes:
|
||||
languages:
|
||||
- id: quest
|
||||
aliases:
|
||||
- Quest
|
||||
- quest
|
||||
extensions:
|
||||
- .quest
|
||||
configuration: ./language-configuration.json
|
||||
grammars:
|
||||
- language: quest
|
||||
scopeName: source.quest
|
||||
path: ./syntaxes/quest.tmLanguage.json
|
||||
configuration:
|
||||
title: OpenQuest
|
||||
properties:
|
||||
openquest.handlingMode:
|
||||
scope: window
|
||||
type: string
|
||||
enum:
|
||||
- Local Path
|
||||
- WebSocket
|
||||
default: Local Path
|
||||
description: >-
|
||||
Where and how to connect to a language server, or spawn a new process
|
||||
of one
|
||||
openquest.serverAddress:
|
||||
scope: window
|
||||
type: string
|
||||
markdownDescription: Language Server address to connect to (**Example:** localhost:5050)
|
||||
openquest.serverArguments:
|
||||
scope: window
|
||||
type: string
|
||||
description: Arguments to pass when initializing language server
|
||||
openquest.serverBinaryPath:
|
||||
scope: window
|
||||
type: string
|
||||
markdownDescription: >-
|
||||
Path of the language server executable (if not given, it will look in
|
||||
$PATH and consequentially $HOME)
|
||||
scripts:
|
||||
vscode:prepublish: pnpm run compile
|
||||
compile: tsc -b
|
||||
postinstall: cd client && pnpm install && cd ..
|
||||
watch: tsc -b -w
|
||||
lint: eslint ./client/src ./server/src --ext .ts,.tsx
|
||||
test: sh ./scripts/e2e.sh
|
||||
package-y2j: js-yaml package.yaml > package.json
|
||||
grammar-y2j: js-yaml syntaxes/quest.tmGrammar.yaml > syntaxes/quest.tmGrammar.json
|
||||
|
||||
dependencies:
|
||||
generator-code: ^1.7.7
|
||||
js-yaml: ^4.1.0
|
||||
ws: ^8.13.0
|
||||
|
||||
devDependencies:
|
||||
'@types/mocha': ^9.1.1
|
||||
'@types/node': ^16.18.34
|
||||
'@typescript-eslint/eslint-plugin': ^5.59.9
|
||||
'@typescript-eslint/parser': ^5.59.9
|
||||
'@types/ws': ^8.5.5
|
||||
eslint: ^8.42.0
|
||||
mocha: ^9.2.2
|
||||
typescript: ^5.1.3
|
33
syntaxes/quest.tmGrammar.json
Normal file
33
syntaxes/quest.tmGrammar.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||
"scopeName": "source.quest",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#quest_clause"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"quest": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#define_substitution"
|
||||
},
|
||||
{
|
||||
"include": "#quest_clause"
|
||||
}
|
||||
]
|
||||
},
|
||||
"define_substitution": {
|
||||
"name": "keyword.local.define_substitution"
|
||||
},
|
||||
"quest_clause": {
|
||||
"name": "keyword.control.quest_clause"
|
||||
},
|
||||
"state_clause": {
|
||||
"name": "keyword.control.state_clause"
|
||||
},
|
||||
"when_clause": {
|
||||
"name": "keyword.control.when_clause"
|
||||
}
|
||||
}
|
||||
}
|
31
syntaxes/quest.tmGrammar.yaml
Normal file
31
syntaxes/quest.tmGrammar.yaml
Normal file
|
@ -0,0 +1,31 @@
|
|||
$schema: https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json
|
||||
scopeName: source.quest
|
||||
|
||||
patterns:
|
||||
- {include: "#quest_clause"}
|
||||
|
||||
repository:
|
||||
quest:
|
||||
patterns:
|
||||
- {include: "#define_substitution"}
|
||||
- {include: "#quest_clause"}
|
||||
|
||||
# Pattern syntax:
|
||||
# define <name> <value(string, decimal, float, any)>
|
||||
define_substitution:
|
||||
name: keyword.local.define_substitution
|
||||
|
||||
# Pattern syntax:
|
||||
# quest <name> begin <define* | state_clause+> end
|
||||
quest_clause:
|
||||
name: keyword.control.quest_clause
|
||||
|
||||
# Pattern syntax:
|
||||
# state <name> begin <with_clause+> end
|
||||
state_clause:
|
||||
name: keyword.control.state_clause
|
||||
|
||||
# Pattern syntax:
|
||||
# when <name | name.cond> with <lua_expression> begin <lua_expression> end
|
||||
when_clause:
|
||||
name: keyword.control.when_clause
|
59
syntaxes/quest.tmLanguage.json
Normal file
59
syntaxes/quest.tmLanguage.json
Normal file
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||
"name": "Quest",
|
||||
"scopeName": "source.quest",
|
||||
"patterns": [
|
||||
{"include": "#define_substitution"},
|
||||
{"include": "#quest_clause"}
|
||||
],
|
||||
"repository": {
|
||||
|
||||
"define_substitution": {
|
||||
"name": "keyword.control.quest",
|
||||
"match": "\\b(define)\\s(.+)\\s(.+)\\b",
|
||||
"captures": {
|
||||
"1": {"name": "keyword.function"},
|
||||
"2": {"name": "entity.other.attribute-name"},
|
||||
"3": {"name": "variable.other"}
|
||||
}
|
||||
},
|
||||
|
||||
"quest_clause": {
|
||||
"begin": "\\b(quest)\\s(.+)\\s(with)\\s(.+)\\s(begin)",
|
||||
"beginCaptures": {
|
||||
"1": {"name": "keyword"},
|
||||
"2": {"name": "entity.other.attribute-name"},
|
||||
"3": {"name": "keyword"},
|
||||
"4": {"name": "variable.other"},
|
||||
"5": {"name": "punctuation.paren.open"}
|
||||
},
|
||||
"end": "end", "endCaptures": {"0": {"name": "punctuation.paren.close"}},
|
||||
"patterns": [{"include": "#state_clause"}]
|
||||
},
|
||||
|
||||
"state_clause": {
|
||||
"begin": "(state)\\s(.+)\\s(begin)",
|
||||
"beginCaptures": {
|
||||
"1": {"name": "keyword"},
|
||||
"2": {"name": "entity.other.attribute-name"},
|
||||
"3": {"name": "punctuation.paren.open"}
|
||||
},
|
||||
"end": "end", "endCaptures": {"0": {"name": "punctuation.paren.close"}},
|
||||
"patterns": [{"include": "#with_clause"}]
|
||||
},
|
||||
|
||||
"with_clause": {
|
||||
"name": "keyword.control.with_clause",
|
||||
"begin": "when\\s(.+)\\sbegin",
|
||||
"beginCaptures": {
|
||||
"0": {"name": "punctuation.paren.open"},
|
||||
"1": {"name": "storage.modifier.quest"}
|
||||
},
|
||||
"end": "end", "endCaptures": {"0": {"name": "punctuation.paren.close"}}
|
||||
},
|
||||
|
||||
"lua_scope": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2020",
|
||||
"lib": ["es2020"],
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".vscode-test"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "./client" },
|
||||
]
|
||||
}
|
29
vsc-extension-quickstart.md
Normal file
29
vsc-extension-quickstart.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Welcome to your VS Code Extension
|
||||
|
||||
## What's in the folder
|
||||
|
||||
* This folder contains all of the files necessary for your extension.
|
||||
* `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension.
|
||||
* `syntaxes/quest.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization.
|
||||
* `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets.
|
||||
|
||||
## Get up and running straight away
|
||||
|
||||
* Make sure the language configuration settings in `language-configuration.json` are accurate.
|
||||
* Press `F5` to open a new window with your extension loaded.
|
||||
* Create a new file with a file name suffix matching your language.
|
||||
* Verify that syntax highlighting works and that the language configuration settings are working.
|
||||
|
||||
## Make changes
|
||||
|
||||
* You can relaunch the extension from the debug toolbar after making changes to the files listed above.
|
||||
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
|
||||
|
||||
## Add more language features
|
||||
|
||||
* To add features such as IntelliSense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/docs
|
||||
|
||||
## Install your extension
|
||||
|
||||
* To start using your extension with Visual Studio Code copy it into the `<user home>/.vscode/extensions` folder and restart Code.
|
||||
* To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension.
|
Loading…
Reference in a new issue