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

tstack / lnav / 25603066199-3032

09 May 2026 02:05PM UTC coverage: 70.204% (+0.04%) from 70.162%
25603066199-3032

push

github

tstack
[tabular] multi-line support

238 of 261 new or added lines in 9 files covered. (91.19%)

10 existing lines in 3 files now uncovered.

57551 of 81977 relevant lines covered (70.2%)

634088.25 hits per line

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

88.44
/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
    breakpoint,
69
    disabled_breakpoint,
70

71
    play,
72
    edit,
73
    file,
74
    thread,
75
    tag,
76
    partition,
77
    busy,
78
    reload,
79
};
80

81
constexpr auto ui_icon_count
82
    = lnav::enums::to_underlying(ui_icon_t::reload) + 1;
83

84
/** Roles that can be mapped to curses attributes using attrs_for_role() */
85
enum class role_t : int32_t {
86
    VCR_NONE = -1,
87

88
    VCR_TEXT, /*< Raw text. */
89
    VCR_IDENTIFIER,
90
    VCR_SEARCH, /*< A search hit. */
91
    VCR_OK,
92
    VCR_INFO,
93
    VCR_ERROR, /*< An error message. */
94
    VCR_WARNING, /*< A warning message. */
95
    VCR_ALT_ROW, /*< Highlight for alternating rows in a list */
96
    VCR_CONTEXT_LINE,
97
    VCR_HIDDEN,
98
    VCR_CURSOR_LINE,
99
    VCR_DISABLED_CURSOR_LINE,
100
    VCR_ADJUSTED_TIME,
101
    VCR_SKEWED_TIME,
102
    VCR_OFFSET_TIME,
103
    VCR_TIME_AGO,
104
    VCR_TIME_COLUMN,
105
    VCR_TIME_COLUMN_TO_TEXT,
106
    VCR_FILE_OFFSET,
107
    VCR_INVALID_MSG,
108
    VCR_STATUS, /*< Normal status line text. */
109
    VCR_WARN_STATUS,
110
    VCR_ALERT_STATUS, /*< Alert status line text. */
111
    VCR_ACTIVE_STATUS, /*< */
112
    VCR_ACTIVE_STATUS2, /*< */
113
    VCR_STATUS_TITLE,
114
    VCR_STATUS_SUBTITLE,
115
    VCR_STATUS_INFO,
116
    VCR_STATUS_STITCH_TITLE_TO_SUB,
117
    VCR_STATUS_STITCH_SUB_TO_TITLE,
118
    VCR_STATUS_STITCH_SUB_TO_NORMAL,
119
    VCR_STATUS_STITCH_NORMAL_TO_SUB,
120
    VCR_STATUS_STITCH_TITLE_TO_NORMAL,
121
    VCR_STATUS_STITCH_NORMAL_TO_TITLE,
122
    VCR_STATUS_TITLE_HOTKEY,
123
    VCR_STATUS_DISABLED_TITLE,
124
    VCR_STATUS_HOTKEY,
125
    VCR_ALERT_STATUS_TITLE,
126
    VCR_STATUS_STITCH_ALERT_TITLE_TO_NORMAL,
127
    VCR_STATUS_STITCH_NORMAL_TO_ALERT_TITLE,
128
    VCR_INACTIVE_STATUS,
129
    VCR_INACTIVE_WARN_STATUS,
130
    VCR_INACTIVE_ALERT_STATUS,
131
    VCR_SCROLLBAR,
132
    VCR_SCROLLBAR_ERROR,
133
    VCR_SCROLLBAR_WARNING,
134
    VCR_FOCUSED,
135
    VCR_DISABLED_FOCUSED,
136
    VCR_POPUP,
137
    VCR_POPUP_BORDER,
138
    VCR_COLOR_HINT,
139

140
    VCR_QUOTED_CODE,
141
    VCR_CODE_BORDER,
142
    VCR_KEYWORD,
143
    VCR_STRING,
144
    VCR_COMMENT,
145
    VCR_DOC_DIRECTIVE,
146
    VCR_VARIABLE,
147
    VCR_SYMBOL,
148
    VCR_NULL,
149
    VCR_ASCII_CTRL,
150
    VCR_NON_ASCII,
151
    VCR_NUMBER,
152
    VCR_RE_SPECIAL,
153
    VCR_RE_REPEAT,
154
    VCR_FILE,
155

156
    VCR_DIFF_DELETE, /*< Deleted line in a diff. */
157
    VCR_DIFF_ADD, /*< Added line in a diff. */
158
    VCR_DIFF_SECTION, /*< Section marker in a diff. */
159

160
    VCR_LOW_THRESHOLD,
161
    VCR_MED_THRESHOLD,
162
    VCR_HIGH_THRESHOLD,
163

164
    VCR_H1,
165
    VCR_H2,
166
    VCR_H3,
167
    VCR_H4,
168
    VCR_H5,
169
    VCR_H6,
170

171
    VCR_HR,
172
    VCR_HYPERLINK,
173
    VCR_LIST_GLYPH,
174
    VCR_BREADCRUMB,
175
    VCR_TABLE_BORDER,
176
    VCR_TABLE_HEADER,
177
    VCR_QUOTE_BORDER,
178
    VCR_QUOTED_TEXT,
179
    VCR_FOOTNOTE_BORDER,
180
    VCR_FOOTNOTE_TEXT,
181
    VCR_SNIPPET_BORDER,
182
    VCR_INDENT_GUIDE,
183
    VCR_INLINE_CODE,
184
    VCR_FUNCTION,
185
    VCR_TYPE,
186
    VCR_SEP_REF_ACC,
187
    VCR_SUGGESTION,
188

189
    VCR_SELECTED_TEXT,
190
    VCR_FUZZY_MATCH,
191

192
    VCR_OBJECT_KEY,
193

194
    VCR_SPECTRO_THRESHOLD0,
195
    VCR_SPECTRO_THRESHOLD1,
196
    VCR_SPECTRO_THRESHOLD2,
197
    VCR_SPECTRO_THRESHOLD3,
198
    VCR_SPECTRO_THRESHOLD4,
199
    VCR_SPECTRO_THRESHOLD5,
200
    VCR_SPECTRO_THRESHOLD6,
201

202
    VCR_TIMELINE_BAR,
203

204
    VCR__MAX
205
};
206

