Compare commits

..

No commits in common. "7c6c3d7223a78fd316b7e1cc9dc19a7435a1675a" and "8dc1d080d8dfcecf683637e9bca5e7f71b403587" have entirely different histories.

12 changed files with 104 additions and 700 deletions

View File

View File

@ -1,68 +0,0 @@
from dataclasses import dataclass, field
from json import loads
from pydantic import BaseModel
from requests import HTTPError, get
from .common import EnvVar, JSONDataMap, JSONData, JSONDataList, JSONDataScalar
class ClickupTask(BaseModel):
id: str
name: str
@dataclass
class ClickupSession:
auth_key: str = field(
default_factory=EnvVar(
"CLICKUP_AUTH",
"clickup auth token is required to be set",
)
)
workspace_id: str = field(
default_factory=EnvVar(
"CLICKUP_WORKSPACE_ID",
"clickup workspace id is required to be set",
)
)
user_id: str = field(
default_factory=EnvVar(
"CLICKUP_USER_ID",
"clickup user id is required to be set",
)
)
base_url: str = "https://api.clickup.com/api/v2"
def _get(self, endpoint: str, **query_params: str) -> JSONDataMap:
with get(
self.base_url + endpoint,
query_params,
headers={
"accept": "application/json",
"Authorization": self.auth_key,
},
) 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)]
return []
def get_task(self, task_id: str) -> ClickupTask:
return ClickupTask.model_validate(
self._get(
f"/task/{task_id}",
include_markdown_description="true",
),
)

View File

@ -1,32 +0,0 @@
from __future__ import annotations
from dataclasses import dataclass
from os import environ
from typing import TypeAlias
JSONDataScalar: TypeAlias = str | None | float | bool
JSONDataList: TypeAlias = list["JSONDataScalar | JSONDataMap | JSONDataList"]
JSONDataMap: TypeAlias = dict[str, "JSONDataScalar | JSONDataList | JSONDataMap"]
JSONData: TypeAlias = "JSONDataMap | JSONDataList"
@dataclass
class EnvVar:
"""
Environment Variable fetcher for use in dataclass ``field(default_factory=...)``
>>> @dataclass
>>> class SomeDataclass:
... field_name: str = field(default_factory=EnvVar("SOME_VAR_NAME", "err msg"))
"""
var_name: str
err_msg: str = ""
def __call__(self) -> str:
try:
return environ[self.var_name]
except KeyError as e:
e.add_note(self.err_msg)
raise

View File

@ -1,90 +0,0 @@
from lsprotocol.types import (
TEXT_DOCUMENT_COMPLETION,
TEXT_DOCUMENT_DOCUMENT_SYMBOL,
CompletionItem,
CompletionItemKind,
CompletionItemLabelDetails,
CompletionOptions,
CompletionParams,
DocumentSymbol,
DocumentSymbolParams,
NotebookDocumentSyncOptions,
Position,
Range,
SymbolKind,
TextDocumentSyncKind,
WorkDoneProgressBegin,
WorkDoneProgressEnd,
WorkDoneProgressReport,
)
from pygls.lsp.server import LanguageServer
from .clickup import ClickupSession, ClickupTask
class CustomServer(LanguageServer):
cache: dict[str, ClickupTask]
cu_session: ClickupSession
def __init__(
self,
name: str,
version: str,
text_document_sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental,
notebook_document_sync: NotebookDocumentSyncOptions | None = None,
) -> None:
super().__init__(name, version, text_document_sync_kind, notebook_document_sync)
self.cache = {}
self.cu_session = ClickupSession()
self.update_task_cache()
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()
for ti, t in enumerate(tasks):
self.cache[t.id] = t
self.protocol.progress.report(
"startup",
WorkDoneProgressReport(
message="Fetched Cache", percentage=int(100 * (1 + ti) / len(tasks))
),
)
self.protocol.progress.end("startup", WorkDoneProgressEnd(message="Done Caching"))
server = CustomServer("mrpy-server", "0.1.0")
@server.feature(TEXT_DOCUMENT_DOCUMENT_SYMBOL)
async def list_ids(params: DocumentSymbolParams) -> list[DocumentSymbol]:
return [
DocumentSymbol(
t.id,
SymbolKind.Enum,
Range(Position(i, 0), Position(i, 0)),
Range(Position(i, 0), Position(i, 0)),
detail=t.name,
)
for i, t in enumerate(server.cache.values())
]
@server.feature(TEXT_DOCUMENT_COMPLETION)
async def complete_cu_ids(params: CompletionParams) -> list[CompletionItem]:
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()
]
def main() -> None:
server.start_io()

