HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
markup.hpp
Go to the documentation of this file.
1
2
3#pragma once
4
5#include "grapheme.hpp"
6#include "phrasing.hpp"
7#include "gstring.hpp"
8#include "../i18n/i18n.hpp"
9#include "../utility/utility.hpp"
10#include <string>
11#include <string_view>
12#include <algorithm>
13#include <iterator>
14#include <ranges>
15#include <concepts>
16
17hi_export_module(hikogui.unicode.markup);
18
19hi_export namespace hi { inline namespace v1 {
20
49
58hi_export template<std::input_or_output_iterator It, std::sentinel_for<It> ItEnd>
59constexpr It
60apply_markup(It first, ItEnd last, language_tag default_language = language_tag{"en-US"}, phrasing default_phrasing = phrasing::regular) noexcept
61 requires std::same_as<typename It::value_type, grapheme>
62{
63 enum class state_type { idle, command };
64
65 auto src_it = first;
66 auto dst_it = first;
67 auto command_start = first;
68
69 default_language = default_language.expand();
70 auto current_language = default_language;
71 auto current_phrasing = default_phrasing;
72
73 auto write_character = [&](grapheme c) {
74 c.set_language_tag(current_language);
75 c.set_phrasing(current_phrasing);
76 *dst_it++ = c;
77 };
78
79 auto write_command = [&](gstring_view command) {
80 write_character('[');
81 for (auto c : command) {
82 write_character(c);
83 }
84 write_character(']');
85 };
86
87 auto state = state_type::idle;
88 while (src_it != last) {
89 auto c = *src_it++;
90
91 if (state == state_type::idle) {
92 if (c == '[') {
93 command_start = src_it;
94 state = state_type::command;
95 } else {
96 write_character(c);
97 }
98
99 } else if (state == state_type::command) {
100 if (c == '[') {
101 // Escaped open bracket.
102 write_character(c);
103 state = state_type::idle;
104
105 } else if (c == ']') {
106 // End of command.
107 auto command = gstring_view{command_start, src_it - 1};
108 if (command.empty()) {
109 // An empty command is an error, keep the command in the text.
110 write_command(command);
111
112 } else if (command.size() == 1) {
113 if (auto const command_g = command.front(); command_g.is_ascii()) {
114 auto const command_c = char_cast<char>(command_g.starter());
115 if (command_c == '.') {
116 current_language = default_language;
117 current_phrasing = default_phrasing;
118
119 } else if (auto p = to_phrasing(command_c)) {
120 current_phrasing = *p;
121
122 } else {
123 // Unknown command, leep the command in the text.
124 write_command(command);
125 }
126
127 } else {
128 // Unknown command, keep the command in the text.
129 write_command(command);
130 }
131
132 } else {
133 try {
134 current_language = language_tag{to_string(command)}.expand();
135 } catch (...) {
136 // Leave the full command in the output.
137 write_command(command);
138 }
139 }
140 state = state_type::idle;
141 }
142 }
143 }
144
145 return dst_it;
146}
147
155hi_export [[nodiscard]] constexpr gstring
156apply_markup(gstring str, language_tag default_language = language_tag{"en-US"}, phrasing default_phrasing = phrasing::regular) noexcept
157{
158 auto it = apply_markup(str.begin(), str.end(), default_language, default_phrasing);
159 str.erase(it, str.end());
160 return str;
161}
162
170hi_export [[nodiscard]] constexpr gstring
171apply_markup(std::string_view str, language_tag default_language = language_tag{"en-US"}, phrasing default_phrasing = phrasing::regular) noexcept
172{
173 return apply_markup(to_gstring(str), default_language, default_phrasing);
174}
175
176}} // namespace hi::v1
@ grapheme
The gui_event has grapheme data.
Definition gui_event_variant.hpp:40
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
constexpr Out char_cast(In rhs) noexcept
Cast a character.
Definition cast.hpp:560
hi_export constexpr It apply_markup(It first, ItEnd last, language_tag default_language=language_tag{"en-US"}, phrasing default_phrasing=phrasing::regular) noexcept
Inplace-apply markup to a string of graphemes.
Definition markup.hpp:60
The IETF BCP 47 language tag.
Definition language_tag_intf.hpp:30
language_tag expand() const noexcept
Expand the language tag to include script and language.
Definition language_tag_impl.hpp:2043