update
This commit is contained in:
+54
-13
@@ -1,3 +1,4 @@
|
||||
from collections.abc import Iterator
|
||||
from dataclasses import dataclass, field
|
||||
from json import loads
|
||||
from pydantic import BaseModel
|
||||
@@ -6,9 +7,39 @@ from requests import HTTPError, get
|
||||
from .common import EnvVar, JSONDataMap, JSONData, JSONDataList, JSONDataScalar
|
||||
|
||||
|
||||
class ClickupStatus(BaseModel):
|
||||
status: str
|
||||
|
||||
@property
|
||||
def status_symbol(self) -> str:
|
||||
match self.status:
|
||||
case "backlog":
|
||||
return ""
|
||||
case "selected for development":
|
||||
return ""
|
||||
case "in progress":
|
||||
return ""
|
||||
case "in review":
|
||||
return ""
|
||||
case "done":
|
||||
return ""
|
||||
case "closed":
|
||||
return ""
|
||||
case "on hold":
|
||||
return ""
|
||||
case _:
|
||||
return self.status
|
||||
|
||||
|
||||
class ClickupTask(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
markdown_description: str
|
||||
status: ClickupStatus
|
||||
|
||||
|
||||
class ClickupList(BaseModel):
|
||||
task_count: int
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -44,20 +75,27 @@ class ClickupSession:
|
||||
) as resp:
|
||||
return resp.json()
|
||||
|
||||
def get_tasks(self, **filters: str) -> list[ClickupTask]:
|
||||
data = self._get(
|
||||
f"/team/{self.workspace_id}/task",
|
||||
**{
|
||||
"subtasks": "true",
|
||||
"include_markdown_description": "true",
|
||||
"assignees[]": self.user_id,
|
||||
}
|
||||
| filters,
|
||||
).get("tasks", [])
|
||||
if isinstance(data, list):
|
||||
return [ClickupTask.model_validate(t) for t in data if isinstance(t, dict)]
|
||||
def get_tasks(self, **filters: str) -> Iterator[ClickupTask]:
|
||||
pix = 0
|
||||
while True:
|
||||
partial_data = self._get(
|
||||
f"/team/{self.workspace_id}/task",
|
||||
**{
|
||||
"subtasks": "true",
|
||||
"include_markdown_description": "true",
|
||||
"include_closed": "true",
|
||||
"assignees[]": self.user_id,
|
||||
"page": pix,
|
||||
}
|
||||
| filters,
|
||||
).get("tasks", [])
|
||||
pix += 1
|
||||
|
||||
return []
|
||||
for inst in partial_data:
|
||||
yield ClickupTask.model_validate(inst)
|
||||
|
||||
if len(partial_data) < 100:
|
||||
break
|
||||
|
||||
def get_task(self, task_id: str) -> ClickupTask:
|
||||
return ClickupTask.model_validate(
|
||||
@@ -66,3 +104,6 @@ class ClickupSession:
|
||||
include_markdown_description="true",
|
||||
),
|
||||
)
|
||||
|
||||
def get_list(self, list_id: str) -> ClickupList:
|
||||
return ClickupList.model_validate(self._get(f"/list/{list_id}"))
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from requests import get
|
||||
from requests.compat import quote
|
||||
|
||||
from eta.common import EnvVar, JSONDataMap
|
||||
|
||||
|
||||
class GitlabProject(BaseModel):
|
||||
name: str
|
||||
name_with_namespace: str
|
||||
path_with_namespace: str
|
||||
web_url: str
|
||||
id: int
|
||||
|
||||
issues: list["GitlabIssue"] = Field(default_factory=list, init=False)
|
||||
merge_requests: list["GitlabMergeRequest"] = Field(default_factory=list, init=False)
|
||||
|
||||
|
||||
class GitlabMilestone(BaseModel):
|
||||
id: int
|
||||
title: str
|
||||
state: str
|
||||
|
||||
|
||||
class GitlabIssue(BaseModel):
|
||||
title: str
|
||||
description: str | None
|
||||
id: int
|
||||
project_id: int
|
||||
iid: int
|
||||
state: str
|
||||
labels: list[str]
|
||||
milestone: GitlabMilestone | None
|
||||
# web_url: str
|
||||
|
||||
|
||||
class GitlabMergeRequest(BaseModel):
|
||||
id: int
|
||||
iid: int
|
||||
description: str | None
|
||||
draft: bool
|
||||
labels: list[str]
|
||||
milestone: GitlabMilestone | None
|
||||
source_branch: str
|
||||
state: str
|
||||
target_branch: str
|
||||
project_id: int
|
||||
title: str
|
||||
web_url: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class GitlabSession:
|
||||
auth_key: str = field(
|
||||
default_factory=EnvVar(
|
||||
"GITLAB_AUTH",
|
||||
"gitlab auth token is required to be set",
|
||||
)
|
||||
)
|
||||
base_url: str = "https://git.extoll.de/api/v4"
|
||||
|
||||
def _get(self, endpoint: str, **query_params: str) -> JSONDataMap:
|
||||
with get(
|
||||
self.base_url + endpoint,
|
||||
query_params,
|
||||
headers={
|
||||
"accept": "application/json",
|
||||
"PRIVATE-TOKEN": self.auth_key,
|
||||
},
|
||||
verify=False,
|
||||
) as resp:
|
||||
return resp.json()
|
||||
|
||||
def get_projects(self, **filters: str) -> list[GitlabProject]:
|
||||
ret: list[GitlabProject] = []
|
||||
page = 1
|
||||
while projs := self._get(
|
||||
"/projects",
|
||||
active="true",
|
||||
simple="true",
|
||||
per_page="100",
|
||||
page=str(page),
|
||||
):
|
||||
ret.extend(GitlabProject.model_validate(proj) for proj in projs)
|
||||
page = page + 1
|
||||
if len(projs) < 100:
|
||||
break
|
||||
|
||||
return ret
|
||||
|
||||
def get_issues(self, projects: list[GitlabProject]) -> list[GitlabIssue]:
|
||||
ret: list[GitlabIssue] = []
|
||||
pids = {p.id for p in projects}
|
||||
page = 1
|
||||
while True:
|
||||
issues = self._get(
|
||||
"/issues",
|
||||
per_page="100",
|
||||
page=str(page),
|
||||
)
|
||||
ret.extend(
|
||||
GitlabIssue.model_validate(iss) for iss in issues if int(iss["project_id"]) in pids
|
||||
)
|
||||
page = page + 1
|
||||
if len(issues) < 100:
|
||||
break
|
||||
|
||||
return ret
|
||||
|
||||
def get_merge_requests(self, projects: list[GitlabProject]) -> list[GitlabMergeRequest]:
|
||||
ret: list[GitlabMergeRequest] = []
|
||||
pids = {p.id for p in projects}
|
||||
page = 1
|
||||
while True:
|
||||
merge_requests = self._get(
|
||||
"/merge_requests",
|
||||
simple="true",
|
||||
per_page="100",
|
||||
page=str(page),
|
||||
)
|
||||
ret.extend(
|
||||
GitlabMergeRequest.model_validate(mr)
|
||||
for mr in merge_requests
|
||||
if int(mr["project_id"]) in pids
|
||||
)
|
||||
page = page + 1
|
||||
if len(merge_requests) < 100:
|
||||
break
|
||||
|
||||
return ret
|
||||
+367
-22
@@ -1,6 +1,20 @@
|
||||
from enum import Enum, IntEnum
|
||||
import re
|
||||
|
||||
from lsprotocol.types import (
|
||||
INITIALIZED,
|
||||
TEXT_DOCUMENT_CODE_ACTION,
|
||||
TEXT_DOCUMENT_COMPLETION,
|
||||
TEXT_DOCUMENT_DOCUMENT_SYMBOL,
|
||||
TEXT_DOCUMENT_HOVER,
|
||||
TEXT_DOCUMENT_INLAY_HINT,
|
||||
TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
|
||||
WORKSPACE_INLAY_HINT_REFRESH,
|
||||
CodeAction,
|
||||
CodeActionKind,
|
||||
CodeActionOptions,
|
||||
CodeActionParams,
|
||||
Command,
|
||||
CompletionItem,
|
||||
CompletionItemKind,
|
||||
CompletionItemLabelDetails,
|
||||
@@ -8,9 +22,19 @@ from lsprotocol.types import (
|
||||
CompletionParams,
|
||||
DocumentSymbol,
|
||||
DocumentSymbolParams,
|
||||
Hover,
|
||||
HoverParams,
|
||||
InitializedParams,
|
||||
InlayHint,
|
||||
InlayHintParams,
|
||||
MarkupContent,
|
||||
MarkupKind,
|
||||
NotebookDocumentSyncOptions,
|
||||
Position,
|
||||
Range,
|
||||
SemanticTokens,
|
||||
SemanticTokensLegend,
|
||||
SemanticTokensParams,
|
||||
SymbolKind,
|
||||
TextDocumentSyncKind,
|
||||
WorkDoneProgressBegin,
|
||||
@@ -19,13 +43,22 @@ from lsprotocol.types import (
|
||||
)
|
||||
from pygls.lsp.server import LanguageServer
|
||||
|
||||
from eta.gitlab import GitlabProject, GitlabSession
|
||||
|
||||
from .clickup import ClickupSession, ClickupTask
|
||||
|
||||
GL_PRJ_PATTERN = r"#project\/(?P<ns>((\w+)/)+)(?P<prj>\w+)"
|
||||
GL_ID_PATTERN = r"#(?P<idt>mr|issue)\/(?P<sid>\d+)"
|
||||
CU_PATTERN = r"#task/(?P<id>\w{8,})"
|
||||
|
||||
|
||||
class CustomServer(LanguageServer):
|
||||
cache: dict[str, ClickupTask]
|
||||
cu_cache: dict[str, ClickupTask]
|
||||
cu_session: ClickupSession
|
||||
|
||||
gl_cache: dict[str, GitlabProject]
|
||||
gl_session: GitlabSession
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
@@ -34,29 +67,62 @@ class CustomServer(LanguageServer):
|
||||
notebook_document_sync: NotebookDocumentSyncOptions | None = None,
|
||||
) -> None:
|
||||
super().__init__(name, version, text_document_sync_kind, notebook_document_sync)
|
||||
self.cache = {}
|
||||
self.cu_cache = {}
|
||||
self.cu_session = ClickupSession()
|
||||
self.update_task_cache()
|
||||
self.gl_cache = {}
|
||||
self.gl_session = GitlabSession()
|
||||
|
||||
def update_task_cache(self) -> None:
|
||||
self.protocol.progress.begin(
|
||||
"startup", WorkDoneProgressBegin("Fetching Cache ...", percentage=0, cancellable=True)
|
||||
)
|
||||
self.cache = {}
|
||||
tasks = self.cu_session.get_ta()
|
||||
async def update_task_cache(self) -> None:
|
||||
self.cu_cache = {}
|
||||
tasks = self.cu_session.get_tasks()
|
||||
for ti, t in enumerate(tasks):
|
||||
self.cache[t.id] = t
|
||||
self.cu_cache[t.id] = t
|
||||
self.protocol.progress.report(
|
||||
"startup",
|
||||
WorkDoneProgressReport(
|
||||
message="Fetched Cache", percentage=int(100 * (1 + ti) / len(tasks))
|
||||
message="ClickUp Tasks", percentage=int(100 * (1 + ti) / len(tasks))
|
||||
),
|
||||
)
|
||||
|
||||
self.protocol.progress.end("startup", WorkDoneProgressEnd(message="Done Caching"))
|
||||
async def update_proj_cache(self) -> None:
|
||||
self.gl_cache = {}
|
||||
projs = self.gl_session.get_projects()
|
||||
for pi, p in enumerate(projs):
|
||||
self.gl_cache[p.path_with_namespace] = p
|
||||
self.protocol.progress.report(
|
||||
"startup",
|
||||
WorkDoneProgressReport(
|
||||
message="Gitlab Prjects", percentage=int(100 * (1 + pi) / len(projs))
|
||||
),
|
||||
)
|
||||
|
||||
await self.update_issue_cache(projs)
|
||||
await self.update_mr_cache(projs)
|
||||
|
||||
async def update_issue_cache(self, prjs: list[GitlabProject]) -> None:
|
||||
p_by_id = {p.id: p for p in prjs}
|
||||
issues = self.gl_session.get_issues(prjs)
|
||||
for issue in issues:
|
||||
self.gl_cache[p_by_id[issue.project_id].path_with_namespace].issues.append(issue)
|
||||
|
||||
async def update_mr_cache(self, prjs: list[GitlabProject]) -> None:
|
||||
p_by_id = {p.id: p for p in prjs}
|
||||
mrs = self.gl_session.get_merge_requests(prjs)
|
||||
for mr in mrs:
|
||||
self.gl_cache[p_by_id[mr.project_id].path_with_namespace].merge_requests.append(mr)
|
||||
|
||||
|
||||
server = CustomServer("mrpy-server", "0.1.0")
|
||||
server = CustomServer("eta-server", "0.1.0")
|
||||
|
||||
|
||||
@server.feature(INITIALIZED)
|
||||
async def on_init(params: InitializedParams) -> None:
|
||||
server.protocol.progress.begin(
|
||||
"startup", WorkDoneProgressBegin("Caching ", percentage=0, cancellable=True)
|
||||
)
|
||||
await server.update_task_cache()
|
||||
await server.update_proj_cache()
|
||||
server.protocol.progress.end("startup", WorkDoneProgressEnd(message="Done Caching"))
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_DOCUMENT_SYMBOL)
|
||||
@@ -69,22 +135,301 @@ async def list_ids(params: DocumentSymbolParams) -> list[DocumentSymbol]:
|
||||
Range(Position(i, 0), Position(i, 0)),
|
||||
detail=t.name,
|
||||
)
|
||||
for i, t in enumerate(server.cache.values())
|
||||
for i, t in enumerate(server.cu_cache.values())
|
||||
]
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_COMPLETION)
|
||||
@server.feature(TEXT_DOCUMENT_COMPLETION, CompletionOptions(trigger_characters=["/", "!", "#"]))
|
||||
async def complete_cu_ids(params: CompletionParams) -> list[CompletionItem]:
|
||||
doc = server.workspace.get_text_document(params.text_document.uri)
|
||||
line = doc.lines[params.position.line]
|
||||
|
||||
if not line[: params.position.character].strip().endswith(("/", "!", "#")):
|
||||
return []
|
||||
|
||||
prev = (
|
||||
line[: params.position.character]
|
||||
.strip()
|
||||
.removesuffix("/")
|
||||
.removesuffix("!")
|
||||
.removesuffix("#")
|
||||
.split("#")[-1]
|
||||
)
|
||||
if prev.endswith(("task", "cu", "clickup")):
|
||||
return [
|
||||
CompletionItem(
|
||||
f"{t.name}",
|
||||
CompletionItemLabelDetails(detail=f" #{t.id}"),
|
||||
kind=CompletionItemKind.Constant,
|
||||
insert_text=f"{t.id}",
|
||||
)
|
||||
for t in server.cu_cache.values()
|
||||
]
|
||||
if prev.endswith(("project", "gitlab", "gl")):
|
||||
return [
|
||||
CompletionItem(
|
||||
p.path_with_namespace,
|
||||
detail=f" {p.path_with_namespace}",
|
||||
kind=CompletionItemKind.Enum,
|
||||
)
|
||||
for p in server.gl_cache.values()
|
||||
]
|
||||
|
||||
prj = next(re.finditer(GL_PRJ_PATTERN, line), None)
|
||||
if prj is None:
|
||||
return [
|
||||
CompletionItem(
|
||||
f"{line}: {prj}",
|
||||
)
|
||||
]
|
||||
|
||||
if prev.endswith("issue"):
|
||||
return [
|
||||
CompletionItem(
|
||||
i.title,
|
||||
insert_text=f"{i.iid}",
|
||||
detail=f"#{i.iid}: {i.title} {' '.join('[' + t + ']' for t in i.labels)}",
|
||||
documentation=i.description,
|
||||
kind=CompletionItemKind.EnumMember,
|
||||
)
|
||||
for p in server.gl_cache.values()
|
||||
for i in p.issues
|
||||
if i.state == "opened"
|
||||
and p.path_with_namespace == f"{prj.group('ns')}{prj.group('prj')}"
|
||||
]
|
||||
|
||||
if prev.endswith("mr"):
|
||||
return [
|
||||
CompletionItem(
|
||||
f"!{m.title} ({p.path_with_namespace}!{m.iid})",
|
||||
insert_text=f"{m.iid}",
|
||||
detail=f"!{m.iid}: {m.title} {' '.join('[' + t + ']' for t in m.labels)}",
|
||||
documentation=m.description,
|
||||
kind=CompletionItemKind.EnumMember,
|
||||
)
|
||||
for p in server.gl_cache.values()
|
||||
for m in p.merge_requests
|
||||
if m.state == "opened"
|
||||
and p.path_with_namespace.casefold()
|
||||
== f"{prj.group('ns')}{prj.group('prj')}".casefold()
|
||||
]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_INLAY_HINT)
|
||||
async def inlay_info(params: InlayHintParams) -> list[InlayHint]:
|
||||
ret: list[InlayHint] = []
|
||||
for lid, line in enumerate(server.workspace.text_documents[params.text_document.uri].lines):
|
||||
# for m in re.finditer(GL_PATTERN, line):
|
||||
# ns = m.group("ns")
|
||||
# prj = m.group("prj")
|
||||
# idt = m.group("styp")
|
||||
# id = m.group("sid")
|
||||
#
|
||||
# if p := server.gl_cache.get(f"{ns}{prj}"):
|
||||
# if not idt:
|
||||
# pass
|
||||
# elif idt == "!" and (mr := next(m for m in p.merge_requests if str(m.iid) == id)):
|
||||
# ret.append(
|
||||
# InlayHint(
|
||||
# Position(line=lid, character=m.end()),
|
||||
# label=f"({mr.title} | {mr.state})",
|
||||
# padding_right=True,
|
||||
# padding_left=True,
|
||||
# )
|
||||
# )
|
||||
# elif idt == "#" and (issue := next(i for i in p.issues if str(i.iid) == id)):
|
||||
# ret.append(
|
||||
# InlayHint(
|
||||
# Position(line=lid, character=m.end()),
|
||||
# label=f"({issue.title} | {issue.state})",
|
||||
# padding_right=True,
|
||||
# padding_left=True,
|
||||
# )
|
||||
# )
|
||||
for m in re.finditer(CU_PATTERN, line):
|
||||
id = m.group(1)
|
||||
if t := server.cu_cache.get(id):
|
||||
ret.append(
|
||||
InlayHint(
|
||||
Position(line=lid, character=m.start()),
|
||||
label=f"{t.status.status_symbol}",
|
||||
padding_left=False,
|
||||
padding_right=False,
|
||||
)
|
||||
)
|
||||
ret.append(
|
||||
InlayHint(
|
||||
Position(line=lid, character=m.end()),
|
||||
label=f"{t.name}",
|
||||
padding_left=True,
|
||||
padding_right=False,
|
||||
)
|
||||
)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@server.command("recache_gl")
|
||||
async def recache_gl(*_) -> None:
|
||||
await server.update_proj_cache()
|
||||
await server.protocol.send_request_async(WORKSPACE_INLAY_HINT_REFRESH, None)
|
||||
|
||||
|
||||
@server.command("recache_cu")
|
||||
async def recache_cu(*_) -> None:
|
||||
await server.update_task_cache()
|
||||
await server.protocol.send_request_async(WORKSPACE_INLAY_HINT_REFRESH, None)
|
||||
|
||||
|
||||
@server.feature(
|
||||
TEXT_DOCUMENT_CODE_ACTION,
|
||||
CodeActionOptions(code_action_kinds=[CodeActionKind.QuickFix]),
|
||||
)
|
||||
def code_actions(params: CodeActionParams) -> list[CodeAction]:
|
||||
return [
|
||||
CompletionItem(
|
||||
t.name,
|
||||
CompletionItemLabelDetails(detail=f" #{t.id}"),
|
||||
kind=CompletionItemKind.Constant,
|
||||
insert_text=f"[{t.name} #{t.id}](https://app.clickup.com/t/{t.id})",
|
||||
)
|
||||
for t in server.cache.values()
|
||||
CodeAction(
|
||||
"Re-Cache GitLab Project Info",
|
||||
kind=CodeActionKind.QuickFix,
|
||||
command=Command("recache gl", "recache_gl"),
|
||||
),
|
||||
CodeAction(
|
||||
"Re-Cache ClickUp Task Info",
|
||||
kind=CodeActionKind.QuickFix,
|
||||
command=Command("recache cu", "recache_cu"),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_HOVER)
|
||||
def on_hover(params: HoverParams) -> Hover | None:
|
||||
doc = server.workspace.get_text_document(params.text_document.uri)
|
||||
line = doc.lines[params.position.line]
|
||||
|
||||
# prj_match = list(re.finditer(GL_PRJ_PATTERN, line))[0]
|
||||
# ns = prj_match.group("ns")
|
||||
# prj = prj_match.group("prj")
|
||||
# id_match = list(re.finditer(GL_ID_PATTERN, line))
|
||||
#
|
||||
# if p := server.gl_cache.get(f"{ns}{prj}"):
|
||||
# for m in id_match:
|
||||
# if params.position.character >= m.start() and params.position.character < m.end():
|
||||
# idt = m.group("idt")
|
||||
# id = m.group("sid")
|
||||
#
|
||||
# if not idt:
|
||||
# pass
|
||||
# elif idt == "mr" and (mr := next(m for m in p.merge_requests if str(m.iid) == id)):
|
||||
# return Hover(
|
||||
# MarkupContent(
|
||||
# kind=MarkupKind.Markdown,
|
||||
# value=f"# {mr.title}\n\n{mr.description or ''}",
|
||||
# ),
|
||||
# range=Range(
|
||||
# Position(line=params.position.line, character=m.start()),
|
||||
# Position(line=params.position.line, character=m.end()),
|
||||
# ),
|
||||
# )
|
||||
# elif idt == "issue" and (issue := next(i for i in p.issues if str(i.iid) == id)):
|
||||
# return Hover(
|
||||
# MarkupContent(
|
||||
# kind=MarkupKind.Markdown,
|
||||
# value=f"# {issue.title}\n\n{issue.description or ''}",
|
||||
# ),
|
||||
# range=Range(
|
||||
# Position(line=params.position.line, character=m.start()),
|
||||
# Position(line=params.position.line, character=m.end()),
|
||||
# ),
|
||||
# )
|
||||
|
||||
for m in re.finditer(CU_PATTERN, line):
|
||||
if params.position.character >= m.start() and params.position.character < m.end():
|
||||
id = m.group("id")
|
||||
|
||||
if t := server.cu_cache.get(id):
|
||||
return Hover(
|
||||
MarkupContent(
|
||||
kind=MarkupKind.Markdown,
|
||||
value=f"# {t.name} - {t.status.status}\n\n{t.markdown_description}",
|
||||
),
|
||||
range=Range(
|
||||
Position(line=params.position.line, character=m.start()),
|
||||
Position(line=params.position.line, character=m.end()),
|
||||
),
|
||||
)
|
||||
else:
|
||||
return Hover(
|
||||
MarkupContent(
|
||||
kind=MarkupKind.Markdown,
|
||||
value=f"# {id}: {m.group(0)}\n\n{list(server.cu_cache)}",
|
||||
),
|
||||
range=Range(
|
||||
Position(line=params.position.line, character=m.start()),
|
||||
Position(line=params.position.line, character=m.end()),
|
||||
),
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def token_offset(rest: list[int], current: tuple[int, int]) -> tuple[int, int]:
|
||||
lines = rest[::5]
|
||||
# offsets = rest[:-4:-5]
|
||||
|
||||
last_line = sum(lines)
|
||||
return (current[0] - last_line, current[1])
|
||||
|
||||
|
||||
class TaskModifiers(Enum):
|
||||
Backlog = "backlog"
|
||||
Selected = "selected for development"
|
||||
Progress = "in progress"
|
||||
Review = "in review"
|
||||
Done = "done"
|
||||
Closed = "closed"
|
||||
|
||||
|
||||
@server.feature(
|
||||
TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
|
||||
SemanticTokensLegend(["cuTask"], list(t.name for t in TaskModifiers)),
|
||||
)
|
||||
def sem_tokens(params: SemanticTokensParams) -> SemanticTokens:
|
||||
ret: list[int] = []
|
||||
doc = server.workspace.get_text_document(params.text_document.uri)
|
||||
|
||||
for lix, line in enumerate(doc.lines):
|
||||
# ms = re.finditer(GL_PATTERN, line)
|
||||
#
|
||||
# for m in ms:
|
||||
# idt = m.group("styp")
|
||||
# id = m.group("sid")
|
||||
# rel_line, rel_char = token_offset(ret, (lix, m.start()))
|
||||
#
|
||||
# if not idt:
|
||||
# ret.extend([rel_line, rel_char, len(m.group(0)), 0, 0])
|
||||
# elif idt == "!":
|
||||
# ret.extend([rel_line, rel_char, len(m.group(0)), 2, 0])
|
||||
# elif idt == "#":
|
||||
# ret.extend([rel_line, rel_char, len(m.group(0)), 2, 0])
|
||||
|
||||
for m in re.finditer(CU_PATTERN, line):
|
||||
id = m.group("id")
|
||||
rel_line, rel_char = token_offset(ret, (lix, m.start()))
|
||||
|
||||
if t := server.cu_cache.get(id):
|
||||
ret.extend(
|
||||
[
|
||||
rel_line,
|
||||
rel_char,
|
||||
len(m.group(0)),
|
||||
0,
|
||||
list(t.value for t in TaskModifiers).index(t.status.status),
|
||||
]
|
||||
)
|
||||
|
||||
return SemanticTokens(data=ret)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server.start_io()
|
||||
|
||||
Reference in New Issue
Block a user