Skip to content

Title: viewer: add ANSI SGR color rendering#47

Merged
ilia-maslakov merged 7 commits into
masterfrom
DEV_ascii_highlight
Apr 12, 2026
Merged

Title: viewer: add ANSI SGR color rendering#47
ilia-maslakov merged 7 commits into
masterfrom
DEV_ascii_highlight

Conversation

@ilia-maslakov

@ilia-maslakov ilia-maslakov commented Apr 12, 2026

Copy link
Copy Markdown
Owner

Auto summary

Commits: 7
Files changed: 18

Commit messages

  • mcviewer (ansi.c): add ANSI SGR escape sequence parser. (4c45cd9)
  • mcviewer (ascii.c): wire ANSI parser into text rendering pipeline. (67dc010)
  • mcviewer (ansi.c): harden SGR parser per review feedback. (07111db)
  • fix: remove duplicate tests/src/viewer/Makefile in configure.ac (cadc734)
  • viewer: add CK_AnsiMode toggle (Shift+F9) to activate ANSI color rendering (670887d)
  • ext.d: preserve procyon ANSI colors when viewing .class files (eae61d3)
  • viewer: preserve ANSI state across newlines in text renderer (0b552f7)

Changed files

added (3)

  • src/viewer/ansi.c
  • src/viewer/ansi.h
  • tests/src/viewer/ansi_parser.c

modified (15)

  • lib/keybind.c
  • lib/keybind.h
  • misc/ext.d/misc.sh.in
  • misc/mc.default.keymap
  • misc/mc.emacs.keymap
  • misc/mc.vim.keymap
  • src/viewer/Makefile.am
  • src/viewer/actions_cmd.c
  • src/viewer/ascii.c
  • src/viewer/display.c
  • src/viewer/internal.h
  • src/viewer/lib.c
  • src/viewer/mcviewer.c
  • src/viewer/mcviewer.h
  • tests/src/viewer/Makefile.am

This block is auto-generated. Edit outside this section.

Summary

Overview

This branch ports the ANSI color rendering work from MidnightCommander/mc#5065 (author: noctuum) into the local tree, adapting it for integration and adding the missing interactive toggle.

The original PR implements an ANSI SGR escape sequence parser and wires it into mc's internal viewer so that files containing ANSI color codes (log output, decompiled sources, colorized command output)
are displayed with proper foreground/background colors, bold, underline, italic, blink, and reverse attributes.

What is included

  • src/viewer/ansi.c / ansi.h -- stateful SGR parser supporting
    standard 8/16 colors, 256-color (38;5;n / 48;5;n), truecolor
    (38;2;r;g;b), and colon sub-separator notation (ITU T.416).
    Written by noctuum; adapted by Ilia Maslakov.

  • src/viewer/ascii.c -- ANSI rendering wired into the text display
    pipeline via mcview_get_next_maybe_nroff_char. ANSI state is
    now preserved across newlines (SGR attributes legally span lines).

  • CK_AnsiMode toggle bound to Shift+F9 -- enables/disables ANSI
    color rendering at runtime, consistent with the existing F8/F9
    MagicMode/NroffMode toggles.

  • misc/ext.d/misc.sh.in -- .class viewer now runs procyon inside
    a pseudo-TTY via script(1) so its native ANSI colors reach the
    viewer unchanged.

  • tests/src/viewer/ansi_parser.c -- 35 unit tests for the SGR
    parser covering standard colors, 256-color, truecolor, colon
    notation, attribute on/off codes, incomplete escapes, and newline
    state persistence.

What is NOT included

The external syntax-highlight command backend from the original PR
was intentionally left out; this branch focuses solely on ANSI
escape sequence rendering.

How to test

  1. Open any file containing ANSI codes in the viewer (F3).
  2. Press Shift+F9 to toggle ANSI mode on.
  3. For .class files: F3 + Shift+F9 renders procyon's color output.

noctuum and others added 6 commits April 12, 2026 14:14
Add a state machine parser for ANSI SGR (Select Graphic Rendition)
escape sequences.  Supports standard colors (0-7), bright (8-15),
256-color (38;5;N / 48;5;N), and truecolor (38;2;R;G;B / 48;2;R;G;B)
which is approximated to the nearest xterm 256-color palette index.
Bold, underline, italic, and individual/global resets are handled.

Includes 23 unit tests covering color parsing, attribute tracking,
truecolor approximation, escape sequence edge cases, and combined
sequences.

Signed-off-by: noctuum <25441068+noctuum@users.noreply.github.com>
Integrate the ANSI SGR parser into mcview's text display pipeline.
When syntax mode is active, bytes are fed through the parser and
ANSI escape sequences are consumed while displayable characters
are rendered with the appropriate colors.

Key additions:
- mcview_ansi_get_color(): maps ANSI parser state to MC color pairs,
  inheriting the viewer skin's fg/bg when ANSI values are default
  (fixes background mismatch with source-highlight)
- mcview_get_next_maybe_ansi_char(): new rendering layer between raw
  byte reading and nroff processing
- mcview_fill_line_remaining(): fills remaining columns on each line
  with spaces using the last drawn color, giving full-width background
- syntax_fill_color tracking across lines for consistent empty-line
  coloring

Signed-off-by: noctuum <25441068+noctuum@users.noreply.github.com>
Address reviewer feedback on the ANSI SGR parser:

Parser improvements:
- Add italic (3), blink (5), reverse (7) attribute support
- Add individual off codes: 23, 25, 27
- Map SGR 21 (double underline) to regular underline
- Fix empty parameter bug: \e[1;;3m now correctly treats
  empty param as 0 (reset)
- Add colon ':' sub-separator with proper nested semantics:
  \e[38:5:4:7m does NOT set reverse (all sub-params belong
  to the color group), while \e[38;5;4;7m correctly does
- Support de jure truecolor: \e[38:2:CS:R:G:Bm

Large file protection:
- Skip syntax highlighting for files > 2 MB to avoid long
  processing times from external highlighters

12 new tests (35 total for ANSI parser).

Signed-off-by: noctuum <25441068+noctuum@users.noreply.github.com>
Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
…ering

Add mcview_toggle_ansi_mode() and CK_AnsiMode key command (bound to
Shift+F9) to allow the user to enable or disable ANSI SGR color
rendering in the viewer.

The ANSI SGR parser and rendering pipeline were written by noctuum
as part of MidnightCommander/mc PR #5065.  This commit wires the
toggle mechanism so the feature is accessible at runtime.

Adapted-by: Ilia Maslakov <il.smind@gmail.com>
Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
procyon detects whether stdout is a TTY and emits ANSI color codes
only in that case.  When mc pipes the output through the viewer, stdout
is not a TTY, so colors are stripped.

Use script(1) to run procyon inside a pseudo-TTY, preserving its
ANSI output so the viewer can render it with AnsiMode enabled.

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
ANSI SGR attributes (color, bold, etc.) legally span newlines: a
sequence like ESC[31m applied before '\n' must remain active on the
next line until an explicit reset.  The previous code called
mcview_state_machine_init() on every newline, which wiped the ANSI
parser state.

Fix: save state->ansi before mcview_state_machine_init() and restore
it after, so positional/nroff state is reset per line while ANSI
attributes persist.

Add test_ansi_state_persists_across_newline to ansi_parser.c to cover
this invariant at the parser level.

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
@ilia-maslakov ilia-maslakov merged commit 45dc076 into master Apr 12, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants