NAME

mdee - Markdown, Easy on the Eyes

SYNOPSIS

mdee [ options ] file ...

 -h  --help             show help
     --version          show version
 -d  --debug            debug level (repeatable)
 -n  --dryrun           dry-run mode
 -f  --filter           filter mode (--no-fold --no-nup)
     --[no-]fold        line folding (default: on)
     --[no-]table       table formatting (default: on)
     --[no-]nup         nup paged output (default: on)
 -w  --width=#          fold width (default: 80)
 -t  --theme=#          color theme
 -m  --mode=#           light or dark (default: light)
 -B  --base-color=#     override theme's base color
                        (e.g., Ivory, #780043, (120,0,67))
     --list-themes      list built-in themes
     --show=#           set field visibility (e.g., italic=1)
 -C  --pane=#           number of columns
 -R  --row=#            number of rows
 -G  --grid=#           grid layout (e.g., 2x3)
 -P  --page=#           page height in lines
 -S  --pane-width=#     pane width (default: 85)
--bs --border-style=#   border style
     --[no-]pager[=#]   pager command

VERSION

Version 0.06

DESCRIPTION

mdee is a multi-column Markdown viewer with syntax highlighting, combining greple(1) for colorization and nup(1) for paged output.

Supported elements: headers (h1-h6), bold, italic, strikethrough, inline code, code blocks, HTML comments, tables, and list items.

This tool is designed for viewing Markdown not constrained by display formatting, such as output from LLMs (Large Language Models). It applies syntax highlighting with line folding and table alignment, but does not reflow paragraphs with hard line breaks. For full Markdown rendering, many other viewers are available. Combine them with nup(1) for similar paged output (e.g., nup glow README.md).

OPTIONS

General Options

-h, --help

Show help message.

--version

Show version.

-d, --debug

Set debug level. Can be repeated (-d, -dd, -ddd) for increasing verbosity.

-n, --dryrun

Dry-run mode. Show the command without executing.

Processing Options

-f, --filter

Filter mode. Reads from stdin (or files) and outputs highlighted Markdown to stdout. Disables line folding and nup paged output, but keeps table formatting enabled. Useful for piping Markdown content through mdee for syntax highlighting.

--[no-]fold

Enable or disable line folding for list items. When enabled, long lines in list items are wrapped with proper indentation using ansifold(1). Default is enabled.

--[no-]table

Enable or disable table formatting. When enabled, Markdown tables are formatted using ansicolumn(1) for aligned column display. Default is enabled.

--[no-]nup

Enable or disable nup(1) for multi-column paged output. When disabled, output goes directly to stdout without formatting. Default is enabled.

-w N, --width=N

Set the fold width for text wrapping. Default is 80. Only effective when --fold is enabled.

Theme Options

mdee supports color themes for customizing syntax highlighting. Themes define colors for various Markdown elements (headers, code blocks, bold text, etc.).

-t NAME, --theme=NAME

Select a color theme. Default is default.

-m MODE, --mode=MODE

Select light or dark mode. Default is light.

If the terminal supports background color detection (via Getopt::EX::termcolor), the mode is automatically selected based on terminal luminance.

Each theme has light and dark variants optimized for different terminal backgrounds. The built-in default theme uses RoyalBlue as the base color with automatic luminance adjustment:

light - RoyalBlue with luminance 25 (dark text for light backgrounds)
dark - RoyalBlue with luminance 80 (bright text for dark backgrounds)

User configuration is loaded from:

${XDG_CONFIG_HOME:-~/.config}/mdee/config.sh

This is a shell script that can set defaults and override colors:

# ~/.config/mdee/config.sh
default_mode='dark'              # set default mode
colors[base]='<DarkCyan>'        # override base color
colors[h1]='L25DE/${base}'       # header with base background

Color specifications use Term::ANSIColor::Concise format. The FG/BG notation specifies foreground and background colors (e.g., L25DE/${base} means gray foreground on base-colored background). The ${base} string is expanded to the base color value after loading.

-B COLOR, --base-color=COLOR

Override the theme's base color. The base color determines the overall color scheme because all heading colors (h1, h2, h3, etc.) are derived from it by adjusting luminance. For example, h2 might be ${base}+y20 (base color with luminance increased by 20).

Simple color name - luminance is adjusted automatically:

When you specify just a color name (without <> brackets or other syntax), the default luminance adjustment is applied based on the current mode:

-B RoyalBlue          # becomes <RoyalBlue>=y25 in light mode
                      # becomes <RoyalBlue>=y80 in dark mode

This makes it easy to try different colors without worrying about luminance values. The default adjustments (=y25 for light, =y80 for dark) are designed to provide good contrast against typical terminal backgrounds.

Full color specification - used exactly as specified:

If you include <> brackets, luminance modifiers, or use RGB notation, the value is used as-is without any automatic adjustment:

-B '<Ivory>'               # original color, no adjustment
-B '<Ivory>=y50'           # explicit luminance 50
-B '#780043'               # burgundy in hex
-B '(120,0,67)'            # same color in RGB decimal

Customizing the default adjustment:

The automatic luminance adjustment values can be customized with the --adjust option:

--adjust 'light==y30'      # use =y30 instead of =y25 for light mode
--adjust 'dark==y70'       # use =y70 instead of =y80 for dark mode

Note: Basic ANSI color codes (R, G, B, etc.) cannot be used because heading variations require luminance adjustment, which only works with full color specifications (X11 names, RGB hex, or RGB decimal).

--list-themes

List built-in themes with color samples and exit.

Highlight Options

--show=FIELD[=VALUE],...

Control field visibility for highlighting. Empty value or 0 disables the field; any other value (including 1) enables it.

--show italic           # enable italic
--show bold=0           # disable bold
--show all              # enable all fields
--show all= --show bold # disable all, then enable only bold

Multiple fields can be specified with commas or by repeating the option. The special field all affects all fields and is processed first.

Available fields: comment, bold, italic, strike, h1, h2, h3, h4, h5, h6, inline_code, code_block.

All fields are enabled by default.

Layout Options (passed to nup)

-C N, --pane=N

Set the number of columns (panes).

-R N, --row=N

Set the number of rows.

-G CxR, --grid=CxR

Set grid layout. For example, -G2x3 creates 2 columns and 3 rows.

-P N, --page=N

Set the page height in lines.

-S N, --pane-width=N

Set the pane width in characters. Default is 85.

--bs=STYLE, --border-style=STYLE

Set the border style.

Pager Options

--[no-]pager[=COMMAND]

Set the pager command. Use --pager=less to specify a pager, or --no-pager to disable paging.

EXAMPLES

mdee README.md              # view markdown file
mdee -C2 document.md        # 2-column view
mdee -G2x2 manual.md        # 2x2 grid (4-up)
mdee -w60 narrow.md         # narrower text width
mdee --no-pager file.md     # without pager
mdee --no-nup file.md       # output to stdout without nup
mdee --no-fold file.md      # disable line folding
mdee --no-table file.md     # disable table formatting

# Filter mode
cat file.md | mdee -f       # highlight stdin
mdee -f file.md             # highlight only (no paging)

# Theme examples
mdee --mode=dark file.md             # use dark mode
mdee --mode=light file.md            # use light mode
mdee -B Ivory file.md                # override base color
mdee --mode=dark -B '#780043' file.md # dark mode with burgundy
mdee --list-themes                   # list available themes

INSTALLATION

Homebrew (macOS)

brew tap tecolicom/tap
brew install app-mdee

CPAN

cpanm -n App::mdee

DEPENDENCIES

This command requires the following:

IMPLEMENTATION

mdee is implemented as a Bash script that orchestrates multiple specialized tools into a unified pipeline. The architecture follows Unix philosophy: each tool does one thing well, and they communicate through standard streams.

The overall data flow is:

Input File
    |
    v
[greple] --- Syntax Highlighting
    |
    v
[ansifold] --- Text Folding (optional)
    |
    v
[ansicolumn] --- Table Formatting (optional)
    |
    v
[nup] --- Paged Output (optional)
    |
    v
Terminal/Pager

Pipeline Architecture

mdee dynamically constructs a pipeline based on enabled options. Each stage is represented as a Bash array containing the command and its arguments. The --dryrun option displays the constructed pipeline without execution.

Processing Stages

The pipeline consists of four configurable stages. Each stage can be enabled or disabled independently using --[no-]fold, --[no-]table, and --[no-]nup options.

Syntax Highlighting

The first stage uses greple(1) with the -G (grep mode) and --ci=G (capture index) options to apply different colors to each captured group in regular expressions.

Supported Markdown elements:

  • Headers (# h1 through ###### h6)

  • Bold text (**bold** or __bold__)

  • Italic text (*italic* or _italic_)

  • Inline code (`code`)

  • Code blocks (fenced with ``` or ~~~)

  • HTML comments (<!-- comment -->)

Code block detection follows the CommonMark specification:

  • Opening fence: 0-3 spaces indentation, then 3+ backticks or tildes

  • Closing fence: 0-3 spaces indentation, same character, same or more count

  • Backticks and tildes cannot be mixed (``` must close with ```)

Color Specifications

Colors are specified using Term::ANSIColor::Concise format. The --cm option maps colors to captured groups. For example, L00DE/${base} specifies gray foreground on base-colored background.

The color specification supports modifiers:

  • +y10 / -y10: Adjust luminance by percentage

  • =y50: Set absolute luminance

  • D: Bold, U: Underline, E: Erase line

Example greple invocation:

greple -G --ci=G --all --need=0 \
    --cm 'L00DE/${base}' -E '^#\h+.*' \
    --cm '${base}D' -E '\*\*.*?\*\*' \
    file.md

Text Folding

The second stage wraps long lines in list items using ansifold(1) via Greple::tee. It preserves ANSI escape sequences and maintains proper indentation for nested lists.

The folding width is controlled by --width option (default: 80).

Table Formatting

The third stage formats Markdown tables using ansicolumn(1). Tables are detected by the pattern ^(\|.+\|\n){3,} and formatted with aligned columns while preserving ANSI colors.

Output Stage

The final stage uses nup(1) to provide multi-column paged output. Layout options (--pane, --row, --grid, --page) are passed directly to nup.

Theme System

mdee implements a theme system with light and dark mode variants.

Theme Structure

Each theme is defined as a Bash associative array with color definitions for each Markdown element. The ${base} placeholder references the base color (set via --base-color option):

declare -A theme_default_dark=(
    [h1]='L00DE/${base}'
    [h2]='L00DE/${base}-y15'
    [h3]='L00DN/${base}-y25'
    ...
)

Base Color Expansion

The ${base} placeholder is expanded to the effective base color after theme loading. The base color is determined by the --base-color option (default: RoyalBlue) with automatic luminance adjustment based on mode (=y25 for light, =y80 for dark).

Terminal Mode Detection

mdee uses Getopt::EX::termcolor to detect terminal background luminance. If luminance is below 50%, dark mode is automatically selected.

LIMITATIONS

HTML Comments

Only HTML comments starting at the beginning of a line are highlighted. Inline comments are not matched to avoid conflicts with inline code containing comment-like text (e.g., `<!-->`).

Emphasis

Emphasis patterns (bold and italic) do not span multiple lines. Multi-line emphasis text is not supported.

Link patterns do not span multiple lines. The link text and URL must be on the same line.

Reference-style links ([text][ref] with [ref]: url elsewhere) are not supported.

Links are converted to OSC 8 terminal hyperlinks for clickable URLs:

This requires terminal support. Compatible terminals include iTerm2, Kitty, WezTerm, Ghostty, and recent versions of GNOME Terminal. Apple's default Terminal.app does not support OSC 8.

When using less as pager, version 566 or later is required with -R option.

For OSC 8 specification, see: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5fedd

SEE ALSO

nup(1), greple(1), ansifold(1), ansicolumn(1)

AUTHOR

Kazumasa Utashiro

LICENSE

Copyright 2026 Kazumasa Utashiro.

This software is released under the MIT License. https://opensource.org/licenses/MIT