comparison plugins/hghelp/hghelp.vim @ 13:027a85d0e60e

[x] M .vimrc [x] M plugins/hghelp/hghelp.vim [x] M plugins/vim-ai.vim [ ] ? tmp
author Luka Sitas <lsitas@avatarasoftware.com>
date Tue, 02 Dec 2025 11:53:47 -0500
parents 17c557de03e0
children 6ee7fce1cba8
comparison
equal deleted inserted replaced
10:b95a8e2525cc 13:027a85d0e60e
4 function PopupCommand(command) 4 function PopupCommand(command)
5 let buf = term_start(a:command, {'hidden': 1, 'term_finish': 'close'}) 5 let buf = term_start(a:command, {'hidden': 1, 'term_finish': 'close'})
6 let winid = popup_create(buf, {'minwidth': 120, 'minheight': 28}) 6 let winid = popup_create(buf, {'minwidth': 120, 'minheight': 28})
7 endfunction 7 endfunction
8 8
9 function ExecuteCommand(command) 9 function! ExecuteCommand(command)
10 " a:command is a shell command string, e.g. 'hg status'
10 return system(a:command . ' 2>&1') 11 return system(a:command . ' 2>&1')
11 endfunction 12 endfunction
12 13
13 function! s:CommitWithFormat() 14 function! s:CommitWithFormat()
14 wa 15 wa
31 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile 32 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile
32 execute 'vert diffsplit' l:current_file 33 execute 'vert diffsplit' l:current_file
33 endfunction 34 endfunction
34 35
35 command HGDiff call s:OpenHgDiff(expand('%')) 36 command HGDiff call s:OpenHgDiff(expand('%'))
36 command Commit call s:CommitWithFormat() 37 command! HGCommit call <SID>HgCommitUI()
37 38 " command Commit call s:CommitWithFormat()
38 map <C-k> :Commit<CR> 39 " map <C-k> :Commit<CR>
40 "
41
39 nnoremap <Leader>df :HGDiff<CR> 42 nnoremap <Leader>df :HGDiff<CR>
43 nnoremap <C-k> :HGCommit<CR>
44
45
46
47 " HG UI
48 function! s:HgCommitUI()
49 " Save current window to go back if needed
50 let l:save_winid = win_getid()
51
52 " Get hg status
53 let l:status = ExecuteCommand('hg status -T"[ ] {status} {path}\n"')
54 if v:shell_error != 0
55 echohl ErrorMsg
56 echom "hg status failed:"
57 echom l:status
58 echohl None
59 return
60 endif
61 let l:lines = split(l:status, "\n")
62 if empty(l:lines)
63 echo "No changes to commit."
64 return
65 endif
66
67 " Open a new tab for this commit UI
68 tabnew
69 " Top window for file selection
70 enew
71 let b:hgcommit_type = 'filelist'
72 call setline(1, s:FormatHgStatusLines(l:lines))
73 setlocal buftype=acwrite bufhidden=wipe nobuflisted noswapfile
74 setlocal nomodifiable
75 setlocal cursorline
76 nnoremap <silent> <buffer> <CR> :call <SID>ToggleHgFileSelection()<CR>
77 nnoremap <silent> <buffer> <leader>aa :call <SID>ToggleHgSelectAll()<CR>
78
79 " Split for commit message
80 belowright split
81 resize 10
82 enew
83 let b:hgcommit_type = 'message'
84 setlocal buftype=acwrite bufhidden=wipe nobuflisted noswapfile
85 " Optional: initial comment
86 call setline(1, ['# Enter commit message above. Lines starting with # are ignored.'])
87 " Map to commit
88 nnoremap <silent> <buffer> <leader>cc :call <SID>DoHgCommit()<CR>
89
90 " Go back to top window to start there
91 wincmd k
92 endfunction
93
94 function! s:FormatHgStatusLines(lines) abort
95 let l:out = []
96 for l in a:lines
97 if empty(l)
98 continue
99 endif
100 " Typical hg status line: "M path/to/file"
101 " We keep status char and the rest of line, but prepend [ ]
102 call add(l:out, l)
103 endfor
104 return l:out
105 endfunction
106
107 function! s:ToggleHgFileSelection() abort
108 if get(b:, 'hgcommit_type', '') !=# 'filelist'
109 return
110 endif
111 setlocal modifiable
112 let l:lnum = line('.')
113 let l:line = getline(l:lnum)
114 if l:line =~# '^\[ \]'
115 " select
116 let l:line = substitute(l:line, '^\[ \]', '[x]', '')
117 elseif l:line =~# '^\[x\]'
118 " unselect
119 let l:line = substitute(l:line, '^\[x\]', '[ ]', '')
120 endif
121 call setline(l:lnum, l:line)
122 setlocal nomodifiable
123 endfunction
124
125
126 function! s:ToggleHgSelectAll() abort
127 if get(b:, 'hgcommit_type', '') !=# 'filelist'
128 return
129 endif
130 setlocal modifiable
131 let l:lines = getline(1, '$')
132
133 " Decide if we're selecting all or deselecting all:
134 let l:any_unselected = 0
135 for l:l in l:lines
136 if l:l =~# '^\[ \]'
137 let l:any_unselected = 1
138 break
139 endif
140 endfor
141
142 let l:new = []
143 if l:any_unselected
144 " select all
145 for l:l in l:lines
146 if l:l =~# '^\[ \]'
147 call add(l:new, substitute(l:l, '^\[ \]', '[x]', ''))
148 else
149 call add(l:new, l:l)
150 endif
151 endfor
152 else
153 " deselect all
154 for l:l in l:lines
155 if l:l =~# '^\[x\]'
156 call add(l:new, substitute(l:l, '^\[x\]', '[ ]', ''))
157 else
158 call add(l:new, l:l)
159 endif
160 endfor
161 endif
162
163 call setline(1, l:new)
164 setlocal nomodifiable
165 endfunction
166
167
168 function! s:GetSelectedHgFiles() abort
169 " Find the filelist buffer in this tab
170 let l:files = []
171 for l:w in range(1, winnr('$'))
172 execute l:w . 'wincmd w'
173 if get(b:, 'hgcommit_type', '') ==# 'filelist'
174 let l:lines = getline(1, '$')
175 for l:L in l:lines
176 if l:L =~# '^\[x\] '
177 " Format: "[x] X path/to/file"
178 " Strip "[x] "
179 let l:rest = substitute(l:L, '^\[x\] ', '', '')
180 " First char is hg status, then space, then filename
181 if len(l:rest) >= 3
182 let l:file = strpart(l:rest, 2)
183 call add(l:files, l:file)
184 endif
185 endif
186 endfor
187 break
188 endif
189 endfor
190 " Go back to original window (optional; this simple version just leaves you where you end)
191 return l:files
192 endfunction
193
194
195 function! s:DoHgCommit() abort
196 if get(b:, 'hgcommit_type', '') !=# 'message'
197 return
198 endif
199
200 " Get selected files
201 let l:files = s:GetSelectedHgFiles()
202 if empty(l:files)
203 echohl ErrorMsg
204 echom "No files selected for commit."
205 echohl None
206 return
207 endif
208
209 " Get commit message lines, ignoring leading '#' lines
210 let l:all_lines = getline(1, '$')
211 let l:msg_lines = []
212 for l:L in l:all_lines
213 if l:L =~# '^#'
214 continue
215 endif
216 call add(l:msg_lines, l:L)
217 endfor
218
219 let l:msg = join(l:msg_lines, "\n")
220 if empty(l:msg)
221 echohl ErrorMsg
222 echom "Commit message is empty."
223 echohl None
224 return
225 endif
226
227 " Write commit message to temp file
228 let l:tmpfile = tempname()
229 call writefile(l:msg_lines, l:tmpfile)
230
231 " Build command: hg commit -l tmpfile file1 file2 ...
232 let l:cmd = 'hg commit -l ' . shellescape(l:tmpfile)
233 for l:f in l:files
234 let l:cmd .= ' ' . shellescape(l:f)
235 endfor
236
237 " Run it
238 let l:out = ExecuteCommand(l:cmd)
239 let l:status = v:shell_error
240
241 " Clean up temp file
242 call delete(l:tmpfile)
243
244 if l:status != 0
245 echohl ErrorMsg
246 echom "hg commit failed:"
247 echom l:out
248 echohl None
249 else
250 echom "hg commit succeeded."
251 endif
252
253 " Close the commit tab
254 tabclose
255 endfunction