• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tstack / lnav / 21219323786-2766

21 Jan 2026 05:28PM UTC coverage: 68.961% (-0.04%) from 68.999%
21219323786-2766

push

github

tstack
[log_format] display an error if there is a JSON timestamp property, but it does not parse correctly

41 of 50 new or added lines in 3 files covered. (82.0%)

40 existing lines in 6 files now uncovered.

51838 of 75170 relevant lines covered (68.96%)

437089.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.53
/src/base/string_attr_type.hh
1
/**
2
 * Copyright (c) 2020, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29

30
#ifndef lnav_string_attr_type_hh
31
#define lnav_string_attr_type_hh
32

33
#include <memory>
34
#include <optional>
35
#include <string>
36
#include <utility>
37

38
#include <stdint.h>
39

40
#include "base/file_range.hh"
41
#include "base/intern_string.hh"
42
#include "base/string_util.hh"
43
#include "color_spaces.hh"
44
#include "enum_util.hh"
45
#include "mapbox/variant.hpp"
46
#include "text_format_enum.hh"
47

48
class logfile;
49
struct bookmark_metadata;
50

51
enum class ui_icon_t : int32_t {
52
    hidden,
53
    ok,
54
    info,
55
    warning,
56
    error,
57

58
    log_level_trace,
59
    log_level_debug,
60
    log_level_info,
61
    log_level_stats,
62
    log_level_notice,
63
    log_level_warning,
64
    log_level_error,
65
    log_level_critical,
66
    log_level_fatal,
67

68
    play,
69
    edit,
70
    file,
71
    thread,
72
};
73

74
constexpr auto ui_icon_count = lnav::enums::to_underlying(ui_icon_t::thread) + 1;
75

76
/** Roles that can be mapped to curses attributes using attrs_for_role() */
77
enum class role_t : int32_t {
78
    VCR_NONE = -1,
79

80
    VCR_TEXT, /*< Raw text. */
81
    VCR_IDENTIFIER,
82
    VCR_SEARCH, /*< A search hit. */
83
    VCR_OK,
84
    VCR_INFO,
85
    VCR_ERROR, /*< An error message. */
86
    VCR_WARNING, /*< A warning message. */
87
    VCR_ALT_ROW, /*< Highlight for alternating rows in a list */
88
    VCR_HIDDEN,
89
    VCR_CURSOR_LINE,
90
    VCR_DISABLED_CURSOR_LINE,
91
    VCR_ADJUSTED_TIME,
92
    VCR_SKEWED_TIME,
93
    VCR_OFFSET_TIME,
94
    VCR_TIME_COLUMN,
95
    VCR_TIME_COLUMN_TO_TEXT,
96
    VCR_FILE_OFFSET,
97
    VCR_INVALID_MSG,
98
    VCR_STATUS, /*< Normal status line text. */
99
    VCR_WARN_STATUS,
100
    VCR_ALERT_STATUS, /*< Alert status line text. */
101
    VCR_ACTIVE_STATUS, /*< */
102
    VCR_ACTIVE_STATUS2, /*< */
103
    VCR_STATUS_TITLE,
104
    VCR_STATUS_SUBTITLE,
105
    VCR_STATUS_INFO,
106
    VCR_STATUS_STITCH_TITLE_TO_SUB,
107
    VCR_STATUS_STITCH_SUB_TO_TITLE,
108
    VCR_STATUS_STITCH_SUB_TO_NORMAL,
109
    VCR_STATUS_STITCH_NORMAL_TO_SUB,
110
    VCR_STATUS_STITCH_TITLE_TO_NORMAL,
111
    VCR_STATUS_STITCH_NORMAL_TO_TITLE,
112
    VCR_STATUS_TITLE_HOTKEY,
113
    VCR_STATUS_DISABLED_TITLE,
114
    VCR_STATUS_HOTKEY,
115
    VCR_INACTIVE_STATUS,
116
    VCR_INACTIVE_ALERT_STATUS,
117
    VCR_SCROLLBAR,
118
    VCR_SCROLLBAR_ERROR,
119
    VCR_SCROLLBAR_WARNING,
120
    VCR_FOCUSED,
121
    VCR_DISABLED_FOCUSED,
122
    VCR_POPUP,
123
    VCR_POPUP_BORDER,
124
    VCR_COLOR_HINT,
125

126
    VCR_QUOTED_CODE,
127
    VCR_CODE_BORDER,
128
    VCR_KEYWORD,
129
    VCR_STRING,
130
    VCR_COMMENT,
131
    VCR_DOC_DIRECTIVE,
132
    VCR_VARIABLE,
133
    VCR_SYMBOL,
134
    VCR_NULL,
135
    VCR_ASCII_CTRL,
136
    VCR_NON_ASCII,
137
    VCR_NUMBER,
138
    VCR_RE_SPECIAL,
139
    VCR_RE_REPEAT,
140
    VCR_FILE,
141

142
    VCR_DIFF_DELETE, /*< Deleted line in a diff. */
143
    VCR_DIFF_ADD, /*< Added line in a diff. */
144
    VCR_DIFF_SECTION, /*< Section marker in a diff. */
145

146
    VCR_LOW_THRESHOLD,
147
    VCR_MED_THRESHOLD,
148
    VCR_HIGH_THRESHOLD,
149

150
    VCR_H1,
151
    VCR_H2,
152
    VCR_H3,
153
    VCR_H4,
154
    VCR_H5,
155
    VCR_H6,
156

157
    VCR_HR,
158
    VCR_HYPERLINK,
159
    VCR_LIST_GLYPH,
160
    VCR_BREADCRUMB,
161
    VCR_TABLE_BORDER,
162
    VCR_TABLE_HEADER,
163
    VCR_QUOTE_BORDER,
164
    VCR_QUOTED_TEXT,
165
    VCR_FOOTNOTE_BORDER,
166
    VCR_FOOTNOTE_TEXT,
167
    VCR_SNIPPET_BORDER,
168
    VCR_INDENT_GUIDE,
169
    VCR_INLINE_CODE,
170
    VCR_FUNCTION,
171
    VCR_TYPE,
172
    VCR_SEP_REF_ACC,
173
    VCR_SUGGESTION,
174
    VCR_SELECTED_TEXT,
175
    VCR_FUZZY_MATCH,
176

177
    VCR_OBJECT_KEY,
178

179
    VCR_SPECTRO_THRESHOLD0,
180
    VCR_SPECTRO_THRESHOLD1,
181
    VCR_SPECTRO_THRESHOLD2,
182
    VCR_SPECTRO_THRESHOLD3,
183
    VCR_SPECTRO_THRESHOLD4,
184
    VCR_SPECTRO_THRESHOLD5,
185
    VCR_SPECTRO_THRESHOLD6,
186

187
    VCR__MAX
188
};
189

