diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..06965af --- /dev/null +++ b/.editorconfig @@ -0,0 +1,39 @@ +root = true + +# Language indent/EOL/charset overlap with .vscode/settings.json. +# Rulers, renderWhitespace, detectIndentation, mergeEditor, and +# language-server settings cannot be expressed here — they stay in +# settings.json. + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = tab +insert_final_newline = true +trim_trailing_whitespace = true + +# [json] +[*.json] +indent_size = 2 +indent_style = space + +# [markdown] +[*.md] +indent_size = 2 +indent_style = space + +# [shellscript] +[*.{bash,sh,zsh}] +indent_size = 2 +indent_style = space + +# [yaml] +[*.{yaml,yml}] +indent_size = 2 +indent_style = space + +# [zig] +[*.zig] +indent_size = 4 +indent_style = space diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b6d4b9c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,68 @@ +# .gitattributes — Zig (GitHub-hosted) +# +# Sources: GitHub Docs (line endings), git-scm gitattributes (no built-in +# zig diff driver), ziglang conventions for artefacts, github-linguist overrides. + +# Default: detect text, normalize to LF in the repository +* text=auto + +# --- Source --- +*.zig text eol=lf +*.zon text eol=lf +build.zig text eol=lf +build.zig.zon text eol=lf + +# --- Scripts --- +*.bash text eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.sh text eol=lf +*.zsh text eol=lf + +# --- Docs / meta --- +*.adoc text +*.markdown text diff=markdown +*.md text diff=markdown +*.txt text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +LICENSE text +NEWS text +README text +TODO text +.gitattributes text +.gitignore text + +# --- Serialisation --- +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + +# --- Binary --- +*.a binary +*.exe binary +*.o binary +*.obj binary +*.so binary + +# --- Archives / images (common) --- +*.gif binary +*.gz binary +*.ico binary +*.jpeg binary +*.jpg binary +*.png binary +*.tar binary +*.zip binary + +# --- GitHub Linguist --- +# Prefer .gitignore for these; mark if ever committed +**/.zig-cache/** linguist-generated +**/zig-cache/** linguist-generated +**/zig-out/** linguist-generated diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7ce3330 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,57 @@ +name: CI + +on: + push: + branches: + - master + - dev + - boilerplate + - idiomatic + - rc1 + - rc2 + - rc3 + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint & Format + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Zig + uses: mlugg/setup-zig@v2 + with: + version: 0.16.0 + + - name: Check Formatting + run: zig fmt --check . + + test: + name: Build & Test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Zig + uses: mlugg/setup-zig@v2 + with: + version: 0.16.0 + + - name: Run Unit Tests + run: zig build test --global-cache-dir .zig-cache + + - name: Run Example + run: zig build run-example --global-cache-dir .zig-cache diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d14c0b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Synesis Information Systems .gitignore for Zig projects + + +# directories (by name) + +/.zig-cache/ +/scratch/ +/zig-out/ + + +# directories (by pattern) + + +# files (by name) + +.DS_Store + + +# files (by pattern) + +*~ +*.sw[pon] +*.tmp +*.zip diff --git a/.vimrc b/.vimrc new file mode 100644 index 0000000..3b044aa --- /dev/null +++ b/.vimrc @@ -0,0 +1,64 @@ +" Synesis C/C++ & Zig project .vimrc — aligned with .vscode/settings.json + +set nocompatible +filetype indent plugin on +syntax enable +set autoindent +set backspace=indent,eol,start +set hlsearch +set incsearch +set number + +" files.insertFinalNewline +set eol +set fixeol + +" editor.renderWhitespace: all +set list +set listchars=tab:->,trail:-,extends:>,precedes:<,nbsp:+ + +" editor.detectIndentation: false — global defaults (editor.tabSize: 4, insertSpaces: true) +set tabstop=4 +set shiftwidth=4 +set softtabstop=4 +set expandtab +set colorcolumn=76 + +if has('termguicolors') + " set termguicolors +endif + +function! s:ConfigureColorColumn() abort + highlight ColorColumn ctermbg=236 guibg=#2a2a2a cterm=NONE gui=NONE +endfunction + +call s:ConfigureColorColumn() +autocmd ColorScheme * call s:ConfigureColorColumn() + +" files.trimTrailingWhitespace +autocmd BufWritePre * %s/\s\+$//e + +augroup sis_c_cxx_zig + autocmd! + " [bat] + autocmd FileType bat,dosbatch setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76 + + " [c] / [cpp] + autocmd FileType c,cpp setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,64,68,72,76 + + " [cmake] + autocmd FileType cmake setlocal noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 + + " [json] / [markdown] / [ruby] / [yaml] + autocmd FileType json,markdown,ruby,yaml setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 + + " [shellscript] + autocmd FileType bash,sh,zsh setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 colorcolumn=60,76 + + " [toml] + autocmd FileType toml setlocal noexpandtab tabstop=2 shiftwidth=2 softtabstop=2 + + " [zig] + autocmd FileType zig setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=76 + +augroup END diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..50947dc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,36 @@ +{ + "[json]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + }, + "[markdown]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + }, + "[toml]": { + "editor.insertSpaces": false, + "editor.tabSize": 2, + }, + "[zig]": { + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.organizeImports": "explicit", + }, + "editor.defaultFormatter": "ziglang.vscode-zig", + "editor.formatOnSave": true, + "editor.insertSpaces": true, + "editor.suggest.insertMode": "replace", + "editor.tabSize": 4, + }, + "cmake.configureOnOpen": false, + "debug.allowBreakpointsEverywhere": true, + "editor.detectIndentation": false, + "editor.insertSpaces": false, + "editor.renderWhitespace": "all", + "editor.rulers": [ 76 ], + "editor.tabSize": 2, + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "git.mergeEditor": false, + "zig.zls.enabled": "on", +} diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..0e727c9 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,21 @@ +# woad.Zig - Authors + + +## Major Contributors + +| Name | GitHub | +| ----------- | --------------------------------- | +| Matt Wilson | [mwsis](https://github.com/mwsis) | + + +## Defect reports, fixes and suggestions (for which we are very grateful) + +| Name | GitHub | +| ------- | ------ | +| \ | | + + +Contributions are welcomed. + + + diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..838f2de --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,9 @@ +# woad.Zig - Changes + + +## 0.0.1 - 18th September 2026 + +* SGR colour and reset codes (`RESET`, `FG_*`, `BG_*`, including bright variants); + + + diff --git a/EXAMPLES.md b/EXAMPLES.md new file mode 100644 index 0000000..c637cdc --- /dev/null +++ b/EXAMPLES.md @@ -0,0 +1,9 @@ +# woad.Zig - Examples + + +| Name | Source | Summary | +| ----------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------- | +| **show_colours** | [examples/show_colours.zig](./examples/show_colours.zig) | Prints standard, bright, and background SGR samples via **woad** codes | + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..95082c3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +woad.Zig - BSD 3-Clause License + +Copyright (c) 2026, Matthew Wilson and Synesis Information Systems +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..1547b3b --- /dev/null +++ b/NEWS.md @@ -0,0 +1,9 @@ +# woad.Zig - News + + +| Date | News Item | Details | +| ------------------- | --------- | ------- | +| 18th September 2026 | [**woad.Zig** 0.0.1](https://github.com/synesissoftware/woad.Zig/releases/tag/0.0.1) | SGR colour and reset codes | + + + diff --git a/README.md b/README.md index 89fb672..f870c41 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,138 @@ -# woad.Zig -Rock-bottom colour library, for Zig +# woad.Zig + +Minimal ANSI terminal colour codes, for Zig + +![Language](https://img.shields.io/badge/Zig-F7A41D?style=flat&logo=zig&logoColor=white) +[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) +[![GitHub release](https://img.shields.io/github/v/release/synesissoftware/woad.Zig.svg)](https://github.com/synesissoftware/woad.Zig/releases/latest) +[![Last Commit](https://img.shields.io/github/last-commit/synesissoftware/woad.Zig)](https://github.com/synesissoftware/woad.Zig/commits/master) +[![CI](https://github.com/synesissoftware/woad.Zig/actions/workflows/ci.yml/badge.svg)](https://github.com/synesissoftware/woad.Zig/actions/workflows/ci.yml) + + +## Table of Contents + +- [Introduction](#introduction) +- [Installation](#installation) +- [Components](#components) +- [Examples](#examples) +- [Project Information](#project-information) + - [Where to get help](#where-to-get-help) + - [Contribution guidelines](#contribution-guidelines) + - [Dependencies](#dependencies) + - [Efferent (fan-out)](#efferent-fan-out) + - [Development Dependencies](#development-dependencies) + - [Afferent (fan-in)](#afferent-fan-in) + - [Related projects](#related-projects) + - [License](#license) + + +## Introduction + +**woad** provides the smallest useful set of fixed ANSI SGR colour sequences for library authors. It is not a console or TUI framework. + +**woad.Zig** is the **Zig** implementation. + + +## Installation + +Add **woad.Zig** to your `build.zig.zon`: + +```zig +.{ + .name = "my-project", + .version = "0.1.0", + .dependencies = .{ + .woad = .{ + .url = "https://github.com/synesissoftware/woad.Zig/archive/refs/tags/0.0.1.tar.gz", + // .hash = "...", + }, + }, +} +``` + +Then import and expose the module in your `build.zig`: + +```zig +const woad_dep = b.dependency("woad", .{ + .target = target, + .optimize = optimize, +}); +exe.root_module.addImport("woad", woad_dep.module("woad")); +``` + + +## Components + +**woad.Zig** ships SGR string constants (`RESET`, `FG_*`, `BG_*`, including bright variants) and `VERSION`. TTY/stream gating and Windows virtual-terminal opt-in are not implemented yet. + +```zig +const std = @import("std"); +const woad = @import("woad"); + +pub fn main(init: std.process.Init) !void { + var buffer: [256]u8 = undefined; + var stdout_impl = std.Io.File.stdout().writer(init.io, &buffer); + const stdout = &stdout_impl.interface; + + try stdout.print("{s}ok{s}\n", .{ woad.FG_GREEN, woad.RESET }); + try stdout.flush(); +} +``` + + +## Examples + +See [EXAMPLES.md](./EXAMPLES.md). Run the sample with: + +```bash +zig build run-example +``` + + +## Project Information + + +### Where to get help + +[GitHub Page](https://github.com/synesissoftware/woad.Zig "GitHub Page") + + +### Contribution guidelines + +Defect reports, feature requests, and pull requests are welcome on https://github.com/synesissoftware/woad.Zig. + + +### Dependencies + + +#### Efferent (fan-out) + +None. + + +#### Development Dependencies + +None. + + +#### Afferent (fan-in) + +None (currently). + + +### Related projects + +* [**woad**](https://github.com/synesissoftware/woad/) +* [**woad.Go**](https://github.com/synesissoftware/woad.Go/) +* [**woad.NET**](https://github.com/synesissoftware/woad.NET/) +* [**woad.Python**](https://github.com/synesissoftware/woad.Python/) +* [**woad.Ruby**](https://github.com/synesissoftware/woad.Ruby/) +* [**woad.Rust**](https://github.com/synesissoftware/woad.Rust/) + + +### License + +**woad.Zig** is released under the 3-clause BSD license. See [LICENSE](./LICENSE) for details. + + + diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..cb43698 --- /dev/null +++ b/TODO.md @@ -0,0 +1,28 @@ +# woad.Zig - TODO + + +## Table of Contents + +- [Functional improvements](#functional-improvements) +- [Performance improvements](#performance-improvements) +- [Packaging improvements](#packaging-improvements) + + +## Functional improvements + +* [x] ~~~SGR colour and reset codes~~~ - ✅; +* [ ] TTY-conditional colour codes (process and per-stream); +* [ ] Windows virtual-terminal gating (OS build + `GetConsoleMode`); + + +## Performance improvements + +* \ diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..64880f7 --- /dev/null +++ b/build.zig @@ -0,0 +1,50 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + // Create a module for other packages to import + const woad_module = b.addModule("woad", .{ + .root_source_file = b.path("src/root.zig"), + .target = target, + .optimize = optimize, + }); + + // Static library using the module + const lib = b.addLibrary(.{ + .name = "woad", + .linkage = .static, + .root_module = woad_module, + }); + b.installArtifact(lib); + + // Unit tests using the module + const lib_unit_tests = b.addTest(.{ + .root_module = woad_module, + }); + const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); + + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&run_lib_unit_tests.step); + + // Example: show_colours + const example = b.addExecutable(.{ + .name = "show_colours", + .root_module = b.createModule(.{ + .root_source_file = b.path("examples/show_colours.zig"), + .target = target, + .optimize = optimize, + }), + }); + example.root_module.addImport("woad", woad_module); + b.installArtifact(example); + + const run_example = b.addRunArtifact(example); + if (b.args) |args| { + run_example.addArgs(args); + } + + const run_example_step = b.step("run-example", "Run the show_colours example"); + run_example_step.dependOn(&run_example.step); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..2e6316c --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,22 @@ +.{ + .authors = .{ + "Matt Wilson ", + }, + .description = "Minimal ANSI terminal colour codes, for Zig", + .fingerprint = 0xa21e34833b201d51, + .name = .woad, + .paths = .{ + "AUTHORS.md", + "CHANGES.md", + "EXAMPLES.md", + "LICENSE", + "NEWS.md", + "README.md", + "TODO.md", + "build.zig", + "build.zig.zon", + "examples", + "src", + }, + .version = "0.0.1", +} diff --git a/examples/show_colours.zig b/examples/show_colours.zig new file mode 100644 index 0000000..d526cbc --- /dev/null +++ b/examples/show_colours.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const woad = @import("woad"); + +pub fn main(init: std.process.Init) !void { + var buffer: [4096]u8 = undefined; + var stdout_impl = std.Io.File.stdout().writer(init.io, &buffer); + const stdout = &stdout_impl.interface; + + try stdout.print("woad.Zig version: {s}\n\n", .{woad.VERSION}); + + try stdout.print("Standard foreground colours:\n", .{}); + try stdout.print(" {s}Black{s}\n", .{ woad.FG_BLACK, woad.RESET }); + try stdout.print(" {s}Red{s}\n", .{ woad.FG_RED, woad.RESET }); + try stdout.print(" {s}Green{s}\n", .{ woad.FG_GREEN, woad.RESET }); + try stdout.print(" {s}Yellow{s}\n", .{ woad.FG_YELLOW, woad.RESET }); + try stdout.print(" {s}Blue{s}\n", .{ woad.FG_BLUE, woad.RESET }); + try stdout.print(" {s}Magenta{s}\n", .{ woad.FG_MAGENTA, woad.RESET }); + try stdout.print(" {s}Cyan{s}\n", .{ woad.FG_CYAN, woad.RESET }); + try stdout.print(" {s}White{s}\n\n", .{ woad.FG_WHITE, woad.RESET }); + + try stdout.print("Bright foreground colours:\n", .{}); + try stdout.print(" {s}Bright Black{s}\n", .{ woad.FG_BRIGHT_BLACK, woad.RESET }); + try stdout.print(" {s}Bright Red{s}\n", .{ woad.FG_BRIGHT_RED, woad.RESET }); + try stdout.print(" {s}Bright Green{s}\n", .{ woad.FG_BRIGHT_GREEN, woad.RESET }); + try stdout.print(" {s}Bright Yellow{s}\n", .{ woad.FG_BRIGHT_YELLOW, woad.RESET }); + try stdout.print(" {s}Bright Blue{s}\n", .{ woad.FG_BRIGHT_BLUE, woad.RESET }); + try stdout.print(" {s}Bright Magenta{s}\n", .{ woad.FG_BRIGHT_MAGENTA, woad.RESET }); + try stdout.print(" {s}Bright Cyan{s}\n", .{ woad.FG_BRIGHT_CYAN, woad.RESET }); + try stdout.print(" {s}Bright White{s}\n\n", .{ woad.FG_BRIGHT_WHITE, woad.RESET }); + + try stdout.print("Background colours:\n", .{}); + try stdout.print(" {s} Black {s}\n", .{ woad.BG_BLACK, woad.RESET }); + try stdout.print(" {s} Red {s}\n", .{ woad.BG_RED, woad.RESET }); + try stdout.print(" {s} Green {s}\n", .{ woad.BG_GREEN, woad.RESET }); + try stdout.print(" {s} Yellow {s}\n", .{ woad.BG_YELLOW, woad.RESET }); + try stdout.print(" {s} Blue {s}\n", .{ woad.BG_BLUE, woad.RESET }); + try stdout.print(" {s} Magenta {s}\n", .{ woad.BG_MAGENTA, woad.RESET }); + try stdout.print(" {s} Cyan {s}\n", .{ woad.BG_CYAN, woad.RESET }); + try stdout.print(" {s} White {s}\n", .{ woad.BG_WHITE, woad.RESET }); + + try stdout.flush(); +} diff --git a/src/root.zig b/src/root.zig new file mode 100644 index 0000000..0180c04 --- /dev/null +++ b/src/root.zig @@ -0,0 +1,186 @@ +//! Minimal ANSI terminal colour codes, for Zig. +//! +//! **woad** provides the smallest useful set of fixed SGR sequences for +//! library authors. It is not a console or TUI framework. + +/// Package version. +pub const VERSION = "0.0.1"; + +// Reset + +/// Reset all attributes. +pub const RESET = "\x1b[0m"; + +// Foreground (standard) + +/// Foreground black. +pub const FG_BLACK = "\x1b[30m"; +/// Foreground red. +pub const FG_RED = "\x1b[31m"; +/// Foreground green. +pub const FG_GREEN = "\x1b[32m"; +/// Foreground yellow. +pub const FG_YELLOW = "\x1b[33m"; +/// Foreground blue. +pub const FG_BLUE = "\x1b[34m"; +/// Foreground magenta. +pub const FG_MAGENTA = "\x1b[35m"; +/// Foreground cyan. +pub const FG_CYAN = "\x1b[36m"; +/// Foreground white. +pub const FG_WHITE = "\x1b[37m"; + +// Foreground (bright) + +/// Foreground bright black. +pub const FG_BRIGHT_BLACK = "\x1b[90m"; +/// Foreground bright red. +pub const FG_BRIGHT_RED = "\x1b[91m"; +/// Foreground bright green. +pub const FG_BRIGHT_GREEN = "\x1b[92m"; +/// Foreground bright yellow. +pub const FG_BRIGHT_YELLOW = "\x1b[93m"; +/// Foreground bright blue. +pub const FG_BRIGHT_BLUE = "\x1b[94m"; +/// Foreground bright magenta. +pub const FG_BRIGHT_MAGENTA = "\x1b[95m"; +/// Foreground bright cyan. +pub const FG_BRIGHT_CYAN = "\x1b[96m"; +/// Foreground bright white. +pub const FG_BRIGHT_WHITE = "\x1b[97m"; + +// Background (standard) + +/// Background black. +pub const BG_BLACK = "\x1b[40m"; +/// Background red. +pub const BG_RED = "\x1b[41m"; +/// Background green. +pub const BG_GREEN = "\x1b[42m"; +/// Background yellow. +pub const BG_YELLOW = "\x1b[43m"; +/// Background blue. +pub const BG_BLUE = "\x1b[44m"; +/// Background magenta. +pub const BG_MAGENTA = "\x1b[45m"; +/// Background cyan. +pub const BG_CYAN = "\x1b[46m"; +/// Background white. +pub const BG_WHITE = "\x1b[47m"; + +// Background (bright) + +/// Background bright black. +pub const BG_BRIGHT_BLACK = "\x1b[100m"; +/// Background bright red. +pub const BG_BRIGHT_RED = "\x1b[101m"; +/// Background bright green. +pub const BG_BRIGHT_GREEN = "\x1b[102m"; +/// Background bright yellow. +pub const BG_BRIGHT_YELLOW = "\x1b[103m"; +/// Background bright blue. +pub const BG_BRIGHT_BLUE = "\x1b[104m"; +/// Background bright magenta. +pub const BG_BRIGHT_MAGENTA = "\x1b[105m"; +/// Background bright cyan. +pub const BG_BRIGHT_CYAN = "\x1b[106m"; +/// Background bright white. +pub const BG_BRIGHT_WHITE = "\x1b[107m"; + +const std = @import("std"); +const testing = std.testing; + +test "version" { + try testing.expectEqualStrings("0.0.1", VERSION); +} + +test "reset code" { + try testing.expectEqualStrings("\x1b[0m", RESET); +} + +test "foreground standard codes" { + try testing.expectEqualStrings("\x1b[30m", FG_BLACK); + try testing.expectEqualStrings("\x1b[31m", FG_RED); + try testing.expectEqualStrings("\x1b[32m", FG_GREEN); + try testing.expectEqualStrings("\x1b[33m", FG_YELLOW); + try testing.expectEqualStrings("\x1b[34m", FG_BLUE); + try testing.expectEqualStrings("\x1b[35m", FG_MAGENTA); + try testing.expectEqualStrings("\x1b[36m", FG_CYAN); + try testing.expectEqualStrings("\x1b[37m", FG_WHITE); +} + +test "foreground bright codes" { + try testing.expectEqualStrings("\x1b[90m", FG_BRIGHT_BLACK); + try testing.expectEqualStrings("\x1b[91m", FG_BRIGHT_RED); + try testing.expectEqualStrings("\x1b[92m", FG_BRIGHT_GREEN); + try testing.expectEqualStrings("\x1b[93m", FG_BRIGHT_YELLOW); + try testing.expectEqualStrings("\x1b[94m", FG_BRIGHT_BLUE); + try testing.expectEqualStrings("\x1b[95m", FG_BRIGHT_MAGENTA); + try testing.expectEqualStrings("\x1b[96m", FG_BRIGHT_CYAN); + try testing.expectEqualStrings("\x1b[97m", FG_BRIGHT_WHITE); +} + +test "background standard codes" { + try testing.expectEqualStrings("\x1b[40m", BG_BLACK); + try testing.expectEqualStrings("\x1b[41m", BG_RED); + try testing.expectEqualStrings("\x1b[42m", BG_GREEN); + try testing.expectEqualStrings("\x1b[43m", BG_YELLOW); + try testing.expectEqualStrings("\x1b[44m", BG_BLUE); + try testing.expectEqualStrings("\x1b[45m", BG_MAGENTA); + try testing.expectEqualStrings("\x1b[46m", BG_CYAN); + try testing.expectEqualStrings("\x1b[47m", BG_WHITE); +} + +test "background bright codes" { + try testing.expectEqualStrings("\x1b[100m", BG_BRIGHT_BLACK); + try testing.expectEqualStrings("\x1b[101m", BG_BRIGHT_RED); + try testing.expectEqualStrings("\x1b[102m", BG_BRIGHT_GREEN); + try testing.expectEqualStrings("\x1b[103m", BG_BRIGHT_YELLOW); + try testing.expectEqualStrings("\x1b[104m", BG_BRIGHT_BLUE); + try testing.expectEqualStrings("\x1b[105m", BG_BRIGHT_MAGENTA); + try testing.expectEqualStrings("\x1b[106m", BG_BRIGHT_CYAN); + try testing.expectEqualStrings("\x1b[107m", BG_BRIGHT_WHITE); +} + +test "all codes are CSI SGR" { + const codes = [_][]const u8{ + RESET, + FG_BLACK, + FG_RED, + FG_GREEN, + FG_YELLOW, + FG_BLUE, + FG_MAGENTA, + FG_CYAN, + FG_WHITE, + FG_BRIGHT_BLACK, + FG_BRIGHT_RED, + FG_BRIGHT_GREEN, + FG_BRIGHT_YELLOW, + FG_BRIGHT_BLUE, + FG_BRIGHT_MAGENTA, + FG_BRIGHT_CYAN, + FG_BRIGHT_WHITE, + BG_BLACK, + BG_RED, + BG_GREEN, + BG_YELLOW, + BG_BLUE, + BG_MAGENTA, + BG_CYAN, + BG_WHITE, + BG_BRIGHT_BLACK, + BG_BRIGHT_RED, + BG_BRIGHT_GREEN, + BG_BRIGHT_YELLOW, + BG_BRIGHT_BLUE, + BG_BRIGHT_MAGENTA, + BG_BRIGHT_CYAN, + BG_BRIGHT_WHITE, + }; + + for (codes) |code| { + try testing.expect(std.mem.startsWith(u8, code, "\x1b[")); + try testing.expect(std.mem.endsWith(u8, code, "m")); + } +}