[vim/vim] Fix ANSI colors in terminal on Windows (PR #18931)

23 views
Skip to first unread message

MURAOKA Taro

unread,
Dec 15, 2025, 8:16:36 AM (yesterday) Dec 15
to vim/vim, Subscribed

Problem: ANSI escape colors are not displayed correctly in nontermguicolors in vim (cli) on Windows. The red and blue channels seem to be swapped.

A file used for testing: ansi.txt

Result image before applying this change:
image.png (view on web)
(Please ignore translated messages)

Result image after applying this change:
image.png (view on web)

Cause: When converting VTerm ANSI index colors to cterm colors in terminal.c, the Windows case equivalent to NR-16 (:help cterm-colors) is ignored.

Solution: Created and used a table to convert ANSI indexed colors to cterm's NR-16 representation (Windows only). This table corresponds to the inverse conversion of cterm_ansi_idx in term.c. The values in both tables are exactly the same, but the meanings are opposite, so they are separate tables.


You can view, comment on, or merge this pull request online at:

  https://github.com/vim/vim/pull/18931

Commit Summary

  • 338d664 Fix ANSI colors in terminal on Windows

File Changes

(1 file)

Patch Links:


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931@github.com>

h_east

unread,
Dec 15, 2025, 8:28:06 AM (yesterday) Dec 15
to vim/vim, Subscribed

@h-east commented on this pull request.


In src/terminal.c:

> +	    if (index < 16) {
+		index = ansi_to_cterm_nr16[index];
+	    }

There are coding style issue.

⬇️ Suggested change
-	    if (index < 16) {
-		index = ansi_to_cterm_nr16[index];
-	    }
+	    if (index < 16)
+		index = ansi_to_cterm_nr16[index];


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/review/3578189842@github.com>

MURAOKA Taro

unread,
Dec 15, 2025, 11:34:32 AM (yesterday) Dec 15
to vim/vim, Push

@koron pushed 1 commit.


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/before/338d664dac7a3207ccbd466a8fe5833a4b658681/after/f136762cfbf12a4d9e2214f7b4d9509c6872dd29@github.com>

MURAOKA Taro

unread,
Dec 15, 2025, 11:34:47 AM (yesterday) Dec 15
to vim/vim, Subscribed

@koron commented on this pull request.


In src/terminal.c:

> +	    if (index < 16) {
+		index = ansi_to_cterm_nr16[index];
+	    }

Thank you @h-east 👍


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/review/3579122274@github.com>

Christian Brabandt

unread,
Dec 15, 2025, 1:41:24 PM (yesterday) Dec 15
to vim/vim, Subscribed

@chrisbra commented on this pull request.


In src/terminal.c:

> @@ -3013,6 +3013,12 @@ may_toggle_cursor(term_T *term)
 	cursor_off();
 }
 
+#ifdef MSWIN
+static const uint8_t ansi_to_cterm_nr16[] = {
+    0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15
+};
+#endif

We have similar logic already in term.c, search for cterm_ansi_idx


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/review/3579624343@github.com>

Christian Brabandt