190
struct text_attrs {
191
    enum class style : uint32_t {
192
        none = 0x0000,
193
        struck = 0x0001u,
194
        bold = 0x0002u,
195
        undercurl = 0x0004u,
196
        underline = 0x0008u,
197
        italic = 0x0010u,
198
        altcharset = 0x0020u,
199
        blink = 0x0040u,
200
        reverse = 0x1000u,
201
    };
202

203
    static text_attrs with_struck()
622✔
204
    {
205
        return text_attrs{
206
            lnav::enums::to_underlying(style::struck),
207
        };
622✔
208
    }
209

210
    static text_attrs with_bold()
845✔
211
    {
212
        return text_attrs{
213
            lnav::enums::to_underlying(style::bold),
214
        };
845✔
215
    }
216

217
    static text_attrs with_undercurl()
218
    {
219
        return text_attrs{
220
            lnav::enums::to_underlying(style::undercurl),
221
        };
222
    }
223

224
    static text_attrs with_underline()
47,617✔
225
    {
226
        return text_attrs{
227
            lnav::enums::to_underlying(style::underline),
228
        };
47,617✔
229
    }
230

231
    static text_attrs with_italic()
622✔
232
    {
233
        return text_attrs{
234
            lnav::enums::to_underlying(style::italic),
235
        };
622✔
236
    }
237

238
    static text_attrs with_reverse()
48,974✔
239
    {
240
        return text_attrs{
241
            lnav::enums::to_underlying(style::reverse),
242
        };
48,974✔
243
    }
244

245
    static text_attrs with_altcharset()
114✔
246
    {
247
        return text_attrs{
248
            lnav::enums::to_underlying(style::altcharset),
249
        };
114✔
250
    }
251

252
    static text_attrs with_blink()
253
    {
254
        return text_attrs{
255
            lnav::enums::to_underlying(style::blink),
256
        };
257
    }
258

259
    template<typename... Args>
260
    static text_attrs with_styles(Args... args)
249✔
261
    {
262
        auto retval = text_attrs{};
249✔
263

264
        for (auto arg : {args...}) {
747✔
265
            retval.ta_attrs |= lnav::enums::to_underlying(arg);
498✔
266
        }
267
        return retval;
249✔
268
    }
269

270
    bool empty() const
52,699✔
271
    {
272
        return this->ta_attrs == 0 && this->ta_fg_color.empty()
42,100✔
273
            && this->ta_bg_color.empty();
94,799✔
274
    }
275

276
    text_attrs operator|(const text_attrs& other) const
60,591✔
277
    {
278
        return text_attrs{
279
            this->ta_attrs | other.ta_attrs,
60,591✔
280
            !this->ta_fg_color.empty() ? this->ta_fg_color : other.ta_fg_color,
60,591✔
281
            !this->ta_bg_color.empty() ? this->ta_bg_color : other.ta_bg_color,
60,591✔
282
        };
181,773✔
283
    }
284

285
    text_attrs operator|(const style other) const
850✔
286
    {
287
        return text_attrs{
288
            this->ta_attrs | lnav::enums::to_underlying(other),
1,700✔
289
            this->ta_fg_color,
290
            this->ta_bg_color,
291
        };
850✔
292
    }
293

294
    text_attrs& operator|=(const style other)
746,783✔
295
    {
296
        this->ta_attrs |= lnav::enums::to_underlying(other);
746,783✔
297
        return *this;
746,783✔
298
    }
299

300
    void clear_style(style other)
10✔
301
    {
302
        this->ta_attrs &= ~lnav::enums::to_underlying(other);
10✔
303
    }
10✔
304

305
    bool has_style(style other) const
30,516✔
306
    {
307
        return this->ta_attrs & lnav::enums::to_underlying(other);
30,516✔
308
    }
309

310
    bool operator==(const text_attrs& other) const
×
311
    {
312
        return this->ta_attrs == other.ta_attrs
×
313
            && this->ta_fg_color == other.ta_fg_color
×
314
            && this->ta_bg_color == other.ta_bg_color;
×
315
    }
316

317
    uint32_t ta_attrs{0};
318
    styling::color_unit ta_fg_color{styling::color_unit::EMPTY};
319
    styling::color_unit ta_bg_color{styling::color_unit::EMPTY};
320
    std::optional<text_align_t> ta_align;
321
};
322

