Pretty Printer for Modern C++

Overview

pprint

Highlights

  • Single header file
  • Requires C++17
  • MIT License

Quick Start

Simply include pprint.hpp and you're good to go.

#include <pprint.hpp>

To start printing, create a PrettyPrinter

pprint::PrettyPrinter printer;

You can construct a PrettyPrinter with any stream that inherits from std::ostream , e.g, std::stringstream

std::stringstream stream;
pprint::PrettyPrinter printer(stream);

Fundamental Types

printer.print(5);
printer.print(3.14f);
printer.print(2.718);
printer.print(true);
printer.print('x');
printer.print("Hello, 世界");
printer.print(nullptr);
5
3.14f
2.718
true
x
Hello, 世界
nullptr

Strings

Maybe you want your strings to be quoted? Simply set printer.quotes(true)

printer.quotes(true);
printer.print("A", "B", "C");
"A" "B" "C"

Complex Numbers

using namespace std::complex_literals;
std::complex<double> foo = 1. + 2.5i;
std::complex<double> bar = 9. + 4i;
printer.print(foo, "*", bar, "=", (foo * bar));   // parameter packing
(1 + 2.5i) * (9 + 4i) = (-1 + 26.5i)

Enumeration Types

enum Color { RED = 2, BLUE = 4, GREEN = 8 };
Color color = BLUE;
printer.print(color);
4

If you compile with

  • Clang/LLVM >= 5
  • Visual C++ >= 15.3 / Visual Studio >= 2017
  • Xcode >= 10.2
  • GCC >= 9

then pprint will print the name of the enum for you (thanks to magic_enum)

enum Level { LOW, MEDIUM, HIGH };
Level current_level = MEDIUM;
std::cout << "Current level: ";
printer.print(current_level);
Current level: MEDIUM

STL Sequence Containers

pprint supports a variety of STL sequence containers including std::vector, std::list, std::deque, and std::array.

Here's an example pretty print of a simple 3x3 matrix:

typedef std::array<std::array<int, 3>, 3> Mat3x3;
Mat3x3 matrix;
matrix[0] = {1, 2, 3};
matrix[1] = {4, 5, 6};
matrix[2] = {7, 8, 9};
printer.print("Matrix =", matrix);
Matrix = [
  [1, 2, 3], 
  [4, 5, 6], 
  [7, 8, 9]
]

Compact Printing

pprint also supports compact printing of containers. Simply call printer.compact(true) to enable this:

std::vector<std::map<std::string, int>> foo {{{"a", 1}, {"b", 2}}, {{"c", 3}, {"d", 4}}};
printer.compact(true);
printer.print("Foo =", foo);
Foo = [{a : 1, b : 2}, {c : 3, d : 4}]

STL Associative Containers

Support for associative containers includes pretty printing of std::map, std::multimap, std::unordered_map, std::unordered_multimap, std::set, std::multiset, std::unordered_set and , std::unordered_multiset

printer.print(std::map<std::string, std::set<int>>{ 
    {"foo", {1, 2, 3, 3, 2, 1}}, {"bar", {7, 6, 5, 4}}});
{
  "bar" : {4, 5, 6, 7}, 
  "foo" : {1, 2, 3}
}

STL Container Adaptors

pprint can print container adaptors including std::queue, std::priority_queue and std::stack. Here's an example print of a priority queue:

std::priority_queue<int> queue;
for(int n : {1,8,5,6,3,4,0,9,7,2}) queue.push(n);
printer.print(queue);
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Fixed-size Heterogeneous Tuples

auto get_student = [](int id) {
  if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");
  if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
  if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
  throw std::invalid_argument("id");
};
printer.print({ get_student(0), get_student(1), get_student(2) });
{(1.7, 'D', "Ralph Wiggum"), (2.9, 'C', "Milhouse Van Houten"), (3.8, 'A', "Lisa Simpson")}

Type-safe Unions

// Construct a vector of values
std::vector<std::variant<bool, int, int *, float, std::string, std::vector<int>,		      
       std::map<std::string, std::map<std::string, int>>, 
       std::pair<double, double>>> var;
