From fc328089d08af61b85e3e8c6c170491151f78d20 Mon Sep 17 00:00:00 2001 From: mityu Date: Sun, 19 Oct 2025 20:16:03 +0900 Subject: [PATCH] feat: Add source/action to select and execute vim-gin's actions --- action/gin_action_execute.ts | 30 ++++++++++++++++++++++++ action/mod.ts | 1 + deno.jsonc | 3 +++ source/gin_action.ts | 45 ++++++++++++++++++++++++++++++++++++ source/mod.ts | 1 + 5 files changed, 80 insertions(+) create mode 100644 action/gin_action_execute.ts create mode 100644 source/gin_action.ts diff --git a/action/gin_action_execute.ts b/action/gin_action_execute.ts new file mode 100644 index 0000000..0e5813a --- /dev/null +++ b/action/gin_action_execute.ts @@ -0,0 +1,30 @@ +import { useEval } from "@denops/std/eval/use-eval"; +import { feedkeys } from "@denops/std/function"; +import { type Action, defineAction } from "@vim-fall/std/action"; +import type { Detail } from "@vim-fall/extra/source/gin-action"; + +/** + * Execute a gin action on the current vim-gin's buffer. + * + * @param denops - The Denops instance for executing Vim commands. + * @param item - The item containing the -mapping to invoke a gin action. + */ +export function ginActionExecute(): Action { + return defineAction( + async (denops, { item }, { signal }) => { + if (item) { + const key = item.detail.gin.actionKey; + signal?.throwIfAborted(); + await useEval(denops, async (denops) => { + await feedkeys(denops, key, "i"); + }); + } + }, + ); +} + +export const defaultGinActionExecuteActions: { + "gin-action-execute": Action; +} = { + "gin-action-execute": ginActionExecute(), +}; diff --git a/action/mod.ts b/action/mod.ts index 7aed2d1..25026fd 100644 --- a/action/mod.ts +++ b/action/mod.ts @@ -1,2 +1,3 @@ // This file is generated by gen-mod.ts +export * from "./gin_action_execute.ts"; export * from "./mr_delete.ts"; diff --git a/deno.jsonc b/deno.jsonc index 8fd4ea7..4122de3 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -4,6 +4,7 @@ "exports": { ".": "./mod.ts", "./action": "./action/mod.ts", + "./action/gin-action-execute": "./action/gin_action_execute.ts", "./action/mr-delete": "./action/mr_delete.ts", "./matcher": "./matcher/mod.ts", "./matcher/kensaku": "./matcher/kensaku.ts", @@ -12,6 +13,7 @@ "./renderer/nerdfont": "./renderer/nerdfont.ts", "./renderer/nvim-web-devicons": "./renderer/nvim_web_devicons.ts", "./source": "./source/mod.ts", + "./source/gin-action": "./source/gin_action.ts", "./source/mr": "./source/mr.ts" }, "publish": { @@ -42,6 +44,7 @@ "update:commit": "deno task -q update --commit --prefix :package: --pre-commit=fmt,lint" }, "imports": { + "@core/iterutil": "jsr:@core/iterutil@^0.9.0", "@denops/std": "jsr:@denops/std@^7.3.0", "@std/assert": "jsr:@std/assert@^1.0.7", "@std/collections": "jsr:@std/collections@^1.0.9", diff --git a/source/gin_action.ts b/source/gin_action.ts new file mode 100644 index 0000000..885b189 --- /dev/null +++ b/source/gin_action.ts @@ -0,0 +1,45 @@ +import type { Denops } from "@denops/std"; +import { type RawString, rawString as r } from "@denops/std/eval/string"; +import { enumerate } from "@core/iterutil/enumerate"; +import { defineSource, type Source } from "@vim-fall/std/source"; + +export type Detail = { + gin: { actionKey: RawString }; +}; + +// This function returns all of the -mappings of gin's actions. +async function listGinMaps(denops: Denops) { + return await denops.eval( + "maplist()->filter({_, v -> stridx(v.lhs, '(gin-action-') == 0})->map({_, v -> v.lhs})", + ) as string[]; +} + +// This function defines a source for gin's actions mainly provided by vim-gin +// plugin. +export function ginAction(): Source { + return defineSource(async function* (denops, _params, { signal }) { + const maps = await listGinMaps(denops); + signal?.throwIfAborted(); + + const allActions = maps.map((v) => + v.match(/^\(gin-action-(.*)\)/)![1] + ); + const actions = new Set(allActions); + + signal?.throwIfAborted(); + allActions.filter((v) => v.endsWith("=")).forEach((v) => { + if (actions.has(v.substring(0, v.length - 1))) { + actions.delete(v); + } + }); + + for (const [id, action] of enumerate(actions)) { + signal?.throwIfAborted(); + yield { + id, + value: action, + detail: { gin: { actionKey: r`\(gin-action-${action})` } }, + }; + } + }); +} diff --git a/source/mod.ts b/source/mod.ts index 6d6b722..4c69b37 100644 --- a/source/mod.ts +++ b/source/mod.ts @@ -1,2 +1,3 @@ // This file is generated by gen-mod.ts +export * from "./gin_action.ts"; export * from "./mr.ts";