323
struct block_elem_t {
324
    char32_t value;
325
    role_t role;
326

327
    bool operator==(const block_elem_t& rhs) const
328
    {
329
        return this->value == rhs.value && this->role == rhs.role;
330
    }
331
};
332

333
struct ui_command {
334
    source_location uc_location;
335
    std::string uc_command;
336

337
    bool operator==(const ui_command& rhs) const
338
    {
339
        return this->uc_location == rhs.uc_location
340
            && this->uc_command == rhs.uc_command;
341
    }
342
};
343

344
using string_attr_value = mapbox::util::variant<int64_t,
345
                                                role_t,
346
                                                text_attrs,
347
                                                intern_string_t,
348
                                                std::string,
349
                                                std::shared_ptr<logfile>,
350
                                                bookmark_metadata*,
351
                                                string_fragment,
352
                                                block_elem_t,
353
                                                styling::color_unit,
354
                                                ui_icon_t,
355
                                                const char*,
356
                                                ui_command,
357
                                                text_format_t>;
358

359
class string_attr_type_base {
360
public:
361
    explicit constexpr string_attr_type_base(const char* name) noexcept
362
        : sat_name(name)
363
    {
364
    }
365

366
    const char* const sat_name;
367
};
368

369
using string_attr_pair
370
    = std::pair<const string_attr_type_base*, string_attr_value>;