var.push_back(5);
var.push_back(nullptr);
var.push_back(3.14f);
var.push_back(std::string{"Hello World"});
var.push_back(std::vector<int>{1, 2, 3, 4});
var.push_back(std::map<std::string, std::map<std::string, int>>{{"a",{{"b",1}}}, {"c",{{"d",2}, {"e",3}}}});
var.push_back(true);
var.push_back(std::pair<double, double>{1.1, 2.2});

// Print the vector
pprint::PrettyPrinter printer;
printer.indent(2);
printer.quotes(true);
printer.print(var);
[
  5, 
  nullptr,
  3.14f, 
  "Hello World", 
  [1, 2, 3, 4], 
  {"a" : {"b" : 1}, "c" : {"d" : 2, "e" : 3}}, 
  true, 
  (1.1, 2.2)
]

Optional Values

std::optional<int> opt = 5;
std::optional<int> opt2;

printer.print(opt);
printer.print(opt2);
5
nullopt

Class Objects

pprint print class objects with or without an overloaded << operator

class Foo {};
Foo foo;
printer.print(foo);
<Object main::Foo>

If an << operator is available, pprint will use it to print your object:

class Date {
  unsigned int month, day, year;
public:
  Date(unsigned int m, unsigned int d, unsigned int y) : month(m), day(d), year(y) {}
  friend std::ostream& operator<<(std::ostream& os, const Date& dt);
};

    
std::ostream& operator<<(std::ostream& os, const Date& dt) {
  os << dt.month << '/' << dt.day << '/' << dt.year;
  return os;
}
Date date(04, 07, 2019);
printer.print("Today's date is", date);
Today's date is 4/7/2019

User-defined types

Here's an example to print user-defined types. Let's say you want to print Mesh objects

struct Vector3 {
  float x, y, z;
};

struct Mesh {
  std::vector<Vector3> vertices;
};

First, overload the << operator for these structs:

std::ostream& operator<<(std::ostream& os, const Vector3& v) {
  pprint::PrettyPrinter printer(os);
  printer.print_inline(std::make_tuple(v.x, v.y, v.z));
  return os;
}

std::ostream& operator<<(std::ostream& os, const Mesh& mesh) {
  pprint::PrettyPrinter printer(os);
  printer.print("Mesh {");
  printer.indent(2);
  printer.print_inline("vertices:", mesh.vertices);
  printer.print("}");
  return os;
}

then simply call printer.print(Mesh)

Mesh quads = {{
  {0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {0, 1, 0},
  {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}, {0, 1, 1},
  }};

pprint::PrettyPrinter printer;
printer.print(quads);
Mesh {
  vertices: [
      (0, 0, 0), 
      (1, 0, 0), 
      (1, 1, 0), 
      (0, 0, 0), 
      (1, 1, 0), 
      (0, 1, 0), 
      (0, 0, 1), 
      (1, 0, 1), 
      (1, 1, 1), 
      (0, 0, 1), 
      (1, 1, 1), 
      (0, 1, 1)
  ]
}

License

The project is available under the MIT license.

Issues
  • [SOLVED] Printing hex numbers

    [SOLVED] Printing hex numbers

    Tried to define a specific operator for uint to be printed as hex in my client code:

    std::ostream& operator<<(std::ostream& os, const uint64_t& uNum) {
      os << std::hex << uNum << std::dec;
      return os;
    }
    

    But it fails with

    src/ext/pprint/pprint.hpp:526:43: error: ambiguous overload for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'long unsigned int')
      526 |       stream_ << std::string(indent, ' ') << value << line_terminator;
          |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
    

    Is there maybe already a way to print integers in hex format?

    opened by pyramid3d 2
  • Doesn't compile when printing std::unordered_set

    Doesn't compile when printing std::unordered_set

    This test case can't compile w/ Apple clang version 11.0.0 or gcc 8.3.0.

    TEST_CASE("Print empty set (line_terminator = '\n', indent = 2)",
    	  "[std::unordered_set]") {
      std::unordered_set<int> foo {};
    
      std::stringstream stream;
      pprint::PrettyPrinter printer(stream);
      printer.print(foo);
    
      const std::string expected = "{}\n";
    
      REQUIRE(stream.str() == expected);
    }
    
    opened by ncihnegn 1
  • Enable CMake release

    Enable CMake release

    1. Include CMakeLists.txt in the archive
    2. Add pprintConfigVersion.cmake
    3. Fix inconsistency: CMake install to <pprint/pprint.hpp>, not <pprint.hpp>.
    opened by ncihnegn 1
  • Add canon support

    Add canon support

    The title says it all...

    Using this lib in corporate invironments requires using packaging instead of copy pasting code due to software clearing... so conan and cmake would be great...

    opened by gocarlos 1
  • Newlines, quotes, escape characters, etc in strings?

    Newlines, quotes, escape characters, etc in strings?

    I'm not sure what's the intended behavior, but this library doesn't seem to do anything special to handle quotes or newlines or other "special" characters within strings.

    int main() {
      pprint::PrettyPrinter printer;
      printer.print("x'x\"x");
      printer.print("x\nx\nx");
    }
    

    It produces just the contents of the string with quotes. Is this intended behavior?

    opened by kccqzy 1
  • CMake fixes

    CMake fixes

    1. use CPack to create source packages: this should make it easy and fast to create a new release. Simply run mkdir build && cd build && cmake .. && make --build . --target package_source. To create the release, cmake copies all files in the source directory except those in the ignore list, which I've created from the .gitignore file. So it is important to keep the source tree clean when doing a source release.
    2. create+install a pprint.pc pkg-config file
    3. optionally use catch2 from the system repositories 4.. only enable install+cpack when pprint is built as a main project
    4. test install + packaging on ci
    5. add appveyor script: sample output: https://ci.appveyor.com/project/madebr/pprint/builds/30827828
    opened by madebr 0
  • conan: conan 'create .' will now build the recipe

    conan: conan 'create .' will now build the recipe

    My previous pr broke conan in that it the version of the conanfile was not set properly. Also, conan build did not work at all.. This is fixed in this pr. It is now possible to create a conan package using:

    conan create .
    
    opened by madebr 0
  • CMake updates + ci

    CMake updates + ci

    • create & install pprintConfigVersion.cmake
    • add .travis.yml file: sample ci result: https://travis-ci.com/madebr/pprint/builds/149076286
    • update conanfile.py
    • enable ctest support
    opened by madebr 0
  • added inline so pprint can be included in multiple translation units …

    added inline so pprint can be included in multiple translation units …

    …of larger codebases

    This allows various header files can include pprint and with no conflict of multiple redefinition. Maybe I missed more, but this fixes it for my needs at the moment.

    opened by JorySchossau 0
  • Fix incorrect setting of INTERFACE_INCLUDE_DIRECTORIES

    Fix incorrect setting of INTERFACE_INCLUDE_DIRECTORIES

    Currently, the INTERFACE_INCLUDE_DIRECTORIES property in pprintConfig.cmake is set as:

    set_target_properties(pprint::pprint PROPERTIES
      INTERFACE_COMPILE_FEATURES "cxx_std_17"
      INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;/include"
    )
    

    and it causes building error for some users: https://github.com/microsoft/vcpkg/issues/7301 .

    opened by myd7349 0
  • Enable warnings as errors in tests and fix warning

    Enable warnings as errors in tests and fix warning

    Great library, I have warnings as errors which I'd like to not exempt dependencies from. I think this helps improve the quality of this project. Thanks.

    opened by wrayste 0
  • Compiling with structopt fails

    Compiling with structopt fails

    It seems like including both <pprint.hpp> and <structopt/structopt.hpp> will lead to conflicts, as magic_enum gets redefined. Is there a standard way to use both pprint and structopt or am I missing something obvious?

    opened by GaniAliguzhinov 1
Owner
Pranav
Pranav
Localify "ウマ娘: Pretty Derby" DMM client

中文 赛马娘 (DMM版) 本地化补丁 使用方法: 将 version.dll 和 config.json 以及 config.json 中引用的字典放置于 umamusume.exe 边上 启动游戏 设置选项: enableConsole 启用用来输出调试信息的控制台 (true/false) e

GEEKiDoS 200 Jun 26, 2022
Juice the carrots from ウマ娘プリティーダービー (Umamusume Pretty Derby) - Windows implementation

Hooks the decryption function in libnative.dll of ウマ娘プリティーダービー (Umamusume Pretty Derby), to allow inspecting the packets (and provide some useful information during the game).

