diff --git a/CLAUDE.md b/CLAUDE.md index acefe61..693f7f3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -105,7 +105,7 @@ Other filetypes rely on Vim's default syntax → generic-group links (`String`, ## Autocomplete -IDE-style auto-completion via `plugin/autocomplete.vim`. As you type in insert mode, a popup appears automatically: word characters (≥2 prefix) trigger keyword completion (``) from the current file and other open buffers; filetype-configured trigger characters (`.`, `::`, `->`, etc.) trigger `omnifunc` (``). Disabled in prose filetypes (markdown, gitcommit, text, help) — those buffers get no `TextChangedI` autocmd attached at all. +IDE-style auto-completion via `plugin/autocomplete.vim`. As you type in insert mode, a popup appears automatically: word characters (≥2 prefix) trigger keyword completion (``) from the current file and other open buffers; filetype-configured trigger characters (single chars only — the union across ftplugins is `.`, `>`, `:`, `<`, `/`, `$`, and space) trigger `omnifunc` (``). Disabled in prose filetypes (markdown, gitcommit, text, help) — those buffers get no `TextChangedI` autocmd attached at all. ### Popup navigation @@ -167,7 +167,7 @@ On Vim 8.2.1978+ the trigger uses `popup PopUp` so insert mode is prese - Uses `term_start(['bash', '--init-file', l:rcfile], {…})` with a list argument — NOT `:execute 'below terminal …'` — so paths containing spaces do not misparse (Vim's `:terminal` splits its command on whitespace regardless of quoting) - `terminal.bashrc` sources `/etc/profile` and `~/.bashrc` first (full user env inherited), then sets a green-user / cyan-host / blue-cwd / purple-branch prompt using a nerd-font branch glyph; detached HEAD renders as `detached:` - `terminal.bashrc` guards against recursive sourcing via `_IVIM_TERMINAL_SOURCED` so any `~/.bashrc` loop is a no-op on re-entry -- Auto-closes terminal buffers on quit (`QuitPre` autocommand) +- Auto-closes terminal buffers when Vim exits — `QuitPre` autocommand gated on the last non-terminal window, so a single-window or aborted `:q` never kills terminals, and `:qall` never trips `E947` (job still running) - `ivim_terminal_mouse` autogroup clears netrw mouse mappings that would otherwise leak into the terminal buffer - ANSI colors set via `g:terminal_ansi_colors` in colorscheme (guarded by `has('terminal')`) diff --git a/get-ivim.sh b/get-ivim.sh index a84bd74..7c44649 100755 --- a/get-ivim.sh +++ b/get-ivim.sh @@ -75,17 +75,25 @@ find_latest_backup() { # shared-HOME system. local latest="" local latest_ts=0 + local latest_ctr=0 shopt -s nullglob for f in "${target}.bak."*; do - local ts="${f##*.bak.}" - if ! [[ "$ts" =~ ^[0-9]+$ ]]; then + # Suffix is or, for same-second collisions, .. + # Both components must be integers — anything else is a crafted name. + local suffix="${f##*.bak.}" + local ts="${suffix%%.*}" + local ctr="${suffix#*.}" + [ "$ctr" = "$suffix" ] && ctr=0 + if ! [[ "$ts" =~ ^[0-9]+$ ]] || ! [[ "$ctr" =~ ^[0-9]+$ ]]; then continue fi if [ ! -O "$f" ]; then continue fi - if [ "$ts" -gt "$latest_ts" ]; then + if [ "$ts" -gt "$latest_ts" ] \ + || { [ "$ts" -eq "$latest_ts" ] && [ "$ctr" -gt "$latest_ctr" ]; }; then latest_ts="$ts" + latest_ctr="$ctr" latest="$f" fi done diff --git a/install.sh b/install.sh index 8cf6a56..d2b7fd2 100755 --- a/install.sh +++ b/install.sh @@ -72,17 +72,25 @@ find_latest_backup() { # on the next uninstall-and-restore). local latest="" local latest_ts=0 + local latest_ctr=0 shopt -s nullglob for f in "${target}.bak."*; do - local ts="${f##*.bak.}" - if ! [[ "$ts" =~ ^[0-9]+$ ]]; then + # Suffix is or, for same-second collisions, .. + # Both components must be integers — anything else is a crafted name. + local suffix="${f##*.bak.}" + local ts="${suffix%%.*}" + local ctr="${suffix#*.}" + [ "$ctr" = "$suffix" ] && ctr=0 + if ! [[ "$ts" =~ ^[0-9]+$ ]] || ! [[ "$ctr" =~ ^[0-9]+$ ]]; then continue fi if [ ! -O "$f" ]; then continue fi - if [ "$ts" -gt "$latest_ts" ]; then + if [ "$ts" -gt "$latest_ts" ] \ + || { [ "$ts" -eq "$latest_ts" ] && [ "$ctr" -gt "$latest_ctr" ]; }; then latest_ts="$ts" + latest_ctr="$ctr" latest="$f" fi done diff --git a/plugin/keymaps.vim b/plugin/keymaps.vim index c36ab27..7ba6d79 100644 --- a/plugin/keymaps.vim +++ b/plugin/keymaps.vim @@ -15,12 +15,27 @@ function! s:CloseTerminals() abort endfor endfunction -" VimLeavePre — only fires when Vim is actually exiting. QuitPre fired on -" every :q, so an aborted quit (e.g. unsaved changes in another window) -" would silently kill all running terminal jobs while Vim stayed open. +" Wipe terminal jobs only when Vim is actually about to exit — i.e. the +" window being quit is the last non-terminal ("ordinary") window. Cleaning +" unconditionally on QuitPre would kill terminals on a single-window or +" aborted quit while Vim stays open; VimLeavePre fires too late to pre-empt +" the E947 "job still running" check that blocks :qall. The last-ordinary- +" window gate threads between both: no spurious kills, no E947 on exit. +function! s:CloseTerminalsOnExit() abort + let l:ordinary = 0 + for l:win in getwininfo() + if getbufvar(l:win.bufnr, '&buftype') !=# 'terminal' + let l:ordinary += 1 + endif + endfor + if l:ordinary <= 1 + call s:CloseTerminals() + endif +endfunction + augroup ivim_terminal_cleanup autocmd! - autocmd VimLeavePre * call s:CloseTerminals() + autocmd QuitPre * call s:CloseTerminalsOnExit() augroup END " Exit insert mode when entering a non-modifiable buffer (e.g. via mouse