diff 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
line wrap: on
line diff
--- a/plugins/hghelp/hghelp.vim	Fri Nov 28 08:44:05 2025 -0500
+++ b/plugins/hghelp/hghelp.vim	Tue Dec 02 11:53:47 2025 -0500
@@ -6,7 +6,8 @@
 	let winid = popup_create(buf, {'minwidth': 120, 'minheight': 28})
 endfunction
 
-function ExecuteCommand(command)
+function! ExecuteCommand(command)
+  " a:command is a shell command string, e.g. 'hg status'
   return system(a:command . ' 2>&1')
 endfunction
 
@@ -33,7 +34,222 @@
 endfunction
 
 command HGDiff call s:OpenHgDiff(expand('%'))
-command Commit call s:CommitWithFormat()
+command! HGCommit call <SID>HgCommitUI()
+" command Commit call s:CommitWithFormat()
+" map <C-k> :Commit<CR>
+"
+
+nnoremap <Leader>df :HGDiff<CR>
+nnoremap <C-k> :HGCommit<CR>
+
+
+
+" HG UI
+function! s:HgCommitUI()
+  " Save current window to go back if needed
+  let l:save_winid = win_getid()
+
+  " Get hg status
+  let l:status = ExecuteCommand('hg status -T"[ ] {status} {path}\n"')
+  if v:shell_error != 0
+    echohl ErrorMsg
+    echom "hg status failed:"
+    echom l:status
+    echohl None
+    return
+  endif
+  let l:lines = split(l:status, "\n")
+  if empty(l:lines)
+    echo "No changes to commit."
+    return
+  endif
+
+  " Open a new tab for this commit UI
+  tabnew
+  " Top window for file selection
+  enew
+  let b:hgcommit_type = 'filelist'
+  call setline(1, s:FormatHgStatusLines(l:lines))
+  setlocal buftype=acwrite bufhidden=wipe nobuflisted noswapfile
+  setlocal nomodifiable
+  setlocal cursorline
+  nnoremap <silent> <buffer> <CR> :call <SID>ToggleHgFileSelection()<CR>
+  nnoremap <silent> <buffer> <leader>aa :call <SID>ToggleHgSelectAll()<CR>
+
+  " Split for commit message
+  belowright split
+  resize 10
+  enew
+  let b:hgcommit_type = 'message'
+  setlocal buftype=acwrite bufhidden=wipe nobuflisted noswapfile
+  " Optional: initial comment
+  call setline(1, ['# Enter commit message above. Lines starting with # are ignored.'])
+  " Map to commit
+  nnoremap <silent> <buffer> <leader>cc :call <SID>DoHgCommit()<CR>
+
+  " Go back to top window to start there
+  wincmd k
+endfunction
+
+function! s:FormatHgStatusLines(lines) abort
+  let l:out = []
+  for l in a:lines
+    if empty(l)
+      continue
+    endif
+    " Typical hg status line: "M path/to/file"
+    " We keep status char and the rest of line, but prepend [ ]
+    call add(l:out, l)
+  endfor
+  return l:out
+endfunction
+
+function! s:ToggleHgFileSelection() abort
+  if get(b:, 'hgcommit_type', '') !=# 'filelist'
+    return
+  endif
+  setlocal modifiable
+  let l:lnum = line('.')
+  let l:line = getline(l:lnum)
+  if l:line =~# '^\[ \]'
+    " select
+    let l:line = substitute(l:line, '^\[ \]', '[x]', '')
+  elseif l:line =~# '^\[x\]'
+    " unselect
+    let l:line = substitute(l:line, '^\[x\]', '[ ]', '')
+  endif
+  call setline(l:lnum, l:line)
+  setlocal nomodifiable
+endfunction
+
+
+function! s:ToggleHgSelectAll() abort
+  if get(b:, 'hgcommit_type', '') !=# 'filelist'
+    return
+  endif
+  setlocal modifiable
+  let l:lines = getline(1, '$')
+
+  " Decide if we're selecting all or deselecting all:
+  let l:any_unselected = 0
+  for l:l in l:lines
+    if l:l =~# '^\[ \]'
+      let l:any_unselected = 1
+      break
+    endif
+  endfor
 
-map <C-k> :Commit<CR>
-nnoremap <Leader>df :HGDiff<CR>
+  let l:new = []
+  if l:any_unselected
+    " select all
+    for l:l in l:lines
+      if l:l =~# '^\[ \]'
+        call add(l:new, substitute(l:l, '^\[ \]', '[x]', ''))
+      else
+        call add(l:new, l:l)
+      endif
+    endfor
+  else
+    " deselect all
+    for l:l in l:lines
+      if l:l =~# '^\[x\]'
+        call add(l:new, substitute(l:l, '^\[x\]', '[ ]', ''))
+      else
+        call add(l:new, l:l)
+      endif
+    endfor
+  endif
+
+  call setline(1, l:new)
+  setlocal nomodifiable
+endfunction
+
+
+function! s:GetSelectedHgFiles() abort
+  " Find the filelist buffer in this tab
+  let l:files = []
+  for l:w in range(1, winnr('$'))
+    execute l:w . 'wincmd w'
+    if get(b:, 'hgcommit_type', '') ==# 'filelist'
+      let l:lines = getline(1, '$')
+      for l:L in l:lines
+        if l:L =~# '^\[x\] '
+          " Format: "[x] X path/to/file"
+          " Strip "[x] "
+          let l:rest = substitute(l:L, '^\[x\] ', '', '')
+          " First char is hg status, then space, then filename
+          if len(l:rest) >= 3
+            let l:file = strpart(l:rest, 2) 
+            call add(l:files, l:file)
+          endif
+        endif
+      endfor
+      break
+    endif
+  endfor
+  " Go back to original window (optional; this simple version just leaves you where you end)
+  return l:files
+endfunction
+
+
+function! s:DoHgCommit() abort
+  if get(b:, 'hgcommit_type', '') !=# 'message'
+    return
+  endif
+
+  " Get selected files
+  let l:files = s:GetSelectedHgFiles()
+  if empty(l:files)
+    echohl ErrorMsg
+    echom "No files selected for commit."
+    echohl None
+    return
+  endif
+
+  " Get commit message lines, ignoring leading '#' lines
+  let l:all_lines = getline(1, '$')
+  let l:msg_lines = []
+  for l:L in l:all_lines
+    if l:L =~# '^#'
+      continue
+    endif
+    call add(l:msg_lines, l:L)
+  endfor
+
+  let l:msg = join(l:msg_lines, "\n")
+  if empty(l:msg)
+    echohl ErrorMsg
+    echom "Commit message is empty."
+    echohl None
+    return
+  endif
+
+  " Write commit message to temp file
+  let l:tmpfile = tempname()
+  call writefile(l:msg_lines, l:tmpfile)
+
+  " Build command: hg commit -l tmpfile file1 file2 ...
+  let l:cmd = 'hg commit -l ' . shellescape(l:tmpfile)
+  for l:f in l:files
+    let l:cmd .= ' ' . shellescape(l:f)
+  endfor
+
+  " Run it
+  let l:out = ExecuteCommand(l:cmd)
+  let l:status = v:shell_error
+
+  " Clean up temp file
+  call delete(l:tmpfile)
+
+  if l:status != 0
+    echohl ErrorMsg
+    echom "hg commit failed:"
+    echom l:out
+    echohl None
+  else
+    echom "hg commit succeeded."
+  endif
+
+  " Close the commit tab
+  tabclose
+endfunction