mrpy.nvim/rplugin/python3/mrpy/main.py

146 lines
4.3 KiB
Python

from collections.abc import Callable, Sequence
from pynvim import Nvim, command, plugin
from pynvim.api import Buffer
from .clickup import ClickupSession
from .hints import JSONData
from .yaml import load, dump
def usernames_from_objs(objs: JSONData) -> JSONData:
assert isinstance(objs, list)
return [k["username"] for k in objs if isinstance(k, dict)]
@plugin
class MrPyPlugin:
nvim: Nvim
clickup: ClickupSession
frontmatter_keys: dict[str, Callable[[JSONData], JSONData]]
def __init__(self, nvim: Nvim) -> None:
self.nvim = nvim
self.clickup = ClickupSession()
self.frontmatter_keys = {
"id": str,
"name": str,
"assignees": usernames_from_objs,
}
def select_task_id(self) -> None:
tasks = self.clickup.get_tasks()
task_names_by_id = [
{
"idx": tix + 1,
"id": t.id,
"name": t.name,
"status": t.status,
"is_child": bool(t.parent),
"preview": {
"text": f"---\n{dump(t.showables)}---\n{t.markdown_description}",
"ft": "markdown",
},
"action": f":Mrpy {t.id}",
}
for tix, t in enumerate(tasks)
if not t.name.endswith("Absence")
]
self.nvim.exec_lua(
"""require('snacks').picker.pick({
title="Select Task",
format = function(item, _)
local ret = {}
local hl = "SnacksPickerComment"
if item.status == "in progress" then
hl = "@method"
elseif item.status == "selected for development" then
hl = "@constant.builtin"
elseif item.status == "in review" then
hl = "@keyword"
elseif item.status == "done" then
hl = "@variable.builtin"
end
if item.is_child == true then
ret[#ret + 1] = { "󰘍 ", "SnacksPickerComment" }
end
ret[#ret + 1] = { item.name, hl }
ret[#ret + 1] = {
" (#" .. item.id .. ")",
"SnacksPickerComment"
}
return ret
end,
preview="preview",
confirm=function(_, item) vim.cmd(("Mrpy %s"):format(item.id)) end,
items=...
})""",
task_names_by_id,
)
def open_task_buffer(self, task_id: str) -> None:
if " " in task_id:
*_, last = task_id.split(" ")
task_id = last.removeprefix("(#").removesuffix(")")
task = self.clickup.get_task(task_id)
temp_buf: Buffer = self.nvim.api.create_buf(True, False)
self.nvim.api.buf_set_name(temp_buf, f"[ClickUp] {task.name}")
self.nvim.buffers[temp_buf.number].options["filetype"] = "markdown"
self.nvim.api.create_autocmd(
["BufWriteCmd"],
{"buffer": temp_buf.number, "command": "MrpyPush " + str(temp_buf.number)},
)
content = ["---"]
content.extend(
dump(
task.showables,
).splitlines()
)
content.append("---")
content.extend(task.markdown_description.splitlines())
self.nvim.api.buf_set_lines(temp_buf, 0, 0, False, content)
self.nvim.buffers[temp_buf.number].options["modified"] = False
self.nvim.api.win_set_buf(0, temp_buf)
@command("Mrpy", nargs="?")
def entry(self, args: Sequence[str] = ()) -> None:
match args:
case (str() as task_id,):
self.open_task_buffer(task_id)
case ():
self.select_task_id()
case _:
pass
@command("MrpyPush", nargs="?")
def on_vbuf_write(self, args: Sequence[str] = ()) -> None:
match args:
case "0", *_:
return
case buf_no, *_:
buf_no = int(buf_no)
case _:
return
try:
a = self.nvim.buffers[buf_no][0:-1]
_, fm, *text = "\n".join(a).split("---\n")
data = load(fm)
assert isinstance(data, dict)
data["markdown_description"] = "\n\n".join(text)
self.nvim.err_write(str(data) + "\n")
# self.clickup.update(data)
self.nvim.buffers[buf_no].options["modified"] = False
except ValueError:
pass