371

372
template<typename T>
373
class string_attr_type : public string_attr_type_base {
374
public:
375
    using value_type = T;
376

377
    explicit constexpr string_attr_type(const char* name) noexcept
378
        : string_attr_type_base(name)
379
    {
380
    }
381

382
    template<typename U = T>
383
    std::enable_if_t<std::is_void_v<U>, string_attr_pair> value() const
123,918✔
384
    {
385
        return std::make_pair(this, string_attr_value{mapbox::util::no_init{}});
123,918✔
386
    }
387

388
    template<std::size_t N>
389
    std::enable_if_t<(N > 0) && std::is_same_v<std::string, T>,
390
                     string_attr_pair>
UNCOV
391
    value(const char (&val)[N]) const
×
392
    {
UNCOV
393
        return std::make_pair(this, std::string(val));
×
394
    }
395

396
    template<typename U = T>
397
    constexpr std::enable_if_t<!std::is_void_v<U>
398
                                   && std::is_convertible_v<U, T>,
399
                               string_attr_pair>
400
    value(U&& val) const
1,518,832✔
401
    {
402
        if constexpr (std::is_same_v<const char*, U>
403
                      && std::is_same_v<std::string, T>)
404
        {
405
            return std::make_pair(this, std::string(val));
406
        }
407
        return std::make_pair(this, val);
1,518,832✔
408
    }
409
};
410

411
extern const string_attr_type<void> SA_ORIGINAL_LINE;
412
extern const string_attr_type<void> SA_BODY;
413
extern const string_attr_type<void> SA_SRC_FILE;
414
extern const string_attr_type<void> SA_SRC_LINE;
415
extern const string_attr_type<void> SA_THREAD_ID;
416
extern const string_attr_type<void> SA_DURATION;
417
extern const string_attr_type<void> SA_EXTRA_CONTENT;
418
extern const string_attr_type<ui_icon_t> SA_HIDDEN;
419
extern const string_attr_type<void> SA_REPLACED;
420
extern const string_attr_type<intern_string_t> SA_FORMAT;
421
extern const string_attr_type<void> SA_REMOVED;
422
extern const string_attr_type<void> SA_PREFORMATTED;
423
extern const string_attr_type<std::string> SA_INVALID;
424
extern const string_attr_type<std::string> SA_ERROR;
425
extern const string_attr_type<int64_t> SA_LEVEL;
426
extern const string_attr_type<int64_t> SA_ORIGIN_OFFSET;
427
extern const string_attr_type<text_format_t> SA_QUOTED_TEXT;
428

429
extern const string_attr_type<std::string> VC_ANCHOR;
430
extern const string_attr_type<role_t> VC_ROLE;
431
extern const string_attr_type<role_t> VC_ROLE_FG;
432
extern const string_attr_type<text_attrs> VC_STYLE;
433
extern const string_attr_type<const char*> VC_GRAPHIC;
434
extern const string_attr_type<block_elem_t> VC_BLOCK_ELEM;
435
extern const string_attr_type<styling::color_unit> VC_FOREGROUND;
436
extern const string_attr_type<styling::color_unit> VC_BACKGROUND;
437
extern const string_attr_type<std::string> VC_HYPERLINK;
438
extern const string_attr_type<ui_icon_t> VC_ICON;
439
extern const string_attr_type<ui_command> VC_COMMAND;
440