207
struct text_attrs {
208
    enum class style : uint32_t {
209
        none = 0x0000,
210
        struck = 0x0001u,
211
        bold = 0x0002u,
212
        undercurl = 0x0004u,
213
        underline = 0x0008u,
214
        italic = 0x0010u,
215
        altcharset = 0x0020u,
216
        blink = 0x0040u,
217
        reverse = 0x1000u,
218
    };
219

220
    static text_attrs with_struck()
797✔
221
    {
222
        return text_attrs{
223
            lnav::enums::to_underlying(style::struck),
224
        };
797✔
225
    }
226

227
    static text_attrs with_bold()
1,620✔
228
    {
229
        return text_attrs{
230
            lnav::enums::to_underlying(style::bold),
231
        };
1,620✔
232
    }
233

234
    static text_attrs with_undercurl()
235
    {
236
        return text_attrs{
237
            lnav::enums::to_underlying(style::undercurl),
238
        };
239
    }
240

241
    static text_attrs with_underline()
63,724✔
242
    {
243
        return text_attrs{
244
            lnav::enums::to_underlying(style::underline),
245
        };
63,724✔
246
    }
247

248
    static text_attrs with_italic()
797✔
249
    {
250
        return text_attrs{
251
            lnav::enums::to_underlying(style::italic),
252
        };
797✔
253
    }
254

255
    static text_attrs with_reverse()
59,952✔
256
    {
257
        return text_attrs{
258
            lnav::enums::to_underlying(style::reverse),
259
        };
59,952✔
260
    }
261

262
    static text_attrs with_altcharset()
114✔
263
    {
264
        return text_attrs{
265
            lnav::enums::to_underlying(style::altcharset),
266
        };
114✔
267
    }
268

269
    static text_attrs with_blink()
270
    {
271
        return text_attrs{
272
            lnav::enums::to_underlying(style::blink),
273
        };
274
    }
275

276
    template<typename... Args>
277
    static text_attrs with_styles(Args... args)
267✔
278
    {
279
        auto retval = text_attrs{};
267✔
280

281
        for (auto arg : {args...}) {
570✔
282
            retval.ta_attrs |= lnav::enums::to_underlying(arg);
303✔
283
        }
284
        return retval;
267✔
285
    }
286

287
    bool empty() const
66,497✔
288
    {
289
        return this->ta_attrs == 0 && this->ta_fg_color.empty()
52,849✔
290
            && this->ta_bg_color.empty();
119,346✔
291
    }
292

293
    text_attrs operator|(const text_attrs& other) const
60,785✔
294
    {
295
        return text_attrs{
296
            this->ta_attrs | other.ta_attrs,
60,785✔
297
            !this->ta_fg_color.empty() ? this->ta_fg_color : other.ta_fg_color,
60,785✔
298
            !this->ta_bg_color.empty() ? this->ta_bg_color : other.ta_bg_color,
60,785✔
299
        };
182,355✔
300
    }
301

302
    text_attrs operator|(const style other) const
918✔
303
    {
304
        return text_attrs{
305
            this->ta_attrs | lnav::enums::to_underlying(other),
1,836✔
306
            this->ta_fg_color,
307
            this->ta_bg_color,
308
        };
918✔
309
    }
310

311
    text_attrs& operator|=(const style other)
1,036,415✔
312
    {
313
        this->ta_attrs |= lnav::enums::to_underlying(other);
1,036,415✔
314
        return *this;
1,036,415✔
315
    }
316

317
    void clear_style(style other)
×
318
    {
319
        this->ta_attrs &= ~lnav::enums::to_underlying(other);
×
320
    }
321

322
    bool has_style(style other) const
33,140✔
323
    {
324
        return this->ta_attrs & lnav::enums::to_underlying(other);
33,140✔
325
    }
326

327
    bool operator==(const text_attrs& other) const
×
328
    {
329
        return this->ta_attrs == other.ta_attrs
×
330
            && this->ta_fg_color == other.ta_fg_color
×
331
            && this->ta_bg_color == other.ta_bg_color;
×
332
    }
333

334
    uint32_t ta_attrs{0};
335
    styling::color_unit ta_fg_color{styling::color_unit::EMPTY};
336
    styling::color_unit ta_bg_color{styling::color_unit::EMPTY};
337
    std::optional<text_align_t> ta_align;
338
};
339

