r/vim • • 9d ago

Plugin python-syntax-enhanced: Python syntax for Vim that highlights type annotations

Vim's built-in Python syntax doesn't treat annotations differently from other code. In def get(key: str) -> User | None, str gets the same color as a str(x) call, and ->, User and | aren't highlighted at all. I write a lot of typed Python and wanted the types to stand out, so I made a replacement syntax/python.vim that colors types only where they're actually types:

  • parameter and return annotations, x: T and self.attr: T, class bases, and PEP 695 def f[T] / type X = ...
  • list(...) in code stays a builtin, | outside a type is still bitwise or, and key: value in a multi-line dict isn't treated as an annotation
  • # type: comments, docstrings after wrapped signatures, match/case, except*

By default every group links to a standard one (Type, Operator, ...), so your colorscheme picks the colors; the screenshots use retrobox. The second image shows the optional palette (let g:python_enhanced_colors = 1).

Install with Plug 'aaronbcarlisle/python-syntax-enhanced', any other plugin manager, or pack/*/start. It replaces the built-in syntax file (it started from Vim's own python.vim, credited in AUTHORS), so you'll need to disable other Python syntax plugins.

Limitations: types are found by position, not analysis, so any name inside an annotation gets the type color. It's also slower: highlighting a whole file from scratch takes about twice as long as the built-in syntax (measured on an 11k-line file). While you edit, Vim only highlights what's on screen, so I haven't noticed it in practice, but it's next on my list. That said, if you have an 11k-line Python file, I probably have more questions for you than you have for me :p

On AI: I built this with a lot of help from Claude Code and Cursor, which you'll see in the commit history. I'm one of only a handful of Vim users at work, and when we moved to Python 3 and made type hints part of our coding standard, I couldn't find a Python syntax plugin that handled them. I didn't have the time to write it all by hand, so I worked back and forth "with the agents that be". I spent my own time on making sure it wasn't just a solution for my own setup: the highlighting is covered by 86 assertions that check the highlight group at specific positions, and CI runs them on Linux, macOS and Windows. We're on Python 3.11 at work (the VFX Reference Platform just moved to 3.13, I believe), so that's what it's seen the most real use on, but the 3.12 syntax is covered by the tests too.

The biggest headache with using AI was all the regressions along the way: fixes that weren't ideal and had side effects on how other things highlighted. A lot of the work on my end was testing scenarios that hadn't been considered, like taking a long list on a single line and splitting it across multiple lines, just to watch every item except the first one and the closing bracket change to a different color, or the whole file turning yellow when scrolling >.>

Overall, it was a nice quality-of-life win: AI did the building, so nobody asked why I wasn't staying on task (or worse, shamed me for not using an IDE). Hopefully others will find it useful too.

https://github.com/aaronbcarlisle/python-syntax-enhanced. Bug reports with a code snippet are most welcome.

65 Upvotes

8 comments sorted by

7

u/gbrennon 9d ago

im happy to see someone else writing pep 695 compliant code

3

u/LloydBatair 9d ago edited 9d ago

Same! It feels like the generics and type alias syntax finally caught up with how Python is supposed to read. No more creating a TypeVar "bucket" up front just to use it once, and since type aliases are evaluated lazily, there's a lot less importing things under TYPE_CHECKING and then dressing them up as strings. It's kinda chef's kiss now; I honestly hated all the typing module boilerplate >.> lol

3

u/gbrennon 8d ago edited 8d ago

YEP!

i can see a interesting future for python 👌

pep 695 e awesome

2

u/LloydBatair 8d ago

2

u/gbrennon 8d ago

👌👌👌

2

u/Shay-Hill 5d ago

Waiting for 3.11 EOL, but that's the main thing I'm looking forward to sweeping through my libraries.

-6

u/No_Departure_1878 9d ago

Or you can move to neovim and use treesitter that is built natively there.

13

u/LloydBatair 9d ago

I could but I prefer vim, it always just works, even after all these years; there's never updates that break anything (kinda reminds me of MEL in Maya 😅). Also, I prefer vimscript over lua (most likely because it's what I'm used to).

That said, I'm sure I'm missing out on some really nice QoL features by not using Neovim. I'm just a little set in my ways :p