diff --git a/.github/workflows/release-nightly.yaml b/.github/workflows/release-nightly.yaml deleted file mode 100644 index 56d3a01..0000000 --- a/.github/workflows/release-nightly.yaml +++ /dev/null @@ -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 }} - diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..91323fb --- /dev/null +++ b/.github/workflows/release.yaml @@ -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 }}" + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index 501e100..c6debff 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/flake.nix b/flake.nix index d7c5018..8f466eb 100644 --- a/flake.nix +++ b/flake.nix @@ -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 ]; }; } diff --git a/server/main.go b/server/main.go index 763d422..9e9f2a2 100644 --- a/server/main.go +++ b/server/main.go @@ -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) diff --git a/server/root-handler/common.go b/server/root-handler/common.go new file mode 100644 index 0000000..7ef05c8 --- /dev/null +++ b/server/root-handler/common.go @@ -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 diff --git a/server/root-handler/handler.go b/server/root-handler/handler.go index 6884739..85af3fa 100644 --- a/server/root-handler/handler.go +++ b/server/root-handler/handler.go @@ -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 } diff --git a/server/root-handler/lsp-utils.go b/server/root-handler/lsp-utils.go deleted file mode 100644 index 983faaf..0000000 --- a/server/root-handler/lsp-utils.go +++ /dev/null @@ -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=' 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 -} diff --git a/server/root-handler/text-document-code-action.go b/server/root-handler/lsp/text-document-code-action.go similarity index 65% rename from server/root-handler/text-document-code-action.go rename to server/root-handler/lsp/text-document-code-action.go index 8cbf1a2..bf4cc45 100644 --- a/server/root-handler/text-document-code-action.go +++ b/server/root-handler/lsp/text-document-code-action.go @@ -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) } diff --git a/server/root-handler/text-document-completion.go b/server/root-handler/lsp/text-document-completion.go similarity index 72% rename from server/root-handler/text-document-completion.go rename to server/root-handler/lsp/text-document-completion.go index a82a4eb..f452090 100644 --- a/server/root-handler/text-document-completion.go +++ b/server/root-handler/lsp/text-document-completion.go @@ -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) } diff --git a/server/root-handler/text-document-definition.go b/server/root-handler/lsp/text-document-definition.go similarity index 64% rename from server/root-handler/text-document-definition.go rename to server/root-handler/lsp/text-document-definition.go index 593cfad..c28b1f3 100644 --- a/server/root-handler/text-document-definition.go +++ b/server/root-handler/lsp/text-document-definition.go @@ -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) } diff --git a/server/root-handler/text-document-did-change.go b/server/root-handler/lsp/text-document-did-change.go similarity index 67% rename from server/root-handler/text-document-did-change.go rename to server/root-handler/lsp/text-document-did-change.go index 27c79e9..63edf6e 100644 --- a/server/root-handler/text-document-did-change.go +++ b/server/root-handler/lsp/text-document-did-change.go @@ -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) } diff --git a/server/root-handler/text-document-did-close.go b/server/root-handler/lsp/text-document-did-close.go similarity index 63% rename from server/root-handler/text-document-did-close.go rename to server/root-handler/lsp/text-document-did-close.go index 724d9a6..7dd0bce 100644 --- a/server/root-handler/text-document-did-close.go +++ b/server/root-handler/lsp/text-document-did-close.go @@ -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: } diff --git a/server/root-handler/text-document-did-open.go b/server/root-handler/lsp/text-document-did-open.go similarity index 66% rename from server/root-handler/text-document-did-open.go rename to server/root-handler/lsp/text-document-did-open.go index abe9a2b..20ebc44 100644 --- a/server/root-handler/text-document-did-open.go +++ b/server/root-handler/lsp/text-document-did-open.go @@ -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 } diff --git a/server/root-handler/text-document-hover.go b/server/root-handler/lsp/text-document-hover.go similarity index 71% rename from server/root-handler/text-document-hover.go rename to server/root-handler/lsp/text-document-hover.go index 72f6c65..d64a53a 100644 --- a/server/root-handler/text-document-hover.go +++ b/server/root-handler/lsp/text-document-hover.go @@ -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) } diff --git a/server/root-handler/text-document-prepare-rename.go b/server/root-handler/lsp/text-document-prepare-rename.go similarity index 61% rename from server/root-handler/text-document-prepare-rename.go rename to server/root-handler/lsp/text-document-prepare-rename.go index 19b6fd4..812908f 100644 --- a/server/root-handler/text-document-prepare-rename.go +++ b/server/root-handler/lsp/text-document-prepare-rename.go @@ -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) } diff --git a/server/root-handler/text-document-range-formatting.go b/server/root-handler/lsp/text-document-range-formatting.go similarity index 63% rename from server/root-handler/text-document-range-formatting.go rename to server/root-handler/lsp/text-document-range-formatting.go index 5f917f2..19fc00b 100644 --- a/server/root-handler/text-document-range-formatting.go +++ b/server/root-handler/lsp/text-document-range-formatting.go @@ -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 } diff --git a/server/root-handler/text-document-rename.go b/server/root-handler/lsp/text-document-rename.go similarity index 60% rename from server/root-handler/text-document-rename.go rename to server/root-handler/lsp/text-document-rename.go index 084d4f8..d630bb3 100644 --- a/server/root-handler/text-document-rename.go +++ b/server/root-handler/lsp/text-document-rename.go @@ -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) } diff --git a/server/root-handler/text-document-signature-help.go b/server/root-handler/lsp/text-document-signature-help.go similarity index 71% rename from server/root-handler/text-document-signature-help.go rename to server/root-handler/lsp/text-document-signature-help.go index 2be884a..639d6df 100644 --- a/server/root-handler/text-document-signature-help.go +++ b/server/root-handler/lsp/text-document-signature-help.go @@ -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) } diff --git a/server/root-handler/workspace-execute-command.go b/server/root-handler/lsp/workspace-execute-command.go similarity index 98% rename from server/root-handler/workspace-execute-command.go rename to server/root-handler/lsp/workspace-execute-command.go index bd04e34..4deb017 100644 --- a/server/root-handler/workspace-execute-command.go +++ b/server/root-handler/lsp/workspace-execute-command.go @@ -1,4 +1,4 @@ -package roothandler +package lsp import ( aliases "config-lsp/handlers/aliases/lsp" diff --git a/server/root-handler/shared.go b/server/root-handler/shared.go deleted file mode 100644 index e0575e0..0000000 --- a/server/root-handler/shared.go +++ /dev/null @@ -1,5 +0,0 @@ -package roothandler - -import protocol "github.com/tliron/glsp/protocol_3_16" - -var openedFiles = make(map[protocol.DocumentUri]struct{}) diff --git a/server/root-handler/shared/constants.go b/server/root-handler/shared/constants.go new file mode 100644 index 0000000..c3aceb3 --- /dev/null +++ b/server/root-handler/shared/constants.go @@ -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), +} diff --git a/server/root-handler/shared/indexes.go b/server/root-handler/shared/indexes.go new file mode 100644 index 0000000..514d7cb --- /dev/null +++ b/server/root-handler/shared/indexes.go @@ -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{} diff --git a/server/root-handler/singleton.go b/server/root-handler/shared/singleton.go similarity index 87% rename from server/root-handler/singleton.go rename to server/root-handler/shared/singleton.go index f06aae0..cb83c1d 100644 --- a/server/root-handler/singleton.go +++ b/server/root-handler/shared/singleton.go @@ -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 diff --git a/server/root-handler/utils/code-actions.go b/server/root-handler/utils/code-actions.go new file mode 100644 index 0000000..b86027d --- /dev/null +++ b/server/root-handler/utils/code-actions.go @@ -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 +} diff --git a/server/root-handler/utils/language-detection.go b/server/root-handler/utils/language-detection.go new file mode 100644 index 0000000..24c91d7 --- /dev/null +++ b/server/root-handler/utils/language-detection.go @@ -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=' 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 +} diff --git a/server/root-handler/utils/notification.go b/server/root-handler/utils/notification.go new file mode 100644 index 0000000..2153ce3 --- /dev/null +++ b/server/root-handler/utils/notification.go @@ -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='.", + }, + ) +} + +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), + }, + ) +} diff --git a/vs-code-extension/.vscodeignore b/vs-code-extension/.vscodeignore deleted file mode 100644 index 2ca7fc3..0000000 --- a/vs-code-extension/.vscodeignore +++ /dev/null @@ -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/** diff --git a/vs-code-extension/LICENSE.md b/vs-code-extension/LICENSE.md new file mode 100644 index 0000000..e69de29 diff --git a/vs-code-extension/README.md b/vs-code-extension/README.md index 9b1bd25..cd3bfb3 100644 --- a/vs-code-extension/README.md +++ b/vs-code-extension/README.md @@ -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= -- Completions for HTML tags -- Completions for CSS in `` to try CSS completion - - Have `` to see CSS Diagnostics diff --git a/vs-code-extension/build-extension.sh b/vs-code-extension/build-extension.sh deleted file mode 100755 index aa68497..0000000 --- a/vs-code-extension/build-extension.sh +++ /dev/null @@ -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 - diff --git a/vs-code-extension/esbuild.js b/vs-code-extension/esbuild.js new file mode 100644 index 0000000..2f12533 --- /dev/null +++ b/vs-code-extension/esbuild.js @@ -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); +}); diff --git a/vs-code-extension/icon.png b/vs-code-extension/icon.png new file mode 100644 index 0000000..596c2d6 Binary files /dev/null and b/vs-code-extension/icon.png differ diff --git a/vs-code-extension/package.json b/vs-code-extension/package.json index a7fc5c5..82a9b0c 100644 --- a/vs-code-extension/package.json +++ b/vs-code-extension/package.json @@ -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" } } diff --git a/vs-code-extension/src/events/on-undetectable.ts b/vs-code-extension/src/events/on-undetectable.ts new file mode 100644 index 0000000..0802071 --- /dev/null +++ b/vs-code-extension/src/events/on-undetectable.ts @@ -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(); + +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=' 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; + } +} + diff --git a/vs-code-extension/src/events/types.ts b/vs-code-extension/src/events/types.ts new file mode 100644 index 0000000..8bae362 --- /dev/null +++ b/vs-code-extension/src/events/types.ts @@ -0,0 +1,6 @@ +interface LSPNotification { + Uri: string; +} + +interface LSPLanguageUndetectable extends LSPNotification {} + diff --git a/vs-code-extension/src/extension.ts b/vs-code-extension/src/extension.ts index 661ed43..c07b319 100644 --- a/vs-code-extension/src/extension.ts +++ b/vs-code-extension/src/extension.ts @@ -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; } diff --git a/vs-code-extension/tsconfig.tsbuildinfo b/vs-code-extension/tsconfig.tsbuildinfo deleted file mode 100644 index 81f1d74..0000000 --- a/vs-code-extension/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./src/extension.ts"],"version":"5.6.2"} \ No newline at end of file diff --git a/vs-code-extension/update-yarn.sh b/vs-code-extension/update-yarn.sh new file mode 100755 index 0000000..3b50451 --- /dev/null +++ b/vs-code-extension/update-yarn.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd vs-code-extension && yarn install --no-frozen-lockfile && yarn2nix > yarn.nix + diff --git a/vs-code-extension/yarn.lock b/vs-code-extension/yarn.lock index 1c40492..c92bd7b 100644 --- a/vs-code-extension/yarn.lock +++ b/vs-code-extension/yarn.lock @@ -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" diff --git a/vs-code-extension/yarn.nix b/vs-code-extension/yarn.nix index 2f4876a..f480218 100644 --- a/vs-code-extension/yarn.nix +++ b/vs-code-extension/yarn.nix @@ -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 {