340
struct block_elem_t {
341
    char32_t value;
342
    role_t role;
343

344
    bool operator==(const block_elem_t& rhs) const
345
    {
346
        return this->value == rhs.value && this->role == rhs.role;
347
    }
348
};
349

350
struct ui_command {
351
    source_location uc_location;
352
    std::string uc_command;
353

354
    bool operator==(const ui_command& rhs) const
355
    {
356
        return this->uc_location == rhs.uc_location
357
            && this->uc_command == rhs.uc_command;
358
    }
359
};
360

361
using string_attr_value = mapbox::util::variant<int64_t,
362
                                                role_t,
363
                                                text_attrs,
364
                                                intern_string_t,
365
                                                std::string,
366
                                                std::shared_ptr<logfile>,
367
                                                logfile*,
368
                                                bookmark_metadata*,
369
                                                string_fragment,
370
                                                block_elem_t,
371
                                                styling::color_unit,
372
                                                ui_icon_t,
373
                                                const char*,
374
                                                ui_command,
375
                                                text_format_t>;
376

377
class string_attr_type_base {
378
public:
379
    explicit constexpr string_attr_type_base(const char* name) noexcept
380
        : sat_name(name)
381
    {
382
    }
383

384
    const char* const sat_name;
385
};
386

387
using string_attr_pair
388
    = std::pair<const string_attr_type_base*, string_attr_value>;
389

390
template<typename T>
391
class string_attr_type : public string_attr_type_base {
392
public:
393
    using value_type = T;
394

395
    explicit constexpr string_attr_type(const char* name) noexcept
396
        : string_attr_type_base(name)
397
    {
398
    }
399

400
    template<typename U = T>
401
    std::enable_if_t<std::is_void_v<U>, string_attr_pair> value() const
136,841✔
402
    {
403
        return std::make_pair(this, string_attr_value{mapbox::util::no_init{}});
136,841✔
404
    }
405

406
    template<std::size_t N>
407
    std::enable_if_t<(N > 0) && std::is_same_v<std::string, T>,
408
                     string_attr_pair>
409
    value(const char (&val)[N]) const
×
410
    {
411
        return std::make_pair(this, std::string(val));
×
412
    }
413

414
    template<typename U = T>
415
    constexpr std::enable_if_t<!std::is_void_v<U>
416
                                   && std::is_convertible_v<U, T>,
417
                               string_attr_pair>
418
    value(U&& val) const
2,067,161✔
419
    {
420
        if constexpr (std::is_same_v<const char*, U>
421
                      && std::is_same_v<std::string, T>)
422
        {
423
            return std::make_pair(this, std::string(val));
424
        }
425
        return std::make_pair(this, val);
2,067,161✔
426
    }
427
};
428

