ysaie

31 / ⚧ / code, music, art, games

──────────────────────────────
🌸 many-shaped creature
✨ too many projects
🚀 cannot be stopped
🌙 stayed up too late
:eggbug: eggbug enjoyer
──────────────────────────────
header image: chapter 8 complete from celeste
avatar: made using this character builder


📩 email
contact@echowritescode.dev

i finally made a Thing with Crucible! it's super silly and small but it's technically an application!

i really like when console apps have colorized output. as a certified No Head Brain Empty girlie i like it when information is easy to pick out from a big text dump. so i try to write all of my console apps with at least some degree of color support. Crucible is designed to make colors easy to use right out of the box, so you don't need to go download a library or look up ANSI color codes just to have pretty colors. it's even baked right into the formatting system!


here's the program:

#include "crucible/core.hpp"

namespace console_colors
{
	auto hello_world() -> void
	{
		crucible::core::console().format_out_line("[fg:magenta]Hello,[reset] [fg:yellow]world![reset]");
	}

	auto color_grid() -> void
	{
		using enum crucible::core::Console_Color;

		crucible::core::console().format_out_line("[fg:cyan]Color test:[reset]");

		crucible::core::Console_Color colors[] { Black, Red, Green, Yellow, Blue, Magenta, Cyan, White };

		crucible::core::iterate(colors)
			.examine([](auto const color) {
				crucible::core::console()
					.write_out_fg(color)
					.write_out("#####")
					.write_out_reset()
					.format_out_line("[fg:white] = {}[reset]", color);
			})
			.consume();
	}

	auto rainbow_divider() -> void
	{
		crucible::core::console()
			.format_out_line("[newline][fg:black]#[fg:red]#[fg:green]#[fg:yellow]#[fg:blue]#[fg:magenta]#[fg:cyan]#[fg:white]#[reset][newline]");
	}

	auto boot(crucible::core::Immutable_View<crucible::core::String_View> const /* arguments */) -> crucible::core::Exit_Status
	{
		hello_world();
		rainbow_divider();
		color_grid();

		return crucible::core::Exit_Status::Success;
	}
}

CRUCIBLE_CORE_MAIN(console_colors::boot)

so the way this works is

  • there's a synchronized singleton accessible through crucible::core::console() that prevents multiple threads from trampling over each other's output (at least within a single function call)
  • this singleton provides several methods: format_XXX, format_XXX_line, write_XXX, write_XXX_line, write_XXX_fg, and write_XXX_reset (where XXX is either out or err, corresponding to the standard streams)
  • the format variants hook into the formatting system, which is very similar to std::format but with some extensions i'll talk about below
  • the write variants directly do I/O on the stream; no buffering (unless the OS does it), no calls into the formatting system, just straight onto the file descriptor (or console handle on Windows). i'll probably add a buffered version later
  • the line variants append a newline at the end automatically
  • the fg variants set the foreground color
  • the reset variants reset all special output flags (just foreground color, for now)

all of these are pretty self-explanatory except for the format one. like i said, my formatting system is quite similar to std::format, except (A) you hook into it differently (i'll probably post about this in the future), and (B) it supports a feature i'm calling "directives", which are the [fg:red] etc. portions of the format strings (anything in square brackets).

a formatting directive is basically a way to influence the formatter's state without having to interpolate something at the same time. it's pretty similar to the I/O manipulators from the STL, actually, except it's just part of the format string; no need to end the string, splice another pair of operator<< invocations with some weird static object, open a new string, etc.

directives are currently only used for the Console formatters in practice. i'm hoping i can find other places they'll be useful, but even if not, i much prefer this to having to adjust my whole argument list every time i decide i want to color/uncolor something.


You must log in to comment.