FE 0.6.1
A header-only C++ library for writing frontends
Loading...
Searching...
No Matches
format.h
Go to the documentation of this file.
1#pragma once
2
3#include <format>
4
5#include "fe/loc.h"
6#include "fe/utf8.h"
7
8namespace fe {
9
10/// Make types that support ostream operators available for `std::format`.
11/// Use like this:
12/// ```
13/// template<> struct std::formatter<T> : fe::ostream_formatter {};
14/// ```
15/// @sa [Stack Overflow](https://stackoverflow.com/a/75738462).
16template<class Char>
17struct basic_ostream_formatter : std::formatter<std::basic_string_view<Char>, Char> {
18 template<class T, class O>
19 O format(const T& value, std::basic_format_context<O, Char>& ctx) const {
20 std::basic_stringstream<Char> ss;
21 ss << value;
22#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000
23 return std::formatter<std::basic_string_view<Char>, Char>::format(ss.str(), ctx);
24#else
25 return std::formatter<std::basic_string_view<Char>, Char>::format(ss.view(), ctx);
26#endif
27 }
28};
29
31
32/// @name out/outln/err/errln
33/// Print to `std::cout`/`std::cerr` via `std::format`; the `*ln` variants conclude with `std::endl`.
34///@{
35// clang-format off
36template<class... Args> void err (std::format_string<Args...> fmt, Args&&... args) { std::cerr << std::format(fmt, std::forward<Args>(args)...); }
37template<class... Args> void out (std::format_string<Args...> fmt, Args&&... args) { std::cout << std::format(fmt, std::forward<Args>(args)...); }
38template<class... Args> void errln(std::format_string<Args...> fmt, Args&&... args) { std::cerr << std::format(fmt, std::forward<Args>(args)...) << std::endl; }
39template<class... Args> void outln(std::format_string<Args...> fmt, Args&&... args) { std::cout << std::format(fmt, std::forward<Args>(args)...) << std::endl; }
40// clang-format on
41
42/// Keeps track of indentation level during output
43class Tab {
44public:
45 Tab(const Tab&) = default;
46 Tab(std::string_view tab = {"\t"}, size_t indent = 0)
47 : tab_(tab)
48 , indent_(indent) {}
49
50 /// @name Getters
51 ///@{
52 size_t indent() const { return indent_; }
53 std::string_view tab() const { return tab_; }
54 ///@}
55
56 /// @name Setters
57 ///@{
58 Tab& operator=(size_t indent) {
59 indent_ = indent;
60 return *this;
61 }
62 Tab& operator=(std::string tab) {
63 tab_ = tab;
64 return *this;
65 }
66 ///@}
67
68 // clang-format off
69 /// @name Indent/Dedent
70 ///@{
71 Tab& operator++() { ++indent_; return *this; }
72 Tab& operator--() { assert(indent_ > 0); --indent_; return *this; }
73 Tab& operator+=(size_t indent) { indent_ += indent; return *this; }
74 Tab& operator-=(size_t indent) { assert(indent_ > 0); indent_ -= indent; return *this; }
75 Tab operator++(int) { auto res = *this; ++indent_; return res; }
76 Tab operator--(int) { assert(indent_ > 0); auto res = *this; --indent_; return res; }
77 Tab operator+(size_t indent) const { return {tab_, indent_ + indent}; }
78 Tab operator-(size_t indent) const { assert(indent_ > 0); return {tab_, indent_ - indent}; }
79 ///@}
80 // clang-format on
81
82 friend std::ostream& operator<<(std::ostream& os, Tab tab) {
83 for (size_t i = 0; i != tab.indent_; ++i)
84 os << tab.tab_;
85 return os;
86 }
87
88private:
89 std::string_view tab_;
90 size_t indent_ = 0;
91};
92
93} // namespace fe
94
95#ifndef DOXYGEN
96// clang-format off
97template<> struct std::formatter<fe::Pos> : fe::ostream_formatter {};
98template<> struct std::formatter<fe::Loc> : fe::ostream_formatter {};
99template<> struct std::formatter<fe::Sym> : fe::ostream_formatter {};
100template<> struct std::formatter<fe::Tab> : fe::ostream_formatter {};
101template<> struct std::formatter<fe::utf8::Char32> : fe::ostream_formatter {};
102// clang-format on
103#endif
Keeps track of indentation level during output.
Definition format.h:43
Tab operator-(size_t indent) const
Definition format.h:78
Tab & operator--()
Definition format.h:72
Tab & operator-=(size_t indent)
Definition format.h:74
friend std::ostream & operator<<(std::ostream &os, Tab tab)
Definition format.h:82
Tab(std::string_view tab={"\t"}, size_t indent=0)
Definition format.h:46
size_t indent() const
Definition format.h:52
Tab operator+(size_t indent) const
Definition format.h:77
Tab operator++(int)
Definition format.h:75
Tab & operator+=(size_t indent)
Definition format.h:73
Tab & operator=(std::string tab)
Definition format.h:62
Tab & operator=(size_t indent)
Definition format.h:58
Tab(const Tab &)=default
Tab & operator++()
Definition format.h:71
Tab operator--(int)
Definition format.h:76
std::string_view tab() const
Definition format.h:53
Definition arena.h:10
void errln(std::format_string< Args... > fmt, Args &&... args)
Definition format.h:38
void err(std::format_string< Args... > fmt, Args &&... args)
Definition format.h:36
void outln(std::format_string< Args... > fmt, Args &&... args)
Definition format.h:39
void out(std::format_string< Args... > fmt, Args &&... args)
Definition format.h:37
Make types that support ostream operators available for std::format.
Definition format.h:17
O format(const T &value, std::basic_format_context< O, Char > &ctx) const
Definition format.h:19