@@ -32,165 +32,150 @@ function M.select(opts)
3232 return require (" opencode.cli.server" )
3333 .get ()
3434 :next (function (server ) --- @param server opencode.cli.server.Server
35- if opts .sections .commands then
36- return Promise .new (function (resolve )
37- require (" opencode.cli.client" ).get_commands (server .port , function (custom_commands )
38- resolve ({ server = server , custom_commands = custom_commands })
39- end )
40- end )
41- else
42- return { server = server }
35+ local prompts = require (" opencode.config" ).opts .prompts or {}
36+ local commands = require (" opencode.config" ).opts .select .sections .commands or {}
37+ for _ , command in ipairs (server .custom_commands ) do
38+ commands [command .name ] = command .description
4339 end
44- end )
45- :next (
46- function (result ) --- @param result { server : opencode.cli.server.Server , custom_commands : opencode.cli.client.Command[] }
47- local prompts = require (" opencode.config" ).opts .prompts or {}
48- local commands = require (" opencode.config" ).opts .select .sections .commands or {}
49- for _ , command in ipairs (result .custom_commands ) do
50- commands [command .name ] = command .description
51- end
5240
53- --- @class opencode.select.Item : snacks.picker.finder.Item , { __type : "prompt " | "command " | "server ", ask ?: boolean , submit ?: boolean }
41+ --- @class opencode.select.Item : snacks.picker.finder.Item , { __type : "prompt " | "command " | "server ", ask ?: boolean , submit ?: boolean }
42+ local items = {}
5443
55- --- @type opencode.select.Item[]
56- local items = {}
57-
58- -- Prompts section
59- if opts .sections .prompts then
60- table.insert (items , { __group = true , name = " PROMPT" , preview = { text = " " } })
61- local prompt_items = {}
62- for name , prompt in pairs (prompts ) do
63- local rendered = context :render (prompt .prompt , result .server .subagents )
64- --- @type snacks.picker.finder.Item
65- local item = {
66- __type = " prompt" ,
67- name = name ,
68- text = prompt .prompt .. (prompt .ask and " …" or " " ),
69- highlights = rendered .input , -- `snacks.picker`'s `select` seems to ignore this, so we incorporate it ourselves in `format_item`
70- preview = {
71- text = context .plaintext (rendered .output ),
72- extmarks = context .extmarks (rendered .output ),
73- },
74- ask = prompt .ask ,
75- submit = prompt .submit ,
76- }
77- table.insert (prompt_items , item )
78- end
79- -- Sort: ask=true, submit=false, name
80- table.sort (prompt_items , function (a , b )
81- if a .ask and not b .ask then
82- return true
83- elseif not a .ask and b .ask then
84- return false
85- elseif not a .submit and b .submit then
86- return true
87- elseif a .submit and not b .submit then
88- return false
89- else
90- return a .name < b .name
91- end
92- end )
93- for _ , item in ipairs (prompt_items ) do
94- table.insert (items , item )
95- end
44+ -- Prompts section
45+ if opts .sections .prompts then
46+ table.insert (items , { __group = true , name = " PROMPT" , preview = { text = " " } })
47+ local prompt_items = {}
48+ for name , prompt in pairs (prompts ) do
49+ local rendered = context :render (prompt .prompt , server .subagents )
50+ --- @type snacks.picker.finder.Item
51+ local item = {
52+ __type = " prompt" ,
53+ name = name ,
54+ text = prompt .prompt .. (prompt .ask and " …" or " " ),
55+ highlights = rendered .input , -- `snacks.picker`'s `select` seems to ignore this, so we incorporate it ourselves in `format_item`
56+ preview = {
57+ text = context .plaintext (rendered .output ),
58+ extmarks = context .extmarks (rendered .output ),
59+ },
60+ ask = prompt .ask ,
61+ submit = prompt .submit ,
62+ }
63+ table.insert (prompt_items , item )
9664 end
97-
98- -- Commands section
99- if type (opts .sections .commands ) == " table" then
100- table.insert (items , { __group = true , name = " COMMAND" , preview = { text = " " } })
101- local command_items = {}
102- for name , description in pairs (commands ) do
103- table.insert (command_items , {
104- __type = " command" ,
105- name = name , -- TODO: Truncate if it'd run into `text`
106- text = description ,
107- highlights = { { description , " Comment" } },
108- preview = {
109- text = " " ,
110- },
111- })
112- end
113- table.sort (command_items , function (a , b )
65+ -- Sort: ask=true, submit=false, name
66+ table.sort (prompt_items , function (a , b )
67+ if a .ask and not b .ask then
68+ return true
69+ elseif not a .ask and b .ask then
70+ return false
71+ elseif not a .submit and b .submit then
72+ return true
73+ elseif a .submit and not b .submit then
74+ return false
75+ else
11476 return a .name < b .name
115- end )
116- for _ , item in ipairs (command_items ) do
117- table.insert (items , item )
11877 end
78+ end )
79+ for _ , item in ipairs (prompt_items ) do
80+ table.insert (items , item )
11981 end
82+ end
12083
121- -- Server section
122- if opts .sections .server then
123- table.insert (items , { __group = true , name = " SERVER" , preview = { text = " " } })
124- table.insert (items , {
125- __type = " server" ,
126- name = " server.select" ,
127- text = " Select server" ,
128- highlights = { { " Select server" , " Comment" } },
129- preview = { text = " " },
130- })
131- table.insert (items , {
132- __type = " server" ,
133- name = " server.start" ,
134- text = " Start server" ,
135- highlights = { { " Start server" , " Comment" } },
136- preview = { text = " " },
137- })
138- table.insert (items , {
139- __type = " server" ,
140- name = " server.stop" ,
141- text = " Stop server" ,
142- highlights = { { " Stop server" , " Comment" } },
143- preview = { text = " " },
144- })
145- table.insert (items , {
146- __type = " server" ,
147- name = " server.toggle" ,
148- text = " Toggle server" ,
149- highlights = { { " Toggle server" , " Comment" } },
150- preview = { text = " " },
84+ -- Commands section
85+ if type (opts .sections .commands ) == " table" then
86+ table.insert (items , { __group = true , name = " COMMAND" , preview = { text = " " } })
87+ local command_items = {}
88+ for name , description in pairs (commands ) do
89+ table.insert (command_items , {
90+ __type = " command" ,
91+ name = name , -- TODO: Truncate if it'd run into `text`
92+ text = description ,
93+ highlights = { { description , " Comment" } },
94+ preview = {
95+ text = " " ,
96+ },
15197 })
15298 end
153-
154- for i , item in ipairs (items ) do
155- item .idx = i -- Store the index for non-snacks formatting
99+ table.sort (command_items , function (a , b )
100+ return a .name < b .name
101+ end )
102+ for _ , item in ipairs (command_items ) do
103+ table.insert (items , item )
156104 end
105+ end
157106
158- --- @type snacks.picker.ui_select.Opts
159- local select_opts = {
160- --- @param item snacks.picker.finder.Item
161- --- @param is_snacks boolean
162- format_item = function ( item , is_snacks )
163- if is_snacks then
164- if item . __group then
165- return { { item . name , " Title " } }
166- end
167- local formatted = vim . deepcopy ( item . highlights or { })
168- if item . ask then
169- table.insert ( formatted , { " … " , " Keyword " })
170- end
171- table.insert ( formatted , 1 , { item . name , " Keyword " })
172- table.insert ( formatted , 2 , { string.rep ( " " , 18 - # item . name ) })
173- return formatted
174- else
175- local indent = # tostring ( # items ) - # tostring ( item . idx )
176- if item . __group then
177- local divider = string.rep ( " — " , ( 80 - # item . name ) / 2 )
178- return string.rep ( " " , indent ) .. divider .. item . name .. divider
179- end
180- return ( " %s[%s]%s%s " ): format (
181- string.rep ( " " , indent ),
182- item . name ,
183- string.rep ( " " , 18 - # item . name ) ,
184- item . text or " "
185- )
186- end
187- end ,
188- }
189- select_opts = vim . tbl_deep_extend ( " force " , select_opts , opts )
107+ -- Server section
108+ if opts . sections . server then
109+ table.insert ( items , { __group = true , name = " SERVER " , preview = { text = " " } })
110+ table.insert ( items , {
111+ __type = " server " ,
112+ name = " server.select " ,
113+ text = " Select server " ,
114+ highlights = { { " Select server " , " Comment " } },
115+ preview = { text = " " },
116+ })
117+ table.insert ( items , {
118+ __type = " server " ,
119+ name = " server.start " ,
120+ text = " Start server " ,
121+ highlights = { { " Start server " , " Comment " } },
122+ preview = { text = " " },
123+ })
124+ table.insert ( items , {
125+ __type = " server " ,
126+ name = " server.stop " ,
127+ text = " Stop server " ,
128+ highlights = { { " Stop server " , " Comment " } },
129+ preview = { text = " " },
130+ })
131+ table.insert ( items , {
132+ __type = " server " ,
133+ name = " server.toggle " ,
134+ text = " Toggle server " ,
135+ highlights = { { " Toggle server " , " Comment " } },
136+ preview = { text = " " } ,
137+ })
138+ end
190139
191- return Promise .select (items , select_opts )
140+ for i , item in ipairs (items ) do
141+ item .idx = i -- Store the index for non-snacks formatting
192142 end
193- )
143+
144+ --- @type snacks.picker.ui_select.Opts
145+ local select_opts = {
146+ --- @param item snacks.picker.finder.Item
147+ --- @param is_snacks boolean
148+ format_item = function (item , is_snacks )
149+ if is_snacks then
150+ if item .__group then
151+ return { { item .name , " Title" } }
152+ end
153+ local formatted = vim .deepcopy (item .highlights or {})
154+ if item .ask then
155+ table.insert (formatted , { " …" , " Keyword" })
156+ end
157+ table.insert (formatted , 1 , { item .name , " Keyword" })
158+ table.insert (formatted , 2 , { string.rep (" " , 18 - # item .name ) })
159+ return formatted
160+ else
161+ local indent = # tostring (# items ) - # tostring (item .idx )
162+ if item .__group then
163+ local divider = string.rep (" —" , (80 - # item .name ) / 2 )
164+ return string.rep (" " , indent ) .. divider .. item .name .. divider
165+ end
166+ return (" %s[%s]%s%s" ):format (
167+ string.rep (" " , indent ),
168+ item .name ,
169+ string.rep (" " , 18 - # item .name ),
170+ item .text or " "
171+ )
172+ end
173+ end ,
174+ }
175+ select_opts = vim .tbl_deep_extend (" force" , select_opts , opts )
176+
177+ return Promise .select (items , select_opts )
178+ end )
194179 :next (function (choice ) --- @param choice opencode.select.Item
195180 if choice .__type == " prompt" then
196181 --- @type opencode.Prompt
0 commit comments