From 784a6cc244a6dabed49dec4fd7cec12a70e282c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ivan=20Nikoli=C4=87?= <niksy5@gmail.com>
Date: Tue, 12 Nov 2024 09:21:26 +0100
Subject: [PATCH] Add initial implementation

---
 .github/dependabot.yml            |   7 ++
 .gitignore                        |   2 +
 .python-version                   |   1 +
 LSP-twiggy.sublime-commands       |  10 +++
 LSP-twiggy.sublime-settings       |  13 +++
 Main.sublime-menu                 |  34 ++++++++
 README.md                         |  18 +++++
 dependencies.json                 |   8 ++
 language-server/package-lock.json | 130 ++++++++++++++++++++++++++++++
 language-server/package.json      |   7 ++
 plugin.py                         |  16 ++++
 sublime-package.json              |  96 ++++++++++++++++++++++
 tox.ini                           |  24 ++++++
 13 files changed, 366 insertions(+)
 create mode 100644 .github/dependabot.yml
 create mode 100644 .gitignore
 create mode 100644 .python-version
 create mode 100644 LSP-twiggy.sublime-commands
 create mode 100644 LSP-twiggy.sublime-settings
 create mode 100644 Main.sublime-menu
 create mode 100644 README.md
 create mode 100644 dependencies.json
 create mode 100644 language-server/package-lock.json
 create mode 100644 language-server/package.json
 create mode 100644 plugin.py
 create mode 100644 sublime-package.json
 create mode 100644 tox.ini

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..2e6915c
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,7 @@
+version: 2
+updates:
+  - package-ecosystem: npm
+    directory: /language-server
+    schedule:
+      interval: daily
+      time: "11:00"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fd4f2b0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+.DS_Store
diff --git a/.python-version b/.python-version
new file mode 100644
index 0000000..cc1923a
--- /dev/null
+++ b/.python-version
@@ -0,0 +1 @@
+3.8
diff --git a/LSP-twiggy.sublime-commands b/LSP-twiggy.sublime-commands
new file mode 100644
index 0000000..e269297
--- /dev/null
+++ b/LSP-twiggy.sublime-commands
@@ -0,0 +1,10 @@
+[
+    {
+        "caption": "Preferences: LSP-twiggy Settings",
+        "command": "edit_settings",
+        "args": {
+            "base_file": "${packages}/LSP-twiggy/LSP-twiggy.sublime-settings",
+            "default": "// Settings in here override those in \"LSP-twiggy/LSP-twiggy.sublime-settings\"\n\n{\n\t$0\n}\n",
+        },
+    },
+]
diff --git a/LSP-twiggy.sublime-settings b/LSP-twiggy.sublime-settings
new file mode 100644
index 0000000..acae913
--- /dev/null
+++ b/LSP-twiggy.sublime-settings
@@ -0,0 +1,13 @@
+{
+	"command": ["${node_bin}", "${server_path}", "--stdio"],
+	"settings": {
+		"twiggy.autoInsertSpaces": true,
+		"twiggy.inlayHints.macroArguments": true,
+		"twiggy.inlayHints.macro": true,
+		"twiggy.inlayHints.block": true,
+		"twiggy.phpExecutable": "php",
+		"twiggy.framework": "ignore",
+		"twiggy.symfonyConsolePath": "bin/console"
+	},
+	"selector": "text.html.twig"
+}
diff --git a/Main.sublime-menu b/Main.sublime-menu
new file mode 100644
index 0000000..980dfda
--- /dev/null
+++ b/Main.sublime-menu
@@ -0,0 +1,34 @@
+[
+  {
+    "id": "preferences",
+    "children": [
+      {
+        "caption": "Package Settings",
+        "mnemonic": "P",
+        "id": "package-settings",
+        "children": [
+          {
+            "caption": "LSP",
+            "id": "lsp-settings",
+            "children": [
+              {
+                "caption": "Servers",
+                "id": "lsp-servers",
+                "children": [
+                  {
+                    "caption": "LSP-twiggy",
+                    "command": "edit_settings",
+                    "args": {
+                      "base_file": "${packages}/LSP-twiggy/LSP-twiggy.sublime-settings",
+                      "default": "// Settings in here override those in \"LSP-twiggy/LSP-twiggy.sublime-settings\"\n\n{\n\t$0\n}\n",
+                    },
+                  },
+                ],
+              },
+            ],
+          },
+        ],
+      },
+    ],
+  },
+]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6026e1d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# LSP-twiggy
+
+Twig support for Sublime’s LSP.
+
+Provided through [twiggy-language-server](https://github.com/moetelo/twiggy/tree/master/packages/language-server).
+
+### Installation
+
+* Install [LSP](https://packagecontrol.io/packages/LSP) and `LSP-twiggy` via Package Control.
+* Install [Twig syntax higlight package](https://packagecontrol.io/packages/Twig).
+* Restart Sublime.
+
+### Configuration
+
+There are some ways to configure the package and the language server.
+
+- From `Preferences > Package Settings > LSP > Servers > LSP-twiggy`
+- From the command palette `Preferences: LSP-twiggy Settings`
diff --git a/dependencies.json b/dependencies.json
new file mode 100644
index 0000000..3d55a18
--- /dev/null
+++ b/dependencies.json
@@ -0,0 +1,8 @@
+{
+    "*": {
+        "*": [
+            "lsp_utils",
+            "sublime_lib"
+        ]
+    }
+}
diff --git a/language-server/package-lock.json b/language-server/package-lock.json
new file mode 100644
index 0000000..25a8315
--- /dev/null
+++ b/language-server/package-lock.json
@@ -0,0 +1,130 @@
+{
+  "name": "twiggy",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "twiggy",
+      "dependencies": {
+        "twiggy-language-server": "^0.16.1"
+      }
+    },
+    "node_modules/twiggy-language-server": {
+      "version": "0.16.1",
+      "resolved": "https://registry.npmjs.org/twiggy-language-server/-/twiggy-language-server-0.16.1.tgz",
+      "integrity": "sha512-ztUH2D9nOWKrXkeL02Qd6xrSqcXdUiPrQusKVfQGAZaxZ5NwWzYLJug+NxLNRrvKgl95r31q+jNtIXxbS6tShw==",
+      "dependencies": {
+        "vscode-languageserver": "^9.0.1",
+        "vscode-languageserver-textdocument": "^1.0.11",
+        "vscode-uri": "^3.0.8",
+        "web-tree-sitter": "^0.22.5"
+      },
+      "bin": {
+        "twiggy-language-server": "bin/server.js"
+      }
+    },
+    "node_modules/vscode-jsonrpc": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
+      "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/vscode-languageserver": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz",
+      "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==",
+      "dependencies": {
+        "vscode-languageserver-protocol": "3.17.5"
+      },
+      "bin": {
+        "installServerIntoExtension": "bin/installServerIntoExtension"
+      }
+    },
+    "node_modules/vscode-languageserver-protocol": {
+      "version": "3.17.5",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
+      "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
+      "dependencies": {
+        "vscode-jsonrpc": "8.2.0",
+        "vscode-languageserver-types": "3.17.5"
+      }
+    },
+    "node_modules/vscode-languageserver-textdocument": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz",
+      "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="
+    },
+    "node_modules/vscode-languageserver-types": {
+      "version": "3.17.5",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
+      "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
+    },
+    "node_modules/vscode-uri": {
+      "version": "3.0.8",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+      "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="
+    },
+    "node_modules/web-tree-sitter": {
+      "version": "0.22.6",
+      "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.22.6.tgz",
+      "integrity": "sha512-hS87TH71Zd6mGAmYCvlgxeGDjqd9GTeqXNqTT+u0Gs51uIozNIaaq/kUAbV/Zf56jb2ZOyG8BxZs2GG9wbLi6Q=="
+    }
+  },
+  "dependencies": {
+    "twiggy-language-server": {
+      "version": "0.16.1",
+      "resolved": "https://registry.npmjs.org/twiggy-language-server/-/twiggy-language-server-0.16.1.tgz",
+      "integrity": "sha512-ztUH2D9nOWKrXkeL02Qd6xrSqcXdUiPrQusKVfQGAZaxZ5NwWzYLJug+NxLNRrvKgl95r31q+jNtIXxbS6tShw==",
+      "requires": {
+        "vscode-languageserver": "^9.0.1",
+        "vscode-languageserver-textdocument": "^1.0.11",
+        "vscode-uri": "^3.0.8",
+        "web-tree-sitter": "^0.22.5"
+      }
+    },
+    "vscode-jsonrpc": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
+      "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="
+    },
+    "vscode-languageserver": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz",
+      "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==",
+      "requires": {
+        "vscode-languageserver-protocol": "3.17.5"
+      }
+    },
+    "vscode-languageserver-protocol": {
+      "version": "3.17.5",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
+      "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
+      "requires": {
+        "vscode-jsonrpc": "8.2.0",
+        "vscode-languageserver-types": "3.17.5"
+      }
+    },
+    "vscode-languageserver-textdocument": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz",
+      "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="
+    },
+    "vscode-languageserver-types": {
+      "version": "3.17.5",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
+      "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
+    },
+    "vscode-uri": {
+      "version": "3.0.8",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+      "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="
+    },
+    "web-tree-sitter": {
+      "version": "0.22.6",
+      "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.22.6.tgz",
+      "integrity": "sha512-hS87TH71Zd6mGAmYCvlgxeGDjqd9GTeqXNqTT+u0Gs51uIozNIaaq/kUAbV/Zf56jb2ZOyG8BxZs2GG9wbLi6Q=="
+    }
+  }
+}
diff --git a/language-server/package.json b/language-server/package.json
new file mode 100644
index 0000000..f86b4a5
--- /dev/null
+++ b/language-server/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "twiggy",
+  "private": true,
+  "dependencies": {
+    "twiggy-language-server": "^0.16.1"
+  }
+}
diff --git a/plugin.py b/plugin.py
new file mode 100644
index 0000000..bdad29d
--- /dev/null
+++ b/plugin.py
@@ -0,0 +1,16 @@
+from lsp_utils import NpmClientHandler
+import os
+
+
+def plugin_loaded():
+    LspTwigPlugin.setup()
+
+
+def plugin_unloaded():
+    LspTwigPlugin.cleanup()
+
+
+class LspTwigPlugin(NpmClientHandler):
+    package_name = __package__
+    server_directory = 'language-server'
+    server_binary_path = os.path.join(server_directory, 'node_modules', 'twiggy-language-server', 'bin', 'server.js')
diff --git a/sublime-package.json b/sublime-package.json
new file mode 100644
index 0000000..cf8e38d
--- /dev/null
+++ b/sublime-package.json
@@ -0,0 +1,96 @@
+{
+  "contributions": {
+    "settings": [
+      {
+        "file_patterns": [
+          "/LSP-twiggy.sublime-settings"
+        ],
+        "schema": {
+          "$id": "sublime://settings/LSP-twiggy",
+          "definitions": {
+            "PluginConfig": {
+              "properties": {
+                "settings": {
+                  "additionalProperties": false,
+                  "properties": {
+                    "twiggy.autoInsertSpaces": {
+                      "type": "boolean",
+                      "default": true,
+                      "markdownDescription": "Insert spaces inside of `{{ | }}` and `{% | %}`."
+                    },
+                    "twiggy.inlayHints.macroArguments": {
+                      "type": "boolean",
+                      "default": true,
+                      "markdownDescription": "Inlay hints for macro arguments."
+                    },
+                    "twiggy.inlayHints.macro": {
+                      "type": "boolean",
+                      "default": true,
+                      "markdownDescription": "Inlay hints for `{% endmacro %}`."
+                    },
+                    "twiggy.inlayHints.block": {
+                      "type": "boolean",
+                      "default": true,
+                      "markdownDescription": "Inlay hints for `{% endblock %}`."
+                    },
+                    "twiggy.phpExecutable": {
+                      "type": "string",
+                      "scope": "resource",
+                      "default": "php",
+                      "markdownDescription": "Points to the PHP executable."
+                    },
+                    "twiggy.framework": {
+                      "type": "string",
+                      "scope": "resource",
+                      "enum": [
+                        "symfony",
+                        "craft",
+                        "ignore"
+                      ],
+                      "markdownDescription": "Framework to use."
+                    },
+                    "twiggy.symfonyConsolePath": {
+                      "type": "string",
+                      "scope": "resource",
+                      "default": "bin/console",
+                      "markdownDescription": "Path to the Symfony console. See: https://symfony.com/doc/current/templates.html#inspecting-twig-information"
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "type": "object",
+          "allOf": [
+            {
+              "$ref": "sublime://settings/LSP-plugin-base"
+            },
+            {
+              "$ref": "sublime://settings/LSP-twiggy#/definitions/PluginConfig"
+            }
+          ]
+        }
+      },
+      {
+        "file_patterns": [
+          "/*.sublime-project"
+        ],
+        "schema": {
+          "properties": {
+            "settings": {
+              "properties": {
+                "LSP": {
+                  "properties": {
+                    "LSP-twiggy": {
+                      "$ref": "sublime://settings/LSP-twiggy#/definitions/PluginConfig"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..450d820
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,24 @@
+# Tox (http://tox.testrun.org/) is a tool for running tests
+# in multiple virtualenvs. This configuration file will run the
+# test suite on all supported python versions. To use it, "pip install tox"
+# and then run "tox" from this directory.
+
+[tox]
+envlist = py3
+skipsdist = True
+
+[pycodestyle]
+max-line-length = 120
+
+[flake8]
+max-line-length = 120
+
+[testenv]
+deps =
+    flake8==3.7.9
+    mypy==0.750
+    yapf==0.29.0
+commands =
+    mypy plugin.py
+    flake8 plugin.py tests
+    yapf --diff plugin.py