View File

@ -1,103 +0,0 @@
local curl = require("plenary.curl")
local helpers = require("eta.helpers")
local M = {}
---@class eta.clickup.Session: eta.Session
---@field user string
---@field workspace string
---@class eta.clickup.Ref
---@field name string
---@field id string
---@class eta.clickup.Dep
---@field task_id string
---@field depends_on string
---@class eta.clickup.Task
---@field id string
---@field name string
---@field tags? table[]
---@field locations? table[]
---@field list? eta.clickup.Ref
---@field parent? string | nil
---@field dependencies? eta.clickup.Dep[]
---@field [string] string
---@param self eta.clickup.Session
---@return eta.clickup.Task[]
M.latest_tasks = function(self)
local ret = helpers.request("get", self, "/team/" .. self.workspace .. "/task",{subtasks="true", include_markdown_description="true", ['assignees[]']= self.user})
if ret then
return ret.tasks
end
return {}
end
---@param self eta.clickup.Session
---@param id string
---@return eta.clickup.Task
M.task = function(self, id)
local ret = helpers.request("get", self, "/task/" .. id,{include_markdown_description="true"}) or {}
return ret
end
---@param self eta.clickup.Session
---@param id string
M.task_relations = function(self, id)
local ret = helpers.request("get", self, "/task/" .. id .. "/dependency", {}) or {}
return ret
end
M.insert_ref = function()
local pos = vim.api.nvim_win_get_cursor(0)
local row = pos[1] - 1
local col = pos[2]
local tasks = M.latest_tasks(require("plugin.eta").clickup_session)
---@type SelectionItem[]
local items = {}
for tix, t in ipairs(tasks) do
if string.sub(t.name, -7, -1) ~= "Absence" then
local preview_frontmatter = ""
---@type SelectionItem
local prepared = {
idx = tix,
id = t.id,
text = t.name .. t.id .. t.markdown_description,
name = t.name,
tags = require("plugin.eta").retrieve_subkeys(t.tags, { "name" }),
status = t.status.status,
parent = t.parent,
list = t.list.name,
description = t.markdown_description,
preview = {
ft = "markdown",
},
action = M._on_select_task
}
for _, k in ipairs({ "id", "name", "status", "tags", "parent" }) do
preview_frontmatter = preview_frontmatter .. "\n" .. k .. ": " .. vim.json.encode(prepared[k])
end
prepared.preview.text = "---" .. preview_frontmatter .. "\n---\n" .. t.markdown_description
table.insert(items, #items + 1, prepared)
end
end
require("snacks.picker").pick({
title = "Select Task",
format = require("plugin.eta")._item_format,
preview = "preview",
confirm = function(picker, item)
picker:close()
vim.api.nvim_buf_set_text(0, row, col, row, col,
{ "[#" .. item.id .. "](https://app.clickup.com/t/" .. item.id .. ")" })
end,
items = items
})
end
return M

View File

@ -1,149 +0,0 @@
local notify = require("snacks.notifier").notify
local helpers = require("eta.helpers")
local M = {}
---@class eta.gitlab.Session: eta.Session
---@field auth string personal access token `PRIVATE_TOKEN: <auth_token>`
---@class eta.gitlab.Namespace
---@field full_path string
---@class eta.gitlab.Project
---@field id number
---@field name string
---@field path_with_namespace string
---@field tag_list string[]
---@field text? string
---@field namespace eta.gitlab.Namespace
---@field preview? {ft: string, text: string}
---@class eta.gitlab.Milestone
---@field id number
---@field title string
---@class eta.gitlab.Assignee
---@field username string
---@field id number
---@class eta.gitlab.Issue
---@field id number
---@field milestone eta.gitlab.Milestone
---@field title string
---@field assignees eta.gitlab.Assignee[]
---@field description string
---@field labels string[]
---@param session eta.gitlab.Session
---@return eta.gitlab.Project[]
M.possible_projects = function(session)
return helpers.request("get", session, "/projects", {simple="true", per_page="100"}) or {}
end
---@param prj eta.gitlab.Project
M._project_format = function(prj)
local ret = {}
ret[#ret + 1] = { prj.namespace.full_path .. "/", "SnacksPickerComment" }
ret[#ret + 1] = { prj.name }
return ret
end
---@param self eta.gitlab.Session
---@return eta.gitlab.Project | nil
M.update_current_project = function(self)
local cmd = "git remote -v | grep fetch | cut -f2 | cut -d' ' -f1 | cut -d':' -f2"
local handle, _ = io.popen(cmd, 'r')
if not handle then return nil end
local repo = handle:read("*a")
handle:close()
local prjs = M.possible_projects(self)
for _, prj in ipairs(prjs) do
if prj.path_with_namespace == repo then
M.active_project = prj
notify("selected " .. prj.path_with_namespace, "info", { title = "ETA", style = 'fancy' })
return prj
end
end
end
---@type eta.gitlab.Project
M.active_project = nil
---@param picker snacks.Picker
---@param item eta.gitlab.Project
M._on_project_select = function(picker, item)
M.active_project = item
picker:close()
notify("selected " .. item.path_with_namespace, "info", { title = "ETA", style = 'fancy' })
end
---@param self eta.gitlab.Session
M.select_project = function(self)
local prjs = M.possible_projects(self)
require("snacks.picker").pick({
title = "Select Project",
format = M._project_format,
preview = "preview",
confirm = M._on_project_select,
items = prjs
})
end
---@param self eta.gitlab.Session
---@return eta.gitlab.Issue[]
M.active_issues = function(self)
if not M.active_project then
if not M.update_current_project(self) then
M.select_project(self)
end
end
return request("get", self, "/projects/" .. tostring(M.active_project.id) .. "/issues", {})
end
---@param self eta.gitlab.Session
---@param name string
---@param clickup_task_id string
---@param tags string[]
M.new_issue = function(self, name, clickup_task_id, tags)
if not M.active_project then
if not M.update_current_project(self) then
M.select_project(self)
end
end
local description = "%23" .. clickup_task_id
local title = name:gsub("%s", "%20")
return request("post", self, "/projects/" ..
tostring(M.active_project.id) ..
"/issues", {
title=title, description=description, labels=table.concat(tags, ",")
})
end
---@param self eta.gitlab.Session
---@param name string
---@param issue number
---@param clickup_task_id string
---@param tags string[]
M.new_mr = function(self, name, issue, clickup_task_id, tags)
if not M.active_project then
if not M.update_current_project(self) then
M.select_project(self)
end
end
local description = "Closes %23" .. tostring(issue) .. " | %23" .. clickup_task_id
local title = name:gsub("%s", "%20")
return request("post", self, "/projects/" .. tostring(M.active_project.id) .. "/merge_requests", {
title=title, description=description, labels=table.concat(tags, ",")
})
end
return M

View File

@ -1,63 +0,0 @@
local curl = require("plenary.curl")
local M = {}
---@class eta.Session
---@field auth string
---@field base_url string
---@param method `get` | `post`
---@param session eta.Session
---@param endpoint string
---@param params {[string]: string}
---@returns table | nil
M.request = function(method, session, endpoint, params)
local param_list = {}
for param_name, param_value in pairs(params) do
table.insert(param_list, param_name .. "=" .. param_value)
end
local url = session.base_url .. endpoint
if #param_list then
url = url .. "?" .. table.concat(param_list, "&")
end
local resp = nil
if method == "get" then
resp = curl.get(url, {headers = {
-- ['PRIVATE-TOKEN'] = session.auth,
['Authorization'] = session.auth,
["content-type"] = "application/json",
}})
elseif method == "post" then
resp = curl.post(url, {headers = {
-- ['PRIVATE-TOKEN'] = session.auth,
['Authorization'] = session.auth,
["content-type"] = "application/json",
}})
else
return nil
end
if resp.status == 200 then
local prjs = vim.json.decode(resp.body)
for _, prj in ipairs(prjs) do
local fcmd = "echo '" .. vim.json.encode(prj) .. "' | jq"
local fhandle, _ = io.popen(fcmd, 'r')
if not fhandle then goto continue end
local formatted = fhandle:read("*a")
fhandle:close()
prj.text = prj.path_with_namespace
prj.preview = {
ft = "json",
text = formatted
}
::continue::
end
return prjs
end
print("failed http request: " .. tostring(resp.status) .. " (" .. resp.body .. ", " .. url .. ")")
return nil
end
return M

View File

@ -1,7 +1,4 @@
local curl = require("plenary.curl") local curl = require("plenary.curl")
local notify = require("snacks.notifier").notify
local gitlab = require("eta.gitlab")
local clickup = require("eta.clickup")
local M = {} local M = {}
---@param data table ---@param data table
@ -10,7 +7,7 @@ M.table_to_yaml = function(data)
local json = vim.json.encode(data) local json = vim.json.encode(data)
-- Nutzt 'yq' um JSON zu YAML zu konvertieren -- Nutzt 'yq' um JSON zu YAML zu konvertieren
local handle = io.popen("echo '" .. json .. "' | yq -y") local handle = io.popen("echo '" .. json .. "' | yq -P e '. ' -")
local result = handle:read("*a") local result = handle:read("*a")
handle:close() handle:close()
@ -37,11 +34,12 @@ M.yaml_to_table = function(yaml_string)
temp_file_handle:flush() temp_file_handle:flush()
temp_file_handle:close() temp_file_handle:close()
local cmd = "cat " .. temp_file .. " | yq" local cmd = "yq '.' " .. temp_file
local handle, errres = io.popen(cmd, 'r') local handle, errres = io.popen(cmd, 'r')
local json_result = handle:read("*a") local json_result = handle:read("*a")
handle:close() handle:close()
os.remove(temp_file)
-- 2. Fehlerprüfung -- 2. Fehlerprüfung
if json_result == "" then if json_result == "" then
@ -60,19 +58,53 @@ M.yaml_to_table = function(yaml_string)
return nil return nil
end end
os.remove(temp_file)
return table_result return table_result
end end
---@type eta.clickup.Session ---@class ClickupSession
M.clickup_session = nil ---@field auth string
---@field user string
---@field workspace string
---@field base_url string
---@type eta.gitlab.Session ---@type ClickupSession
M.gitlab_session = nil M.session = nil
---@class ClickupRef
---@field name string
---@field id string
---@param task eta.clickup.Task ---@class ClickupTask
---@return eta.clickup.Task ---@field id string
---@field name string
---@field tags? table[]
---@field locations? table[]
---@field list? ClickupRef
---@field parent? string | nil
---@field [string] string
---@return ClickupTask[]
M.latest_tasks = function()
local resp = curl.get(M.session.base_url ..
"/team/" .. M.session.workspace .. "/task?subtasks=true&include_markdown_description=true&assignees[]=" ..
M.session.user, {
headers = {
['Authorization'] = M.session.auth,
["accept"] = "application/json",
["content-type"] = "application/json",
}
})
if resp.status == 200 then
return vim.json.decode(resp.body).tasks
end
print("failed http request: " .. tostring(resp.status) .. " (" .. resp.body .. ")")
return {}
end
---@param task ClickupTask
---@return ClickupTask
M._update_task = function(task) M._update_task = function(task)
local update_table = {} local update_table = {}
@ -82,9 +114,9 @@ M._update_task = function(task)
end end
end end
local resp = curl.put(M.clickup_session.base_url .. "/task/" .. task.id, { local resp = curl.put(M.session.base_url .. "/task/" .. task.id, {
headers = { headers = {
['Authorization'] = M.clickup_session.auth, ['Authorization'] = M.session.auth,
["accept"] = "application/json", ["accept"] = "application/json",
["content-type"] = "application/json", ["content-type"] = "application/json",
}, },
@ -116,16 +148,13 @@ M._on_tempbuf_write = function(args)
end end
end end
table.insert(parts, table.concat(current, "\n")) table.insert(parts, table.concat(current, "\n"))
---@type ClickupTask
---@type eta.clickup.Task local data = vim.json.decode(parts[2])
local data = M.yaml_to_table(parts[2]) or {}
data['markdown_content'] = string.gsub(parts[3], "%-%-%-\n", "") data['markdown_content'] = string.gsub(parts[3], "%-%-%-\n", "")
M._update_task(data) M._update_task(data)
vim.api.nvim_set_option_value("modified", false, { buf = args.buf }) vim.api.nvim_set_option_value("modified", false, { buf = args.buf })
local notif_id = notify("updated task #" .. data.id, "info", { title = "ETA", style = 'fancy' })
end end
---@class SelectionItem ---@class SelectionItem
@ -137,10 +166,8 @@ end
---@field tags string[] ---@field tags string[]
---@field id string ---@field id string
---@param picker snacks.Picker | nil
---@param item SelectionItem ---@param item SelectionItem
M._on_select_task = function(picker, item) M._on_select_task = function(picker, item)
local notif_id = notify("opening task #" .. item.id, "info", { title = "ETA", style = 'fancy' })
local new_name = "[ClickUp] " .. item.name local new_name = "[ClickUp] " .. item.name
local new_buf_no = vim.api.nvim_create_buf(true, false) local new_buf_no = vim.api.nvim_create_buf(true, false)
@ -149,16 +176,14 @@ M._on_select_task = function(picker, item)
-- vim.api.nvim_set_option_value("buftype", "nofile", { buf = new_buf_no }) -- vim.api.nvim_set_option_value("buftype", "nofile", { buf = new_buf_no })
vim.api.nvim_set_option_value("filetype", "markdown", { buf = new_buf_no }) vim.api.nvim_set_option_value("filetype", "markdown", { buf = new_buf_no })
vim.api.nvim_create_autocmd({ "BufWriteCmd" }, { buffer = new_buf_no, callback = M._on_tempbuf_write }) vim.api.nvim_create_autocmd({ "BufWriteCmd" }, { buffer = new_buf_no, callback = M._on_tempbuf_write })
local content = { "---"} local content = { "---", "{" }
local to_dump = {} for _, k in ipairs({ "id", "name", "status", "tags", "list", "parent" }) do
for _, k in ipairs({ "id", "name", "status", "tags", "list", "parent", "dependencies" }) do if content[#content] ~= "{" then
to_dump[k] = item[k] content[#content] = content[#content] .. ","
end end
local yaml_string = M.table_to_yaml(to_dump) or "" table.insert(content, ' "' .. k .. '": ' .. vim.json.encode(item[k]))
for line in yaml_string:gmatch("([^\n]*)\n?") do
table.insert(content, line)
end end
-- table.insert(content, "}") table.insert(content, "}")
table.insert(content, "---") table.insert(content, "---")
for line in string.gmatch(item.description, "[^\r\n]+") do for line in string.gmatch(item.description, "[^\r\n]+") do
table.insert(content, line) table.insert(content, line)
@ -168,12 +193,8 @@ M._on_select_task = function(picker, item)
vim.api.nvim_win_set_buf(0, new_buf_no) vim.api.nvim_win_set_buf(0, new_buf_no)
else else
vim.api.nvim_buf_delete(new_buf_no, {}) vim.api.nvim_buf_delete(new_buf_no, {})
if picker then
picker:close() picker:close()
end end
local to_open = vim.fn.bufnr(new_name)
vim.api.nvim_win_set_buf(0, to_open)
end
end end
---@param item SelectionItem ---@param item SelectionItem
@ -225,38 +246,9 @@ M.retrieve_subkeys = function(list, keys)
return ret return ret
end end
---@param id string
M.open_task = function(id)
if id:match("[a-z0-9]+") then
local notif_id = notify("opening #".. id, "info", { timeout = 1000, title = "ETA", style = 'fancy' })
local t = clickup.task(M.clickup_session, id)
---@type SelectionItem
local item = {
idx = nil,
id = t.id,
text = t.name .. t.id .. t.markdown_description,
name = t.name,
tags = M.retrieve_subkeys(t.tags, { "name" }),
status = t.status.status,
parent = t.parent,
list = t.list.name,
description = t.markdown_description,
preview = {
ft = "markdown",
},
action = nil
}
pcall(M._on_select_task,nil, item)
else
error("invalid id format")
end
end
---@param data vim.api.keyset.create_user_command.command_args ---@param data vim.api.keyset.create_user_command.command_args
M.select_task = function(data) M.select_task = function(data)
local notif_id = notify("fetching tasks", "warn", { timeout = 10000, title = "ETA", style = 'fancy' }) local tasks = M.latest_tasks()
if not pcall(M.open_task,vim.fn.expand("<cword>")) then
local tasks = clickup.latest_tasks(M.clickup_session)
---@type SelectionItem[] ---@type SelectionItem[]
local items = {} local items = {}
@ -265,11 +257,6 @@ M.select_task = function(data)
if string.sub(t.name, -7, -1) ~= "Absence" then if string.sub(t.name, -7, -1) ~= "Absence" then
local preview_frontmatter = "" local preview_frontmatter = ""
local deps = {}
for _, dependency in ipairs(t.dependencies) do
table.insert(deps, dependency.depends_on)
end
---@type SelectionItem ---@type SelectionItem
local prepared = { local prepared = {
idx = tix, idx = tix,
@ -281,14 +268,13 @@ M.select_task = function(data)
parent = t.parent, parent = t.parent,
list = t.list.name, list = t.list.name,
description = t.markdown_description, description = t.markdown_description,
dependencies = deps,
preview = { preview = {
ft = "markdown", ft = "markdown",
}, },
action = M._on_select_task action = M._on_select_task
} }
for _, k in ipairs({ "id", "name", "status", "tags", "parent"}) do for _, k in ipairs({ "id", "name", "status", "tags", "parent" }) do
preview_frontmatter = preview_frontmatter .. "\n" .. k .. ": " .. vim.json.encode(prepared[k]) preview_frontmatter = preview_frontmatter .. "\n" .. k .. ": " .. vim.json.encode(prepared[k])
end end
@ -297,7 +283,6 @@ M.select_task = function(data)
end end
end end
require("snacks.notifier").hide(notif_id)
require("snacks.picker").pick({ require("snacks.picker").pick({
title = "Select Task", title = "Select Task",
format = M._item_format, format = M._item_format,
@ -305,15 +290,6 @@ M.select_task = function(data)
confirm = M._on_select_task, confirm = M._on_select_task,
items = items items = items
}) })
end
end end
---@param data vim.api.keyset.create_user_command.command_args
M.mr_from_task = function(data)
if data.args then
notify(data.args, "info", { title = "ETA" })
end
end
return M return M

View File

@ -1,18 +0,0 @@
local eta = require("eta")
local eta_clickup = require("eta.clickup")
vim.api.nvim_create_user_command("ETA", eta.select_task, {})
---@type eta.clickup.Session
eta.clickup_session = {
auth = os.getenv("CLICKUP_AUTH") or "",
user = os.getenv("CLICKUP_USER_ID") or "",
workspace = os.getenv("CLICKUP_WORKSPACE_ID") or "",
base_url = "https://api.clickup.com/api/v2",
}
---@type eta.gitlab.Session
eta.gitlab_session = {
auth = os.getenv("GITLAB_AUTH") or "",
base_url = "https://git.extoll.de/api/v4",
}

10
plugin/mrpy.lua Normal file
View File

@ -0,0 +1,10 @@
local mrpy = require("mrpy")
vim.api.nvim_create_user_command("MrPy", mrpy.select_task, {})
mrpy.session = {
auth = os.getenv("CLICKUP_AUTH") or "",
user = os.getenv("CLICKUP_USER_ID") or "",
workspace = os.getenv("CLICKUP_WORKSPACE_ID") or "",
base_url = "https://api.clickup.com/api/v2",
}

View File

@ -1,25 +1,10 @@
[build-system]
requires = ['setuptools>=57', "wheel"]
build-backend = "setuptools.build_meta"
[project] [project]
name = "eta-lsp" name = "mrpy-nvim"
version = "0.1.0" version = "0.1.0"
description = "EXTOLL Task Access" description = "Add your description here"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [
"pygls~=2.0", "pynvim~=0.6.0",
"pydantic~=2.12", "requests>=2.32.5",
"requests~=2.32",
] ]
authors = [
{ name = "Patrick Nisble", email = "acereca@outlook.de"},
]
[project.scripts]
eta-lsp = "eta.main:main"
[tool.setuptools.packages.find]
include = ['mrpy']
namespaces = false

View File

@ -1,44 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "ETA yaml frontmatter",
"properties": {
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"backlog",
"selected for development",
"in progress",
"in review",
"on hold",
"done",
"closed"
]
},
"markdown_content": {
"type": "string"
},
"id": {
"type": "string",
"pattern": "^[a-z0-9]+$"
},
"parent_list": {
"anyOf": [
{
"const": 900400316794,
"description": "OPE Tooling"
}
]
}
},
"required": [
"name",
"status",
"markdown_content",
"parent_list"
],
"title": "clickup task",
"type": "object"
}