merge main

This commit is contained in:
Myzel394 2024-11-03 18:24:43 +01:00
commit 1f6ecaff90
No known key found for this signature in database
GPG Key ID: ED20A1D1D423AF3F
42 changed files with 1311 additions and 552 deletions

View File

@ -1,58 +0,0 @@
name: Build nightly release
permissions:
contents: write
on:
release:
types: [ published ]
jobs:
build-release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check git version matches flake version
shell: bash
run: |
if ! [ $(echo '${{ github.ref }}' | cut -d'v' -f 2) = $(grep '# CI:CD-VERSION$' flake.nix | cut -d'"' -f 2) ];
then
echo "Version mismatch between Git and flake"
exit 1
fi
- name: Check version in code matches flake version
shell: bash
run: |
if ! [ $(grep '// CI:CD-VERSION$' server/root-handler/handler.go | cut -d'"' -f 2) = $(grep '# CI:CD-VERSION$' flake.nix | cut -d'"' -f 2) ];
then
echo "Version mismatch between code and flake"
exit 1
fi
- uses: cachix/install-nix-action@v27
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- name: Check Flake
run: nix flake check
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GH_CONFIGLSP_TOKEN }}

135
.github/workflows/release.yaml vendored Normal file
View File

@ -0,0 +1,135 @@
name: build and release
permissions:
contents: write
on:
release:
types: [ published ]
jobs:
build-server:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check git version matches flake version
shell: bash
run: |
if ! [ $(echo '${{ github.ref }}' | cut -d'v' -f 2) = $(grep '# CI:CD-VERSION$' flake.nix | cut -d'"' -f 2) ];
then
echo "Version mismatch between Git and flake"
exit 1
fi
- name: Check version in code matches flake version
shell: bash
run: |
if ! [ $(grep '// CI:CD-VERSION$' server/root-handler/common.go | cut -d'"' -f 2) = $(grep '# CI:CD-VERSION$' flake.nix | cut -d'"' -f 2) ];
then
echo "Version mismatch between code and flake"
exit 1
fi
- name: Check vs code package.json version matches flake version
shell: bash
run: |
if ! [ $(grep '"version": "' vs-code-extension/package.json | cut -d'"' -f 4) = $(grep '# CI:CD-VERSION$' flake.nix | cut -d'"' -f 2) ];
then
echo "Version mismatch between vs code package.json and flake"
exit 1
fi
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GH_CONFIGLSP_TOKEN }}
build-extension:
name: Build extension for ${{ matrix.target }}
runs-on: ubuntu-latest
needs:
# Wait for server to build so that we know the checks have passed
- build-server
strategy:
fail-fast: false
matrix:
include:
- goos: linux
goarch: amd64
vscode_target: linux-x64
- goos: linux
goarch: arm64
vscode_target: linux-arm64
- goos: darwin
goarch: amd64
vscode_target: darwin-x64
- goos: darwin
goarch: arm64
vscode_target: darwin-arm64
- goos: windows
goarch: amd64
vscode_target: win32-x64
- goos: windows
goarch: arm64
vscode_target: win32-arm64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v27
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Create bare extension
run: nix build .#"vs-code-extension-bare"
- name: Build extension
run: cd server && GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build -a -gcflags=all="-l -B" -ldflags="-s -w" -o config-lsp
- name: Prepare folder
run: cp -rL result dist && chmod -R 777 dist
- name: Move binary to extension
run: mv server/config-lsp dist/out/
- name: Shrink binary
if: ${{ matrix.goos == 'linux' }}
run: nix develop .#"vs-code-extension" --command bash -c "upx dist/out/config-lsp"
- name: Package extension
run: nix develop .#"vs-code-extension" --command bash -c "cd dist && vsce package --target ${{ matrix.vscode_target }}"
- name: Move vsix to root
run: mv dist/*.vsix .
- uses: softprops/action-gh-release@v2
with:
files: '*.vsix'
- name: Upload extension to VS Code Marketplace
run: nix develop .#"vs-code-extension" --command bash -c "vsce publish --packagePath *.vsix -p ${{ secrets.VSCE_PAT }}"

0
LICENSE.md Normal file
View File

View File

@ -8,7 +8,7 @@ A language server for configuration files. The goal is to make editing config fi
|-------------|-------------|--------------|---------|---------------|--------------|----------|------------------|
| aliases | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| fstab | ✅ | ✅ | ✅ | ❓ | ❓ | ❓ | 🟡 |
| hosts | ✅ | ✅ | ✅ | ✅ | ❓ | ❓ | 🟡 |
| hosts | ✅ | ✅ | ✅ | ✅ | ❓ | ❓ | |
| ssh_config | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| sshd_config | ✅ | ✅ | ✅ | ❓ | ✅ | ❓ | ✅ |
| wireguard | ✅ | ✅ | ✅ | ✅ | ❓ | ❓ | 🟡 |
@ -28,11 +28,52 @@ You are welcome to request any config file, as far as it's fairly well known.
## Installation
### VS Code Extension
[Install the extension from the marketplace](https://marketplace.visualstudio.com/items?itemName=myzel394.config-lsp)
Alternatively, you can also manually install the extension:
1. Download the latest extension version from the [release page](https://github.com/Myzel394/config-lsp/releases) - You can find the extension under the "assets" section. The filename ends with `.vsix`
2. Open VS Code
3. Open the extensions sidebar
4. In the top bar, click on the three dots and select "Install from VSIX..."
5. Select the just downloaded `.vsix` file
6. You may need to restart VS Code
7. Enjoy!
### Manual installation
To use `config-lsp` in any other editor, you'll need to install it manually.
Don't worry, it's easy!
#### Installing the latest Binary
##### Brew
```sh
brew install myzel394/formulae/config-lsp
```
##### Manual Binary
Download the latest binary from the [releases page](https://github.com/Myzel394/config-lsp/releases) and put it in your PATH.
Follow the instructions for your editor below.
##### Compiling
### Neovim installation
You can either compile the binary using go:
```sh
go build -o config-lsp
```
or build it using Nix:
```sh
nix flake build
```
#### Neovim installation
Using [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) you can add `config-lsp` by adding the following to your `lsp.lua` (filename might differ):
@ -57,14 +98,6 @@ end
lspconfig.config_lsp.setup {}
`````
### VS Code installation
The VS Code extension is currently in development. An official extension will be released soon.
However, at the moment you can also compile the extension yourself and run it in development mode.
**Do not create an extension and publish it yourself. Contribute to the official extension instead.**
## Supporting config-lsp
You can either contribute to the project, [see CONTRIBUTING.md](CONTRIBUTING.md), or you can sponsor me via [GitHub Sponsors](https://github.com/sponsors/Myzel394) or via [crypto currencies](https://github.com/Myzel394/contact-me?tab=readme-ov-file#donations).

View File

@ -23,7 +23,7 @@
"aarch64-windows"
] (system:
let
version = "0.1.0"; # CI:CD-VERSION
version = "0.1.2"; # CI:CD-VERSION
pkgs = import nixpkgs {
inherit system;
overlays = [
@ -37,21 +37,39 @@
inputs = [
pkgs.go_1_22
];
server = pkgs.buildGoModule {
serverUncompressed = pkgs.buildGoModule {
nativeBuildInputs = inputs;
pname = "github.com/Myzel394/config-lsp";
version = version;
src = ./server;
vendorHash = "sha256-s+sjOVvqU20+mbEFKg+RCD+dhScqSatk9eseX2IioPI";
vendorHash = "sha256-eO1eY+2XuOCd/dKwgFtu05+bnn/Cv8ZbUIwRjCwJF+U=";
ldflags = [ "-s" "-w" ];
checkPhase = ''
go test -v $(pwd)/...
'';
};
server = pkgs.stdenv.mkDerivation {
name = "config-lsp-${version}";
src = serverUncompressed;
buildInputs = [
pkgs.upx
];
buildPhase = ''
mkdir -p $out/bin
cp $src/bin/config-lsp $out/bin/
chmod +rw $out/bin/config-lsp
# upx is currently not supported for darwin
if [ "${system}" != "x86_64-darwin" ] && [ "${system}" != "aarch64-darwin" ]; then
upx --ultra-brute $out/bin/config-lsp
fi
'';
};
in {
packages = {
default = server;
"vs-code-extension" = let
name = "config-lsp-vs-code-extension";
"vs-code-extension-bare" = let
name = "config-lsp";
node-modules = pkgs.mkYarnPackage {
src = ./vs-code-extension;
name = name;
@ -60,13 +78,56 @@
yarnNix = ./vs-code-extension/yarn.nix;
buildPhase = ''
yarn --offline run compile
yarn --offline run compile:prod
'';
installPhase = ''
mv deps/${name}/out $out
cp ${server}/bin/config-lsp $out/
mkdir -p extension
# No idea why this is being created
rm deps/${name}/config-lsp
cp -rL deps/${name}/. extension
mkdir -p $out
cp -r extension/. $out
'';
distPhase = "true";
buildInputs = [
pkgs.vsce
];
};
in node-modules;
"vs-code-extension" = let
name = "config-lsp";
node-modules = pkgs.mkYarnPackage {
src = ./vs-code-extension;
name = name;
packageJSON = ./vs-code-extension/package.json;
yarnLock = ./vs-code-extension/yarn.lock;
yarnNix = ./vs-code-extension/yarn.nix;
buildPhase = ''
yarn --offline run compile:prod
'';
installPhase = ''
mkdir -p extension
# No idea why this is being created
rm deps/${name}/config-lsp
cp -rL deps/${name}/. extension
cp ${server}/bin/config-lsp extension/out/config-lsp
cd extension && ${pkgs.vsce}/bin/vsce package
mkdir -p $out
cp *.vsix $out
'';
distPhase = "true";
buildInputs = [
pkgs.vsce
];
};
in node-modules;
};
@ -82,6 +143,8 @@
devShells."vs-code-extension" = pkgs.mkShell {
buildInputs = [
pkgs.nodejs
pkgs.vsce
pkgs.yarn2nix
];
};
}

View File

@ -2,6 +2,8 @@ package main
import (
roothandler "config-lsp/root-handler"
"fmt"
"os"
"github.com/tliron/commonlog"
@ -11,6 +13,13 @@ import (
)
func main() {
if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "version") {
fmt.Println(roothandler.Version)
os.Exit(0)
return
}
// This increases logging verbosity (optional)
commonlog.Configure(1, nil)

View File

@ -0,0 +1,5 @@
package roothandler
// The comment below at the end of the line is required for the CI:CD to work.
// Do not remove it
var Version = "0.1.2" // CI:CD-VERSION

View File

@ -1,6 +1,8 @@
package roothandler
import (
"config-lsp/root-handler/lsp"
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
@ -9,32 +11,29 @@ import (
const lsName = "config-lsp"
// The comment below at the end of the line is required for the CI:CD to work.
// Do not remove it
var version = "0.1.0" // CI:CD-VERSION
var lspHandler protocol.Handler
// The root handler which handles all the LSP requests and then forwards them to the appropriate handler
func SetUpRootHandler() {
rootHandler = NewRootHandler()
shared.Handler = shared.NewRootHandler()
lspHandler = protocol.Handler{
Initialize: initialize,
Initialized: initialized,
Shutdown: shutdown,
SetTrace: setTrace,
TextDocumentDidOpen: TextDocumentDidOpen,
TextDocumentDidChange: TextDocumentDidChange,
TextDocumentCompletion: TextDocumentCompletion,
TextDocumentHover: TextDocumentHover,
TextDocumentDidClose: TextDocumentDidClose,
TextDocumentCodeAction: TextDocumentCodeAction,
TextDocumentDefinition: TextDocumentDefinition,
WorkspaceExecuteCommand: WorkspaceExecuteCommand,
TextDocumentRename: TextDocumentRename,
TextDocumentPrepareRename: TextDocumentPrepareRename,
TextDocumentSignatureHelp: TextDocumentSignatureHelp,
TextDocumentRangeFormatting: TextDocumentRangeFormattingFunc,
TextDocumentDidOpen: lsp.TextDocumentDidOpen,
TextDocumentDidChange: lsp.TextDocumentDidChange,
TextDocumentCompletion: lsp.TextDocumentCompletion,
TextDocumentHover: lsp.TextDocumentHover,
TextDocumentDidClose: lsp.TextDocumentDidClose,
TextDocumentCodeAction: lsp.TextDocumentCodeAction,
TextDocumentDefinition: lsp.TextDocumentDefinition,
WorkspaceExecuteCommand: lsp.WorkspaceExecuteCommand,
TextDocumentRename: lsp.TextDocumentRename,
TextDocumentPrepareRename: lsp.TextDocumentPrepareRename,
TextDocumentSignatureHelp: lsp.TextDocumentSignatureHelp,
TextDocumentRangeFormatting: lsp.TextDocumentRangeFormattingFunc,
}
server := server.NewServer(&lspHandler, lsName, false)
@ -72,7 +71,7 @@ func initialize(context *glsp.Context, params *protocol.InitializeParams) (any,
Capabilities: capabilities,
ServerInfo: &protocol.InitializeResultServerInfo{
Name: lsName,
Version: &version,
Version: &Version,
},
}, nil
}

View File

@ -1,149 +0,0 @@
package roothandler
import (
"config-lsp/common"
"config-lsp/utils"
"fmt"
"regexp"
"strings"
protocol "github.com/tliron/glsp/protocol_3_16"
)
type SupportedLanguage string
const (
LanguageSSHConfig SupportedLanguage = "ssh_config"
LanguageSSHDConfig SupportedLanguage = "sshd_config"
LanguageFstab SupportedLanguage = "fstab"
LanguageWireguard SupportedLanguage = "languagewireguard"
LanguageHosts SupportedLanguage = "hosts"
LanguageAliases SupportedLanguage = "aliases"
)
var AllSupportedLanguages = []string{
string(LanguageSSHConfig),
string(LanguageSSHDConfig),
string(LanguageFstab),
string(LanguageWireguard),
string(LanguageHosts),
string(LanguageAliases),
}
type FatalFileNotReadableError struct {
FileURI protocol.DocumentUri
Err error
}
func (e FatalFileNotReadableError) Error() string {
return fmt.Sprintf("Fatal error! config-lsp was unable to read the file (%s); error: %s", e.FileURI, e.Err.Error())
}
type UnsupportedLanguageError struct {
SuggestedLanguage string
}
func (e UnsupportedLanguageError) Error() string {
return fmt.Sprintf("Language '%s' is not supported. Choose one of: %s", e.SuggestedLanguage, strings.Join(AllSupportedLanguages, ", "))
}
type LanguageUndetectableError struct{}
func (e LanguageUndetectableError) Error() string {
return "Please add: '#?lsp.language=<language>' to the top of the file. config-lsp was unable to detect the appropriate language for this file."
}
var valueToLanguageMap = map[string]SupportedLanguage{
"sshd_config": LanguageSSHDConfig,
"sshdconfig": LanguageSSHDConfig,
"ssh_config": LanguageSSHConfig,
"sshconfig": LanguageSSHConfig,
".ssh/config": LanguageSSHConfig,
"~/.ssh/config": LanguageSSHConfig,
"fstab": LanguageFstab,
"etc/fstab": LanguageFstab,
"wireguard": LanguageWireguard,
"wg": LanguageWireguard,
"languagewireguard": LanguageWireguard,
"host": LanguageHosts,
"hosts": LanguageHosts,
"etc/hosts": LanguageHosts,
"aliases": LanguageAliases,
"mailaliases": LanguageAliases,
"etc/aliases": LanguageAliases,
}
var typeOverwriteRegex = regexp.MustCompile(`#\?\s*lsp\.language\s*=\s*(\w+)\s*`)
var wireguardPattern = regexp.MustCompile(`/wg\d+\.conf$`)
var undetectableError = common.ParseError{
Line: 0,
Err: LanguageUndetectableError{},
}
func DetectLanguage(
content string,
advertisedLanguage string,
uri protocol.DocumentUri,
) (SupportedLanguage, error) {
if match := typeOverwriteRegex.FindStringSubmatch(content); match != nil {
suggestedLanguage := strings.ToLower(match[1])
foundLanguage, ok := valueToLanguageMap[suggestedLanguage]
if ok {
return foundLanguage, nil
}
matchIndex := strings.Index(content, match[0])
contentUntilMatch := content[:matchIndex]
return "", common.ParseError{
Line: uint32(utils.CountCharacterOccurrences(contentUntilMatch, '\n')),
Err: UnsupportedLanguageError{
SuggestedLanguage: suggestedLanguage,
},
}
}
if language, ok := valueToLanguageMap[advertisedLanguage]; ok {
return language, nil
}
switch uri {
case "file:///etc/ssh/sshd_config":
fallthrough
case "file:///etc/ssh/ssh_config":
return LanguageSSHDConfig, nil
case "file:///etc/fstab":
return LanguageFstab, nil
// Darwin
case "file:///private/etc/hosts":
fallthrough
case "file:///etc/hosts":
return LanguageHosts, nil
// Darwin
case "file:///private/etc/aliases":
fallthrough
case "file:///etc/aliases":
return LanguageAliases, nil
}
if strings.HasPrefix(uri, "file:///etc/wireguard/") || wireguardPattern.MatchString(uri) {
return LanguageWireguard, nil
}
if strings.HasSuffix(uri, ".ssh/config") {
return LanguageSSHConfig, nil
}
return "", undetectableError
}

View File

@ -1,40 +1,36 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
hosts "config-lsp/handlers/hosts/lsp"
sshconfig "config-lsp/handlers/ssh_config/lsp"
wireguard "config-lsp/handlers/wireguard/lsp"
"config-lsp/root-handler/shared"
utils "config-lsp/root-handler/utils"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentCodeAction(context *glsp.Context, params *protocol.CodeActionParams) (any, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, nil
return utils.FetchAddLanguageActions(params.TextDocument.URI)
}
switch *language {
case LanguageFstab:
case shared.LanguageFstab:
return nil, nil
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentCodeAction(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return nil, nil
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentCodeAction(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentCodeAction(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentCodeAction(context, params)
}

View File

@ -1,4 +1,4 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
@ -7,36 +7,30 @@ import (
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
wireguard "config-lsp/handlers/wireguard/lsp"
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (any, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, nil
}
switch *language {
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentCompletion(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentCompletion(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentCompletion(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentCompletion(context, params)
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentCompletion(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentCompletion(context, params)
}

View File

@ -1,39 +1,35 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
"config-lsp/root-handler/shared"
"config-lsp/root-handler/utils"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentDefinition(context *glsp.Context, params *protocol.DefinitionParams) (any, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, utils.LanguageUndetectableError{}
}
switch *language {
case LanguageHosts:
case shared.LanguageHosts:
return nil, nil
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentDefinition(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentDefinition(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return nil, nil
case LanguageWireguard:
case shared.LanguageWireguard:
return nil, nil
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentDefinition(context, params)
}

View File

@ -1,4 +1,4 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
@ -7,27 +7,27 @@ import (
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
wireguard "config-lsp/handlers/wireguard/lsp"
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentDidChange(context *glsp.Context, params *protocol.DidChangeTextDocumentParams) error {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
content := params.ContentChanges[0].(protocol.TextDocumentContentChangeEventWhole).Text
newLanguage, err := initFile(
context,
content,
params.TextDocument.URI,
"",
)
content := params.ContentChanges[0].(protocol.TextDocumentContentChangeEventWhole).Text
newLanguage, err := initFile(
context,
content,
params.TextDocument.URI,
"",
)
if err != nil {
return err
}
if err != nil {
return err
}
if newLanguage != language {
language = newLanguage
params := &protocol.DidOpenTextDocumentParams{
@ -40,33 +40,33 @@ func TextDocumentDidChange(context *glsp.Context, params *protocol.DidChangeText
}
switch *language {
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentDidOpen(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentDidOpen(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentDidOpen(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentDidOpen(context, params)
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentDidOpen(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentDidOpen(context, params)
}
}
switch *language {
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentDidChange(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentDidChange(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentDidChange(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentDidChange(context, params)
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentDidChange(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentDidChange(context, params)
}

View File

@ -1,4 +1,4 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
@ -7,39 +7,34 @@ import (
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
wireguard "config-lsp/handlers/wireguard/lsp"
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentDidClose(context *glsp.Context, params *protocol.DidCloseTextDocumentParams) error {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return undetectableError.Err
return nil
}
delete(openedFiles, params.TextDocument.URI)
rootHandler.RemoveDocument(params.TextDocument.URI)
delete(shared.OpenedFiles, params.TextDocument.URI)
delete(shared.LanguagesOverwrites, params.TextDocument.URI)
shared.Handler.RemoveDocument(params.TextDocument.URI)
switch *language {
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentDidClose(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentDidClose(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentDidClose(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentDidClose(context, params)
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentDidClose(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentDidClose(context, params)
default:
}

View File

@ -1,7 +1,9 @@
package roothandler
package lsp
import (
"config-lsp/common"
"config-lsp/root-handler/shared"
"config-lsp/root-handler/utils"
"fmt"
aliases "config-lsp/handlers/aliases/lsp"
@ -32,60 +34,43 @@ func TextDocumentDidOpen(context *glsp.Context, params *protocol.DidOpenTextDocu
}
switch *language {
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentDidOpen(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentDidOpen(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentDidOpen(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentDidOpen(context, params)
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentDidOpen(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentDidOpen(context, params)
}
panic(fmt.Sprintf("unexpected roothandler.SupportedLanguage: %#v", language))
}
func showParseError(
context *glsp.Context,
uri protocol.DocumentUri,
err common.ParseError,
) {
context.Notify(
"window/showMessage",
protocol.ShowMessageParams{
Type: protocol.MessageTypeError,
Message: err.Err.Error(),
},
)
}
func initFile(
context *glsp.Context,
content string,
uri protocol.DocumentUri,
advertisedLanguage string,
) (*SupportedLanguage, error) {
language, err := DetectLanguage(content, advertisedLanguage, uri)
) (*shared.SupportedLanguage, error) {
language, err := utils.DetectLanguage(content, advertisedLanguage, uri)
if err != nil {
parseError := err.(common.ParseError)
showParseError(
context,
uri,
parseError,
)
utils.NotifyLanguageUndetectable(context, uri)
return nil, parseError.Err
return nil, utils.LanguageUndetectableError{}
} else {
utils.NotifyDetectedLanguage(context, uri, language)
}
openedFiles[uri] = struct{}{}
shared.OpenedFiles[uri] = struct{}{}
// Everything okay, now we can handle the file
rootHandler.AddDocument(uri, language)
shared.Handler.AddDocument(uri, language)
return &language, nil
}

View File

@ -1,4 +1,4 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
@ -7,36 +7,30 @@ import (
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
wireguard "config-lsp/handlers/wireguard/lsp"
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentHover(context *glsp.Context, params *protocol.HoverParams) (*protocol.Hover, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, nil
}
switch *language {
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentHover(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentHover(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentHover(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentHover(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return wireguard.TextDocumentHover(context, params)
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentHover(context, params)
}

View File

@ -1,8 +1,10 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
sshconfig "config-lsp/handlers/ssh_config/lsp"
"config-lsp/root-handler/shared"
"config-lsp/root-handler/utils"
"github.com/tliron/glsp"
@ -10,30 +12,24 @@ import (
)
func TextDocumentPrepareRename(context *glsp.Context, params *protocol.PrepareRenameParams) (any, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, utils.LanguageUndetectableError{}
}
switch *language {
case LanguageHosts:
case shared.LanguageHosts:
return nil, nil
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return nil, nil
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentPrepareRename(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return nil, nil
case LanguageWireguard:
case shared.LanguageWireguard:
return nil, nil
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentPrepareRename(context, params)
}

View File

@ -1,8 +1,10 @@
package roothandler
package lsp
import (
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
"config-lsp/root-handler/shared"
"config-lsp/root-handler/utils"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
@ -12,30 +14,24 @@ func TextDocumentRangeFormattingFunc(
context *glsp.Context,
params *protocol.DocumentRangeFormattingParams,
) ([]protocol.TextEdit, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, utils.LanguageUndetectableError{}
}
switch *language {
case LanguageHosts:
case shared.LanguageHosts:
return nil, nil
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentRangeFormatting(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentRangeFormatting(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return nil, nil
case LanguageWireguard:
case shared.LanguageWireguard:
return nil, nil
case LanguageAliases:
case shared.LanguageAliases:
return nil, nil
}

View File

@ -1,38 +1,34 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
sshconfig "config-lsp/handlers/ssh_config/lsp"
"config-lsp/root-handler/shared"
"config-lsp/root-handler/utils"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentRename(context *glsp.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, utils.LanguageUndetectableError{}
}
switch *language {
case LanguageHosts:
case shared.LanguageHosts:
return nil, nil
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return nil, nil
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentRename(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return nil, nil
case LanguageWireguard:
case shared.LanguageWireguard:
return nil, nil
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentRename(context, params)
}

View File

@ -1,4 +1,4 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"
@ -6,36 +6,30 @@ import (
hosts "config-lsp/handlers/hosts/lsp"
sshconfig "config-lsp/handlers/ssh_config/lsp"
sshdconfig "config-lsp/handlers/sshd_config/lsp"
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func TextDocumentSignatureHelp(context *glsp.Context, params *protocol.SignatureHelpParams) (*protocol.SignatureHelp, error) {
language := rootHandler.GetLanguageForDocument(params.TextDocument.URI)
language := shared.Handler.GetLanguageForDocument(params.TextDocument.URI)
if language == nil {
showParseError(
context,
params.TextDocument.URI,
undetectableError,
)
return nil, undetectableError.Err
return nil, nil
}
switch *language {
case LanguageHosts:
case shared.LanguageHosts:
return hosts.TextDocumentSignatureHelp(context, params)
case LanguageSSHDConfig:
case shared.LanguageSSHDConfig:
return sshdconfig.TextDocumentSignatureHelp(context, params)
case LanguageSSHConfig:
case shared.LanguageSSHConfig:
return sshconfig.TextDocumentSignatureHelp(context, params)
case LanguageFstab:
case shared.LanguageFstab:
return fstab.TextDocumentSignatureHelp(context, params)
case LanguageWireguard:
case shared.LanguageWireguard:
return nil, nil
case LanguageAliases:
case shared.LanguageAliases:
return aliases.TextDocumentSignatureHelp(context, params)
}

View File

@ -1,4 +1,4 @@
package roothandler
package lsp
import (
aliases "config-lsp/handlers/aliases/lsp"

View File

@ -1,5 +0,0 @@
package roothandler
import protocol "github.com/tliron/glsp/protocol_3_16"
var openedFiles = make(map[protocol.DocumentUri]struct{})

View File

@ -0,0 +1,21 @@
package shared
type SupportedLanguage string
const (
LanguageSSHConfig SupportedLanguage = "ssh_config"
LanguageSSHDConfig SupportedLanguage = "sshd_config"
LanguageFstab SupportedLanguage = "fstab"
LanguageWireguard SupportedLanguage = "languagewireguard"
LanguageHosts SupportedLanguage = "hosts"
LanguageAliases SupportedLanguage = "aliases"
)
var AllSupportedLanguages = []string{
string(LanguageSSHConfig),
string(LanguageSSHDConfig),
string(LanguageFstab),
string(LanguageWireguard),
string(LanguageHosts),
string(LanguageAliases),
}

View File

@ -0,0 +1,16 @@
package shared
import (
protocol "github.com/tliron/glsp/protocol_3_16"
)
type LanguageOverwrite struct {
Language SupportedLanguage
// The start of the overwrite
Raw string
Line uint32
Character uint32
}
var LanguagesOverwrites = map[protocol.DocumentUri]LanguageOverwrite{}

View File

@ -1,10 +1,12 @@
package roothandler
package shared
import (
protocol "github.com/tliron/glsp/protocol_3_16"
)
var rootHandler RootHandler
var Handler RootHandler
var OpenedFiles = make(map[protocol.DocumentUri]struct{})
type RootHandler struct {
languageMap map[protocol.DocumentUri]SupportedLanguage

View File

@ -0,0 +1,44 @@
package utils
import (
"config-lsp/root-handler/shared"
"fmt"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func FetchAddLanguageActions(uri protocol.DocumentUri) ([]protocol.CodeAction, error) {
actions := make([]protocol.CodeAction, 0, len(shared.AllSupportedLanguages))
kind := protocol.CodeActionKindQuickFix
isPreferred := true
for _, language := range shared.AllSupportedLanguages {
actions = append(actions, protocol.CodeAction{
Title: fmt.Sprintf("Use %s for this file", language),
Kind: &kind,
IsPreferred: &isPreferred,
Edit: &protocol.WorkspaceEdit{
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
uri: {
{
Range: protocol.Range{
Start: protocol.Position{
Line: 0,
Character: 0,
},
End: protocol.Position{
Line: 0,
Character: 0,
},
},
NewText: fmt.Sprintf("#?lsp.language=%s\n", language),
},
},
},
},
})
}
return actions, nil
}

View File

@ -0,0 +1,158 @@
package utils
import (
"config-lsp/common"
"config-lsp/root-handler/shared"
"config-lsp/utils"
"fmt"
"path"
"regexp"
"strings"
protocol "github.com/tliron/glsp/protocol_3_16"
)
type UnsupportedLanguageError struct {
SuggestedLanguage string
}
func (e UnsupportedLanguageError) Error() string {
return fmt.Sprintf("Language '%s' is not supported. Choose one of: %s", e.SuggestedLanguage, strings.Join(shared.AllSupportedLanguages, ", "))
}
type LanguageUndetectableError struct{}
func (e LanguageUndetectableError) Error() string {
return "Please add: '#?lsp.language=<language>' to the top of the file. config-lsp was unable to detect the appropriate language for this file."
}
var valueToLanguageMap = map[string]shared.SupportedLanguage{
"sshd_config": shared.LanguageSSHDConfig,
"sshdconfig": shared.LanguageSSHDConfig,
"ssh_config": shared.LanguageSSHConfig,
"sshconfig": shared.LanguageSSHConfig,
".ssh/config": shared.LanguageSSHConfig,
"~/.ssh/config": shared.LanguageSSHConfig,
"fstab": shared.LanguageFstab,
"etc/fstab": shared.LanguageFstab,
"wireguard": shared.LanguageWireguard,
"wg": shared.LanguageWireguard,
"languagewireguard": shared.LanguageWireguard,
"host": shared.LanguageHosts,
"hosts": shared.LanguageHosts,
"etc/hosts": shared.LanguageHosts,
"aliases": shared.LanguageAliases,
"mailaliases": shared.LanguageAliases,
"etc/aliases": shared.LanguageAliases,
}
var filenameToLanguageMap = map[string]shared.SupportedLanguage{
"sshd_config": shared.LanguageSSHDConfig,
"sshdconfig": shared.LanguageSSHDConfig,
"sshd": shared.LanguageSSHDConfig,
"sshd_conf": shared.LanguageSSHDConfig,
"sshdconf": shared.LanguageSSHDConfig,
"ssh_config": shared.LanguageSSHConfig,
"sshconfig": shared.LanguageSSHConfig,
"ssh": shared.LanguageSSHConfig,
"ssh_conf": shared.LanguageSSHConfig,
"sshconf": shared.LanguageSSHConfig,
"fstab": shared.LanguageFstab,
"hosts": shared.LanguageHosts,
"aliases": shared.LanguageAliases,
"mailaliases": shared.LanguageAliases,
}
var typeOverwriteRegex = regexp.MustCompile(`#\?\s*lsp\.language\s*=\s*(\w+)\s*`)
var wireguardPattern = regexp.MustCompile(`wg(\d+)?(\.conf)?$`)
var undetectableError = common.ParseError{
Line: 0,
Err: LanguageUndetectableError{},
}
func DetectLanguage(
content string,
advertisedLanguage string,
uri protocol.DocumentUri,
) (shared.SupportedLanguage, error) {
if match := typeOverwriteRegex.FindStringSubmatchIndex(content); match != nil {
text := content[match[0]:match[1]]
language := content[match[2]:match[3]]
suggestedLanguage := strings.ToLower(language)
foundLanguage, ok := valueToLanguageMap[suggestedLanguage]
contentUntilMatch := content[:match[0]]
if ok {
line := uint32(utils.CountCharacterOccurrences(contentUntilMatch, '\n'))
shared.LanguagesOverwrites[uri] = shared.LanguageOverwrite{
Language: foundLanguage,
Raw: text,
Line: line,
Character: uint32(match[0]),
}
return foundLanguage, nil
}
return "", common.ParseError{
Line: uint32(utils.CountCharacterOccurrences(contentUntilMatch, '\n')),
Err: UnsupportedLanguageError{
SuggestedLanguage: suggestedLanguage,
},
}
}
if language, ok := valueToLanguageMap[advertisedLanguage]; ok {
return language, nil
}
switch uri {
case "file:///etc/ssh/sshd_config":
fallthrough
case "file:///etc/ssh/ssh_config":
return shared.LanguageSSHDConfig, nil
case "file:///etc/fstab":
return shared.LanguageFstab, nil
// Darwin
case "file:///private/etc/hosts":
fallthrough
case "file:///etc/hosts":
return shared.LanguageHosts, nil
// Darwin
case "file:///private/etc/aliases":
fallthrough
case "file:///etc/aliases":
return shared.LanguageAliases, nil
}
filename := path.Base(string(uri))
if language, found := filenameToLanguageMap[filename]; found {
return language, nil
}
if strings.HasPrefix(uri, "file:///etc/wireguard/") || wireguardPattern.MatchString(uri) {
return shared.LanguageWireguard, nil
}
if strings.HasSuffix(uri, ".ssh/config") {
return shared.LanguageSSHConfig, nil
}
return "", undetectableError
}

View File

@ -0,0 +1,46 @@
package utils
import (
"config-lsp/root-handler/shared"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)
type lspNotification struct {
Uri string
}
type lspDetectedLanguage struct {
lspNotification
Language string
}
func NotifyLanguageUndetectable(context *glsp.Context, uri protocol.DocumentUri) {
go context.Notify(
"$/config-lsp/languageUndetectable",
lspNotification{
Uri: string(uri),
},
)
go context.Notify(
"window/showMessage",
protocol.ShowMessageParams{
Type: protocol.MessageTypeError,
Message: "config-lsp was unable to detect the appropriate language for this file. Please add: '#?lsp.language=<language>'.",
},
)
}
func NotifyDetectedLanguage(context *glsp.Context, uri protocol.DocumentUri, language shared.SupportedLanguage) {
go context.Notify(
"$/config-lsp/detectedLanguage",
lspDetectedLanguage{
lspNotification: lspNotification{
Uri: string(uri),
},
Language: string(language),
},
)
}

View File

@ -1,14 +0,0 @@
.vscode/**
**/*.ts
**/*.map
.gitignore
**/tsconfig.json
**/tsconfig.base.json
contributing.md
.travis.yml
client/node_modules/**
!client/node_modules/vscode-jsonrpc/**
!client/node_modules/vscode-languageclient/**
!client/node_modules/vscode-languageserver-protocol/**
!client/node_modules/vscode-languageserver-types/**
!client/node_modules/semver/**

View File

View File

@ -1,27 +1,21 @@
# LSP Example for Embedded Language using Language Service
# config-lsp for VS Code
Heavily documented sample code for https://code.visualstudio.com/api/language-extensions/embedded-languages#language-services
`config-lsp` provides language support for various config files.
Currently it supports completions, diagnostics, hints, formatting, hover information,
and definition requests.
## Functionality
Install this extension and load your config files in VS Code to get started.
This extension contributes a new language, `html1`. The new language is for illustration purpose and has basic syntax highlighting.
If `config-lsp` is unable to detect the language of your config file, you can manually
specify it by adding a line in the form of:
This Language Server works for `html1` file. HTML1 is like HTML file but has file extension `.html1`. You can create a `test.html1` file to play with below functionalities:
```plaintext
#?lsp.language=<language>
- Completions for HTML tags
- Completions for CSS in `<style>` tag
- Diagnostics for CSS
# For example
## Running the Sample
#?lsp.language=sshconfig
#?lsp.language=fstab
#?lsp.language=aliases
```
- Run `npm install` in this folder. This installs all necessary npm modules in both the client and server folder
- Open VS Code on this folder.
- Press Ctrl+Shift+B to compile the client and server.
- Switch to the Debug viewlet.
- Select `Launch Client` from the drop down.
- Run the launch config.
- If you want to debug the server as well use the launch configuration `Attach to Server`
- In the [Extension Development Host] instance of VSCode, open a HTML document
- Type `<d|` to try HTML completion
- Type `<style>.foo { c| }</style>` to try CSS completion
- Have `<style>.foo { }</style>` to see CSS Diagnostics

View File

@ -1,10 +0,0 @@
#!/bin/sh
rm -rf ./result
rm -rf ./vs-code-extension/out
nix build .#"vs-code-extension"
mkdir ./vs-code-extension/out
cp ./result/* ./vs-code-extension/out
chmod 777 ./vs-code-extension/out -R

View File

@ -0,0 +1,57 @@
const esbuild = require('esbuild');
const production = process.argv.includes('--production');
const watch = process.argv.includes('--watch');
async function main() {
const ctx = await esbuild.context({
entryPoints: ['src/extension.ts'],
bundle: true,
format: 'cjs',
minify: production,
sourcemap: !production,
sourcesContent: false,
platform: 'node',
outfile: 'out/extension.js',
external: ['vscode'],
logLevel: 'silent',
// According to https://github.com/ewanharris/vscode-versions, VS Code ships with NodeJS version 16.14.2
// and according to https://node.green/ this version supports ES2022.
target: "es2022",
plugins: [
/* add to the end of plugins array */
esbuildProblemMatcherPlugin
]
});
if (watch) {
await ctx.watch();
} else {
await ctx.rebuild();
await ctx.dispose();
}
}
/**
* @type {import('esbuild').Plugin}
*/
const esbuildProblemMatcherPlugin = {
name: 'esbuild-problem-matcher',
setup(build) {
build.onStart(() => {
console.log('[watch] build started');
});
build.onEnd(result => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`);
console.error(` ${location.file}:${location.line}:${location.column}:`);
});
console.log('[watch] build finished');
});
}
};
main().catch(e => {
console.error(e);
process.exit(1);
});

BIN
vs-code-extension/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -1,39 +1,129 @@
{
"name": "config-lsp-vs-code-extension",
"description": "A language server example using language services to support embedded languages",
"author": "Microsoft Corporation",
"license": "MIT",
"version": "0.1.0",
"name": "config-lsp",
"description": "Language Features (completions, diagnostics, etc.) for your config files: gitconfig, fstab, aliases, hosts, wireguard, ssh_config, sshd_config, and more to come!",
"author": "Myzel394",
"version": "0.1.2",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/vscode-extension-samples"
"url": "https://github.com/Myzel394/config-lsp"
},
"publisher": "vscode-samples",
"categories": [],
"keywords": [],
"engines": {
"vscode": "^1.74.0"
"publisher": "myzel394",
"categories": [
"Programming Languages",
"Formatters"
],
"preview": true,
"contributes": {
"languages": [
{
"id": "sshconfig",
"extensions": ["sshconfig", "ssh_config"],
"aliases": ["SSH Config", "sshconfig"],
"filenames": ["sshconfig", "ssh_config"],
"filenamePatterns": ["~/.ssh/config", "**/sshconfig", "**/ssh_config"]
},
{
"id": "sshdconfig",
"extensions": ["sshdconfig", "sshd_config"],
"aliases": ["SSH Daemon Config", "sshdconfig"],
"filenames": ["sshdconfig", "sshd_config"],
"filenamePatterns": ["/etc/ssh/sshd_config", "**/sshdconfig", "**/sshd_config"]
},
{
"id": "aliases",
"extensions": ["aliases", "mailaliases"],
"aliases": ["Mail Aliases", "aliases", "mailaliases"],
"filenames": ["aliases", "mailaliases"],
"filenamePatterns": ["/etc/aliases", "**/aliases", "**/mailaliases"]
},
{
"id": "fstab",
"extensions": ["fstab"],
"aliases": ["fstab"],
"filenames": ["fstab"],
"filenamePatterns": ["/etc/fstab", "**/fstab", "**/etc/fstab"]
},
{
"id": "hosts",
"extensions": ["hosts"],
"aliases": ["hosts"],
"filenames": ["hosts"],
"filenamePatterns": ["/etc/hosts", "**/hosts", "**/etc/hosts"]
},
{
"id": "wireguard",
"extensions": ["wireguard", "wg"],
"aliases": ["WireGuard", "wireguard", "wg"],
"filenames": ["wireguard", "wg0.conf", "wg1.conf", "wg0", "wg1"],
"filenamePatterns": ["/etc/wireguard/*.conf", "**/wireguard", "**/wireguard.conf"]
}
]
},
"activationEvents": [
"onLanguage:plaintext",
"onLanguage:yaml"
"onLanguage:yaml",
"onLanguage:sshconfig",
"onLanguage:sshdconfig",
"onLanguage:aliases",
"onLanguage:fstab",
"onLanguage:hosts",
"onLanguage:wireguard"
],
"main": "./out/extension",
"sponsor": {
"url": "https://github.com/Myzel394/contact-me"
},
"icon": "icon.png",
"galleryBanner": {
"color": "#373435",
"theme": "dark"
},
"files": [
"out",
"package.json",
"LICENSE.md",
"icon.png"
],
"keywords": [
"config",
"lsp",
"language",
"configuration",
"help",
"autocomplete",
"completions",
"diagnostics",
"hints",
"format",
"ssh",
"ssh_config",
"sshd_config",
"wireguard",
"fstab",
"hosts",
"aliases"
],
"engines": {
"vscode": "^1.74.0"
},
"main": "./out/extension.js",
"scripts": {
"compile": "tsc -b",
"compile": "node esbuild.js",
"compile:prod": "node esbuild.js --production",
"watch": "tsc -b -w",
"lint": "eslint ./src --ext .ts,.tsx"
"lint": "eslint ./src"
},
"dependencies": {
"vscode-languageclient": "^9.0.1"
"vscode-languageclient": "^9.0.1",
"esbuild": "^0.24.0"
},
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^22.7.4",
"@types/vscode": "^1.74.0",
"@typescript-eslint/eslint-plugin": "^7.14.0",
"@typescript-eslint/parser": "^7.14.0",
"eslint": "^9.11.1",
"typescript": "^5.5.2",
"@types/vscode": "^1.93.0"
"typescript": "^5.5.2"
}
}

View File

@ -0,0 +1,34 @@
import { GenericNotificationHandler } from "vscode-languageclient";
import * as vscode from "vscode";
const ACTION_SELECT_LANGUAGE = "Select Language";
const ACTION_DISABLE = "Ignore for this file";
const ignoredFiled = new Set<string>();
export const onUndetectable: GenericNotificationHandler = async (params: LSPLanguageUndetectable) => {
if (ignoredFiled.has(params.Uri)) {
return;
}
const result = await vscode.window.showWarningMessage(
"config-lsp was unable to detect the appropriate language for this file",
{
detail: "Either select a language or add '#?lsp.language=<language>' to the top of the file",
},
ACTION_SELECT_LANGUAGE,
ACTION_DISABLE,
)
switch (result) {
case ACTION_SELECT_LANGUAGE:
vscode.commands.executeCommand("workbench.action.editor.changeLanguageMode");
break;
case ACTION_DISABLE:
ignoredFiled.add(params.Uri);
break;
undefined:
break;
}
}

View File

@ -0,0 +1,6 @@
interface LSPNotification {
Uri: string;
}
interface LSPLanguageUndetectable extends LSPNotification {}

View File

@ -1,32 +1,30 @@
import * as path from "path"
import { ExtensionContext, workspace } from 'vscode';
import * as path from "path";
import { ExtensionContext, workspace } from "vscode";
import {
Executable,
LanguageClient,
type LanguageClientOptions,
type ServerOptions,
} from 'vscode-languageclient/node';
} from "vscode-languageclient/node";
import { onUndetectable } from "./events/on-undetectable";
const IS_DEBUG = process.env.VSCODE_DEBUG_MODE === 'true' || process.env.NODE_ENV === 'development';
const IS_DEBUG =
process.env.VSCODE_DEBUG_MODE === "true" ||
process.env.NODE_ENV === "development";
let client: LanguageClient;
export function activate(context: ExtensionContext) {
export async function activate({subscriptions}: ExtensionContext) {
console.info("config-lsp activated");
const initOptions = workspace.getConfiguration('config-lsp');
const initOptions = workspace.getConfiguration("config-lsp");
const clientOptions: LanguageClientOptions = {
documentSelector: [
{
scheme: 'file',
language: 'plaintext',
pattern: "**/{config,sshconfig,sshd_config,sshdconfig,fstab,hosts,aliases}",
},
// Some configs seem to be incorrectly detected as yaml
{
scheme: 'file',
language: 'yaml',
pattern: "**/{config,sshconfig,sshd_config,sshdconfig,fstab,hosts,aliases}",
},
{language: "sshconfig"},
{language: "sshdconfig"},
{language: "aliases"},
{language: "fstab"},
{language: "hosts"},
{language: "wireguard"},
],
initializationOptions: initOptions,
};
@ -34,39 +32,29 @@ export function activate(context: ExtensionContext) {
const path = getBundledPath();
console.info(`Found config-lsp path at ${path}`);
const run: Executable = {
command: getBundledPath(),
}
command: getBundledPath() ,
};
const serverOptions: ServerOptions = {
run,
debug: run,
}
};
client = new LanguageClient(
'config-lsp',
"config-lsp",
serverOptions,
clientOptions,
IS_DEBUG,
IS_DEBUG
);
console.info("Starting config-lsp...");
await client.start();
console.info("Started config-lsp");
client.start();
console.info("config-lsp started");
// const serverOptions: ServerOptions = {
// }
//
// // Create the language client and start the client.
// client = new LanguageClient(
// 'languageServerExample',
// clientOptions
// );
//
// // Start the client. This will also launch the server
// client.start();
subscriptions.push(client.onNotification("$/config-lsp/languageUndetectable", onUndetectable))
}
function getBundledPath(): string {
const filePath = path.resolve(__dirname, "config-lsp")
const filePath = path.resolve(__dirname, "config-lsp");
return filePath;
}

View File

@ -1 +0,0 @@
{"root":["./src/extension.ts"],"version":"5.6.2"}

View File

@ -0,0 +1,4 @@
#!/bin/sh
cd vs-code-extension && yarn install --no-frozen-lockfile && yarn2nix > yarn.nix

View File

@ -2,6 +2,126 @@
# yarn lockfile v1
"@esbuild/aix-ppc64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c"
integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==
"@esbuild/android-arm64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0"
integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==
"@esbuild/android-arm@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810"
integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==
"@esbuild/android-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705"
integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==
"@esbuild/darwin-arm64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd"
integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==
"@esbuild/darwin-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107"
integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==
"@esbuild/freebsd-arm64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7"
integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==
"@esbuild/freebsd-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93"
integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==
"@esbuild/linux-arm64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75"
integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==
"@esbuild/linux-arm@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d"
integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==
"@esbuild/linux-ia32@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb"
integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==
"@esbuild/linux-loong64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c"
integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==
"@esbuild/linux-mips64el@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3"
integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==
"@esbuild/linux-ppc64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e"
integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==
"@esbuild/linux-riscv64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25"
integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==
"@esbuild/linux-s390x@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319"
integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==
"@esbuild/linux-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef"
integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==
"@esbuild/netbsd-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c"
integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==
"@esbuild/openbsd-arm64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2"
integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==
"@esbuild/openbsd-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf"
integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==
"@esbuild/sunos-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4"
integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==
"@esbuild/win32-arm64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b"
integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==
"@esbuild/win32-ia32@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103"
integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==
"@esbuild/win32-x64@0.24.0":
version "0.24.0"
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244"
integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
@ -113,7 +233,7 @@
dependencies:
undici-types "~6.19.2"
"@types/vscode@^1.93.0":
"@types/vscode@^1.74.0":
version "1.94.0"
resolved "https://registry.npmjs.org/@types/vscode/-/vscode-1.94.0.tgz#ccd2111b6ecaba6ad4da19c2d524828fa73ae250"
integrity sha512-UyQOIUT0pb14XSqJskYnRwD2aG0QrPVefIfrW1djR+/J4KeFQ0i1+hjZoaAmeNf3Z2jleK+R2hv+EboG/m8ruw==
@ -326,6 +446,36 @@ dir-glob@^3.0.1:
dependencies:
path-type "^4.0.0"
esbuild@^0.24.0:
version "0.24.0"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7"
integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==
optionalDependencies:
"@esbuild/aix-ppc64" "0.24.0"
"@esbuild/android-arm" "0.24.0"
"@esbuild/android-arm64" "0.24.0"
"@esbuild/android-x64" "0.24.0"
"@esbuild/darwin-arm64" "0.24.0"
"@esbuild/darwin-x64" "0.24.0"
"@esbuild/freebsd-arm64" "0.24.0"
"@esbuild/freebsd-x64" "0.24.0"
"@esbuild/linux-arm" "0.24.0"
"@esbuild/linux-arm64" "0.24.0"
"@esbuild/linux-ia32" "0.24.0"
"@esbuild/linux-loong64" "0.24.0"
"@esbuild/linux-mips64el" "0.24.0"
"@esbuild/linux-ppc64" "0.24.0"
"@esbuild/linux-riscv64" "0.24.0"
"@esbuild/linux-s390x" "0.24.0"
"@esbuild/linux-x64" "0.24.0"
"@esbuild/netbsd-x64" "0.24.0"
"@esbuild/openbsd-arm64" "0.24.0"
"@esbuild/openbsd-x64" "0.24.0"
"@esbuild/sunos-x64" "0.24.0"
"@esbuild/win32-arm64" "0.24.0"
"@esbuild/win32-ia32" "0.24.0"
"@esbuild/win32-x64" "0.24.0"
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"

View File

@ -1,6 +1,198 @@
{ fetchurl, fetchgit, linkFarm, runCommand, gnutar }: rec {
offline_cache = linkFarm "offline" packages;
packages = [
{
name = "https___registry.npmjs.org__esbuild_aix_ppc64___aix_ppc64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_aix_ppc64___aix_ppc64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz";
sha512 = "WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==";
};
}
{
name = "https___registry.npmjs.org__esbuild_android_arm64___android_arm64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_android_arm64___android_arm64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz";
sha512 = "Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==";
};
}
{
name = "https___registry.npmjs.org__esbuild_android_arm___android_arm_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_android_arm___android_arm_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz";
sha512 = "arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==";
};
}
{
name = "https___registry.npmjs.org__esbuild_android_x64___android_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_android_x64___android_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz";
sha512 = "t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==";
};
}
{
name = "https___registry.npmjs.org__esbuild_darwin_arm64___darwin_arm64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_darwin_arm64___darwin_arm64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz";
sha512 = "CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==";
};
}
{
name = "https___registry.npmjs.org__esbuild_darwin_x64___darwin_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_darwin_x64___darwin_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz";
sha512 = "rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_freebsd_arm64___freebsd_arm64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_freebsd_arm64___freebsd_arm64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz";
sha512 = "6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_freebsd_x64___freebsd_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_freebsd_x64___freebsd_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz";
sha512 = "D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_arm64___linux_arm64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_arm64___linux_arm64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz";
sha512 = "TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_arm___linux_arm_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_arm___linux_arm_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz";
sha512 = "gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_ia32___linux_ia32_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_ia32___linux_ia32_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz";
sha512 = "K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_loong64___linux_loong64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_loong64___linux_loong64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz";
sha512 = "0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_mips64el___linux_mips64el_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_mips64el___linux_mips64el_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz";
sha512 = "hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_ppc64___linux_ppc64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_ppc64___linux_ppc64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz";
sha512 = "HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_riscv64___linux_riscv64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_riscv64___linux_riscv64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz";
sha512 = "bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_s390x___linux_s390x_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_s390x___linux_s390x_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz";
sha512 = "ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==";
};
}
{
name = "https___registry.npmjs.org__esbuild_linux_x64___linux_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_linux_x64___linux_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz";
sha512 = "vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_netbsd_x64___netbsd_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_netbsd_x64___netbsd_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz";
sha512 = "hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==";
};
}
{
name = "https___registry.npmjs.org__esbuild_openbsd_arm64___openbsd_arm64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_openbsd_arm64___openbsd_arm64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz";
sha512 = "MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==";
};
}
{
name = "https___registry.npmjs.org__esbuild_openbsd_x64___openbsd_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_openbsd_x64___openbsd_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz";
sha512 = "4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==";
};
}
{
name = "https___registry.npmjs.org__esbuild_sunos_x64___sunos_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_sunos_x64___sunos_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz";
sha512 = "jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_win32_arm64___win32_arm64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_win32_arm64___win32_arm64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz";
sha512 = "iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==";
};
}
{
name = "https___registry.npmjs.org__esbuild_win32_ia32___win32_ia32_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_win32_ia32___win32_ia32_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz";
sha512 = "vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==";
};
}
{
name = "https___registry.npmjs.org__esbuild_win32_x64___win32_x64_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org__esbuild_win32_x64___win32_x64_0.24.0.tgz";
url = "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz";
sha512 = "7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==";
};
}
{
name = "https___registry.npmjs.org__eslint_community_eslint_utils___eslint_utils_4.4.0.tgz";
path = fetchurl {
@ -369,6 +561,14 @@
sha512 = "WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==";
};
}
{
name = "https___registry.npmjs.org_esbuild___esbuild_0.24.0.tgz";
path = fetchurl {
name = "https___registry.npmjs.org_esbuild___esbuild_0.24.0.tgz";
url = "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz";
sha512 = "FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==";
};
}
{
name = "https___registry.npmjs.org_escape_string_regexp___escape_string_regexp_4.0.0.tgz";
path = fetchurl {