441
namespace lnav {
442

443
namespace string::attrs {
444

445
template<typename S>
446
std::pair<S, string_attr_pair>
447
preformatted(S str)
448
{
449
    return std::make_pair(std::move(str), SA_PREFORMATTED.value());
450
}
451

452
template<typename S>
453
std::pair<S, string_attr_pair>
454
href(S str, std::string href)
18✔
455
{
456
    return std::make_pair(std::move(str), VC_HYPERLINK.value(std::move(href)));
18✔
457
}
458

459
}  // namespace string::attrs
460

461
namespace roles {
462

463
template<typename S>
464
std::pair<S, string_attr_pair>
465
for_flag(S str, bool flag)
16✔
466
{
467
    return std::make_pair(
468
        std::move(str),
16✔
469
        VC_ROLE.value(flag ? role_t::VCR_OK : role_t::VCR_ERROR));
32✔
470
}
471

472
template<typename S>
473
std::pair<S, string_attr_pair>
474
error(S str)
419✔
475
{
476
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_ERROR));
419✔
477
}
478

479
template<typename S>
480
std::pair<S, string_attr_pair>
481
warning(S str)
400✔
482
{
483
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_WARNING));
400✔
484
}
485

486
template<typename S>
487
std::pair<S, string_attr_pair>
488
status(S str)
489
{
490
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_STATUS));
491
}
492

493
template<typename S>
494
std::pair<S, string_attr_pair>
495
inactive_status(S str)
496
{
497
    return std::make_pair(std::move(str),
498
                          VC_ROLE.value(role_t::VCR_INACTIVE_STATUS));
499
}
500

501
template<typename S>
502
std::pair<S, string_attr_pair>
503
status_title(S str)
16✔
504
{
505
    return std::make_pair(std::move(str),
16✔
506
                          VC_ROLE.value(role_t::VCR_STATUS_TITLE));
32✔
507
}
508

509
template<typename S>
510
std::pair<S, string_attr_pair>
511
status_subtitle(S str)
512
{
513
    return std::make_pair(std::move(str),
514
                          VC_ROLE.value(role_t::VCR_STATUS_SUBTITLE));
515
}
516

517
template<typename S>
518
std::pair<S, string_attr_pair>
519
ok(S str)
3✔
520
{
521
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_OK));
3✔
522
}
523

524
template<typename S>
525
std::pair<S, string_attr_pair>
526
hidden(S str)
26✔
527
{
528
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HIDDEN));
26✔
529
}
530

531
template<typename S>
532
std::pair<S, string_attr_pair>
533
file(S str)
370✔
534
{
535
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_FILE));
370✔
536
}
537

538
template<typename S>
539
std::pair<S, string_attr_pair>
540
symbol(S str)
15,917✔
541
{
542
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_SYMBOL));
15,917✔
543
}
544

545
template<typename S>
546
std::pair<S, string_attr_pair>
547
keyword(S str)
150✔
548
{
549
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_KEYWORD));
150✔
550
}
551

552
template<typename S>
553
std::pair<S, string_attr_pair>
554
variable(S str)
2,568✔
555
{
556
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_VARIABLE));
2,568✔
557
}
558

559
template<typename S>
560
std::pair<S, string_attr_pair>
561
number(S str)
4,180✔
562
{
563
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_NUMBER));
4,180✔
564
}
565

566
template<typename S>
567
std::pair<S, string_attr_pair>
568
comment(S str)
4✔
569
{
570
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_COMMENT));
4✔
571
}
572

573
template<typename S>
574
std::pair<S, string_attr_pair>
575
identifier(S str)
2,802✔
576
{
577
    return std::make_pair(std::move(str),
2,802✔
578
                          VC_ROLE.value(role_t::VCR_IDENTIFIER));
5,604✔
579
}
580

581
template<typename S>
582
std::pair<S, string_attr_pair>
583
string(S str)
1✔
584
{
585
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_STRING));
1✔
586
}
587

588
template<typename S>
589
std::pair<S, string_attr_pair>
590
hr(S str)
×
591
{
592
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HR));
×
593
}
594

595
template<typename S>
596
std::pair<S, string_attr_pair>
597
hyperlink(S str)
332✔
598
{
599
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HYPERLINK));
332✔
600
}
601

