Skip to content

Commit 4196d00

Browse files
authored
fix(vim): resolve <Tab> conflict between copilot and snipMate (#10)
* fix(vim): resolve <Tab> mapping conflict between copilot and snipMate copilot.vim maps <Tab> in insert mode by default, which collided with vim-snipmate's `imap <unique> <Tab>` and raised E227 at startup. Set g:copilot_no_tab_map before plug#end() so <Tab> stays with snipMate, and accept Copilot suggestions with <C-L> instead. * ci(vim): verify vim-plug setup and guard the <Tab> mapping fix Add a path-filtered Vim workflow that runs only when Vim files change. It installs every declared plugin via vim-plug (excluding the heavy YouCompleteMe native build) and asserts the vimrc sources without an E227 <Tab> mapping conflict, locking in the copilot/snipMate fix from this branch. * ci(vim): source vimrc with -u during PlugInstall The install step ran vim without -u, so the vimrc (and thus plug#begin / PlugInstall) was never sourced and no plugins installed — which also made the E227 check pass vacuously. Pass -u "$HOME/.vimrc" so PlugInstall runs, and fail loudly if plugged/ ends up empty.
1 parent 197f9fb commit 4196d00

2 files changed

Lines changed: 108 additions & 0 deletions

File tree

.github/workflows/vim.yml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Vim
2+
3+
# Only run when something Vim-related changes, so unrelated PRs don't pay for
4+
# a full plugin install.
5+
on:
6+
push:
7+
branches: [master]
8+
paths:
9+
- 'rc.d/vimrc'
10+
- 'rc.d/vim/**'
11+
- 'setup.d/vim.sh'
12+
- '.github/workflows/vim.yml'
13+
pull_request:
14+
paths:
15+
- 'rc.d/vimrc'
16+
- 'rc.d/vim/**'
17+
- 'setup.d/vim.sh'
18+
- '.github/workflows/vim.yml'
19+
20+
jobs:
21+
vim-setup:
22+
# Verify the Vim setup: vim-plug installs every declared plugin and the
23+
# vimrc sources without a <Tab> mapping conflict (E227, copilot vs snipMate).
24+
# YouCompleteMe is excluded here — its huge recursive clone and native
25+
# compile (handled by setup.d/vim.sh) are too heavy for CI — but every other
26+
# declared plugin is installed and checked.
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 20
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
- name: Install Vim
33+
run: |
34+
sudo apt-get update
35+
sudo apt-get install -y vim
36+
37+
- name: Link Vim config into $HOME
38+
run: |
39+
ln -sfn "$PWD/rc.d/vimrc" "$HOME/.vimrc"
40+
ln -sfn "$PWD/rc.d/vim" "$HOME/.vim"
41+
42+
- name: Install vim-plug and plugins
43+
run: |
44+
curl -sfLo rc.d/vim/autoload/plug.vim --create-dirs \
45+
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
46+
# Install every declared plugin except YouCompleteMe (see job comment).
47+
# Some `do` hooks need toolchains not present here (go/yarn/npm); they
48+
# may warn but don't block clones, and the assertions below check what
49+
# actually matters.
50+
list="$(grep -oE "Plug '[^']+'" rc.d/vimrc \
51+
| sed "s/Plug '//; s/'//; s#.*/##" \
52+
| grep -vx 'YouCompleteMe' | sort -u | tr '\n' ' ')"
53+
echo "Installing: $list"
54+
# -u is required so the vimrc (which calls plug#begin) is sourced and
55+
# PlugInstall is defined; otherwise the command is unknown and nothing
56+
# installs.
57+
vim --not-a-term -es -u "$HOME/.vimrc" -c "PlugInstall --sync $list" -c 'qall!' || true
58+
# Fail loudly if nothing was actually installed (e.g. vimrc didn't load).
59+
if [ ! -d "$HOME/.vim/plugged" ] || [ -z "$(ls -A "$HOME/.vim/plugged")" ]; then
60+
echo "✗ no plugins were installed — vimrc/plug#begin likely did not run"
61+
exit 1
62+
fi
63+
64+
- name: Verify vimrc sources without a <Tab> conflict (E227)
65+
run: |
66+
set -euo pipefail
67+
out="$(mktemp)"
68+
# Load the real vimrc with all plugins active; E227 fires here if
69+
# copilot and snipMate both try to own <Tab>.
70+
vim --not-a-term -es -u "$HOME/.vimrc" \
71+
-c 'redir! > '"$out" \
72+
-c 'silent! echon "errmsg=[" . v:errmsg . "]"' \
73+
-c 'redir END' -c 'qall!' 2>/dev/null || true
74+
echo "startup $(cat "$out")"
75+
if grep -q 'E227' "$out"; then
76+
echo "✗ <Tab> mapping conflict (E227) at startup"
77+
exit 1
78+
fi
79+
echo "✓ no <Tab> mapping conflict at startup"
80+
81+
- name: Verify all declared plugins are installed
82+
run: |
83+
set -euo pipefail
84+
grep -oE "Plug '[^']+'" rc.d/vimrc \
85+
| sed "s/Plug '//; s/'//; s#.*/##" \
86+
| grep -vx 'YouCompleteMe' | sort -u > /tmp/declared.txt
87+
ls "$HOME/.vim/plugged" | sort > /tmp/installed.txt
88+
missing="$(comm -23 /tmp/declared.txt /tmp/installed.txt)"
89+
if [ -n "$missing" ]; then
90+
echo "✗ declared but not installed:"
91+
echo "$missing"
92+
exit 1
93+
fi
94+
echo "✓ all $(wc -l < /tmp/declared.txt) declared plugins installed (YouCompleteMe excluded)"

rc.d/vimrc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ if v:version > 801 || (v:version == 801 && has( 'patch2269' ))
5353
Plug 'ycm-core/YouCompleteMe'
5454
endif
5555

56+
" Reserve <Tab> for vim-snipmate. copilot.vim maps <Tab> in insert mode by
57+
" default, which collides with snipMate's `imap <unique> <Tab>` (E227). This
58+
" must be set before plug#end() because copilot installs its mapping while its
59+
" plugin is sourced there. Copilot suggestions are accepted with <C-L> instead
60+
" (see the Copilot section below).
61+
let g:copilot_no_tab_map = v:true
62+
5663
" All of your Plugins must be added before the following line
5764
call plug#end()
5865
filetype plugin indent on " required
@@ -233,6 +240,13 @@ endif
233240
" =================================================
234241
let g:goyo_width = 120
235242

243+
" =================================================
244+
" Copilot
245+
" =================================================
246+
" <Tab> is reserved for snipMate (see g:copilot_no_tab_map before plug#end()).
247+
" Accept Copilot suggestions with <C-L> instead.
248+
imap <silent><script><expr> <C-L> copilot#Accept("\<CR>")
249+
236250
" =================================================
237251
" Snipmate
238252
" =================================================

0 commit comments

Comments
 (0)