unread,
Dec 15, 2025, 1:42:11 PM (yesterday) Dec 15
to vim/vim, Subscribed
chrisbra left a comment (vim/vim#18931)

Thanks, but please don't duplicate code. Is it also possible to create a test for this?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3657071059@github.com>

MURAOKA Taro

unread,
Dec 15, 2025, 10:08:33 PM (20 hours ago) Dec 15
to vim/vim, Push

@koron pushed 3 commits.

  • 148db6d Fix ANSI colors in terminal on Windows
  • 33c3d10 Fix coding styles
  • cff8223 make cterm_ansi_idx public, and remove a duplicated table

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/before/f136762cfbf12a4d9e2214f7b4d9509c6872dd29/after/cff82234cc42fcacbd869d5db38b0c16be3adfa5@github.com>

MURAOKA Taro

unread,
Dec 15, 2025, 10:22:16 PM (20 hours ago) Dec 15
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

please don't duplicate code.

Fixed in cff8223

Is it also possible to create a test for this?

No. That's not possible for now.

Because to write tests for this change, we need to access cterm_attr_table (and `attrentry_T.ae_u.cterm in it) in src/highlight.c, but there are no ways to access it from Vim script.
Such a built-in function can be written, but since it will be a public function, it will require time to discuss the specifications.

Do you think it's worth creating such a built-in function for this PR?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3658555608@github.com>

h_east

unread,
1:30 AM (16 hours ago) 1:30 AM
to vim/vim, Subscribed
h-east left a comment (vim/vim#18931)

Wouldn’t you use screen dumps? Try searching for these keywords in vim/src/testdir/:

  • CheckScreendump
  • RunVimInTerminal
  • VerifyScreenDump


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3659035847@github.com>

zeertzjq

unread,
1:35 AM (16 hours ago) 1:35 AM
to vim/vim, Subscribed
zeertzjq left a comment (vim/vim#18931)

CheckScreendump shouldn't be used. It'll skip the test on Windows.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3659047141@github.com>

Christian Brabandt

unread,
4:21 AM (14 hours ago) 4:21 AM
to vim/vim, Subscribed
chrisbra left a comment (vim/vim#18931)

And what about using term_scrape() and testing for the returned fg attributes? Would this work? Or perhaps a hex dump including the ansi color attributes that we could use?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3659570933@github.com>

MURAOKA Taro

unread,
8:32 AM (9 hours ago) 8:32 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

Wouldn’t you use screen dumps?

And what about using term_scrape() and testing for the returned fg attributes?

Yes, of course I tried it.

These output the internal state of VTerm. However, the problem in this case is converting from VTerm to cterm. To test this, we need to know the internal state of cterm after conversion.

The internal state of VTerm was normal before the conversion. Therefore, these functions cannot work for testing.

The following sentence I wrote previously means that there is no way to obtain the internal state of this cterm in Vim script.

Because to write tests for this change, we need to access cterm_attr_table (and `attrentry_T.ae_u.cterm in it) in src/highlight.c, but there are no ways to access it from Vim script.


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3660536438@github.com>

MURAOKA Taro

unread,
8:35 AM (9 hours ago) 8:35 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

A screen dump can capture the attr (number), but it does not provide access to the actual detailed data (attrentry_T.ae_u.cterm). Therefore, it could not be used in this case.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3660548355@github.com>

MURAOKA Taro

unread,
8:52 AM (9 hours ago) 8:52 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

RunVimInTerminal

I hadn't tried this before, so I gave it a go.
Interestingly, the correct colors were displayed in a Vim terminal launched inside a Vim terminal.
This means that converting twice restores the correct value.

This approach is interesting, so I'll play around with it a bit more, but thinking that the real problem is happening in cterm , don't get your hopes up.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3660622425@github.com>

MURAOKA Taro

unread,
9:09 AM (9 hours ago) 9:09 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

But shouldn't I use RunVimInTerminal on Windows?
There seems to be a rule that you must use CheckRunVimInTerminal before using RunVimInTerminal.
And CheckRunVimInTerminal says "Skipped: cannot run Vim in a terminal window on Windows".


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3660721598@github.com>

zeertzjq

unread,
9:56 AM (8 hours ago) 9:56 AM
to vim/vim, Subscribed
zeertzjq left a comment (vim/vim#18931)

Hmm, then just use term_start() directly.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3660965381@github.com>

MURAOKA Taro

unread,
11:11 AM (7 hours ago) 11:11 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

I wrote a script like this. Maybe I can write a test.

func Test_ansi_color()
  let lines = [
        \ 'call term_start("cmd /C type ansi.txt")'
        \ ]
  call writefile(lines, 'XloadANSI', 'D')

  let cmd = GetVimCommandCleanTerm()
  "let options = #{curwin: 1}
  let buf = term_start(cmd .. '-S XloadANSI')
  sleep 500m
  let data = term_scrape(buf, 1)
  call assert_equal('#e00000', data[5]['bg'])
endfunc


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3661314817@github.com>

MURAOKA Taro

unread,
11:47 AM (6 hours ago) 11:47 AM
to vim/vim, Push

@koron pushed 1 commit.

  • c65664d Add test for ANSI color in terminal

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/before/cff82234cc42fcacbd869d5db38b0c16be3adfa5/after/c65664d32d3ab9777368ab0993adf4640661a7fe@github.com>

MURAOKA Taro

unread,
11:55 AM (6 hours ago) 11:55 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

I added a test for Windows non-GUI specific in c65664d

Thanks @h-east @zeertzjq @chrisbra


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3661500294@github.com>

MURAOKA Taro

unread,
11:58 AM (6 hours ago) 11:58 AM
to vim/vim, Subscribed
koron left a comment (vim/vim#18931)

Hmm the last color is different...

https://github.com/vim/vim/actions/runs/20275732854/job/58223772179?pr=18931#step:12:11591


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/c3661512246@github.com>

MURAOKA Taro

unread,
12:04 PM (6 hours ago) 12:04 PM
to vim/vim, Push

@koron pushed 1 commit.

  • 8153a36 Add test for ANSI color in terminal

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/18931/before/c65664d32d3ab9777368ab0993adf4640661a7fe/after/8153a3693dded4f7f17b195099151b84cd22dde3@github.com>

Reply all
Reply to author
Forward
0 new messages