76 lines
2.2 KiB
Python
76 lines
2.2 KiB
Python
|
|
"""
|
||
|
|
pylsp plugin: injects i80/LRU packages into import completions.
|
||
|
|
|
||
|
|
Registered via entry_points group "pylsp" in pyproject.toml.
|
||
|
|
pylsp calls these hooks automatically when the plugin is installed.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import asyncio
|
||
|
|
import logging
|
||
|
|
|
||
|
|
from pylsp import hookimpl
|
||
|
|
|
||
|
|
from .catalog import PypiCatalog
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
# Trigger characters that indicate we're completing an import statement
|
||
|
|
_IMPORT_TRIGGERS = {"import", "from"}
|
||
|
|
|
||
|
|
|
||
|
|
def _is_import_context(document, position) -> bool:
|
||
|
|
"""Return True if the cursor is on an import line."""
|
||
|
|
line_num = position["line"]
|
||
|
|
if line_num >= len(document.lines):
|
||
|
|
return False
|
||
|
|
line = document.lines[line_num].strip()
|
||
|
|
return any(line.startswith(kw) for kw in _IMPORT_TRIGGERS)
|
||
|
|
|
||
|
|
|
||
|
|
@hookimpl
|
||
|
|
def pylsp_completions(config, workspace, document, position):
|
||
|
|
"""Inject i80 pypi packages when completing import statements."""
|
||
|
|
if not _is_import_context(document, position):
|
||
|
|
return []
|
||
|
|
|
||
|
|
# PypiCatalog._packages is populated at startup; safe to read synchronously
|
||
|
|
packages = PypiCatalog._packages
|
||
|
|
if not packages:
|
||
|
|
return []
|
||
|
|
|
||
|
|
return [
|
||
|
|
{
|
||
|
|
"label": pkg["name"],
|
||
|
|
"kind": 9, # Module
|
||
|
|
"detail": "i80 — pypi-server.i80.dk",
|
||
|
|
"sortText": f"{pkg['sort_prefix']}{pkg['name']}",
|
||
|
|
"documentation": {
|
||
|
|
"kind": "markdown",
|
||
|
|
"value": f"**{pkg['name']}**\n\nCustom i80/LRU package from `pypi-server.i80.dk`",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
for pkg in packages
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
@hookimpl
|
||
|
|
def pylsp_hover(config, workspace, document, position):
|
||
|
|
"""Show package docs on hover for i80 packages."""
|
||
|
|
word = document.word_at_position(position)
|
||
|
|
if not word:
|
||
|
|
return None
|
||
|
|
|
||
|
|
for pkg in PypiCatalog._packages:
|
||
|
|
if pkg["name"] == word:
|
||
|
|
return {
|
||
|
|
"contents": {
|
||
|
|
"kind": "markdown",
|
||
|
|
"value": (
|
||
|
|
f"**{pkg['name']}** — i80 internal package\n\n"
|
||
|
|
f"Source: `pypi-server.i80.dk`\n\n"
|
||
|
|
f"Install: `pip install {pkg['name']} --index-url https://pypi-server.i80.dk/simple/`"
|
||
|
|
),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return None
|