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