Rix is the official package layer for Vix.cpp Browse packages
Skip to content

Debug ​

rix/debug is the Rix package for simple development-time output, formatting, printing, and inspection.

It is designed for examples, local diagnostics, learning, and small tools.

The examples on this page use the public Rix facade:

cpp
#include <rix.hpp>

and access Debug through:

cpp
rix.debug

What rix/debug provides ​

rix/debug provides a small API for:

txt
printing values
printing errors
debug-only prints
formatting strings
formatting printed values into strings
inspecting values
simple local diagnostics

The goal is to keep examples and development code easy to read.

For production application logs, prefer the Vix logging system.

Basic example ​

Create a file:

bash
mkdir -p ~/rix-debug-example
cd ~/rix-debug-example
touch debug.cpp

Add:

cpp
#include <rix.hpp>

#include <string>

int main()
{
  rix.debug.print("Hello", "Rix");

  const std::string package =
      rix.debug.format("Package: {}", "rix/rix");

  rix.debug.print(package);

  rix.debug.eprint("error output:", "example");

  rix.debug.inspect(package);

  return 0;
}

Run it:

bash
vix run debug.cpp

If Rix is not available yet for single-file usage:

bash
vix install -g rix/rix
vix run debug.cpp

Expected output ​

The output should look like this:

txt
Hello Rix
Package: rix/rix

The eprint output is written to stderr.

The exact inspection output depends on the value being inspected.

Install ​

For normal usage through the unified facade, install:

bash
vix add rix/rix
vix install

In vix.app, declare:

txt
deps = [
  "rix/rix",
]

If you want to use only the independent debug package, install:

bash
vix add rix/debug
vix install

and declare:

txt
deps = [
  "rix/debug",
]

For most documentation examples, prefer the facade package:

cpp
#include <rix.hpp>

Use:

cpp
rix.debug.print(...)

Example:

cpp
rix.debug.print("Hello", "Rix");
rix.debug.print("rows:", 3);
rix.debug.print("ready:", true);

print writes values separated by spaces and adds a trailing newline.

It is useful for examples and quick checks.

Use:

cpp
rix.debug.eprint(...)

Example:

cpp
rix.debug.eprint("error:", "something failed");

eprint writes to stderr.

Use it for local error output in examples.

Debug-only print ​

Use:

cpp
rix.debug.dprint(...)

Example:

cpp
rix.debug.dprint("debug value:", 42);

Use dprint for debug-only output.

The exact behavior depends on the debug package configuration.

Format a string ​

Use:

cpp
rix.debug.format(...)

Example:

cpp
const auto message =
    rix.debug.format("Package: {}", "rix/rix");

rix.debug.print(message);

Output:

txt
Package: rix/rix

Formatting placeholders ​

rix.debug.format supports simple placeholders:

txt
{}      automatic argument indexing
{0}     explicit positional indexing
{{      escaped opening brace
}}      escaped closing brace

Examples:

cpp
auto a = rix.debug.format("Hello, {}", "Ada");

auto b = rix.debug.format(
    "Value = {0}, name = {1}",
    42,
    "Ada");

auto c = rix.debug.format(
    "{{ package }} = {}",
    "rix/rix");

Automatic placeholders ​

Use {} for automatic argument order:

cpp
auto message =
    rix.debug.format("{} uses {}", "Rix", "C++");

Result:

txt
Rix uses C++

Explicit placeholders ​

Use {0}, {1}, and other numeric indexes when the order should be explicit:

cpp
auto message =
    rix.debug.format("{0} + {0} = {1}", "C++", "Vix.cpp");

Result:

txt
C++ + C++ = Vix.cpp

Do not mix automatic and explicit indexing in the same format string.

Escaped braces ​

Use double opening braces and double closing braces when you need literal braces:

cpp
auto message =
    rix.debug.format("{{ package }} = {}", "rix/debug");

Result:

txt
{ package } = rix/debug

Unsupported format specifiers ​

rix.debug.format intentionally keeps formatting small.

It does not support format specifiers such as:

txt
{:>10}
{:.2f}
{:04d}

Use simple placeholders for Rix debug formatting.

For advanced formatting, use another formatting library or normal C++ formatting tools where appropriate.

Append formatted output ​

You can append formatted text to an existing string:

cpp
std::string out = "Rix: ";

rix.debug.format.append(
    out,
    "{}",
    "debug");

rix.debug.print(out);

Expected output:

txt
Rix: debug

Replace a string with formatted output ​

Use:

cpp
rix.debug.format.to(out, "Package: {}", "rix/debug");

Example:

cpp
std::string out;

rix.debug.format.to(
    out,
    "Package: {}",
    "rix/debug");

rix.debug.print(out);

Sprint ​

Use:

cpp
rix.debug.sprint(...)

when you want the same value rendering as print, but returned as a string.

Example:

cpp
const auto line = rix.debug.sprint("rows:", 3);

rix.debug.print(line);

This is useful when you want to build a message before printing or storing it.

Inspect values ​

Use:

cpp
rix.debug.inspect(value);

Example:

cpp
std::string package = "rix/rix";

rix.debug.inspect(package);

Inspection is useful during development when you want to see a value clearly.

Local debug output ​

rix/debug is useful in documentation examples because it keeps output simple:

cpp
rix.debug.print("registered user");
rix.debug.print("id:", user.id());
rix.debug.print("email:", user.email());

