Skip to content

Commit

Permalink
refactor: port functions from my other LSP plugins
Browse files Browse the repository at this point in the history
Signed-off-by: Jack Cherng <jfcherng@gmail.com>
  • Loading branch information
jfcherng committed Jul 18, 2024
1 parent 17104dd commit 60291fc
Show file tree
Hide file tree
Showing 18 changed files with 352 additions and 30 deletions.
24 changes: 24 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.dependabot export-ignore
.editorconfig export-ignore
.flake8 export-ignore
.gitattributes export-ignore
.github/ export-ignore
.gitignore export-ignore
.gitmodules export-ignore
.style.yapf export-ignore
.travis.yml export-ignore
codecov.yml export-ignore
docs/ export-ignore
Makefile export-ignore
Makefile.* export-ignore
mkdocs.yml export-ignore
mypy.ini export-ignore
pyproject.toml export-ignore
pyrightconfig.json export-ignore
requirements-* export-ignore
scripts/ export-ignore
stubs/ export-ignore
tests/ export-ignore
tox.ini export-ignore
typings/ export-ignore
unittesting.json export-ignore
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.mypy_cache
.tox
.venv-*/
.venv/
__pycache__
11 changes: 10 additions & 1 deletion LSP-ruff.sublime-settings
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
{
"settings": {
// There are quite a lot of settings for intelephense...
// For a full list, you can check the link above or just use LSP-json for autocompletion.

// The (Jinja2) template of the status bar text which is inside the parentheses `(...)`.
// See https://jinja.palletsprojects.com/templates/
"statusText": "{% if server_version %}v{{ server_version }}{% endif %}",
},
"initializationOptions": {
"settings": {
// same as globalSettings
Expand Down Expand Up @@ -35,7 +43,8 @@
},
"command": [
"$server_path",
"server"
"server",
"--preview", // I like preview features
],
"schemes": [
"file", // regular files
Expand Down
35 changes: 35 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
MAKEFLAGS += --silent

UV_INSTALL_FLAGS :=

.PHONY: all
all:

.PHONY: install
install:
uv pip install $(UV_INSTALL_FLAGS) -r requirements-prod.txt

.PHONY: install-dev
install-dev:
uv pip install $(UV_INSTALL_FLAGS) -r requirements-dev.txt

.PHONY: pip-compile
pip-compile:
uv pip compile --upgrade requirements-prod.in -o requirements-prod.txt
uv pip compile --upgrade requirements-dev.in -o requirements-dev.txt

.PHONY: ci-check
ci-check:
@echo "========== check: mypy =========="
mypy -p plugin
@echo "========== check: ruff (lint) =========="
ruff check --diff .
@echo "========== check: ruff (format) =========="
ruff format --diff .

.PHONY: ci-fix
ci-fix:
@echo "========== fix: ruff (lint) =========="
ruff check --fix .
@echo "========== fix: ruff (format) =========="
ruff format .
15 changes: 15 additions & 0 deletions boot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from __future__ import annotations


def reload_plugin() -> None:
import sys

# remove all previously loaded plugin modules
prefix = f"{__package__}."
for module_name in tuple(filter(lambda m: m.startswith(prefix) and m != __name__, sys.modules)):
del sys.modules[module_name]


reload_plugin()

from .plugin import * # noqa: E402, F401, F403
16 changes: 9 additions & 7 deletions dependencies.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
{
"*": {
"*": [
"lsp_utils",
"sublime_lib"
]
}
}
"*": {
"*": [
"Jinja2",
"lsp_utils",
"markupsafe",
"sublime_lib"
]
}
}
15 changes: 0 additions & 15 deletions plugin.py

This file was deleted.

21 changes: 21 additions & 0 deletions plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from __future__ import annotations

from .client import LspRuffPlugin

__all__ = (
# ST: core
"plugin_loaded",
"plugin_unloaded",
# ...
"LspRuffPlugin",
)


def plugin_loaded() -> None:
"""Executed when this plugin is loaded."""
LspRuffPlugin.setup()


def plugin_unloaded() -> None:
"""Executed when this plugin is unloaded."""
LspRuffPlugin.cleanup()
81 changes: 81 additions & 0 deletions plugin/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from __future__ import annotations

from pathlib import Path
from typing import Any

import sublime
from LSP.plugin import ClientConfig, DottedDict, WorkspaceFolder
from lsp_utils.pip_client_handler import PipClientHandler

from .constants import PACKAGE_NAME
from .log import log_warning
from .template import load_string_template


class LspRuffPlugin(PipClientHandler):
package_name = PACKAGE_NAME
requirements_txt_path = "requirements.txt"
server_filename = "ruff"

server_requirements_txt_path = "requirements.txt"
"""The path to the `requirements.txt` file of the language server."""
server_version = ""
"""The version of the language server."""

@classmethod
def should_ignore(cls, view: sublime.View) -> bool:
return bool(
# ignore REPL views (https://github.com/sublimelsp/LSP-pyright/issues/343)
view.settings().get("repl")
# ignore Python-like syntax test files
or view.substr(sublime.Region(0, 20)).startswith("# SYNTAX TEST ")
)

@classmethod
def on_pre_start(
cls,
window: sublime.Window,
initiating_view: sublime.View,
workspace_folders: list[WorkspaceFolder],
configuration: ClientConfig,
) -> str | None:
super().on_pre_start(window, initiating_view, workspace_folders, configuration)

cls.server_version = cls.parse_server_version()
return None

def on_settings_changed(self, settings: DottedDict) -> None:
super().on_settings_changed(settings)

self.update_status_bar_text()

# -------------- #
# custom methods #
# -------------- #

def update_status_bar_text(self, extra_variables: dict[str, Any] | None = None) -> None:
if not (session := self.weaksession()):
return

variables: dict[str, Any] = {
"server_version": self.server_version,
}

if extra_variables:
variables.update(extra_variables)

rendered_text = ""
if template_text := str(session.config.settings.get("statusText") or ""):
try:
rendered_text = load_string_template(template_text).render(variables)
except Exception as e:
log_warning(f'Invalid "statusText" template: {e}')
session.set_config_status_async(rendered_text)

@classmethod
def parse_server_version(cls) -> str:
with open(Path(cls.package_storage()) / cls.server_requirements_txt_path, encoding="utf-8") as f:
for line in f:
if line.startswith("ruff=="):
return line[6:].strip()
return ""
5 changes: 5 additions & 0 deletions plugin/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from __future__ import annotations

assert __package__

PACKAGE_NAME = __package__.partition(".")[0]
43 changes: 43 additions & 0 deletions plugin/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from __future__ import annotations

from typing import Any

import sublime

from .constants import PACKAGE_NAME


def log_debug(message: str) -> None:
print(f"[{PACKAGE_NAME}][DEBUG] {message}")


def log_info(message: str) -> None:
print(f"[{PACKAGE_NAME}][INFO] {message}")


def log_warning(message: str) -> None:
print(f"[{PACKAGE_NAME}][WARNING] {message}")


def log_error(message: str) -> None:
print(f"[{PACKAGE_NAME}][ERROR] {message}")


def pluginfy_msg(msg: str, *args: Any, **kwargs: Any) -> str:
return msg.format(*args, _=PACKAGE_NAME, **kwargs)


def console_msg(msg: str, *args: Any, **kwargs: Any) -> None:
print(pluginfy_msg(msg, *args, **kwargs))


def status_msg(msg: str, *args: Any, **kwargs: Any) -> None:
sublime.status_message(pluginfy_msg(msg, *args, **kwargs))


def info_box(msg: str, *args: Any, **kwargs: Any) -> None:
sublime.message_dialog(pluginfy_msg(msg, *args, **kwargs))


def error_box(msg: str, *args: Any, **kwargs: Any) -> None:
sublime.error_message(pluginfy_msg(msg, *args, **kwargs))
26 changes: 26 additions & 0 deletions plugin/template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import annotations

from functools import lru_cache

import jinja2
import sublime

from .constants import PACKAGE_NAME

JINJA_TEMPLATE_ENV = jinja2.Environment(
extensions=[
"jinja2.ext.do",
"jinja2.ext.loopcontrols",
],
)


@lru_cache
def load_string_template(template: str) -> jinja2.Template:
return JINJA_TEMPLATE_ENV.from_string(template)


@lru_cache
def load_resource_template(resource_name: str) -> jinja2.Template:
content = sublime.load_resource(f"Packages/{PACKAGE_NAME}/plugin/templates/{resource_name}")
return load_string_template(content)
57 changes: 50 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
[tool.mypy]
# ignore_missing_imports = False
check_untyped_defs = true
strict_optional = true
mypy_path = 'typings:stubs'
python_version = '3.8'

[[tool.mypy.overrides]]
module = ["plugin.libs.*"]
ignore_errors = true
ignore_missing_imports = true

[tool.pyright]
include = ['./']
exclude = [
'**/__pycache__/',
'**/node_modules/',
# git-related
'**/.git/',
'**/br-*/',
'**/branch-*/',
]
ignore = ['**/.venv', '**/libs']
stubPath = 'typings'
pythonVersion = '3.8'

[tool.ruff]
ignore = []
line-length = 88
select = [
"E",
"F",
"W",
]
preview = true
line-length = 120
target-version = 'py38'
exclude = [
"*/libs/*",
".git",
".mypy_cache",
".venv",
".venv-*",
"branch-*",
"stubs",
"tests/files",
"typings",
"vendor",
"venv",
"venv-*",
]

[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "FURB"]
ignore = ["E203"]

[tool.ruff.lint.per-file-ignores]
"boot.py" = ["E402"]
4 changes: 4 additions & 0 deletions requirements-dev.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-r requirements-prod.in

mypy
ruff>=0.5
10 changes: 10 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file was autogenerated by uv via the following command:
# uv pip compile requirements-dev.in -o requirements-dev.txt
mypy==1.10.1
# via -r requirements-dev.in
mypy-extensions==1.0.0
# via mypy
ruff==0.5.3
# via -r requirements-dev.in
typing-extensions==4.12.2
# via mypy
Loading

0 comments on commit 60291fc

Please sign in to comment.