diff --git a/README b/README index a7c56b9..6fd4483 100644 --- a/README +++ b/README @@ -178,6 +178,36 @@ run"sleep""0.25" --- +## evergarden - Vim Colorscheme + +A classic-Vim port of the [evergarden](https://evergarden.moe) palette. Single +file, no dependencies, Vim 8.0+ (no Neovim, by design). + +### Install +```bash +cd evergarden && ./install.sh # → ~/.vim/colors on every platform +./install.sh status +./install.sh uninstall +``` + +### Usage +```vim +set runtimepath^=~/.vim " needed when ~/.vim is not already on runtimepath +set termguicolors +let g:evergarden_keyword = 'skye' " keyword hue; any palette name +colorscheme evergarden +``` + +### Preview without installing +```bash +cd evergarden && ./test/run.sh # hitest + C/Vim/Markdown samples + a live diff +./test/run.sh 256 # 256-colour cterm fallback +``` + +In the preview, `:Kw ` retints keywords live. + +--- + ## Building All Tools Use the wrapper script to build all tools at once: diff --git a/evergarden/README.md b/evergarden/README.md new file mode 100644 index 0000000..5584978 --- /dev/null +++ b/evergarden/README.md @@ -0,0 +1,144 @@ +# evergarden.vim + +A classic-Vim port of the [evergarden](https://evergarden.moe) palette — forest +tones, soft pastels, dark background. Single file, no dependencies, no plugin +manager. Vim 8.0+. **No Neovim support, by design.** + +``` +red #f57f82 orange #f7a182 yellow #f5d098 lime #dbe6af +green #cbe3b3 aqua #b3e3ca skye #b3e6db snow #afd9e6 +blue #b2caed purple #d2bdf3 pink #f3c0e5 cherry #fae6ef +``` + +## Install + +```bash +cd evergarden && ./install.sh # copy into ~/.vim/colors on every platform +./install.sh status # where is it? +./install.sh uninstall # remove +``` + +The installer uses only `~/.vim/colors/`, creating it if necessary, on Windows +and Unix alike. It never creates or modifies `~/vimfiles`. Uninstall removes +only `~/.vim/colors/evergarden.vim`, leaving directories and other files intact. + +Or manually: drop `colors/evergarden.vim` into `~/.vim/colors/`. + +### Not listed by `:colorscheme `? + +Check inside the Vim you use: + +```vim +:echo expand('~') +:set runtimepath? +:echo globpath(&runtimepath, 'colors/evergarden.vim') +``` + +`runtimepath` must include `~/.vim`, the **parent** of `colors`, not the +`colors` directory itself. Native Windows Vim does not include `~/.vim` by +default. + +Plugins under `~/.vim/bundle` can still work: managers such as Vundle add each +plugin's runtime root separately, without adding `~/.vim` itself. To keep +using `~/.vim/colors` on Windows, add this before the colorscheme in your vimrc: + +```vim +set runtimepath^=~/.vim +colorscheme evergarden +``` + +If Vim uses a different home from the shell or a custom `runtimepath`, install +manually into a runtime root shown by `:set runtimepath?`. + +## Use + +In `~/.vimrc` (or `~/_vimrc` on Windows): + +```vim +set runtimepath^=~/.vim " needed when ~/.vim is not already on runtimepath +set termguicolors " strongly recommended +colorscheme evergarden +``` + +Without `termguicolors` the scheme falls back to xterm-256 approximations +(needs `set t_Co=256`). + +## Options + +Set before `:colorscheme`: + +| Option | Default | Effect | +|---|---|---| +| `g:evergarden_italic` | `1` | Italic comments and special comments | +| `g:evergarden_transparent` | `0` | Keep the terminal background | +| `g:evergarden_keyword` | `'skye'` | Hue for `if`/`for`/`switch`/`function` etc. Any palette name | + +```vim +let g:evergarden_transparent = 1 +let g:evergarden_italic = 0 +let g:evergarden_keyword = 'blue' +colorscheme evergarden +``` + +### Keyword hue + +Control flow is the most-repeated token on screen, so it gets its own knob. +The default `skye` (`#b3e6db`) keeps it cool and out of the way; `Function` +stays blue, `Type` yellow, `String` green, `Constant` orange, and operators +and delimiters are muted so the keyword hue reads cleanly. + +| Value | Feel | +|---|---| +| `skye` (default) | Cool cyan, low contrast against strings | +| `aqua` | Greener, softer; closer to `String` | +| `blue` | Cooler still — but shares the hue with `Function` | +| `orange` | Warm; shares the hue with `Constant`/`Number` | +| `purple` | The original mapping | + +Audition them live in the preview with `:Kw skye`, `:Kw blue`, … (tab completes). + +## Test it without installing + +```bash +cd evergarden +./test/run.sh # true colour +./test/run.sh 256 # 256-colour cterm fallback +``` + +Five tabs (`gt` / `gT` to move, `:qa` to quit): + +| Tab | Shows | +|---|---| +| `syntax/hitest.vim` | Every defined highlight group, each in its own colours (Vim built-in) | +| `sample.c` | Comment / PreProc / Type / Statement / Constant / String / Special | +| `sample.vim` | Vimscript: functions, options, autocommands, registers | +| `sample.md` | Headings, code, links, `spell` on so `SpellBad` shows | +| diff | `DiffAdd` / `DiffChange` / `DiffDelete` / `DiffText` side by side | + +The two Vim built-ins are worth knowing on their own: + +```vim +:runtime syntax/hitest.vim " all groups in their own colours +:runtime syntax/colortest.vim " the cterm colour grid +``` + +## Covers + +Every group in `:help highlight-groups`, plus diffs, spell, netrw, popup +windows, the toolbar, `termdebug` markers, markdown/help filetypes, and +`g:terminal_ansi_colors` for `:terminal`. + +## Installer regression tests + +```sh +sh evergarden/test/install.sh +``` + +Tests use temporary homes to check install/status/uninstall into `~/.vim/colors` +and verify that `~/vimfiles` is untouched. If `vim` is available, they also +verify discovery, completion, loading, and removal with the documented +`set runtimepath^=~/.vim` configuration. + +## Spec + +`specs/010-evergarden-colorscheme/spec.md` diff --git a/evergarden/colors/evergarden.vim b/evergarden/colors/evergarden.vim new file mode 100644 index 0000000..eaede51 --- /dev/null +++ b/evergarden/colors/evergarden.vim @@ -0,0 +1,230 @@ +" Name: evergarden +" Description: A forest-toned dark colorscheme inspired by The Minish Cap. Evergarden.moe used as basis +" Author: AI / mandus +" Maintainer: mandus +" URL: https://evergarden.moe +" License: Vim License (see `:help license`) +" Last Change: 2026.09.26 +" +" Spec: specs/010-evergarden-colorscheme/spec.md +" +" Options: +" let g:evergarden_italic = 0 " disable italics (default 1) +" let g:evergarden_transparent = 1 " keep terminal background (default 0) +" let g:evergarden_keyword = 'blue' " keyword hue (default 'skye'); any +" " palette name: skye, aqua, blue, +" " green, lime, orange, purple, pink... + +set background=dark + +hi clear +let g:colors_name = 'evergarden' + +let s:t_Co = has('gui_running') ? 16777216 : str2nr(&t_Co) +let s:tgc = has('termguicolors') && &termguicolors + +let g:terminal_ansi_colors = ['#374145', '#f57f82', '#cbe3b3', '#f5d098', '#b2caed', '#d2bdf3', '#b3e6db', '#adc9bc', '#4a585c', '#f7a182', '#dbe6af', '#f5d098', '#afd9e6', '#f3c0e5', '#b3e3ca', '#f8f9e8'] + +hi! link Boolean Constant +hi! link Conditional Statement +hi! link CursorIM Cursor +hi! link CursorLineFold FoldColumn +hi! link CursorLineSign SignColumn +hi! link Define PreProc +hi! link Float Constant +hi! link Include PreProc +hi! link Keyword Statement +hi! link Label Statement +hi! link LineNrAbove LineNr +hi! link LineNrBelow LineNr +hi! link Macro PreProc +hi! link Number Constant +hi! link PopupSelected PmenuSel +hi! link PreCondit PreProc +hi! link PreInsert NonText +hi! link Repeat Statement +hi! link SpecialChar Special +hi! link StatusLineTermNC StatusLineNC +hi! link StorageClass Type +hi! link Structure Type +hi! link TabPanel TabLine +hi! link TabPanelFill TabLineFill +hi! link Terminal Normal +hi! link Typedef Type +hi! link VertSplitNC VertSplit +hi! link diffAdded Added +hi! link diffChanged Changed +hi! link diffRemoved Removed +hi! link lCursor Cursor +hi! link markdownH1 htmlH1 +hi! link markdownH2 htmlH2 +hi! link markdownUrl Underlined +hi! link netrwComment Comment +hi! link netrwHelpCmd Statement + +hi Normal guifg=#f8f9e8 guibg=#1e2528 guisp=NONE gui=NONE ctermfg=255 ctermbg=235 cterm=NONE term=NONE +hi Added guifg=#cbe3b3 guibg=NONE guisp=NONE gui=NONE ctermfg=151 ctermbg=NONE cterm=NONE term=NONE +hi Changed guifg=#f5d098 guibg=NONE guisp=NONE gui=NONE ctermfg=222 ctermbg=NONE cterm=NONE term=NONE +hi Character guifg=#b3e3ca guibg=NONE guisp=NONE gui=NONE ctermfg=158 ctermbg=NONE cterm=NONE term=NONE +hi ColorColumn guifg=NONE guibg=#262f33 guisp=NONE gui=NONE ctermfg=NONE ctermbg=236 cterm=NONE term=reverse +hi Comment guifg=#6f8788 guibg=NONE guisp=NONE gui=italic ctermfg=66 ctermbg=NONE cterm=italic term=bold +hi Conceal guifg=#6f8788 guibg=NONE guisp=NONE gui=NONE ctermfg=66 ctermbg=NONE cterm=NONE term=NONE +hi Constant guifg=#f7a182 guibg=NONE guisp=NONE gui=NONE ctermfg=216 ctermbg=NONE cterm=NONE term=NONE +hi CurSearch guifg=#1e2528 guibg=#f7a182 guisp=NONE gui=NONE ctermfg=235 ctermbg=216 cterm=NONE term=reverse +hi Cursor guifg=#1e2528 guibg=#f8f9e8 guisp=NONE gui=NONE ctermfg=235 ctermbg=255 cterm=NONE term=reverse +hi CursorColumn guifg=NONE guibg=#262f33 guisp=NONE gui=NONE ctermfg=NONE ctermbg=236 cterm=NONE term=NONE +hi CursorLine guifg=NONE guibg=#262f33 guisp=NONE gui=NONE ctermfg=NONE ctermbg=236 cterm=NONE term=underline +hi CursorLineNr guifg=#f5d098 guibg=NONE guisp=NONE gui=bold ctermfg=222 ctermbg=NONE cterm=bold term=bold +hi Debug guifg=#f57f82 guibg=NONE guisp=NONE gui=NONE ctermfg=210 ctermbg=NONE cterm=NONE term=NONE +hi Delimiter guifg=#839e9a guibg=NONE guisp=NONE gui=NONE ctermfg=246 ctermbg=NONE cterm=NONE term=NONE +hi DiffAdd guifg=#cbe3b3 guibg=#262f33 guisp=NONE gui=NONE ctermfg=151 ctermbg=236 cterm=NONE term=reverse +hi DiffChange guifg=#f5d098 guibg=#262f33 guisp=NONE gui=NONE ctermfg=222 ctermbg=236 cterm=NONE term=NONE +hi DiffDelete guifg=#f57f82 guibg=#262f33 guisp=NONE gui=NONE ctermfg=210 ctermbg=236 cterm=NONE term=reverse +hi DiffText guifg=#1e2528 guibg=#f5d098 guisp=NONE gui=bold ctermfg=235 ctermbg=222 cterm=bold term=reverse +hi Directory guifg=#b2caed guibg=NONE guisp=NONE gui=NONE ctermfg=111 ctermbg=NONE cterm=NONE term=NONE +hi EndOfBuffer guifg=#374145 guibg=#1e2528 guisp=NONE gui=NONE ctermfg=238 ctermbg=235 cterm=NONE term=NONE +hi Error guifg=#f57f82 guibg=NONE guisp=NONE gui=bold ctermfg=210 ctermbg=NONE cterm=bold term=bold,reverse +hi ErrorMsg guifg=#f57f82 guibg=NONE guisp=NONE gui=bold ctermfg=210 ctermbg=NONE cterm=bold term=bold,reverse +hi Exception guifg=#f57f82 guibg=NONE guisp=NONE gui=NONE ctermfg=210 ctermbg=NONE cterm=NONE term=NONE +hi FoldColumn guifg=#58686d guibg=#1e2528 guisp=NONE gui=NONE ctermfg=241 ctermbg=235 cterm=NONE term=NONE +hi Folded guifg=#96b4aa guibg=#262f33 guisp=NONE gui=NONE ctermfg=109 ctermbg=236 cterm=NONE term=NONE +hi Function guifg=#b2caed guibg=NONE guisp=NONE gui=NONE ctermfg=111 ctermbg=NONE cterm=NONE term=NONE +hi Identifier guifg=#adc9bc guibg=NONE guisp=NONE gui=NONE ctermfg=145 ctermbg=NONE cterm=NONE term=NONE +hi Ignore guifg=#58686d guibg=NONE guisp=NONE gui=NONE ctermfg=241 ctermbg=NONE cterm=NONE term=NONE +hi IncSearch guifg=#1e2528 guibg=#f7a182 guisp=NONE gui=NONE ctermfg=235 ctermbg=216 cterm=NONE term=bold,reverse,underline +hi LineNr guifg=#4a585c guibg=#1e2528 guisp=NONE gui=NONE ctermfg=240 ctermbg=235 cterm=NONE term=NONE +hi MatchParen guifg=#f7a182 guibg=#4a585c guisp=NONE gui=bold ctermfg=216 ctermbg=240 cterm=bold term=bold,underline +hi Menu guifg=#f8f9e8 guibg=#262f33 guisp=NONE gui=NONE ctermfg=255 ctermbg=236 cterm=NONE term=NONE +hi MessageWindow guifg=#f8f9e8 guibg=#262f33 guisp=NONE gui=NONE ctermfg=255 ctermbg=236 cterm=NONE term=NONE +hi ModeMsg guifg=#f8f9e8 guibg=NONE guisp=NONE gui=bold ctermfg=255 ctermbg=NONE cterm=bold term=bold +hi MoreMsg guifg=#cbe3b3 guibg=NONE guisp=NONE gui=NONE ctermfg=151 ctermbg=NONE cterm=NONE term=NONE +hi NonText guifg=#4a585c guibg=NONE guisp=NONE gui=NONE ctermfg=240 ctermbg=NONE cterm=NONE term=NONE +hi Operator guifg=#96b4aa guibg=NONE guisp=NONE gui=NONE ctermfg=109 ctermbg=NONE cterm=NONE term=NONE +hi Pmenu guifg=#adc9bc guibg=#262f33 guisp=NONE gui=NONE ctermfg=145 ctermbg=236 cterm=NONE term=reverse +hi PmenuBorder guifg=#6f8788 guibg=#262f33 guisp=NONE gui=NONE ctermfg=66 ctermbg=236 cterm=NONE term=NONE +hi PmenuExtra guifg=#839e9a guibg=#262f33 guisp=NONE gui=NONE ctermfg=246 ctermbg=236 cterm=NONE term=reverse +hi PmenuExtraSel guifg=#1e2528 guibg=#cbe3b3 guisp=NONE gui=NONE ctermfg=235 ctermbg=151 cterm=NONE term=NONE +hi PmenuKind guifg=#d2bdf3 guibg=#262f33 guisp=NONE gui=NONE ctermfg=183 ctermbg=236 cterm=NONE term=reverse +hi PmenuKindSel guifg=#1e2528 guibg=#cbe3b3 guisp=NONE gui=NONE ctermfg=235 ctermbg=151 cterm=NONE term=NONE +hi PmenuMatch guifg=#f7a182 guibg=#262f33 guisp=NONE gui=bold ctermfg=216 ctermbg=236 cterm=bold term=bold +hi PmenuMatchSel guifg=#1e2528 guibg=#cbe3b3 guisp=NONE gui=bold ctermfg=235 ctermbg=151 cterm=bold term=bold +hi PmenuSbar guifg=NONE guibg=#374145 guisp=NONE gui=NONE ctermfg=NONE ctermbg=238 cterm=NONE term=reverse +hi PmenuSel guifg=#1e2528 guibg=#cbe3b3 guisp=NONE gui=bold ctermfg=235 ctermbg=151 cterm=bold term=bold +hi PmenuShadow guifg=#6f8788 guibg=#171c1f guisp=NONE gui=NONE ctermfg=66 ctermbg=233 cterm=NONE term=NONE +hi PmenuThumb guifg=NONE guibg=#58686d guisp=NONE gui=NONE ctermfg=NONE ctermbg=241 cterm=NONE term=NONE +hi Popup guifg=#f8f9e8 guibg=#191e21 guisp=NONE gui=NONE ctermfg=255 ctermbg=234 cterm=NONE term=NONE +hi PopupBorder guifg=#6f8788 guibg=#191e21 guisp=NONE gui=NONE ctermfg=66 ctermbg=234 cterm=NONE term=NONE +hi PopupNotification guifg=#1e2528 guibg=#f5d098 guisp=NONE gui=NONE ctermfg=235 ctermbg=222 cterm=NONE term=NONE +hi PopupTitle guifg=#f8f9e8 guibg=#191e21 guisp=NONE gui=bold ctermfg=255 ctermbg=234 cterm=bold term=bold +hi PreProc guifg=#f3c0e5 guibg=NONE guisp=NONE gui=NONE ctermfg=218 ctermbg=NONE cterm=NONE term=NONE +hi Question guifg=#cbe3b3 guibg=NONE guisp=NONE gui=NONE ctermfg=151 ctermbg=NONE cterm=NONE term=standout +hi QuickFixLine guifg=NONE guibg=#374145 guisp=NONE gui=bold ctermfg=NONE ctermbg=238 cterm=bold term=bold +hi Removed guifg=#f57f82 guibg=NONE guisp=NONE gui=NONE ctermfg=210 ctermbg=NONE cterm=NONE term=NONE +hi Scrollbar guifg=#58686d guibg=#262f33 guisp=NONE gui=NONE ctermfg=241 ctermbg=236 cterm=NONE term=NONE +hi Search guifg=#1e2528 guibg=#f5d098 guisp=NONE gui=NONE ctermfg=235 ctermbg=222 cterm=NONE term=reverse +hi SignColumn guifg=#58686d guibg=#1e2528 guisp=NONE gui=NONE ctermfg=241 ctermbg=235 cterm=NONE term=reverse +hi Special guifg=#d2bdf3 guibg=NONE guisp=NONE gui=NONE ctermfg=183 ctermbg=NONE cterm=NONE term=NONE +hi SpecialComment guifg=#839e9a guibg=NONE guisp=NONE gui=italic ctermfg=246 ctermbg=NONE cterm=italic term=bold +hi SpecialKey guifg=#6f8788 guibg=NONE guisp=NONE gui=NONE ctermfg=66 ctermbg=NONE cterm=NONE term=bold +hi SpellBad guifg=NONE guibg=NONE guisp=#f57f82 gui=undercurl ctermfg=210 ctermbg=NONE cterm=underline term=underline +hi SpellCap guifg=NONE guibg=NONE guisp=#f5d098 gui=undercurl ctermfg=222 ctermbg=NONE cterm=underline term=underline +hi SpellLocal guifg=NONE guibg=NONE guisp=#b3e6db gui=undercurl ctermfg=152 ctermbg=NONE cterm=underline term=underline +hi SpellRare guifg=NONE guibg=NONE guisp=#d2bdf3 gui=undercurl ctermfg=183 ctermbg=NONE cterm=underline term=underline +hi Statement guifg=#b3e6db guibg=NONE guisp=NONE gui=NONE ctermfg=152 ctermbg=NONE cterm=NONE term=NONE +hi StatusLine guifg=#f8f9e8 guibg=#262f33 guisp=NONE gui=NONE ctermfg=255 ctermbg=236 cterm=NONE term=bold,reverse +hi StatusLineNC guifg=#6f8788 guibg=#191e21 guisp=NONE gui=NONE ctermfg=66 ctermbg=234 cterm=NONE term=bold,underline +hi StatusLineTerm guifg=#1e2528 guibg=#cbe3b3 guisp=NONE gui=bold ctermfg=235 ctermbg=151 cterm=bold term=bold,reverse +hi String guifg=#cbe3b3 guibg=NONE guisp=NONE gui=NONE ctermfg=151 ctermbg=NONE cterm=NONE term=NONE +hi TabLine guifg=#839e9a guibg=#191e21 guisp=NONE gui=NONE ctermfg=246 ctermbg=234 cterm=NONE term=bold,underline +hi TabLineFill guifg=NONE guibg=#171c1f guisp=NONE gui=NONE ctermfg=NONE ctermbg=233 cterm=NONE term=NONE +hi TabLineSel guifg=#1e2528 guibg=#cbe3b3 guisp=NONE gui=bold ctermfg=235 ctermbg=151 cterm=bold term=bold,reverse +hi Tag guifg=#b3e3ca guibg=NONE guisp=NONE gui=NONE ctermfg=158 ctermbg=NONE cterm=NONE term=NONE +hi Title guifg=#cbe3b3 guibg=NONE guisp=NONE gui=bold ctermfg=151 ctermbg=NONE cterm=bold term=bold +hi TitleBar guifg=#f8f9e8 guibg=#374145 guisp=NONE gui=NONE ctermfg=255 ctermbg=238 cterm=NONE term=NONE +hi TitleBarNC guifg=#6f8788 guibg=#262f33 guisp=NONE gui=NONE ctermfg=66 ctermbg=236 cterm=NONE term=NONE +hi Todo guifg=#1e2528 guibg=#f5d098 guisp=NONE gui=bold ctermfg=235 ctermbg=222 cterm=bold term=bold,reverse +hi ToolbarButton guifg=#f8f9e8 guibg=#374145 guisp=NONE gui=bold ctermfg=255 ctermbg=238 cterm=bold term=bold,reverse +hi ToolbarLine guifg=NONE guibg=#262f33 guisp=NONE gui=NONE ctermfg=NONE ctermbg=236 cterm=NONE term=reverse +hi Tooltip guifg=#f8f9e8 guibg=#374145 guisp=NONE gui=NONE ctermfg=255 ctermbg=238 cterm=NONE term=NONE +hi Type guifg=#f5d098 guibg=NONE guisp=NONE gui=NONE ctermfg=222 ctermbg=NONE cterm=NONE term=NONE +hi Underlined guifg=#afd9e6 guibg=NONE guisp=NONE gui=underline ctermfg=153 ctermbg=NONE cterm=underline term=underline +hi VertSplit guifg=#374145 guibg=#1e2528 guisp=NONE gui=NONE ctermfg=238 ctermbg=235 cterm=NONE term=NONE +hi Visual guifg=NONE guibg=#374145 guisp=NONE gui=bold ctermfg=NONE ctermbg=238 cterm=bold term=reverse +hi VisualNOS guifg=NONE guibg=#374145 guisp=NONE gui=NONE ctermfg=NONE ctermbg=238 cterm=NONE term=reverse +hi WarningMsg guifg=#f5d098 guibg=NONE guisp=NONE gui=NONE ctermfg=222 ctermbg=NONE cterm=NONE term=standout +hi Whitespace guifg=#374145 guibg=NONE guisp=NONE gui=NONE ctermfg=238 ctermbg=NONE cterm=NONE term=NONE +hi WildMenu guifg=#1e2528 guibg=#b3e6db guisp=NONE gui=NONE ctermfg=235 ctermbg=152 cterm=NONE term=bold +hi debugBreakpoint guifg=#1e2528 guibg=#f57f82 guisp=NONE gui=bold ctermfg=235 ctermbg=210 cterm=bold term=bold +hi debugPC guifg=NONE guibg=#374145 guisp=NONE gui=NONE ctermfg=NONE ctermbg=238 cterm=NONE term=reverse +hi diffFile guifg=#b2caed guibg=NONE guisp=NONE gui=bold ctermfg=111 ctermbg=NONE cterm=bold term=bold +hi diffIndexLine guifg=#839e9a guibg=NONE guisp=NONE gui=NONE ctermfg=246 ctermbg=NONE cterm=NONE term=NONE +hi diffLine guifg=#d2bdf3 guibg=NONE guisp=NONE gui=NONE ctermfg=183 ctermbg=NONE cterm=NONE term=NONE +hi helpExample guifg=#dbe6af guibg=NONE guisp=NONE gui=NONE ctermfg=187 ctermbg=NONE cterm=NONE term=NONE +hi helpHyperTextJump guifg=#b2caed guibg=NONE guisp=NONE gui=underline ctermfg=111 ctermbg=NONE cterm=underline term=underline +hi htmlH1 guifg=#cbe3b3 guibg=NONE guisp=NONE gui=bold ctermfg=151 ctermbg=NONE cterm=bold term=bold +hi htmlH2 guifg=#b3e3ca guibg=NONE guisp=NONE gui=bold ctermfg=158 ctermbg=NONE cterm=bold term=bold +hi markdownCode guifg=#dbe6af guibg=NONE guisp=NONE gui=NONE ctermfg=187 ctermbg=NONE cterm=NONE term=NONE +hi markdownH3 guifg=#b3e6db guibg=NONE guisp=NONE gui=bold ctermfg=152 ctermbg=NONE cterm=bold term=bold +hi markdownLinkText guifg=#b2caed guibg=NONE guisp=NONE gui=NONE ctermfg=111 ctermbg=NONE cterm=NONE term=NONE +hi netrwClassify guifg=#6f8788 guibg=NONE guisp=NONE gui=NONE ctermfg=66 ctermbg=NONE cterm=NONE term=NONE +hi netrwDir guifg=#b2caed guibg=NONE guisp=NONE gui=bold ctermfg=111 ctermbg=NONE cterm=bold term=bold +hi netrwExe guifg=#cbe3b3 guibg=NONE guisp=NONE gui=NONE ctermfg=151 ctermbg=NONE cterm=NONE term=NONE +hi netrwMarkFile guifg=#1e2528 guibg=#f7a182 guisp=NONE gui=NONE ctermfg=235 ctermbg=216 cterm=NONE term=reverse +hi netrwSymLink guifg=#b3e6db guibg=NONE guisp=NONE gui=underline ctermfg=152 ctermbg=NONE cterm=underline term=underline +hi netrwTreeBar guifg=#4a585c guibg=NONE guisp=NONE gui=NONE ctermfg=240 ctermbg=NONE cterm=NONE term=NONE +hi netrwVersion guifg=#f5d098 guibg=NONE guisp=NONE gui=NONE ctermfg=222 ctermbg=NONE cterm=NONE term=NONE + +" Options --------------------------------------------------------------- {{{ +if !get(g:, 'evergarden_italic', 1) + hi Comment gui=NONE cterm=NONE + hi SpecialComment gui=NONE cterm=NONE +endif + +if get(g:, 'evergarden_transparent', 0) + hi Normal guibg=NONE ctermbg=NONE + hi EndOfBuffer guibg=NONE ctermbg=NONE + hi FoldColumn guibg=NONE ctermbg=NONE + hi LineNr guibg=NONE ctermbg=NONE + hi SignColumn guibg=NONE ctermbg=NONE + hi VertSplit guibg=NONE ctermbg=NONE +endif + +if exists('g:evergarden_keyword') + let s:hues = {'red': ['#f57f82', 210], 'orange': ['#f7a182', 216], + \ 'yellow': ['#f5d098', 222], 'lime': ['#dbe6af', 187], + \ 'green': ['#cbe3b3', 151], 'aqua': ['#b3e3ca', 158], + \ 'skye': ['#b3e6db', 152], 'snow': ['#afd9e6', 153], + \ 'blue': ['#b2caed', 111], 'purple': ['#d2bdf3', 183], + \ 'pink': ['#f3c0e5', 218], 'cherry': ['#fae6ef', 255], + \ 'text': ['#f8f9e8', 255], 'subtext1': ['#adc9bc', 145], + \ 'subtext0': ['#96b4aa', 109]} + if has_key(s:hues, g:evergarden_keyword) + let s:kw = s:hues[g:evergarden_keyword] + execute 'hi Statement guifg=' . s:kw[0] . ' ctermfg=' . s:kw[1] + unlet s:kw + endif + unlet s:hues +endif +" }}} + +if s:tgc || s:t_Co >= 256 + finish +endif + +" 16- and 8-colour terminals are out of scope (see the spec): +" the 256-colour attributes above are left in place. +if s:t_Co >= 8 + finish +endif + +" Monochrome terminals: groups that are defined only by a link +" still need their own term attributes. +if s:t_Co >= 0 + hi CursorLineFold term=underline + hi CursorLineSign term=underline + hi StatusLineTermNC term=bold,underline + hi Terminal term=NONE + finish +endif + +" vim: et ts=8 sw=2 sts=2 diff --git a/evergarden/install.sh b/evergarden/install.sh new file mode 100755 index 0000000..9ec9556 --- /dev/null +++ b/evergarden/install.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# install.sh -- install / uninstall the evergarden colorscheme +# +# ./install.sh [install|uninstall|status] +# +# Copies colors/evergarden.vim into ~/.vim/colors on every platform. +# Uses copies (not symlinks) for Windows compatibility. +# POSIX sh only: runs under dash, ash/busybox, ksh, bash. + +set -eu + +DIR=$(CDPATH= cd "$(dirname "$0")" && pwd) +SRC="$DIR/colors/evergarden.vim" +NAME="evergarden.vim" + +die() { printf 'error: %s\n' "$1" >&2; exit 1; } + +# Newline-separated list of target directories. +targets() { + printf '%s/.vim/colors\n' "$HOME" +} + +cmd_install() { + [ -f "$SRC" ] || die "missing $SRC" + targets | while IFS= read -r dir; do + [ -n "$dir" ] || continue + mkdir -p "$dir" + cp -f "$SRC" "$dir/$NAME" + printf 'installed %s\n' "$dir/$NAME" + done + printf '\nAdd to your vimrc:\n set runtimepath^=~/.vim\n colorscheme evergarden\n' +} + +cmd_uninstall() { + targets | while IFS= read -r dir; do + [ -n "$dir" ] || continue + if [ -f "$dir/$NAME" ]; then + rm -f "$dir/$NAME" + printf 'removed %s\n' "$dir/$NAME" + else + printf 'absent %s\n' "$dir/$NAME" + fi + done +} + +cmd_status() { + targets | while IFS= read -r dir; do + [ -n "$dir" ] || continue + if [ -f "$dir/$NAME" ]; then + printf 'installed %s\n' "$dir/$NAME" + else + printf 'missing %s\n' "$dir/$NAME" + fi + done +} + +case "${1:-install}" in + install) cmd_install ;; + uninstall) cmd_uninstall ;; + status) cmd_status ;; + -h|--help|help) + sed -n '2,6p' "$0" | sed 's/^# \{0,1\}//' + ;; + *) die "unknown command: $1 (expected install|uninstall|status)" ;; +esac diff --git a/evergarden/test/diff_a.txt b/evergarden/test/diff_a.txt new file mode 100644 index 0000000..99cdcd8 --- /dev/null +++ b/evergarden/test/diff_a.txt @@ -0,0 +1,8 @@ +context line one +context line two +this line is CHANGED on the left +this line only exists on the left +context line three +shared tail A +shared tail B +context line four diff --git a/evergarden/test/diff_b.txt b/evergarden/test/diff_b.txt new file mode 100644 index 0000000..80c2ac1 --- /dev/null +++ b/evergarden/test/diff_b.txt @@ -0,0 +1,8 @@ +context line one +context line two +this line is different on the right +context line three +shared tail A +shared tail B +this line only exists on the right +context line four diff --git a/evergarden/test/run.sh b/evergarden/test/run.sh new file mode 100755 index 0000000..ebbba3c --- /dev/null +++ b/evergarden/test/run.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# run.sh -- preview evergarden without installing it +# +# ./test/run.sh # true colour (termguicolors) +# ./test/run.sh 256 # 256-colour cterm fallback +# +# All Vim setup lives in test/vimrc (Vim allows at most 10 "-c" arguments). +# POSIX sh only: runs under dash, ash/busybox, ksh, bash. +# +# Tab 1: syntax/hitest.vim -- every highlight group in its own colours +# Tab 2: sample.c -- syntax in context +# Tab 3: sample.vim +# Tab 4: sample.md -- spell on, to show SpellBad +# Tab 5: live diff -- DiffAdd / DiffChange / DiffDelete / DiffText + +set -eu + +DIR=$(CDPATH= cd "$(dirname "$0")" && pwd) + +if [ "${1:-}" = "256" ]; then + EVERGARDEN_TEST_256=1 + export EVERGARDEN_TEST_256 +fi + +exec vim -N -u "$DIR/vimrc" diff --git a/evergarden/test/sample.c b/evergarden/test/sample.c new file mode 100644 index 0000000..36ea3f8 --- /dev/null +++ b/evergarden/test/sample.c @@ -0,0 +1,55 @@ +/* sample.c -- exercises Comment, PreProc, Type, Statement, Constant, String, + * Number, Special, Operator, Delimiter, Todo. + * TODO: this comment should stand out. FIXME too. XXX as well. + */ +#include +#include +#define MAX_ITEMS 64 +#define SQUARE(x) ((x) * (x)) + +typedef enum { ST_IDLE, ST_BUSY, ST_DONE } state_t; + +typedef struct { + const char *name; + unsigned id; + double weight; + state_t state; +} item_t; + +static const char *STATES[] = { "idle", "busy", "done" }; + +/* A function with every constant flavour. */ +int main(int argc, char **argv) +{ + static item_t items[MAX_ITEMS]; + int count = 0; + unsigned mask = 0xDEADBEEF; + double ratio = 1.618e-3; + char tab = '\t'; + _Bool ready = 1; + + if (argc < 2 || argv == NULL) { + fprintf(stderr, "usage: %s \tescape: \\n \"quoted\"\n", argv[0]); + return EXIT_FAILURE; + } + + for (int i = 0; i < MAX_ITEMS && ready; ++i) { + items[i].name = STATES[i % 3]; + items[i].id = (unsigned)i ^ mask; + items[i].weight = ratio * SQUARE(i); + items[i].state = (i & 1) ? ST_BUSY : ST_IDLE; + count++; + } + + switch (items[0].state) { + case ST_IDLE: puts("idle"); break; + case ST_BUSY: puts("busy"); break; + default: goto done; + } + +done: + while (count-- > 0 && tab != '\0') + continue; + + return EXIT_SUCCESS; +} diff --git a/evergarden/test/sample.md b/evergarden/test/sample.md new file mode 100644 index 0000000..c9bebb3 --- /dev/null +++ b/evergarden/test/sample.md @@ -0,0 +1,38 @@ +# evergarden sample + +Headings, `inline code`, **bold**, *italic*, links, lists, and a fenced block. +This paragraph contains a deliberatly misspelled word so `SpellBad` shows up, +plus anuther one for good measure. + +## Second level + +Third paragraph with a [link text](https://evergarden.moe) and a bare URL: +https://evergarden.moe + +### Third level + +- list item one +- list item two with `code` +- [ ] unchecked task +- [x] checked task + +1. ordered one +2. ordered two + +> A blockquote, for the Comment-adjacent colour. + +```c +/* fenced code block */ +int main(void) { return 0; } +``` + +| column | value | +|---|---| +| red | `#f57f82` | +| green | `#cbe3b3` | +| blue | `#b2caed` | + +--- + +Trailing whitespace and a tab are on the next line (`:set list`): + trailing diff --git a/evergarden/test/sample.vim b/evergarden/test/sample.vim new file mode 100644 index 0000000..95b6e40 --- /dev/null +++ b/evergarden/test/sample.vim @@ -0,0 +1,45 @@ +" sample.vim -- vimscript highlighting sample +" TODO: keywords, options, registers, autocommands, functions. + +set nocompatible +set expandtab shiftwidth=4 softtabstop=4 +setlocal listchars=tab:>-,trail:~,nbsp:+ + +let s:name = 'evergarden' +let s:count = 42 +let s:ratio = 0.618 +let s:list = ['red', 'green', 'blue'] +let s:dict = {'fg': '#f8f9e8', 'bg': '#1e2528'} +let g:pattern = '\v^\s*(let|call)\s+' + +function! s:Greet(who, ...) abort + if a:0 > 0 && !empty(a:1) + echomsg printf('hello %s (%d extra)', a:who, a:0) + elseif a:who ==# 'world' + echohl WarningMsg | echo 'generic greeting' | echohl NONE + else + for l:item in s:list + echo l:item . ' => ' . get(s:dict, 'fg', 'NONE') + endfor + endif + return v:true +endfunction + +command! -nargs=? -bang Greet call s:Greet() + +augroup evergarden_sample + autocmd! + autocmd BufWritePre *.vim silent! %s/\s\+$//e + autocmd ColorScheme * echomsg 'colorscheme: ' . g:colors_name +augroup END + +nnoremap g :Greet +inoremap pumvisible() ? "\" : "\" + +try + call s:Greet('world', 1) +catch /^Vim\%((\a\+)\)\=:E/ + echoerr 'failed: ' . v:exception +finally + unlet! s:count +endtry diff --git a/evergarden/test/vimrc b/evergarden/test/vimrc new file mode 100644 index 0000000..f5e59d4 --- /dev/null +++ b/evergarden/test/vimrc @@ -0,0 +1,73 @@ +" test/vimrc -- preview evergarden without installing it. +" +" Loaded by test/run.sh, or by hand: +" +" vim -N -u evergarden/test/vimrc +" +" Set EVERGARDEN_TEST_256=1 in the environment for the cterm fallback. +" Set EVERGARDEN_KEYWORD=blue (or any palette name) to try a keyword hue. +" Inside the preview, :Kw swaps the keyword hue live. + +set nocompatible + +" Repository paths, derived from this file -- cwd does not matter. +let s:test = expand(':p:h') +let s:root = fnamemodify(s:test, ':h') +execute 'set runtimepath^=' . fnameescape(s:root) + +syntax on +filetype plugin indent on + +set background=dark +if empty($EVERGARDEN_TEST_256) + set termguicolors +else + set notermguicolors + set t_Co=256 +endif + +" Options here so the preview exercises the UI groups too. +set number cursorline laststatus=2 showtabline=2 list +set listchars=tab:>-,trail:~,nbsp:+ +set fillchars=vert:\|,fold:- +set nowrap + +if !empty($EVERGARDEN_KEYWORD) + let g:evergarden_keyword = $EVERGARDEN_KEYWORD +endif + +colorscheme evergarden + +" :Kw -- swap the keyword hue and reload, for auditioning. +let s:hues = ['skye', 'aqua', 'blue', 'snow', 'green', 'lime', 'orange', + \ 'yellow', 'purple', 'pink', 'red', 'cherry', 'subtext1'] + +function! s:KwComplete(A, L, P) abort + return filter(copy(s:hues), 'v:val =~# "^" . a:A') +endfunction + +function! s:Kw(name) abort + let g:evergarden_keyword = a:name + colorscheme evergarden + redraw + echo 'keyword hue: ' . a:name +endfunction + +command! -nargs=1 -complete=customlist,s:KwComplete Kw call s:Kw() + +" Tab 1: Vim's own dump of every defined highlight group. +runtime syntax/hitest.vim + +" Tabs 2-5: syntax in context, spell, and a live diff. +execute 'tabnew ' . fnameescape(s:test . '/sample.c') +execute 'tabnew ' . fnameescape(s:test . '/sample.vim') +execute 'tabnew ' . fnameescape(s:test . '/sample.md') +setlocal spell spelllang=en +execute 'tabnew ' . fnameescape(s:test . '/diff_a.txt') +execute 'vertical diffsplit ' . fnameescape(s:test . '/diff_b.txt') +tabfirst + +" :runtime syntax/colortest.vim -- the raw cterm colour grid +redraw +echo 'evergarden preview | gt/gT tabs | :Kw to retint keywords | :qa' + \ . ' | termguicolors=' . (&termguicolors ? 'on' : 'off') diff --git a/specs/010-evergarden-colorscheme/spec.md b/specs/010-evergarden-colorscheme/spec.md new file mode 100644 index 0000000..f283240 --- /dev/null +++ b/specs/010-evergarden-colorscheme/spec.md @@ -0,0 +1,226 @@ +# evergarden Vim Colorscheme Specification + +## Overview + +A Vim colorscheme that ports the [evergarden](https://evergarden.moe) palette — +a forest-toned dark scheme inspired by *The Legend of Zelda: The Minish Cap* — +into a single self-contained Vimscript file for **classic Vim only**. + +## Status + +- **Status**: Implemented ✅ +- **Created**: 2026-02-14 +- **Branch**: `feat/010-evergarden-colorscheme` + +## Background + +`curl -L evergarden.moe` serves the palette as ANSI-coloured plain text. The +upstream project ships a Lua-only Neovim plugin, which is useless to a classic +Vim user. This repository needs a dependency-free Vimscript variant that works +in Vim 8+, both GUI and 256-colour terminals. + +## Goals + +- Reproduce the upstream palette exactly (24 named colours). +- Single file, no plugin manager, no Lua, no runtime dependencies. +- Work in Vim 8.0+, GUI and terminal. +- Degrade gracefully to xterm-256 approximations when `termguicolors` is off. +- Cover every group in `:help highlight-groups`, plus diffs, spell, netrw, + popup/toolbar, and `termdebug`. +- Ship an installer that is symmetric: install and uninstall. + +## Non-Goals + +- **Neovim.** No Lua module, no `@*` Tree-sitter captures, no `Diagnostic*` or + `Lsp*` groups, no `NormalNC`/`Winbar`/`MsgArea`/`WinSeparator`. Tree-sitter + capture names are not even legal group names in Vim (`W18: Invalid character + in group name`). +- Light variant (upstream publishes the dark palette only). +- Third-party plugin groups. +- 16-colour terminal support. + +## Palette + +Verbatim from `evergarden.moe`, with the xterm-256 fallback chosen by nearest +sRGB distance and then hand-adjusted so adjacent hues stay distinguishable. + +| Name | Hex | cterm | +|---|---|---| +| red | `#f57f82` | 210 | +| orange | `#f7a182` | 216 | +| yellow | `#f5d098` | 222 | +| lime | `#dbe6af` | 187 | +| green | `#cbe3b3` | 151 | +| aqua | `#b3e3ca` | 158 | +| skye | `#b3e6db` | 152 | +| snow | `#afd9e6` | 153 | +| blue | `#b2caed` | 111 | +| purple | `#d2bdf3` | 183 | +| pink | `#f3c0e5` | 218 | +| cherry | `#fae6ef` | 255 | +| text | `#f8f9e8` | 255 | +| subtext1 | `#adc9bc` | 145 | +| subtext0 | `#96b4aa` | 109 | +| overlay2 | `#839e9a` | 246 | +| overlay1 | `#6f8788` | 66 | +| overlay0 | `#58686d` | 241 | +| surface2 | `#4a585c` | 240 | +| surface1 | `#374145` | 238 | +| surface0 | `#262f33` | 236 | +| base | `#1e2528` | 235 | +| mantle | `#191e21` | 234 | +| crust | `#171c1f` | 233 | + +## Semantic Mapping + +| Role | Colour | +|---|---| +| Normal text | text on base | +| Comment | overlay1, italic | +| Keyword / Statement / Conditional / Repeat / Label | `g:evergarden_keyword`, default skye | +| Function | blue | +| String | green | +| Constant / Number / Boolean | orange | +| Type / StorageClass | yellow | +| PreProc / Macro / Include | pink | +| Operator | subtext0 | +| Delimiter | overlay2 | +| Special / SpecialChar | purple | +| Tag | aqua | +| Identifier / Variable | subtext1 | +| Error / Exception | red | + +### Keyword hue + +Control-flow keywords are the most repeated token on screen, so the hue is a +single option rather than a hard-coded choice. The first draft used purple, +which read as too loud against the green/orange of strings and literals. The +default is now skye (`#b3e6db`): cool, recessive, and distinct from blue +`Function` and green `String`. + +`g:evergarden_keyword` accepts any palette name and falls back to skye if the +name is unknown, so a typo cannot produce an unreadable buffer. Operators moved +to subtext0 and delimiters to overlay2 to keep punctuation from competing; +Special/SpecialChar inherited purple so the hue is still present, but rarely. + +`test/vimrc` exposes `:Kw ` (with completion) and `$EVERGARDEN_KEYWORD` +for auditioning without editing the scheme. + +## Design + +### Structure + +``` +evergarden/ + colors/evergarden.vim # the colorscheme + install.sh # install / uninstall / status + test/run.sh # preview harness (no install required) + test/sample.{c,vim,md} # in-context syntax samples + test/diff_{a,b}.txt # diff-mode fixture + README.md +``` +`colors/evergarden.vim` follows the layout of the colorschemes shipped with +Vim (`$VIMRUNTIME/colors`, Colortemplate output), so it reads like a member of +that family: + +1. Header block: `Name`, `Description`, `Author`, `Maintainer`, `URL`, + `License`, `Last Change`, then the options. +2. `set background=dark`, `hi clear`, `let g:colors_name`. +3. `s:t_Co` / `s:tgc` capability variables. +4. `g:terminal_ansi_colors`. +5. Alphabetical `hi! link` block for every group that is a synonym of another. +6. One flat `hi` line per group — `Normal` first, then alphabetical — each + spelling out `guifg guibg guisp gui ctermfg ctermbg cterm term`. No helper + function, no dictionary lookups, no `execute`: the file is a plain list of + `:highlight` commands and is safe to re-source. +7. Option overrides (italic / transparent / keyword hue) as a small block of + partial `hi` commands that amend the groups above. +8. Capability tiers ending in `finish`, as in the distribution schemes: + true colour or 256 colours use the block above; 16- and 8-colour terminals + are out of scope and keep those attributes; monochrome terminals get `term` + attributes for the groups that exist only as links. + +`NONE` is used for absent attributes so re-sourcing cannot leave stale colours. + +### Italics + +Comments and special comments use italics, gated behind `g:evergarden_italic` +(default `1`). Terminals without italic support render them upright; no +fallback logic is needed. + +### Transparency + +`g:evergarden_transparent` (default `0`) clears the background of `Normal`, +`SignColumn`, `EndOfBuffer`, `LineNr`, `FoldColumn`, and `VertSplit` so the +terminal's own background shows through. `Terminal` links to `Normal` and +follows automatically. + +### Vim only + +The group list is taken from `:help highlight-groups`. Neovim-only names are +omitted entirely: `@*` captures raise `W18` in Vim, and `Diagnostic*`, `Lsp*`, +`NormalNC`, `NormalFloat`, `FloatBorder`, `MsgArea`, `Winbar`, `WinSeparator`, +`Substitute` are dead weight. Vim-specific groups are included instead: +`LineNrAbove`/`LineNrBelow`, `PmenuMatch`/`PmenuMatchSel`, `StatusLineTerm`, +`Terminal`, `Popup`/`PopupSelected`/`PopupNotification`, `MessageWindow`, +`ToolbarLine`/`ToolbarButton`, `Menu`/`Scrollbar`/`Tooltip`, `debugPC`, +`debugBreakpoint`, plus the newer groups used by the distribution schemes: +`Added`/`Changed`/`Removed`, `PmenuBorder`/`PmenuShadow`, +`PopupBorder`/`PopupTitle`, `TitleBar`/`TitleBarNC`, `VertSplitNC`, +`CursorLineFold`/`CursorLineSign`, `TabPanel`/`TabPanelFill`, `PreInsert`. + +### Terminal Colours + +`g:terminal_ansi_colors` is set from the palette (guarded by `has('terminal')`) +so `:terminal` buffers match. + +### Installation + +`install.sh` copies (not symlinks — Windows-friendly) the colorscheme into +`$HOME/.vim/colors/` on every platform, creating it when absent. This is the +only target: never create or modify `~/vimfiles`, even if it already exists. +All subcommands use the same target; uninstall removes only the colorscheme +file and leaves directories and unrelated files intact. + +Vim's `runtimepath` must contain `~/.vim`, not its `colors` subdirectory. +Native Windows Vim does not include this root by default, so the installer +prints `set runtimepath^=~/.vim` before `colorscheme evergarden` in its vimrc +instructions. It does not edit the user's vimrc. A different Vim home requires +manual installation into a runtime root visible to that Vim. + +Subcommands: `install` (default), `uninstall`, `status`. + +## Testing + +Visual verification uses Vim's own runtime files rather than a bespoke +preview: `syntax/hitest.vim` renders every defined group in its own colours, +and `syntax/colortest.vim` renders the cterm grid. `test/run.sh` wires those +together with in-context samples, loading the scheme via `set rtp+=.` so +nothing has to be installed. + +| Case | Expectation | +|---|---| +| `install.sh install`, fresh home | File present only in `~/.vim/colors`; no `~/vimfiles` created | +| `install.sh install`, existing `~/.vim` | File present in `~/.vim/colors` | +| Existing `~/vimfiles/colors/evergarden.vim` | Install, status, and uninstall ignore it and leave it untouched | +| Home path containing spaces | Install, status, and uninstall all succeed | +| Native Vim, installed into a temporary home | With documented `set runtimepath^=~/.vim`, discovery, colorscheme completion, and `:colorscheme evergarden` work | +| Native Vim after uninstall | File no longer discoverable; completion no longer lists it | +| `install.sh status` | Reports installed/missing only for `~/.vim/colors/evergarden.vim`, without creating directories | +| `install.sh uninstall` | Files removed; empty `colors/` dirs left in place | +| Re-run `install.sh install` | Idempotent overwrite, exit 0 | +| `test/run.sh` | Five tabs, no errors, all groups legible | +| `test/run.sh 256` | Same, via cterm fallback | +| `:Kw ` in the preview | Keyword hue changes, no errors | +| `let g:evergarden_keyword = 'bogus'` | Silently falls back to skye | +| `vim -Nu NONE -c 'set runtimepath^=~/.vim' -c 'set tgc' -c 'colo evergarden' -c q` | Exits 0, no errors | +| `:colorscheme evergarden` twice | No `E` errors (re-sourcing is safe) | +| `:source $VIMRUNTIME/colors/tools/check_colors.vim` | Same report as the bundled schemes | +| Plain Vim 8, `:colorscheme evergarden` | No `W18` warnings | +| Vim without `+terminal` | No error from the `g:terminal_ansi_colors` block | +| `&t_Co == 256`, no termguicolors | cterm attributes applied | + +## References + +- +- `:help highlight-groups`, `:help group-name`