429
extern const string_attr_type<void> SA_ORIGINAL_LINE;
430
extern const string_attr_type<void> SA_BODY;
431
extern const string_attr_type<void> SA_SRC_FILE;
432
extern const string_attr_type<void> SA_SRC_LINE;
433
extern const string_attr_type<void> SA_SRC_LOC;
434
extern const string_attr_type<void> SA_THREAD_ID;
435
extern const string_attr_type<void> SA_DURATION;
436
extern const string_attr_type<void> SA_EXTRA_CONTENT;
437
extern const string_attr_type<ui_icon_t> SA_HIDDEN;
438
extern const string_attr_type<void> SA_REPLACED;
439
extern const string_attr_type<intern_string_t> SA_FORMAT;
440
extern const string_attr_type<void> SA_REMOVED;
441
extern const string_attr_type<void> SA_PREFORMATTED;
442
extern const string_attr_type<std::string> SA_INVALID;
443
extern const string_attr_type<std::string> SA_ERROR;
444
extern const string_attr_type<std::string> SAT_UNSUPPORTED;
445
extern const string_attr_type<int64_t> SA_LEVEL;
446
extern const string_attr_type<int64_t> SA_ORIGIN_OFFSET;
447
extern const string_attr_type<text_format_t> SA_QUOTED_TEXT;
448

449
extern const string_attr_type<std::string> VC_ANCHOR;
450
extern const string_attr_type<role_t> VC_ROLE;
451
extern const string_attr_type<role_t> VC_ROLE_FG;
452
extern const string_attr_type<text_attrs> VC_STYLE;
453
extern const string_attr_type<const char*> VC_GRAPHIC;
454
extern const string_attr_type<block_elem_t> VC_BLOCK_ELEM;
455
extern const string_attr_type<styling::color_unit> VC_FOREGROUND;
456
extern const string_attr_type<styling::color_unit> VC_BACKGROUND;
457
extern const string_attr_type<std::string> VC_HYPERLINK;
458
extern const string_attr_type<ui_icon_t> VC_ICON;
459
extern const string_attr_type<ui_command> VC_COMMAND;
460

461
namespace lnav {
462

463
namespace string::attrs {
464

465
template<typename S>
466
std::pair<S, string_attr_pair>
467
preformatted(S str)
468
{
469
    return std::make_pair(std::move(str), SA_PREFORMATTED.value());
470
}
471

472
template<typename S>
473
std::pair<S, string_attr_pair>
474
href(S str, std::string href)
18✔
475
{
476
    return std::make_pair(std::move(str), VC_HYPERLINK.value(std::move(href)));
18✔
477
}
478

479
}  // namespace string::attrs
480

481
namespace roles {
482

483
template<typename S>
484
std::pair<S, string_attr_pair>
485
for_flag(S str, bool flag)
18✔
486
{
487
    return std::make_pair(
488
        std::move(str),
18✔
489
        VC_ROLE.value(flag ? role_t::VCR_OK : role_t::VCR_ERROR));
36✔
490
}
491

492
template<typename S>
493
std::pair<S, string_attr_pair>
494
error(S str)
661✔
495
{
496
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_ERROR));
661✔
497
}
498

499
template<typename S>
500
std::pair<S, string_attr_pair>
501
warning(S str)
626✔
502
{
503
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_WARNING));
626✔
504
}
505

506
template<typename S>
507
std::pair<S, string_attr_pair>
508
status(S str)
509
{
510
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_STATUS));
511
}
512

513
template<typename S>
514
std::pair<S, string_attr_pair>
515
inactive_status(S str)
516
{
517
    return std::make_pair(std::move(str),
518
                          VC_ROLE.value(role_t::VCR_INACTIVE_STATUS));
519
}
520

521
template<typename S>
522
std::pair<S, string_attr_pair>
523
status_title(S str)
16✔
524
{
525
    return std::make_pair(std::move(str),
16✔
526
                          VC_ROLE.value(role_t::VCR_STATUS_TITLE));
32✔
527
}
528

