diff --git a/language-ids.sublime-settings b/language-ids.sublime-settings index 85f29fa71..4f59059ec 100644 --- a/language-ids.sublime-settings +++ b/language-ids.sublime-settings @@ -3,15 +3,15 @@ // ------------------------------------- // // These are the "exceptional" base scopes. If a base scope is not in this -// map, then the rule is that we split the base scopes on the ".", and take -// the last element. The resuling string is assumed to be the language ID. +// map, nor the first two components or more match any of the entries here, then +// the rule is that we split the base scope on the ".", and take +// the second component. The resulting string is assumed to be the language ID. // -// Examples of this rule: +// Examples: // -// source.julia -> julia +// source.c++ -> cpp // source.rust -> rust // text.tex.latex -> latex -// text.html.vue -> vue // // The official list is maintained at // https://microsoft.github.io/language-server-protocol/specification#textDocumentItem @@ -21,103 +21,35 @@ // request at github.com/sublimelsp/LSP if you believe an entry is missing. { "source.c++": "cpp", - "source.coffee.gulpfile": "coffeescript", // https://github.com/SublimeText/AFileIcon + "source.coffee": "coffeescript", "source.cs": "csharp", - "source.css.tailwind": "css", // https://github.com/SublimeText/TailwindCSS "source.dosbatch": "bat", "source.fixedform-fortran": "fortran", // https://packagecontrol.io/packages/Fortran - "source.groovy.gradle": "groovy", // https://github.com/SublimeText/AFileIcon - "source.groovy.jenkins": "groovy", // https://github.com/SublimeText/AFileIcon "source.js": "javascript", - "source.js.eslint": "javascript", // https://github.com/SublimeText/AFileIcon - "source.js.gruntfile": "javascript", // https://github.com/SublimeText/AFileIcon - "source.js.gulpfile": "javascript", // https://github.com/SublimeText/AFileIcon - "source.js.postcss": "javascript", // https://github.com/SublimeText/AFileIcon - "source.js.puglint": "javascript", // https://github.com/SublimeText/AFileIcon "source.js.react": "javascriptreact", // https://github.com/Thom1729/Sublime-JS-Custom - "source.js.stylelint": "javascript", // https://github.com/SublimeText/AFileIcon - "source.js.unittest": "javascript", // https://github.com/SublimeText/AFileIcon - "source.js.webpack": "javascript", // https://github.com/SublimeText/AFileIcon "source.json-tmlanguage": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.babel": "json", // https://github.com/SublimeText/AFileIcon - "source.json.bower": "json", // https://github.com/SublimeText/AFileIcon - "source.json.composer": "json", // https://github.com/SublimeText/AFileIcon - "source.json.eslint": "json", // https://github.com/SublimeText/AFileIcon - "source.json.npm": "json", // https://github.com/SublimeText/AFileIcon - "source.json.postcss": "json", // https://github.com/SublimeText/AFileIcon - "source.json.puglint": "json", // https://github.com/SublimeText/AFileIcon - "source.json.settings": "json", // https://github.com/SublimeText/AFileIcon - "source.json.stylelint": "json", // https://github.com/SublimeText/AFileIcon "source.json.sublime": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.build": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.color-scheme": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.commands": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.completions": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.keymap": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.macro": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.menu": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.mousemap": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.project": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.settings": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.sublime.theme": "jsonc", // https://github.com/SublimeText/PackageDev - "source.json.tern": "json", // https://github.com/SublimeText/AFileIcon "source.jsx": "javascriptreact", - "source.jsx.unittest": "javascriptreact", // https://github.com/SublimeText/AFileIcon "source.Kotlin": "kotlin", // https://github.com/vkostyukov/kotlin-sublime-package "source.modern-fortran": "fortran", // https://packagecontrol.io/packages/Fortran "source.objc": "objective-c", "source.objc++": "objective-cpp", "source.shader": "shaderlab", // https://github.com/waqiju/unity_shader_st3 - "source.shell.bash": "shellscript", - "source.shell.docker": "shellscript", // https://github.com/SublimeText/AFileIcon - "source.shell.eslint": "shellscript", // https://github.com/SublimeText/AFileIcon - "source.shell.npm": "shellscript", // https://github.com/SublimeText/AFileIcon - "source.shell.ruby": "shellscript", // https://github.com/SublimeText/AFileIcon - "source.shell.stylelint": "shellscript", // https://github.com/SublimeText/AFileIcon + "source.shell": "shellscript", "source.ts": "typescript", "source.ts.react": "typescriptreact", // https://github.com/Thom1729/Sublime-JS-Custom - "source.ts.unittest": "typescript", // https://github.com/SublimeText/AFileIcon "source.tsx": "typescriptreact", - "source.tsx.unittest": "typescriptreact", // https://github.com/SublimeText/AFileIcon "source.unity.unity_shader": "shaderlab", // https://github.com/petereichinger/Unity3D-Shader - "source.viml.vimrc": "viml", // https://github.com/SublimeText/AFileIcon "source.yaml-tmlanguage": "yaml", // https://github.com/SublimeText/PackageDev - "source.yaml.circleci": "yaml", // https://github.com/SublimeText/AFileIcon - "source.yaml.docker": "yaml", // https://github.com/SublimeText/AFileIcon - "source.yaml.eslint": "yaml", // https://github.com/SublimeText/AFileIcon - "source.yaml.lock": "yaml", // https://github.com/SublimeText/AFileIcon - "source.yaml.procfile": "yaml", // https://github.com/SublimeText/AFileIcon - "source.yaml.stylelint": "yaml", // https://github.com/SublimeText/AFileIcon - "source.yaml.sublime.syntax": "yaml", // https://github.com/SublimeText/PackageDev - "source.yaml.yarn": "yaml", // https://github.com/SublimeText/AFileIcon "text.advanced_csv": "csv", // https://github.com/SublimeText/AFileIcon "text.django": "html", // https://github.com/willstott101/django-sublime-syntax - "text.html.basic": "html", - "text.html.elixir": "html", // https://github.com/elixir-editors/elixir-tmbundle - "text.html.markdown.academicmarkdown": "markdown", // https://github.com/mangecoeur/AcademicMarkdown - "text.html.markdown.license": "markdown", // https://github.com/SublimeText/AFileIcon + "text.html.handlebars": "handlebars", + "text.html.markdown": "markdown", "text.html.markdown.rmarkdown": "r", // https://github.com/REditorSupport/sublime-ide-r - "text.html.ngx": "html", // https://github.com/princemaple/ngx-html-syntax + "text.html.vue": "vue", "text.jinja": "html", // https://github.com/Sublime-Instincts/BetterJinja "text.plain": "plaintext", - "text.plain.buildpacks": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.eslint": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.fastq": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.license": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.lnk": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.log": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.nodejs": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.pcb": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.ps": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.python": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.readme": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.ruby": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.sketch": "plaintext", // https://github.com/SublimeText/AFileIcon - "text.plain.visualstudio": "plaintext", // https://github.com/SublimeText/AFileIcon "text.plist": "xml", // https://bitbucket.org/fschwehn/sublime_plist - "text.xml.plist": "xml", // https://github.com/SublimeText/PackageDev - "text.xml.plist.textmate.preferences": "xml", // https://github.com/SublimeText/PackageDev - "text.xml.sublime.snippet": "xml", // https://github.com/SublimeText/PackageDev - "text.xml.svg": "xml", // https://github.com/SublimeText/AFileIcon - "text.xml.visualstudio": "xml", // https://github.com/SublimeText/AFileIcon + "text.tex.latex": "latex", + "text.xml.xsl": "xsl", } diff --git a/plugin/core/types.py b/plugin/core/types.py index 0d16b9132..555e68b7f 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -35,7 +35,18 @@ def basescope2languageid(base_scope: str) -> str: # This the connection between Language IDs and ST selectors. base_scope_map = sublime.load_settings("language-ids.sublime-settings") - result = base_scope_map.get(base_scope, base_scope.split(".")[-1]) + result = "" + # Try to find exact match or less specific match consisting of at least 2 components. + scope_parts = base_scope.split('.') + while len(scope_parts) >= 2: + result = base_scope_map.get('.'.join(scope_parts)) + if result: + break + scope_parts.pop() + if not result: + # If no match, use the second component of the scope as the language ID. + scope_parts = base_scope.split('.') + result = scope_parts[1] if len(scope_parts) > 1 else scope_parts[0] return result if isinstance(result, str) else "" diff --git a/tests/test_types.py b/tests/test_types.py index a66b6a18f..5b1806cfd 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,4 +1,5 @@ from LSP.plugin.core.types import diff +from LSP.plugin.core.types import basescope2languageid from LSP.plugin.core.types import DocumentSelector from LSP.plugin.core.typing import List from unittest.mock import MagicMock @@ -145,3 +146,111 @@ def test_pattern_negated_character_range(self) -> None: self.assertFalse(selector.matches(self._make_html_view("example.7"))) self.assertFalse(selector.matches(self._make_html_view("example.8"))) self.assertFalse(selector.matches(self._make_html_view("example.9"))) + + def test_base_scope_to_language_id_mappings(self) -> None: + scope_test_map = { + "source.js.vite": "javascript", + "source.c++": "cpp", + "source.coffee.gulpfile": "coffeescript", + "source.cs": "csharp", + "source.css.tailwind": "css", + "source.dosbatch": "bat", + "source.fixedform-fortran": "fortran", + "source.groovy.gradle": "groovy", + "source.groovy.jenkins": "groovy", + "source.js": "javascript", + "source.js.eslint": "javascript", + "source.js.gruntfile": "javascript", + "source.js.gulpfile": "javascript", + "source.js.postcss": "javascript", + "source.js.puglint": "javascript", + "source.js.react": "javascriptreact", + "source.js.stylelint": "javascript", + "source.js.unittest": "javascript", + "source.js.webpack": "javascript", + "source.json-tmlanguage": "jsonc", + "source.json.babel": "json", + "source.json.bower": "json", + "source.json.composer": "json", + "source.json.eslint": "json", + "source.json.npm": "json", + "source.json.postcss": "json", + "source.json.puglint": "json", + "source.json.settings": "json", + "source.json.stylelint": "json", + "source.json.sublime": "jsonc", + "source.json.sublime.build": "jsonc", + "source.json.sublime.color-scheme": "jsonc", + "source.json.sublime.commands": "jsonc", + "source.json.sublime.completions": "jsonc", + "source.json.sublime.keymap": "jsonc", + "source.json.sublime.macro": "jsonc", + "source.json.sublime.menu": "jsonc", + "source.json.sublime.mousemap": "jsonc", + "source.json.sublime.project": "jsonc", + "source.json.sublime.settings": "jsonc", + "source.json.sublime.theme": "jsonc", + "source.json.tern": "json", + "source.jsx": "javascriptreact", + "source.jsx.unittest": "javascriptreact", + "source.Kotlin": "kotlin", + "source.modern-fortran": "fortran", + "source.objc": "objective-c", + "source.objc++": "objective-cpp", + "source.shader": "shaderlab", + "source.shell.bash": "shellscript", + "source.shell.docker": "shellscript", + "source.shell.eslint": "shellscript", + "source.shell.npm": "shellscript", + "source.shell.ruby": "shellscript", + "source.shell.stylelint": "shellscript", + "source.ts": "typescript", + "source.ts.react": "typescriptreact", + "source.ts.unittest": "typescript", + "source.tsx": "typescriptreact", + "source.tsx.unittest": "typescriptreact", + "source.unity.unity_shader": "shaderlab", + "source.viml.vimrc": "viml", + "source.yaml-tmlanguage": "yaml", + "source.yaml.circleci": "yaml", + "source.yaml.docker": "yaml", + "source.yaml.eslint": "yaml", + "source.yaml.lock": "yaml", + "source.yaml.procfile": "yaml", + "source.yaml.stylelint": "yaml", + "source.yaml.sublime.syntax": "yaml", + "source.yaml.yarn": "yaml", + "text.advanced_csv": "csv", + "text.django": "html", + "text.html.basic": "html", + "text.html.elixir": "html", + "text.html.markdown.academicmarkdown": "markdown", + "text.html.markdown.license": "markdown", + "text.html.markdown.rmarkdown": "r", + "text.html.ngx": "html", + "text.jinja": "html", + "text.plain": "plaintext", + "text.plain.buildpacks": "plaintext", + "text.plain.eslint": "plaintext", + "text.plain.fastq": "plaintext", + "text.plain.license": "plaintext", + "text.plain.lnk": "plaintext", + "text.plain.log": "plaintext", + "text.plain.nodejs": "plaintext", + "text.plain.pcb": "plaintext", + "text.plain.ps": "plaintext", + "text.plain.python": "plaintext", + "text.plain.readme": "plaintext", + "text.plain.ruby": "plaintext", + "text.plain.sketch": "plaintext", + "text.plain.visualstudio": "plaintext", + "text.plist": "xml", + "text.xml.plist": "xml", + "text.xml.plist.textmate.preferences": "xml", + "text.xml.sublime.snippet": "xml", + "text.xml.svg": "xml", + "text.xml.visualstudio": "xml", + } + + for base_scope, expected_language_id in scope_test_map.items(): + self.assertEqual(basescope2languageid(base_scope), expected_language_id)