@@ -16,10 +16,11 @@ local log = require("leetcode.logger")
1616--- @field console lc.ui.Console
1717--- @field lang string
1818--- @field cache lc.cache.Question
19+ --- @field reset boolean
1920local Question = Object (" LeetQuestion" )
2021
2122--- @param raw ? boolean
22- function Question :get_snippet (raw )
23+ function Question :snippet (raw )
2324 local snippets = self .q .code_snippets ~= vim .NIL and self .q .code_snippets or {}
2425 local snip = vim .tbl_filter (function (snip ) return snip .lang_slug == self .lang end , snippets )[1 ]
2526 if not snip then return end
@@ -28,7 +29,30 @@ function Question:get_snippet(raw)
2829 return raw and code or self :injector (code )
2930end
3031
31- function Question :create_file ()
32+ --- @param code ? string
33+ function Question :set_lines (code )
34+ if not vim .api .nvim_buf_is_valid (self .bufnr ) then return end
35+
36+ pcall (vim .cmd .undojoin )
37+ local s_i , e_i = self :range ()
38+ code = code and code or (self :snippet (true ) or " " )
39+ vim .api .nvim_buf_set_lines (self .bufnr , s_i - 1 , e_i , false , vim .split (code , " \n " ))
40+ end
41+
42+ function Question :reset_lines ()
43+ if not self .reset then return end
44+
45+ local new_lines = self :snippet (true ) or " "
46+
47+ vim .schedule (function () --
48+ log .info (" Previous code found, resetting…\n To undo, simply press `u`" )
49+ end )
50+
51+ self :set_lines (new_lines )
52+ end
53+
54+ --- @return string path , boolean ? existed
55+ function Question :path ()
3256 local lang = utils .get_lang (self .lang )
3357 local alt = lang .alt and (" ." .. lang .alt ) or " "
3458
@@ -38,47 +62,39 @@ function Question:create_file()
3862 self .file = config .storage .home :joinpath (fn_legacy )
3963
4064 if self .file :exists () then --
41- return self .file :absolute ()
65+ return self .file :absolute (), true
4266 end
4367
4468 local fn = (" %s.%s%s.%s" ):format (self .q .frontend_id , self .q .title_slug , alt , lang .ft )
4569 self .file = config .storage .home :joinpath (fn )
70+ local existed = true
4671
4772 if not self .file :exists () then --
48- self .file :write (self :get_snippet (), " w" )
73+ self .file :write (self :snippet (), " w" )
74+ existed = false
4975 end
5076
51- return self .file :absolute ()
77+ return self .file :absolute (), existed
5278end
5379
54- --- @param new_tabp ? boolean
55- --- @return boolean was_loaded
56- function Question :create_buffer (new_tabp )
57- local file_name = self :create_file ()
80+ function Question :create_buffer ()
81+ local path , existed = self :path ()
5882
59- local buf = vim .fn .bufadd (file_name )
60- assert (buf ~= 0 , " Failed to create buffer" )
83+ vim .cmd (" $tabe " .. path )
6184
62- self .bufnr = buf
63- if vim .fn .bufloaded (self .bufnr ) == 1 then
64- return true
65- else
66- vim .fn .bufload (self .bufnr )
67- end
85+ self .bufnr = vim .api .nvim_get_current_buf ()
86+ self .winid = vim .api .nvim_get_current_win ()
6887
69- local cmd
70- if new_tabp then
71- cmd = (" $tabe %s" ):format (file_name )
72- else
73- cmd = (" edit %s" ):format (file_name )
74- end
88+ vim .api .nvim_set_option_value (" buflisted" , true , { buf = self .bufnr })
7589
7690 local i = self :fold_range ()
77- if i then cmd = cmd .. ( " | %d,%dfold " ): format ( 1 , i ) end
78-
79- vim . api . nvim_exec2 ( cmd , {})
91+ if i then --
92+ pcall ( vim . cmd , ( " %d,%dfold " ): format ( 1 , i ))
93+ end
8094
81- return false
95+ if existed then --
96+ self :reset_lines ()
97+ end
8298end
8399
84100--- @param before boolean
@@ -99,7 +115,7 @@ function Question:inject(before)
99115 end
100116
101117 if res and res ~= " " then
102- return before and (res .. " \n\n " ) or (" \n \n" .. res )
118+ return before and (res .. " \n " ) or (" \n " .. res )
103119 else
104120 return nil
105121 end
@@ -109,50 +125,62 @@ end
109125function Question :injector (code )
110126 local lang = utils .get_lang (self .lang )
111127
112- local inj_before = self :inject (true ) or " "
113- local inj_after = self :inject (false ) or " "
128+ local parts = {
129+ (" %s @leet start" ):format (lang .comment ),
130+ code ,
131+ (" %s @leet end" ):format (lang .comment ),
132+ }
114133
115- return inj_before --
116- .. (" %s @leet start\n " ):format (lang .comment )
117- .. code
118- .. (" \n %s @leet end" ):format (lang .comment )
119- .. inj_after
120- end
134+ local before = self :inject (true )
135+ if before then table.insert (parts , 1 , before ) end
121136
122- --- @param pre ? boolean
123- function Question :_unmount (pre )
124- self .info :unmount ()
125- self .console :unmount ()
126- self .description :unmount ()
137+ local after = self :inject (false )
138+ if after then table.insert (parts , after ) end
127139
128- if not pre and vim .api .nvim_buf_is_valid (self .bufnr ) then
129- vim .api .nvim_buf_delete (self .bufnr , { force = true })
130- end
140+ return table.concat (parts , " \n " )
141+ end
131142
132- if vim .api .nvim_win_is_valid (self .winid ) then --
133- vim .api .nvim_win_close (self .winid , true )
143+ function Question :unmount ()
144+ if vim .v .dying ~= 0 then --
145+ return
134146 end
135147
136- _Lc_questions = vim .tbl_filter (function (q ) return q .bufnr ~= self .bufnr end , _Lc_questions )
148+ vim .schedule (function ()
149+ self .info :unmount ()
150+ self .console :unmount ()
151+ self .description :unmount ()
152+
153+ if vim .api .nvim_buf_is_valid (self .bufnr ) then
154+ vim .api .nvim_buf_delete (self .bufnr , { force = true , unload = false })
155+ end
156+
157+ _Lc_questions = vim .tbl_filter (function (q ) --
158+ return q .bufnr ~= self .bufnr
159+ end , _Lc_questions )
137160
138- self = nil
161+ self = nil
162+ end )
139163end
140164
141- --- @param self lc.ui. Question
142- --- @param pre ? boolean
143- Question . unmount = vim . schedule_wrap ( function ( self , pre ) self : _unmount ( pre ) end )
165+ function Question : _unmount ()
166+ if vim . api . nvim_win_is_valid ( self . winid ) then vim . api . nvim_win_close ( self . winid , true ) end
167+ end
144168
145- function Question :handle_mount ()
146- self :create_buffer (true )
169+ local group = vim .api .nvim_create_augroup (" leetcode_questions" , { clear = true })
170+ function Question :autocmds ()
171+ vim .api .nvim_create_autocmd (" WinClosed" , {
172+ group = group ,
173+ buffer = self .bufnr ,
174+ callback = function () self :unmount () end ,
175+ })
176+ end
147177
148- self .winid = vim .api .nvim_get_current_win ()
178+ function Question :handle_mount ()
179+ self :create_buffer ()
149180
150181 table.insert (_Lc_questions , self )
151182
152- vim .api .nvim_create_autocmd (" QuitPre" , {
153- buffer = self .bufnr ,
154- callback = function () self :unmount (true ) end ,
155- })
183+ self :autocmds ()
156184
157185 self .description = Description (self ):mount ()
158186 self .console = Console (self )
@@ -173,7 +201,7 @@ function Question:mount()
173201 end
174202 self .q = q
175203
176- if self :get_snippet () then
204+ if self :snippet () then
177205 self :handle_mount ()
178206 else
179207 local msg = (" Snippet for `%s` not found. Select a different language" ):format (self .lang )
@@ -232,37 +260,55 @@ end
232260--- @param self lc.ui.Question
233261--- @param lang lc.lang
234262Question .change_lang = vim .schedule_wrap (function (self , lang )
235- if vim .api .nvim_get_current_win () ~= self .winid then
236- vim .api .nvim_set_current_win (self .winid )
237- end
238-
239263 local old_lang , old_bufnr = self .lang , self .bufnr
240- self .lang = lang
241264
242- local ok , was_loaded = pcall (Question .create_buffer , self )
243- if ok then
244- vim .api .nvim_buf_set_option (old_bufnr , " buflisted" , false )
245- vim .api .nvim_buf_set_option (self .bufnr , " buflisted" , true )
265+ local ok , err = pcall (function ()
266+ self .lang = lang
267+ local path , existed = self :path ()
268+
269+ self .bufnr = vim .fn .bufadd (path )
270+ assert (self .bufnr ~= 0 , " Failed to create buffer " .. path )
246271
247- if was_loaded then
248- vim .api .nvim_win_set_buf (self .winid , self .bufnr )
249- else
272+ local loaded = vim .api .nvim_buf_is_loaded (self .bufnr )
273+ vim .fn .bufload (self .bufnr )
274+
275+ vim .api .nvim_win_set_buf (self .winid , self .bufnr )
276+
277+ vim .api .nvim_set_option_value (" buflisted" , false , { buf = old_bufnr })
278+ vim .api .nvim_set_option_value (" buflisted" , true , { buf = self .bufnr })
279+
280+ local i = self :fold_range ()
281+ if i then --
282+ pcall (vim .cmd , (" %d,%dfold" ):format (1 , i ))
283+ end
284+
285+ if existed then --
286+ self :reset_lines ()
287+ end
288+
289+ if not loaded then --
250290 utils .exec_hook (" question_enter" , self )
251291 end
252- else
253- log .error (" Changing language failed" )
292+
293+ self :autocmds ()
294+ end )
295+
296+ if not ok then
297+ log .error (" Failed to change language\n " .. err )
254298 self .lang = old_lang
255299 self .bufnr = old_bufnr
256300 end
257301end )
258302
259303--- @param problem lc.cache.Question
260- function Question :init (problem )
304+ --- @param reset boolean
305+ function Question :init (problem , reset )
261306 self .cache = problem
262307 self .lang = config .lang
308+ self .reset = reset and true or false
263309end
264310
265- --- @type fun ( question : lc.cache.Question ): lc.ui.Question
311+ --- @type fun ( question : lc.cache.Question , reset ?: boolean ): lc.ui.Question
266312local LeetQuestion = Question
267313
268314return LeetQuestion
0 commit comments