529
template<typename S>
530
std::pair<S, string_attr_pair>
531
status_subtitle(S str)
532
{
533
    return std::make_pair(std::move(str),
534
                          VC_ROLE.value(role_t::VCR_STATUS_SUBTITLE));
535
}
536

537
template<typename S>
538
std::pair<S, string_attr_pair>
539
ok(S str)
562✔
540
{
541
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_OK));
562✔
542
}
543

544
template<typename S>
545
std::pair<S, string_attr_pair>
546
time_ago(S str)
401✔
547
{
548
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_TIME_AGO));
401✔
549
}
550

551
template<typename S>
552
std::pair<S, string_attr_pair>
553
hidden(S str)
30✔
554
{
555
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HIDDEN));
30✔
556
}
557

558
template<typename S>
559
std::pair<S, string_attr_pair>
560
file(S str)
419✔
561
{
562
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_FILE));
419✔
563
}
564

565
template<typename S>
566
std::pair<S, string_attr_pair>
567
symbol(S str)
21,925✔
568
{
569
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_SYMBOL));
21,925✔
570
}
571

572
template<typename S>
573
std::pair<S, string_attr_pair>
574
keyword(S str)
200✔
575
{
576
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_KEYWORD));
200✔
577
}
578

579
template<typename S>
580
std::pair<S, string_attr_pair>
581
variable(S str)
3,583✔
582
{
583
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_VARIABLE));
3,583✔
584
}
585

586
template<typename S>
587
std::pair<S, string_attr_pair>
588
number(S str)
6,345✔
589
{
590
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_NUMBER));
6,345✔
591
}
592

593
template<typename S>
594
std::pair<S, string_attr_pair>
595
comment(S str)
6✔
596
{
597
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_COMMENT));
6✔
598
}
599

600
template<typename S>
601
std::pair<S, string_attr_pair>
602
identifier(S str)
4,421✔
603
{
604
    return std::make_pair(std::move(str),
4,421✔
605
                          VC_ROLE.value(role_t::VCR_IDENTIFIER));
8,842✔
606
}
607

608
template<typename S>
609
std::pair<S, string_attr_pair>
610
string(S str)
1✔
611
{
612
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_STRING));
1✔
613
}
614

615
template<typename S>
616
std::pair<S, string_attr_pair>
617
hr(S str)
×
618
{
619
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HR));
×
620
}
621

622
template<typename S>
623
std::pair<S, string_attr_pair>
624
hyperlink(S str)
339✔
625
{
626
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HYPERLINK));
339✔
627
}
628

629
template<typename S>
630
std::pair<S, string_attr_pair>
631
list_glyph(S str)
414✔
632
{
633
    return std::make_pair(std::move(str),
414✔
634
                          VC_ROLE.value(role_t::VCR_LIST_GLYPH));
828✔
635
}
636

637
template<typename S>
638
std::pair<S, string_attr_pair>
639
breadcrumb(S str)
640
{
641
    return std::make_pair(std::move(str),
642
                          VC_ROLE.value(role_t::VCR_BREADCRUMB));
643
}
644

645
template<typename S>
646
std::pair<S, string_attr_pair>
647
quoted_code(S str)
3,832✔
648
{
649
    return std::make_pair(std::move(str),
3,832✔
650
                          VC_ROLE.value(role_t::VCR_QUOTED_CODE));
7,664✔
651
}
652

653
template<typename S>
654
std::pair<S, string_attr_pair>
655
code_border(S str)
656
{
657
    return std::make_pair(std::move(str),
658
                          VC_ROLE.value(role_t::VCR_CODE_BORDER));
659
}
660

661
template<typename S>
662
std::pair<S, string_attr_pair>
663
snippet_border(S str)
1✔
664
{
665
    return std::make_pair(std::move(str),
1✔
666
                          VC_ROLE.value(role_t::VCR_SNIPPET_BORDER));
2✔
667
}
668

669
template<typename S>
670
std::pair<S, string_attr_pair>
671
table_border(S str)
1,253✔
672
{
673
    return std::make_pair(std::move(str),
1,253✔
674
                          VC_ROLE.value(role_t::VCR_TABLE_BORDER));
2,506✔
675
}
676

677
template<typename S>
678
std::pair<S, string_attr_pair>
679
table_header(S str)
×
680
{
681
    return std::make_pair(std::move(str),
×
682
                          VC_ROLE.value(role_t::VCR_TABLE_HEADER));
×
683
}
684

685
template<typename S>
686
std::pair<S, string_attr_pair>
687
quote_border(S str)
688
{
689
    return std::make_pair(std::move(str),
690
                          VC_ROLE.value(role_t::VCR_QUOTE_BORDER));
691
}
692

693
template<typename S>
694
std::pair<S, string_attr_pair>
695
quoted_text(S str)
696
{
697
    return std::make_pair(std::move(str),
698
                          VC_ROLE.value(role_t::VCR_QUOTED_TEXT));
699
}
700

701
template<typename S>
702
std::pair<S, string_attr_pair>
703
footnote_border(S str)
704
{
705
    return std::make_pair(std::move(str),
706
                          VC_ROLE.value(role_t::VCR_FOOTNOTE_BORDER));
707
}
708

709
template<typename S>
710
std::pair<S, string_attr_pair>
711
footnote_text(S str)
652✔
712
{
713
    return std::make_pair(std::move(str),
652✔
714
                          VC_ROLE.value(role_t::VCR_FOOTNOTE_TEXT));
1,304✔
715
}
716

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

724
template<typename S>
725
std::pair<S, string_attr_pair>
726
h2(S str)
63✔
727
{
728
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H2));
63✔
729
}
730

731
template<typename S>
732
std::pair<S, string_attr_pair>
733
h3(S str)
×
734
{
735
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H3));
×
736
}
737

738
template<typename S>
739
std::pair<S, string_attr_pair>
740
h4(S str)
741
{
742
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H4));
743
}
744

745
template<typename S>
746
std::pair<S, string_attr_pair>
747
h5(S str)
×
748
{
749
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H5));
×
750
}
751

752
template<typename S>
753
std::pair<S, string_attr_pair>
754
h6(S str)
755
{
756
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H6));
757
}
758

759
template<typename S>
760
std::pair<S, string_attr_pair>
761
suggestion(S str)
762
{
763
    return std::make_pair(std::move(str),
764
                          VC_ROLE.value(role_t::VCR_SUGGESTION));
765
}
766

767
namespace literals {
768

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

775
constexpr std::pair<string_fragment, role_t> operator""_error(const char* str,
1,198✔
776
                                                               std::size_t len)
777
{
778
    return std::make_pair(string_fragment{str, 0, (int) len},
1,198✔
779
                          role_t::VCR_ERROR);
2,396✔
780
}
781

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

789
constexpr std::pair<string_fragment, role_t> operator""_info(const char* str,
58,896✔
790
                                                              std::size_t len)
791
{
792
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_INFO);
58,896✔
793
}
794

795
constexpr std::pair<string_fragment, role_t> operator""_status_title(
796
    const char* str, std::size_t len)
797
{
798
    return std::make_pair(string_fragment{str, 0, (int) len},
799
                          role_t::VCR_STATUS_TITLE);
800
}
801

NEW
802
constexpr std::pair<string_fragment, role_t> operator""_status_subtitle(
×
803
    const char* str, std::size_t len)
804
{
805
    return std::make_pair(string_fragment{str, 0, (int) len},
×
806
                          role_t::VCR_STATUS_SUBTITLE);
×
807
}
808

809
constexpr std::pair<string_fragment, role_t> operator""_symbol(const char* str,
47✔
810
                                                                std::size_t len)
811
{
812
    return std::make_pair(string_fragment{str, 0, (int) len},
47✔
813
                          role_t::VCR_SYMBOL);
94✔
814
}
815

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

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

830
constexpr std::pair<string_fragment, role_t> operator""_comment(
341✔
831
    const char* str, std::size_t len)
832
{
833
    return std::make_pair(string_fragment{str, 0, (int) len},
341✔
834
                          role_t::VCR_COMMENT);
682✔
835
}
836

837
constexpr std::pair<string_fragment, role_t> operator""_hotkey(const char* str,
1,190✔
838
                                                                std::size_t len)
839
{
840
    return std::make_pair(string_fragment{str, 0, (int) len},
1,190✔
841
                          role_t::VCR_STATUS_HOTKEY);
2,380✔
842
}
843

844
constexpr std::pair<string_fragment, role_t> operator""_h1(const char* str,
160✔
845
                                                            std::size_t len)
846
{
847
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H1);
160✔
848
}
849

850
constexpr std::pair<string_fragment, role_t> operator""_h2(const char* str,
392✔
851
                                                            std::size_t len)
852
{
853
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H2);
392✔
854
}
855

856
constexpr std::pair<string_fragment, role_t> operator""_h3(const char* str,
84✔
857
                                                            std::size_t len)
858
{
859
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H3);
84✔
860
}
861

862
constexpr std::pair<string_fragment, role_t> operator""_h4(const char* str,
2,592✔
863
                                                            std::size_t len)
864
{
865
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H4);
2,592✔
866
}
867

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

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

880
constexpr std::pair<string_fragment, role_t> operator""_hyperlink(
1✔
881
    const char* str, std::size_t len)
882
{
883
    return std::make_pair(string_fragment{str, 0, (int) len},
1✔
884
                          role_t::VCR_HYPERLINK);
2✔
885
}
886

887
constexpr std::pair<string_fragment, role_t> operator""_list_glyph(
1,052✔
888
    const char* str, std::size_t len)
889
{
890
    return std::make_pair(string_fragment{str, 0, (int) len},
1,052✔
891
                          role_t::VCR_LIST_GLYPH);
2,104✔
892
}
893

894
constexpr std::pair<string_fragment, role_t> operator""_breadcrumb(
51✔
895
    const char* str, std::size_t len)
896
{
897
    return std::make_pair(string_fragment{str, 0, (int) len},
51✔
898
                          role_t::VCR_BREADCRUMB);
102✔
899
}
900

901
constexpr std::pair<string_fragment, role_t> operator""_quoted_code(
1✔
902
    const char* str, std::size_t len)
903
{
904
    return std::make_pair(string_fragment{str, 0, (int) len},
1✔
905
                          role_t::VCR_QUOTED_CODE);
2✔
906
}
907

908
constexpr std::pair<string_fragment, role_t> operator""_code_border(
371✔
909
    const char* str, std::size_t len)
910
{
911
    return std::make_pair(string_fragment{str, 0, (int) len},
371✔
912
                          role_t::VCR_CODE_BORDER);
742✔
913
}
914

915
constexpr std::pair<string_fragment, role_t> operator""_table_header(
166✔
916
    const char* str, std::size_t len)
917
{
918
    return std::make_pair(string_fragment{str, 0, (int) len},
166✔
919
                          role_t::VCR_TABLE_HEADER);
332✔
920
}
921

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

929
constexpr std::pair<string_fragment, role_t> operator""_quote_border(
107✔
930
    const char* str, std::size_t len)
931
{
932
    return std::make_pair(string_fragment{str, 0, (int) len},
107✔
933
                          role_t::VCR_QUOTE_BORDER);
214✔
934
}
935

936
constexpr std::pair<string_fragment, role_t> operator""_quoted_text(
937
    const char* str, std::size_t len)
938
{
939
    return std::make_pair(string_fragment{str, 0, (int) len},
940
                          role_t::VCR_QUOTED_TEXT);
941
}
942

943
constexpr std::pair<string_fragment, role_t> operator""_footnote_border(
331✔
944
    const char* str, std::size_t len)
945
{
946
    return std::make_pair(string_fragment{str, 0, (int) len},
331✔
947
                          role_t::VCR_FOOTNOTE_BORDER);
662✔
948
}
949

950
constexpr std::pair<string_fragment, role_t> operator""_footnote_text(
951
    const char* str, std::size_t len)
952
{
953
    return std::make_pair(string_fragment{str, 0, (int) len},
954
                          role_t::VCR_FOOTNOTE_BORDER);
955
}
956

957
constexpr std::pair<string_fragment, role_t> operator""_snippet_border(
2,671✔
958
    const char* str, std::size_t len)
959
{
960
    return std::make_pair(string_fragment{str, 0, (int) len},
2,671✔
961
                          role_t::VCR_SNIPPET_BORDER);
5,342✔
962
}
963

964
inline std::pair<std::string, string_attr_pair> operator""_link(
965
    const char* str, std::size_t len)
966
{
967
    return std::make_pair(std::string(str, len),
968
                          VC_HYPERLINK.value(std::string(str, len)));
969
}
970

971
}  // namespace literals
972

973
}  // namespace roles
974
}  // namespace lnav
975

976
#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