From 6b8d691c613aa0aba02f136fdb22ac7c313b29be Mon Sep 17 00:00:00 2001 From: m1ngsama Date: Sat, 28 Mar 2026 18:45:25 +0800 Subject: [PATCH] UX audit: startup experience, ergonomics, and interaction fixes (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Startup / welcome screen: - Startify header is now dynamic: shows config name, Vim version, current dir, git branch, and key usage hints (leader, Ctrl-p, ,rg) - Reorder Startify sections: Sessions first (project restore), then directory files, recent files, bookmarks - Add default bookmarks: ~/.vimrc, ~/.zshrc, ~/.bashrc - vim : NERDTree opens left, Startify opens right (replaces the broken `ene` empty-buffer hack that left an unnamed buffer) - vim (no args): NERDTree opens alongside Startify via User Startified event, keeping Startify focused — both panels visible from the start - Consolidate StdinReadPre into a single top-level autocmd so pipe/ heredoc input is correctly detected in all startup branches Mapping fixes: - bd: remove `:tabclosegT` chain — it was closing the entire tab on every buffer close regardless of other open buffers - tnoremap : change to — single Esc now passes through to the running terminal program (fzf, htop, etc.); double Esc exits - : smart file search — uses GFiles (respects .gitignore) inside git repos, falls back to Files outside git trees General UX: - set lazyredraw moved to TTY-only block — it caused CoC floating window flicker in capable terminals; still active in TTY for perf - Markdown FileType: add tw=0 — prevents global tw=500 from mangling gq line wrapping in markdown buffers - CleanExtraSpaces: expand from 6 hardcoded extensions to all files; function is cursor-safe (saves/restores position) so it is harmless when ALE trim_whitespace also runs which-key: - Add 'd': 'diagnostics' to [a] group — ad was mapped to CocDiagnostics but invisible in the key hint overlay --- .vimrc | 104 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/.vimrc b/.vimrc index 4a53d0a..c091c7e 100644 --- a/.vimrc +++ b/.vimrc @@ -106,9 +106,6 @@ set hid " Configure backspace so it acts as it should act (enhanced from earlier basic setting) set whichwrap+=<,>,h,l -" Don't redraw while executing macros (good performance config) -set lazyredraw - " For regular expressions turn magic on set magic @@ -324,8 +321,8 @@ map k map h map l -" Close the current buffer -map bd :Bclose:tabclosegT +" Close the current buffer (Bclose preserves window layout) +map bd :Bclose " Close all the buffers map ba :bufdo bd @@ -439,15 +436,40 @@ let NERDTreeIgnore=['\.pyc$', '\~$', '\.swp$', '\.git$', '\.DS_Store', 'node_mod " NERDTree window size let NERDTreeWinSize=35 -" Automatically open NERDTree when vim starts on a directory -" Disabled in TTY for faster startup +" Track stdin reads so startup autocmds can skip pipe/heredoc input +autocmd StdinReadPre * let s:std_in=1 + +" Startup layout (non-TTY only — keeps TTY startup instant) if !g:is_tty - autocmd StdinReadPre * let s:std_in=1 - autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") | exe 'NERDTree' argv()[0] | wincmd p | ene | exe 'cd '.argv()[0] | endif + augroup ChopstickStartup + autocmd! + " vim → NERDTree on left + Startify (or blank buffer) on right + autocmd VimEnter * + \ if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') | + \ exe 'NERDTree ' . fnameescape(argv()[0]) | + \ exe 'cd ' . fnameescape(argv()[0]) | + \ wincmd p | + \ if exists(':Startify') == 2 | Startify | else | enew | endif | + \ endif + " vim (no args) → Startify renders first; open NERDTree alongside it + autocmd User Startified + \ if argc() == 0 && !exists('s:std_in') | + \ NERDTree | + \ wincmd p | + \ endif + augroup END endif " --- FZF --- -map :Files +" Smart file search: use GFiles (respects .gitignore) inside git repos, Files elsewhere +function! s:SmartFiles() abort + if !empty(system('git rev-parse --show-toplevel 2>/dev/null')) + GFiles + else + Files + endif +endfunction +map :call SmartFiles() map b :Buffers map rg :Rg map rt :Tags @@ -797,7 +819,8 @@ fun! CleanExtraSpaces() endfun if has("autocmd") - autocmd BufWritePre *.txt,*.js,*.py,*.wiki,*.sh,*.coffee :call CleanExtraSpaces() + " Run for all files; ALE trim_whitespace is idempotent so no conflict + autocmd BufWritePre * call CleanExtraSpaces() endif " ============================================================================ @@ -829,7 +852,7 @@ autocmd FileType html,css setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType yaml setlocal expandtab shiftwidth=2 tabstop=2 " Markdown specific settings -autocmd FileType markdown setlocal wrap linebreak spell +autocmd FileType markdown setlocal wrap linebreak spell tw=0 " Shell script settings autocmd FileType sh setlocal expandtab shiftwidth=2 tabstop=2 @@ -997,7 +1020,8 @@ if has('terminal') nnoremap th :terminal ++rows=10 " Terminal mode mappings - tnoremap + " Double-Esc to exit terminal mode (single Esc passes through to the running program) + tnoremap tnoremap h tnoremap j tnoremap k @@ -1038,6 +1062,9 @@ if g:is_tty " Reduce syntax highlighting complexity in TTY (global is 200, lower here) set synmaxcol=120 + + " lazyredraw is safe in TTY; avoid globally as it causes CoC float flicker + set lazyredraw endif " Provide helpful message on first run in TTY @@ -1079,10 +1106,11 @@ if exists('g:plugs["vim-which-key"]') let g:which_key_map['y'] = 'clipboard-yank' let g:which_key_map['Y'] = 'clipboard-yank-line' - " [a]LE lint group ([e/]e navigate; aD for detail) + " [a]LE lint group ([e/]e navigate; aD for detail; ad for diagnostics) let g:which_key_map['a'] = { \ 'name': '+ale-lint', \ 'D': 'ale-detail', + \ 'd': 'diagnostics', \ } " [c]ode / [c]opy group @@ -1172,32 +1200,52 @@ endif " ============================================================================ if exists('g:plugs["vim-startify"]') - " Simple ASCII header, no icons (KISS) - let g:startify_custom_header = [ - \ ' VIM - Vi IMproved', - \ ' Type :help if you are in trouble', - \ '', + " Dynamic header: config name, vim version, current dir, git branch, key tips + function! StartifyHeader() abort + let l:ver = 'Vim ' . (v:version / 100) . '.' . printf('%02d', v:version % 100) + let l:cwd = fnamemodify(getcwd(), ':t') + let l:git = '' + if executable('git') + let l:branch = system('git -C ' . shellescape(getcwd()) . + \ ' rev-parse --abbrev-ref HEAD 2>/dev/null') + if v:shell_error == 0 + let l:git = ' [' . substitute(l:branch, '\n\+$', '', '') . ']' + endif + endif + return [ + \ ' chopsticks | ' . l:ver . ' | ' . l:cwd . l:git, + \ ' , = leader | , + pause = key hints | Ctrl-p = files | ,rg = search', + \ '', + \ ] + endfunction + let g:startify_custom_header = 'StartifyHeader()' + + " Sessions first: restores full project state; dir + recent files below + let g:startify_lists = [ + \ { 'type': 'sessions', 'header': [' Sessions'] }, + \ { 'type': 'dir', 'header': [' Directory: ' . getcwd()] }, + \ { 'type': 'files', 'header': [' Recent Files'] }, + \ { 'type': 'bookmarks', 'header': [' Bookmarks'] }, \ ] - " Sections shown on start screen - let g:startify_lists = [ - \ { 'type': 'files', 'header': [' Recent Files'] }, - \ { 'type': 'dir', 'header': [' Directory: '. getcwd()] }, - \ { 'type': 'sessions', 'header': [' Sessions'] }, - \ { 'type': 'bookmarks', 'header': [' Bookmarks'] }, + " Quick-access bookmarks for common config files + let g:startify_bookmarks = [ + \ {'v': '~/.vimrc'}, + \ {'z': '~/.zshrc'}, + \ {'b': '~/.bashrc'}, \ ] " Session integration let g:startify_session_persistence = 1 " Auto-save session on quit let g:startify_session_autoload = 1 " Auto-load Session.vim if present let g:startify_change_to_vcs_root = 1 " cd to git root on open - let g:startify_fortune_use_unicode = 0 " No unicode in fortune (KISS) - let g:startify_enable_special = 0 " No / entries + let g:startify_fortune_use_unicode = 0 " ASCII only (KISS) + let g:startify_enable_special = 0 " Hide / clutter " Limit recent files shown let g:startify_files_number = 10 - " Don't open NERDTree when startify is active + " Required for NERDTree compatibility (prevents buftype conflicts) autocmd User Startified setlocal buftype= endif