602
template<typename S>
603
std::pair<S, string_attr_pair>
604
list_glyph(S str)
370✔
605
{
606
    return std::make_pair(std::move(str),
370✔
607
                          VC_ROLE.value(role_t::VCR_LIST_GLYPH));
740✔
608
}
609

610
template<typename S>
611
std::pair<S, string_attr_pair>
612
breadcrumb(S str)
613
{
614
    return std::make_pair(std::move(str),
615
                          VC_ROLE.value(role_t::VCR_BREADCRUMB));
616
}
617

618
template<typename S>
619
std::pair<S, string_attr_pair>
620
quoted_code(S str)
2,768✔
621
{
622
    return std::make_pair(std::move(str),
2,768✔
623
                          VC_ROLE.value(role_t::VCR_QUOTED_CODE));
5,536✔
624
}
625

626
template<typename S>
627
std::pair<S, string_attr_pair>
628
code_border(S str)
629
{
630
    return std::make_pair(std::move(str),
631
                          VC_ROLE.value(role_t::VCR_CODE_BORDER));
632
}
633

634
template<typename S>
635
std::pair<S, string_attr_pair>
636
snippet_border(S str)
1✔
637
{
638
    return std::make_pair(std::move(str),
1✔
639
                          VC_ROLE.value(role_t::VCR_SNIPPET_BORDER));
2✔
640
}
641

642
template<typename S>
643
std::pair<S, string_attr_pair>
644
table_border(S str)
901✔
645
{
646
    return std::make_pair(std::move(str),
901✔
647
                          VC_ROLE.value(role_t::VCR_TABLE_BORDER));
1,802✔
648
}
649

650
template<typename S>
651
std::pair<S, string_attr_pair>
652
table_header(S str)
×
653
{
654
    return std::make_pair(std::move(str),
×
655
                          VC_ROLE.value(role_t::VCR_TABLE_HEADER));
×
656
}
657

658
template<typename S>
659
std::pair<S, string_attr_pair>
660
quote_border(S str)
661
{
662
    return std::make_pair(std::move(str),
663
                          VC_ROLE.value(role_t::VCR_QUOTE_BORDER));
664
}
665

666
template<typename S>
667
std::pair<S, string_attr_pair>
668
quoted_text(S str)
669
{
670
    return std::make_pair(std::move(str),
671
                          VC_ROLE.value(role_t::VCR_QUOTED_TEXT));
672
}
673

674
template<typename S>
675
std::pair<S, string_attr_pair>
676
footnote_border(S str)
677
{
678
    return std::make_pair(std::move(str),
679
                          VC_ROLE.value(role_t::VCR_FOOTNOTE_BORDER));
680
}
681

682
template<typename S>
683
std::pair<S, string_attr_pair>
684
footnote_text(S str)
646✔
685
{
686
    return std::make_pair(std::move(str),
646✔
687
                          VC_ROLE.value(role_t::VCR_FOOTNOTE_TEXT));
1,292✔
688
}
689

690
template<typename S>
691
std::pair<S, string_attr_pair>
692
h1(S str)
693
{
694
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H1));
695
}
696

697
template<typename S>
698
std::pair<S, string_attr_pair>
699
h2(S str)
63✔
700
{
701
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H2));
63✔
702
}
703

704
template<typename S>
705
std::pair<S, string_attr_pair>
706
h3(S str)
×
707
{
708
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H3));
×
709
}
710

711
template<typename S>
712
std::pair<S, string_attr_pair>
713
h4(S str)
714
{
715
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H4));
716
}
717

718
template<typename S>
719
std::pair<S, string_attr_pair>
720
h5(S str)
×
721
{
722
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H5));
×
723
}
724

725
template<typename S>
726
std::pair<S, string_attr_pair>
727
h6(S str)
728
{
729
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H6));
730
}
731

732
template<typename S>
733
std::pair<S, string_attr_pair>
734
suggestion(S str)
735
{
736
    return std::make_pair(std::move(str),
737
                          VC_ROLE.value(role_t::VCR_SUGGESTION));
738
}
739

