4
4
5
5
local action_state = require (" telescope.actions.state" )
6
6
7
+ --- The diff hunk
7
8
--- @class Previewable
8
- --- @field title fun ( self ): string
9
- --- @field preview fun ( self , opts : table ): { text : string , syntax : string }
10
-
11
- --- @class Value
12
9
--- @field title string
13
- --- @field index string
14
- --- @field type string
15
- --- @field entry Previewable
10
+ --- @field filename fun ( self ): string
11
+ --- Return the index in the workspace_edit, sub_index is only provided for
12
+ --- Edits.
13
+ --- @field index number | { primary : number , secondary : number }
14
+ --- @field preview fun ( self , bufnr : integer , winid : integer , opts : table ): string
16
15
17
- local M = {}
16
+ --- The Entry passed around in Telescope
17
+ --- @class Entry
18
+ --- @field value Previewable
19
+ --- @field display fun ( entry : Entry )
20
+ --- @field ordinal string
18
21
19
- --- @param entry Previewable
20
- local default_make_value = function (entry )
21
- return {
22
- title = entry :title (),
23
- }
24
- end
25
22
26
- --- @param values Value[]
27
- local default_make_make_display = function (values )
23
+ local M = {}
24
+
25
+ --- @param values Previewable[]
26
+ local make_make_display = function (values )
28
27
local entry_display = require (" telescope.pickers.entry_display" )
29
28
local strings = require (" plenary.strings" )
30
29
31
- local index_width = 0
32
30
local title_width = 0
33
31
for _ , value in ipairs (values ) do
34
- index_width = math.max (index_width , strings .strdisplaywidth (value .index ))
35
32
title_width = math.max (title_width , strings .strdisplaywidth (value .title ))
36
33
end
37
34
38
35
local displayer = entry_display .create ({
39
36
separator = " " ,
40
37
items = {
41
- { width = index_width + 1 },
42
38
{ width = title_width },
43
39
},
44
40
})
45
41
return function (entry )
46
42
return displayer ({
47
- { entry .value .index .. " :" , " TelescopePromptPrefix" },
48
43
{ entry .value .title },
49
44
})
50
45
end
51
46
end
52
47
53
- --- @param job_id string
54
- --- @return boolean
55
- local job_is_running = function (job_id )
56
- return vim .fn .jobwait ({ job_id }, 0 )[1 ] == - 1
57
- end
58
-
59
48
--- @param prompt_bufnr integer
60
- --- @return integer []
49
+ --- @return Entry []
61
50
local get_selected_diffs = function (prompt_bufnr )
51
+ --- @type Entry[]
62
52
local selected = {}
63
53
local current_picker = action_state .get_current_picker (prompt_bufnr )
64
- --- @type Value []
54
+ --- @type Previewable []
65
55
local selections = current_picker :get_multi_selection ()
66
56
if vim .tbl_isempty (selections ) then
67
57
vim .notify (" no change selected" )
@@ -73,162 +63,74 @@ local get_selected_diffs = function(prompt_bufnr)
73
63
return selected
74
64
end
75
65
76
- --- @param documentChanges Previewable[]
77
66
--- @param changes Previewable[]
78
67
--- @param apply_selection fun ( selected_indices : integer[] )
79
- function M .apply_action (opts , documentChanges , changes , apply_selection )
68
+ function M .apply_action (opts , changes , apply_selection )
80
69
local actions = require (" telescope.actions" )
81
70
local pickers = require (" telescope.pickers" )
82
- local Previewer = require (" telescope.previewers.previewer " )
71
+ local previewers = require (" telescope.previewers" )
83
72
local finders = require (" telescope.finders" )
84
73
local conf = require (" telescope.config" ).values
85
74
local utils = require (" telescope.utils" )
86
75
local putils = require (" telescope.previewers.utils" )
87
76
88
- local make_value = default_make_value
89
- --- @type Value[]
90
- local values = {}
91
- for index , entry in ipairs (documentChanges ) do
92
- local value = make_value (entry )
77
+ -- validate the table to have everything we need
78
+ for _ , value in ipairs (changes ) do
93
79
if type (value ) ~= " table" then
94
80
error (" 'make_value' must return a table" )
95
81
end
96
- if value .title == nil then
82
+ if type ( value .title ) ~= " string " then
97
83
error (" 'make_value' must return a table containing a field 'title'" )
98
84
end
99
-
100
- value .index = index
101
- value .entry = entry
102
- value .type = " documentChanges"
103
-
104
- table.insert (values , value )
105
85
end
106
- for index , entry in ipairs (changes ) do
107
- local value = make_value (entry )
108
- if type (value ) ~= " table" then
109
- error (" 'make_value' must return a table" )
110
- end
111
- if value .title == nil then
112
- error (" 'make_value' must return a table containing a field 'title'" )
113
- end
114
86
115
- value .index = index
116
- value .entry = entry
117
- value .type = " changes"
87
+ local make_display = make_make_display (changes )
118
88
119
- table.insert (values , value )
120
- end
121
-
122
- local make_display = default_make_make_display (values )
123
-
124
- local buffers = {}
125
- local term_ids = {}
126
-
127
- local previewer = Previewer :new ({
128
- title = " Code Action Preview" ,
129
- setup = function (_self )
89
+ local previewer = previewers .new_buffer_previewer ({
90
+ setup = function (self )
130
91
-- pre-select all changes on picker creation
131
92
local prompt_bufnr = vim .api .nvim_get_current_buf ()
132
93
actions .select_all (prompt_bufnr )
133
94
return {}
134
95
end ,
135
- teardown = function (self )
136
- if not self .state then
137
- return
138
- end
139
-
140
- self .state .winid = nil
141
- self .state .bufnr = nil
142
-
143
- for _ , bufnr in ipairs (buffers ) do
144
- local term_id = term_ids [bufnr ]
145
- if term_id and job_is_running (term_id ) then
146
- vim .fn .jobstop (term_id )
147
- end
148
- utils .buf_delete (bufnr )
149
- end
150
-
151
- buffers = {}
152
- term_ids = {}
153
- end ,
154
- --- @param entry { value : Value }
155
- preview_fn = function (self , entry , status )
156
- local preview_winid = status .layout and status .layout .preview and status .layout .preview .winid or
157
- status .preview_win
158
-
159
- local do_preview = false
160
- local bufnr = buffers [entry .value .index ]
161
- if not bufnr then
162
- bufnr = vim .api .nvim_create_buf (false , true )
163
- buffers [entry .value .index ] = bufnr
164
- do_preview = true
165
-
166
- vim .api .nvim_win_set_option (preview_winid , " winhl" , " Normal:TelescopePreviewNormal" )
167
- vim .api .nvim_win_set_option (preview_winid , " signcolumn" , " no" )
168
- vim .api .nvim_win_set_option (preview_winid , " foldlevel" , 100 )
169
- vim .api .nvim_win_set_option (preview_winid , " wrap" , false )
170
- vim .api .nvim_win_set_option (preview_winid , " scrollbind" , false )
171
- end
172
-
173
- utils .win_set_buf_noautocmd (preview_winid , bufnr )
174
- self .state .winid = preview_winid
175
- self .state .bufnr = bufnr
176
-
177
- if do_preview then
178
- local preview = entry .value .entry :preview (opts )
179
- preview = preview or { syntax = " " , text = " preview not available" }
180
-
181
- vim .api .nvim_buf_set_lines (bufnr , 0 , - 1 , false , vim .split (preview .text , " \n " , { plain = true }))
182
- putils .highlighter (bufnr , preview .syntax , {})
183
- end
96
+ --- @param entry Entry
97
+ define_preview = function (self , entry , status )
98
+ local filetype = entry .value :preview (self .state .bufnr , self .state .winid , opts )
99
+ putils .highlighter (self .state .bufnr , filetype , {})
184
100
end ,
185
- scroll_fn = function (self , direction )
186
- if not self .state then
187
- return
188
- end
189
-
190
- local count = math.abs (direction )
191
- local term_id = term_ids [self .state .bufnr ]
192
- if term_id and job_is_running (term_id ) then
193
- local input = direction > 0 and " d" or " u"
194
-
195
- local termcode = vim .api .nvim_replace_termcodes (count .. input , true , false , true )
196
- vim .fn .chansend (term_id , termcode )
197
- else
198
- local input = direction > 0 and [[ ]] or [[ ]]
199
-
200
- vim .api .nvim_win_call (self .state .winid , function ()
201
- vim .cmd ([[ normal! ]] .. count .. input )
202
- end )
203
- end
101
+ --- @param entry Entry
102
+ --- @return string
103
+ get_buffer_by_name = function (self , entry )
104
+ -- create a single buffer per file.
105
+ return entry .value :filename ()
204
106
end ,
205
107
})
206
108
207
109
local finder = finders .new_table ({
208
- results = values ,
110
+ results = changes ,
209
111
entry_maker = function (value )
210
112
return {
211
113
display = make_display ,
212
- ordinal = value .index .. value . title ,
114
+ ordinal = value .title ,
213
115
value = value ,
214
116
}
215
117
end ,
216
118
})
217
119
218
120
pickers .new (opts , {
219
- prompt_title = " Code Actions " ,
121
+ prompt_title = " Edits to apply " ,
220
122
previewer = previewer ,
221
123
finder = finder ,
222
124
sorter = conf .generic_sorter (opts ),
223
125
attach_mappings = function (prompt_bufnr , map )
224
126
map (" i" , " <c-a>" , actions .toggle_all )
225
127
226
128
actions .select_default :replace (function ()
227
- local selections = get_selected_diffs (prompt_bufnr )
129
+ local selected_entries = get_selected_diffs (prompt_bufnr )
228
130
229
131
actions .close (prompt_bufnr )
230
132
231
- apply_selection (selections )
133
+ apply_selection (selected_entries )
232
134
end )
233
135
234
136
return true
0 commit comments