It is also useful when testing other Rix packages:

cpp
const auto table = rix.csv.parse(input);

rix.debug.print("rows:", table.size());

Logging note ​

rix.debug.log exists as a simple debug package component, but for real application logging prefer the Vix logging system.

Use rix.debug for:

txt
examples
small tools
local diagnostics
quick prints
tests
documentation snippets

Use Vix logging for:

txt
production logs
structured application logs
request logs
service logs
deployment diagnostics
runtime observability

In other words:

txt
rix.debug -> simple development output
Vix logging -> real application logging

Use in a Vix project ​

Create an application:

bash
vix new debug-app --app
cd debug-app

Add Rix:

bash
vix add rix/rix
vix install

In vix.app, add:

txt
deps = [
  "rix/rix",
]

A small manifest can look like this:

txt
name = "debug-app"
type = "executable"
standard = "c++20"
output_dir = "bin"

sources = [
  "src/main.cpp",
]

include_dirs = [
  "include",
  "src",
]

deps = [
  "rix/rix",
]

packages = [
  "vix",
]

links = [
  "vix::vix",
]

Then use Debug in src/main.cpp:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");

  const auto message =
      rix.debug.format("Package: {}", "rix/debug");

  rix.debug.print(message);

  return 0;
}

Build and run:

bash
vix build
vix run

Single-file usage ​

For small scripts, examples, and experiments:

bash
vix run debug.cpp

If Rix is installed globally for single-file usage:

bash
vix install -g rix/rix
vix run debug.cpp

For project usage, prefer:

bash
vix add rix/rix
vix install

and keep the dependency in vix.app:

txt
deps = [
  "rix/rix",
]

Facade usage ​

The recommended documentation style is:

cpp
#include <rix.hpp>

Then:

cpp
rix.debug.print("Hello", "Rix");

This keeps Debug available through the same public object as the other Rix packages:

cpp
rix.csv
rix.debug
rix.auth
rix.pdf

Independent package usage ​

If your project only needs Debug, install:

bash
vix add rix/debug
vix install

In vix.app:

txt
deps = [
  "rix/debug",
]

Then include:

cpp
#include <rix/debug.hpp>

Use this style when you do not need the unified rix.* facade.

For most application documentation, prefer:

cpp
#include <rix.hpp>

Lightweight facade usage ​

If you want the rix.* facade style but only want Debug mounted, define the feature macro before including rix.hpp:

cpp
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");
  return 0;
}

When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.

This keeps the facade style while reducing what gets included.

Debug with CSV ​

Debug is useful for printing parsed CSV data:

cpp
const auto table = rix.csv.parse(
    "name,language\n"
    "Ada,C++\n");

rix.debug.print("rows:", table.size());

for (const auto &row : table)
{
  rix.debug.print("fields:", row.size());
}

Debug with Auth ​

Debug is useful for documentation examples:

cpp
auto auth = rix.auth.memory();

auto registered = auth.register_user({
    "ada@example.com",
    "correct-password"});

if (registered.failed())
{
  const auto &error = registered.error();

  rix.debug.eprint(
      "auth error:",
      rix.auth.error.to_string(error),
      error.message());

  return 1;
}

Do not print authentication secrets in production.

Avoid logging:

txt
plain-text passwords
password hashes
session ids
raw token values

Debug with PDF ​

Debug is useful when checking PDF generation:

cpp
auto doc = rix.pdf.document();

auto &page = doc.add_page();

page.text(
    page.x_left(),
    page.y_top(),
    "Hello from rix.pdf");

auto saved = rix.pdf.save(doc, "example.pdf");

if (saved.failed())
{
  rix.debug.eprint(
      "pdf error:",
      rix.pdf.error.to_string(saved.error()),
      saved.error().message());

  return 1;
}

rix.debug.print("created:", "example.pdf");

Common mistakes ​

Using debug output as production logging ​

rix.debug is for simple development output.

For real application logs, prefer Vix logging.

Printing secrets ​

Do not print:

txt
plain-text passwords
password hashes
session ids
raw token values

This matters especially when using rix/auth.

Mixing automatic and explicit format indexes ​

Wrong:

cpp
rix.debug.format("{} {0}", "Rix");

Use either automatic:

cpp
rix.debug.format("{} {}", "Rix", "Debug");

or explicit:

cpp
rix.debug.format("{0} {1}", "Rix", "Debug");

Expecting advanced format specifiers ​

This is not supported:

cpp
rix.debug.format("{:.2f}", 3.14159);

Use simple placeholders.

Forgetting deps ​

For a Vix project, do not put Rix packages in packages.

Use:

txt
deps = [
  "rix/rix",
]

packages is for CMake package discovery.

deps is for Vix Registry packages.

What you should remember ​

Use the facade:

cpp
#include <rix.hpp>

Print values:

cpp
rix.debug.print("Hello", "Rix");

Print errors:

cpp
rix.debug.eprint("error:", "message");

Format strings:

cpp
auto message = rix.debug.format("Package: {}", "rix/debug");

Inspect values:

cpp
rix.debug.inspect(message);

Use rix.debug for development output and examples.

Prefer Vix logging for real application logs.

For a Vix project, install Rix:

bash
vix add rix/rix
vix install

and use:

txt
deps = [
  "rix/rix",
]

Next step ​

Learn formatting.

Next: Formatting

Released under the MIT License.