PHP port of charmbracelet/glow β a Markdown CLI viewer that composes CandyShine (rendering) and SugarBits Viewport (scrolling).
composer require sugarcraft/sugar-glowsugarglow README.md # render to stdout (default)
sugarglow -p README.md # open in a fullscreen pager
git log -1 --pretty=%B | sugarglow -p # pipe stdin
sugarglow --theme dracula README.md
sugarglow --width 80 --no-hyperlinks README.md
sugarglow --theme-config ./my-theme.json README.mdFlags:
--theme {ansi|plain|dark|light|notty|dracula|tokyo-night|pink|solarized|monokai|github}β picks a CandyShine preset.solarized,monokai, andgithubload JSON theme files fromthemes/.--style/-sβ alias for--theme(glamour-compat).--theme-config <path>β load a custom JSON theme viaTheme::fromJson. Overrides--theme.--width/-w <N>β word-wrap paragraphs / blockquotes / list bodies. 0 = no wrap.--no-hyperlinksβ disable OSC 8 link envelopes; render links astext (url)instead.--pager/-pβ open in a fullscreen pager.
Standard reader keys come from Viewport:
| Key | Action |
|---|---|
β / k |
line up |
β / j |
line down |
PgUp / b |
page up |
PgDn / space / f |
page down |
Ctrl+U / Ctrl+D |
half page |
Home / g |
top |
End / G |
bottom |
q / Esc / Ctrl+C |
exit |
Beyond the CLI, sugar-glow exposes two utility helpers for integrating its behaviour into other PHP projects.
File watching via mtime polling β works cross-platform with no extensions.
use SugarCraft\Glow\FileWatcher;
$watcher = new FileWatcher('/path/to/file.md');
// Check if modified since a given mtime
if ($watcher->hasChangedSince($lastMtime)) {
// re-render
}
// Generator-based watch loop (e.g., in a ReactPHP stream)
foreach (FileWatcher::watch('/path/to/file.md', 500) as $changed) {
// $changed === true each time the file is modified
}CJK and emoji width handling lives in SugarCraft\Core\Util\Width. Use it
directly for visual truncation, padding, and ANSI-aware measurement:
use SugarCraft\Core\Util\Width;
Width::string('hello'); // 5
Width::string('δ½ ε₯½'); // 4 (full-width)
Width::string('π¦'); // 2 (emoji)
Width::padRight('hi', 8); // "hi "
Width::truncate('hello world', 8); // "hello wo"sugar-glow uses candy-palette for terminal capability probing. The
RenderCommand::terminalSupportsColor() wrapper calls
\SugarCraft\Palette\Probe\TerminalProbe::run() and falls back to
true (assume color) if the probe throws β ensuring graceful degradation
on Windows, over SSH, and in old terminals.
Render output is covered by golden-file snapshot tests. Fixture files live
in tests/fixtures/ with a .golden extension and are compared against
actual ANSI byte output via SugarCraft\Testing\Snapshot\Assertions::assertGoldenAnsi().
To re-record fixtures after intentional output changes:
UPDATE_GOLDENS=1 vendor/bin/phpunitcd sugar-glow && composer install && vendor/bin/phpunit