740
namespace literals {
741

742
constexpr std::pair<string_fragment, role_t> operator"" _ok(const char* str,
52✔
743
                                                            std::size_t len)
744
{
745
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_OK);
52✔
746
}
747

748
constexpr std::pair<string_fragment, role_t> operator"" _error(const char* str,
224✔
749
                                                               std::size_t len)
750
{
751
    return std::make_pair(string_fragment{str, 0, (int) len},
224✔
752
                          role_t::VCR_ERROR);
448✔
753
}
754

755
constexpr std::pair<string_fragment, role_t> operator"" _warning(
29✔
756
    const char* str, std::size_t len)
757
{
758
    return std::make_pair(string_fragment{str, 0, (int) len},
29✔
759
                          role_t::VCR_WARNING);
58✔
760
}
761

762
constexpr std::pair<string_fragment, role_t> operator"" _info(const char* str,
43,544✔
763
                                                              std::size_t len)
764
{
765
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_INFO);
43,544✔
766
}
767

768
constexpr std::pair<string_fragment, role_t> operator"" _status_title(
769
    const char* str, std::size_t len)
770
{
771
    return std::make_pair(string_fragment{str, 0, (int) len},
772
                          role_t::VCR_STATUS_TITLE);
773
}
774

775
constexpr std::pair<string_fragment, role_t> operator"" _status_subtitle(
×
776
    const char* str, std::size_t len)
777
{
778
    return std::make_pair(string_fragment{str, 0, (int) len},
×
779
                          role_t::VCR_STATUS_SUBTITLE);
×
780
}
781

782
constexpr std::pair<string_fragment, role_t> operator"" _symbol(const char* str,
47✔
783
                                                                std::size_t len)
784
{
785
    return std::make_pair(string_fragment{str, 0, (int) len},
47✔
786
                          role_t::VCR_SYMBOL);
94✔
787
}
788

789
constexpr std::pair<string_fragment, role_t> operator"" _keyword(
5✔
790
    const char* str, std::size_t len)
791
{
792
    return std::make_pair(string_fragment{str, 0, (int) len},
5✔
793
                          role_t::VCR_KEYWORD);
10✔
794
}
795

796
constexpr std::pair<string_fragment, role_t> operator"" _variable(
211✔
797
    const char* str, std::size_t len)
798
{
799
    return std::make_pair(string_fragment{str, 0, (int) len},
211✔
800
                          role_t::VCR_VARIABLE);
422✔
801
}
802

803
constexpr std::pair<string_fragment, role_t> operator"" _comment(
66✔
804
    const char* str, std::size_t len)
805
{
806
    return std::make_pair(string_fragment{str, 0, (int) len},
66✔
807
                          role_t::VCR_COMMENT);
132✔
808
}
809

810
constexpr std::pair<string_fragment, role_t> operator"" _hotkey(const char* str,
715✔
811
                                                                std::size_t len)
812
{
813
    return std::make_pair(string_fragment{str, 0, (int) len},
715✔
814
                          role_t::VCR_STATUS_HOTKEY);
1,430✔
815
}
816

817
constexpr std::pair<string_fragment, role_t> operator"" _h1(const char* str,
67✔
818
                                                            std::size_t len)
819
{
820
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H1);
67✔
821
}
822

823
constexpr std::pair<string_fragment, role_t> operator"" _h2(const char* str,
145✔
824
                                                            std::size_t len)
825
{
826
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H2);
145✔
827
}
828

829
constexpr std::pair<string_fragment, role_t> operator"" _h3(const char* str,
77✔
830
                                                            std::size_t len)
831
{
832
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H3);
77✔
833
}
834

835
constexpr std::pair<string_fragment, role_t> operator"" _h4(const char* str,
1,860✔
836
                                                            std::size_t len)
837
{
838
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H4);
1,860✔
839
}
840

841
constexpr std::pair<string_fragment, role_t> operator"" _h5(const char* str,
30✔
842
                                                            std::size_t len)
843
{
844
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H5);
30✔
845
}
846

847
constexpr std::pair<string_fragment, role_t> operator"" _hr(const char* str,
848
                                                            std::size_t len)
