@@ -9,38 +9,66 @@ import { type Action, defineAction } from "../../action.ts";
99type Restriction = "file" | "directory" | "directory-or-parent" | "buffer" ;
1010
1111type Options < T > = {
12+ /**
13+ * Function to retrieve the attribute from an item. Defaults to `item.value`.
14+ */
1215 attrGetter ?: ( item : IdItem < T > ) => string | undefined ;
16+ /**
17+ * Executes the command immediately without prompting.
18+ */
1319 immediate ?: boolean ;
20+ /**
21+ * Template for the command, with `{}` as a placeholder for the attribute.
22+ */
1423 template ?: string ;
24+ /**
25+ * Restriction on the type of items to process (e.g., only files or directories).
26+ */
1527 restriction ?: Restriction ;
28+ /**
29+ * Escapes the filename if true.
30+ */
1631 fnameescape ?: boolean ;
32+ /**
33+ * Escapes the value for shell execution if true.
34+ */
1735 shellescape ?: boolean ;
1836} ;
1937
38+ /**
39+ * Creates an action that executes a command based on specified options.
40+ *
41+ * @param options - Configuration options for the command execution.
42+ * @returns An action that executes the command.
43+ */
2044export function cmd < T > ( options : Options < T > = { } ) : Action < T > {
2145 const attrGetter = options . attrGetter ?? ( ( item ) => item . value ) ;
2246 const immediate = options . immediate ?? false ;
2347 const template = options . template ?? "{}" ;
2448 const restriction = options . restriction ;
2549 const fnameescape = options . fnameescape ?? false ;
2650 const shellescape = options . shellescape ?? false ;
51+
2752 return defineAction < T > (
2853 async ( denops , { item, selectedItems } , { signal } ) => {
2954 const items = selectedItems ?? [ item ] ;
3055 for ( const item of items . filter ( ( v ) => ! ! v ) ) {
3156 signal ?. throwIfAborted ( ) ;
3257 let value = attrGetter ( item ) ;
3358 if ( value == undefined ) continue ;
59+
3460 if ( restriction ) {
3561 value = await applyRestriction ( denops , value , restriction ) ;
3662 if ( value == undefined ) continue ;
3763 }
64+
3865 if ( fnameescape ) {
3966 value = await fn . fnameescape ( denops , value ) ;
4067 }
4168 if ( shellescape ) {
4269 value = await fn . shellescape ( denops , value ) ;
4370 }
71+
4472 const cmd = template . replaceAll ( "{}" , value ) ;
4573 try {
4674 await execute ( denops , cmd , immediate ) ;
@@ -52,6 +80,14 @@ export function cmd<T>(options: Options<T> = {}): Action<T> {
5280 ) ;
5381}
5482
83+ /**
84+ * Applies a restriction to an item, ensuring it meets the specified criteria.
85+ *
86+ * @param denops - The Denops instance.
87+ * @param value - The item to check.
88+ * @param restriction - The restriction type to enforce.
89+ * @returns The original or modified value if it meets the restriction, otherwise `undefined`.
90+ */
5591async function applyRestriction (
5692 denops : Denops ,
5793 value : string ,
@@ -65,37 +101,36 @@ async function applyRestriction(
65101 const stat = await Deno . stat ( value ) ;
66102 switch ( restriction ) {
67103 case "file" :
68- if ( stat . isFile ) {
69- return value ;
70- }
104+ if ( stat . isFile ) return value ;
71105 break ;
72106 case "directory" :
73- if ( stat . isDirectory ) {
74- return value ;
75- }
107+ if ( stat . isDirectory ) return value ;
76108 break ;
77109 case "directory-or-parent" :
78- if ( ! stat . isDirectory ) {
79- value = dirname ( value ) ;
80- }
110+ if ( ! stat . isDirectory ) value = dirname ( value ) ;
81111 return value ;
82112 }
83113 } catch ( err ) {
84- if ( ! ( err instanceof Deno . errors . NotFound ) ) {
85- throw err ;
86- }
114+ if ( ! ( err instanceof Deno . errors . NotFound ) ) throw err ;
87115 }
88116 return ;
89117 }
90118 case "buffer" : {
91- if ( ! await fn . bufloaded ( denops , value ) ) {
92- return ;
119+ if ( await fn . bufloaded ( denops , value ) ) {
120+ return value ;
93121 }
94- return value ;
122+ return ;
95123 }
96124 }
97125}
98126
127+ /**
128+ * Executes a command in Denops. If immediate execution is disabled, prompts for confirmation.
129+ *
130+ * @param denops - The Denops instance.
131+ * @param cmd - The command to execute.
132+ * @param immediate - Whether to execute the command immediately.
133+ */
99134async function execute (
100135 denops : Denops ,
101136 cmd : string ,
@@ -107,12 +142,15 @@ async function execute(
107142 completion : "command" ,
108143 } ) ;
109144 if ( command == null ) {
110- // Cancelled
145+ // Command was cancelled
111146 return ;
112147 }
113148 await denops . cmd ( command ) ;
114149}
115150
151+ /**
152+ * Default command actions.
153+ */
116154export const defaultCmdActions : {
117155 cmd : Action < unknown > ;
118156} = {
0 commit comments