Huang Yue 67 Jun 30, 2022
Pretty much the repo name sums it up.

?? Console_Calculator Version Supported Date Ended Support v.1.0 ✔️ ?? Features The ?? Console_Calculator can do basic arithmatic, and yes there is no

Angelo Petrai 3 Dec 31, 2021
its a pretty dodo 0.1% os

Dodo OS why did i make this os? idk im bored and i wanted to learn alot of new stuff. so i decided to make dodo os. i will see for how far i will go i

Voidy Devleoper 5 Jan 4, 2022
Generate code for pretty-printing C++ enums

enums Generate code for pretty-printing C++ enums. Supported platforms Only Linux x86/x86_64 systems are supported. For the missing platforms, the too

Andrei Burdulescu 0 Jan 31, 2022
This is 3d printer motherboard for VORON project.

Features Compact size: 155.3mm x 76.5mm Based on STM32F446 180Mhz,all IOs can withstand 5V voltage 8 TMC stepper drivers support, with Uart&SPI suppor

FYSETC.COM 208 Jun 23, 2022
Firmware of Anycubic 3D printer Vyper

Marlin 3D Printer Firmware Additional documentation can be found at the Marlin Home Page. Please test this firmware and let us know if it misbehaves i

null 69 Jun 19, 2022
3D printer control board based on ESP32,support 8 Driver motors.

PandaZHU use ESP32 as the mcu for 3D printer motherboard. Zhu is Chinese for bamboo it has larger memory and more powerful than normal 32bit 3D printe

Mark 38 Jun 28, 2022
CAN bus extruder, more resistant to noise,reduce a lot of wires for your 3D printer

PandaCAN is an extruder control board that connect to main board with CAN interface, more resistant to signal noise,reduce a lot of wires for your 3D printer.

Mark 78 Jun 17, 2022
Contains firmware and software used for the bead sprite printer v2 robotic system

Bead-Sprite-Printer-V2 Contains firmware and software used for the bead sprite printer v2 robotic system bead_fuser_arduino - this folder contains the

null 3 Jun 23, 2022
ESP32S2 Arduino USB host printer, MIDI, and keyboard demos

ESP32 S2 USB Host Jumpstart A collection of experiments and demos using Espressif ESP32 S2 in USB host mode. Most of the sketches have little or no C+

null 14 Jun 17, 2022
MarlinRB - 3D Printer Firmware based on Marlin 3D v2.0.9.2, for Flyingbear Reborn with MKS Robin Nano v1.2, MKS Robin Nano v1.3, MKS Robin Nano S v1.3

English Прошивка MarlinRB для принтера Flyingbear Reborn Работает с платами: MKS Robin Nano v1.3 (съемные драйвера, контроллер STM32F407), MKS Robin N

AndyBig 11 Jun 29, 2022
Side panels for the Voron Zero printer that has 16 WS2812 RGB LED's per side.

Voron Zero RGB Side Panels Side panels for the Voron Zero printer with 16 WS2812 RGB LED's per side. The build below has some 3mm TAP Plastic black LE

Tim Abraham 2 Dec 6, 2021
Professional Firmware for the Creality Ender 3 v2 3D Printer

Professional Firmware for the Creality Ender 3 v2 3D Printer Please test this firmware and let us know if it misbehaves in any way. Volunteers are sta

Miguel Risco-Castillo 424 Jun 30, 2022
Professional Firmware for the Creality Ender 3 s1 3D Printer

Professional Firmware for the Creality Ender 3 s1 3D Printer Please test this firmware and let us know if it misbehaves in any way. Volunteers are sta

Miguel Risco-Castillo 28 May 16, 2022
This is the repository that contains the firmware for theTINA2 3D Printer.

TINA2 Firmware Summary This is the repository that contains the firmware for the TINA2 3D Printer. The framework of the firmware is based on the Marli

perron 8 Jun 9, 2022
Mods to improve the Kingroom KP3S 3d printer (STM32F407 chip)

Kingroon KP3S Mods Mods for Kingroon KP3S. The original printer started with a titan extruder. The board model on this machines is the STM32F407 so th

Steggy 5 Jun 8, 2022
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more

EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++. Among others, it's used in Minecraft by

Michele Caini 6.9k Jun 24, 2022