849
{
850
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_HR);
851
}
852

853
constexpr std::pair<string_fragment, role_t> operator"" _hyperlink(
1✔
854
    const char* str, std::size_t len)
855
{
856
    return std::make_pair(string_fragment{str, 0, (int) len},
1✔
857
                          role_t::VCR_HYPERLINK);
2✔
858
}
859

860
constexpr std::pair<string_fragment, role_t> operator"" _list_glyph(
720✔
861
    const char* str, std::size_t len)
862
{
863
    return std::make_pair(string_fragment{str, 0, (int) len},
720✔
864
                          role_t::VCR_LIST_GLYPH);
1,440✔
865
}
866

867
constexpr std::pair<string_fragment, role_t> operator"" _breadcrumb(
51✔
868
    const char* str, std::size_t len)
869
{
870
    return std::make_pair(string_fragment{str, 0, (int) len},
51✔
871
                          role_t::VCR_BREADCRUMB);
102✔
872
}
873

874
constexpr std::pair<string_fragment, role_t> operator"" _quoted_code(
1✔
875
    const char* str, std::size_t len)
876
{
877
    return std::make_pair(string_fragment{str, 0, (int) len},
1✔
878
                          role_t::VCR_QUOTED_CODE);
2✔
879
}
880

881
constexpr std::pair<string_fragment, role_t> operator"" _code_border(
332✔
882
    const char* str, std::size_t len)
883
{
884
    return std::make_pair(string_fragment{str, 0, (int) len},
332✔
885
                          role_t::VCR_CODE_BORDER);
664✔
886
}
887

888
constexpr std::pair<string_fragment, role_t> operator"" _table_header(
68✔
889
    const char* str, std::size_t len)
890
{
891
    return std::make_pair(string_fragment{str, 0, (int) len},
68✔
892
                          role_t::VCR_TABLE_HEADER);
136✔
893
}
894

895
constexpr std::pair<string_fragment, role_t> operator"" _table_border(
896
    const char* str, std::size_t len)
897
{
898
    return std::make_pair(string_fragment{str, 0, (int) len},
899
                          role_t::VCR_TABLE_BORDER);
900
}
901

902
constexpr std::pair<string_fragment, role_t> operator"" _quote_border(
100✔
903
    const char* str, std::size_t len)
904
{
905
    return std::make_pair(string_fragment{str, 0, (int) len},
100✔
906
                          role_t::VCR_QUOTE_BORDER);
200✔
907
}
908

909
constexpr std::pair<string_fragment, role_t> operator"" _quoted_text(
910
    const char* str, std::size_t len)
911
{
912
    return std::make_pair(string_fragment{str, 0, (int) len},
913
                          role_t::VCR_QUOTED_TEXT);
914
}
915

916
constexpr std::pair<string_fragment, role_t> operator"" _footnote_border(
328✔
917
    const char* str, std::size_t len)
918
{
919
    return std::make_pair(string_fragment{str, 0, (int) len},
328✔
920
                          role_t::VCR_FOOTNOTE_BORDER);
656✔
921
}
922

923
constexpr std::pair<string_fragment, role_t> operator"" _footnote_text(
924
    const char* str, std::size_t len)
925
{
926
    return std::make_pair(string_fragment{str, 0, (int) len},
927
                          role_t::VCR_FOOTNOTE_BORDER);
928
}
929

930
constexpr std::pair<string_fragment, role_t> operator"" _snippet_border(
2,014✔
931
    const char* str, std::size_t len)
932
{
933
    return std::make_pair(string_fragment{str, 0, (int) len},
2,014✔
934
                          role_t::VCR_SNIPPET_BORDER);
4,028✔
935
}
936

937
inline std::pair<std::string, string_attr_pair> operator"" _link(
938
    const char* str, std::size_t len)
939
{
940
    return std::make_pair(std::string(str, len),
941
                          VC_HYPERLINK.value(std::string(str, len)));
942
}
943

944
}  // namespace literals
945

946
}  // namespace roles
947
}  // namespace lnav
948

949
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc