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

tstack / lnav / 18602397746-2581

17 Oct 2025 07:07PM UTC coverage: 69.26% (-0.6%) from 69.886%
18602397746-2581

push

github

tstack
[log-view] if the top message is not fully in view, display the first line

82 of 105 new or added lines in 5 files covered. (78.1%)

481 existing lines in 35 files now uncovered.

50183 of 72456 relevant lines covered (69.26%)

415322.24 hits per line

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

87.79
/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
};
71

72
constexpr auto ui_icon_count = lnav::enums::to_underlying(ui_icon_t::edit) + 1;
73

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

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

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

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

144
    VCR_LOW_THRESHOLD,
145
    VCR_MED_THRESHOLD,
146
    VCR_HIGH_THRESHOLD,
147

148
    VCR_H1,
149
    VCR_H2,
150
    VCR_H3,
151
    VCR_H4,
152
    VCR_H5,
153
    VCR_H6,
154

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

175
    VCR_OBJECT_KEY,
176

177
    VCR__MAX
178
};
179

180
struct text_attrs {
181
    enum class style : uint32_t {
182
        none = 0x0000,
183
        struck = 0x0001u,
184
        bold = 0x0002u,
185
        undercurl = 0x0004u,
186
        underline = 0x0008u,
187
        italic = 0x0010u,
188
        altcharset = 0x0020u,
189
        blink = 0x0040u,
190
        reverse = 0x1000u,
191
    };
192

193
    static text_attrs with_struck()
588✔
194
    {
195
        return text_attrs{
196
            lnav::enums::to_underlying(style::struck),
197
        };
588✔
198
    }
199

200
    static text_attrs with_bold()
784✔
201
    {
202
        return text_attrs{
203
            lnav::enums::to_underlying(style::bold),
204
        };
784✔
205
    }
206

207
    static text_attrs with_undercurl()
208
    {
209
        return text_attrs{
210
            lnav::enums::to_underlying(style::undercurl),
211
        };
212
    }
213

214
    static text_attrs with_underline()
5,156✔
215
    {
216
        return text_attrs{
217
            lnav::enums::to_underlying(style::underline),
218
        };
5,156✔
219
    }
220

221
    static text_attrs with_italic()
1,067✔
222
    {
223
        return text_attrs{
224
            lnav::enums::to_underlying(style::italic),
225
        };
1,067✔
226
    }
227

228
    static text_attrs with_reverse()
24,133✔
229
    {
230
        return text_attrs{
231
            lnav::enums::to_underlying(style::reverse),
232
        };
24,133✔
233
    }
234

235
    static text_attrs with_altcharset()
34✔
236
    {
237
        return text_attrs{
238
            lnav::enums::to_underlying(style::altcharset),
239
        };
34✔
240
    }
241

242
    static text_attrs with_blink()
243
    {
244
        return text_attrs{
245
            lnav::enums::to_underlying(style::blink),
246
        };
247
    }
248

249
    template<typename... Args>
250
    static text_attrs with_styles(Args... args)
245✔
251
    {
252
        auto retval = text_attrs{};
245✔
253

254
        for (auto arg : {args...}) {
735✔
255
            retval.ta_attrs |= lnav::enums::to_underlying(arg);
490✔
256
        }
257
        return retval;
245✔
258
    }
259

260
    bool empty() const
49,438✔
261
    {
262
        return this->ta_attrs == 0 && this->ta_fg_color.empty()
38,881✔
263
            && this->ta_bg_color.empty();
88,319✔
264
    }
265

266
    text_attrs operator|(const text_attrs& other) const
82,214✔
267
    {
268
        return text_attrs{
269
            this->ta_attrs | other.ta_attrs,
82,214✔
270
            !this->ta_fg_color.empty() ? this->ta_fg_color : other.ta_fg_color,
82,214✔
271
            !this->ta_bg_color.empty() ? this->ta_bg_color : other.ta_bg_color,
82,214✔
272
        };
246,642✔
273
    }
274

275
    text_attrs operator|(const style other) const
839✔
276
    {
277
        return text_attrs{
278
            this->ta_attrs | lnav::enums::to_underlying(other),
1,678✔
279
            this->ta_fg_color,
280
            this->ta_bg_color,
281
        };
839✔
282
    }
283

284
    text_attrs& operator|=(const style other)
629,261✔
285
    {
286
        this->ta_attrs |= lnav::enums::to_underlying(other);
629,261✔
287
        return *this;
629,261✔
288
    }
289

290
    void clear_style(style other)
23✔
291
    {
292
        this->ta_attrs &= ~lnav::enums::to_underlying(other);
23✔
293
    }
23✔
294

295
    bool has_style(style other) const
35,297✔
296
    {
297
        return this->ta_attrs & lnav::enums::to_underlying(other);
35,297✔
298
    }
299

300
    bool operator==(const text_attrs& other) const
×
301
    {
302
        return this->ta_attrs == other.ta_attrs
×
303
            && this->ta_fg_color == other.ta_fg_color
×
304
            && this->ta_bg_color == other.ta_bg_color;
×
305
    }
306

307
    uint32_t ta_attrs{0};
308
    styling::color_unit ta_fg_color{styling::color_unit::EMPTY};
309
    styling::color_unit ta_bg_color{styling::color_unit::EMPTY};
310
    std::optional<text_align_t> ta_align;
311
};
312

313
struct block_elem_t {
314
    char32_t value;
315
    role_t role;
316

317
    bool operator==(const block_elem_t& rhs) const
318
    {
319
        return this->value == rhs.value && this->role == rhs.role;
320
    }
321
};
322

323
struct ui_command {
324
    source_location uc_location;
325
    std::string uc_command;
326

327
    bool operator==(const ui_command& rhs) const
328
    {
329
        return this->uc_location == rhs.uc_location
330
            && this->uc_command == rhs.uc_command;
331
    }
332
};
333

334
using string_attr_value = mapbox::util::variant<int64_t,
335
                                                role_t,
336
                                                text_attrs,
337
                                                intern_string_t,
338
                                                std::string,
339
                                                std::shared_ptr<logfile>,
340
                                                bookmark_metadata*,
341
                                                string_fragment,
342
                                                block_elem_t,
343
                                                styling::color_unit,
344
                                                ui_icon_t,
345
                                                const char*,
346
                                                ui_command,
347
                                                text_format_t>;
348

349
class string_attr_type_base {
350
public:
351
    explicit constexpr string_attr_type_base(const char* name) noexcept
352
        : sat_name(name)
353
    {
354
    }
355

356
    const char* const sat_name;
357
};
358

359
using string_attr_pair
360
    = std::pair<const string_attr_type_base*, string_attr_value>;
361

362
template<typename T>
363
class string_attr_type : public string_attr_type_base {
364
public:
365
    using value_type = T;
366

367
    explicit constexpr string_attr_type(const char* name) noexcept
368
        : string_attr_type_base(name)
369
    {
370
    }
371

372
    template<typename U = T>
373
    std::enable_if_t<std::is_void_v<U>, string_attr_pair> value() const
119,644✔
374
    {
375
        return std::make_pair(this, string_attr_value{mapbox::util::no_init{}});
119,644✔
376
    }
377

378
    template<std::size_t N>
379
    std::enable_if_t<(N > 0) && std::is_same_v<std::string, T>,
380
                     string_attr_pair>
381
    value(const char (&val)[N]) const
14✔
382
    {
383
        return std::make_pair(this, std::string(val));
28✔
384
    }
385

386
    template<typename U = T>
387
    constexpr std::enable_if_t<!std::is_void_v<U>
388
                                   && std::is_convertible_v<U, T>,
389
                               string_attr_pair>
390
    value(U&& val) const
1,185,946✔
391
    {
392
        if constexpr (std::is_same_v<const char*, U>
393
                      && std::is_same_v<std::string, T>)
394
        {
395
            return std::make_pair(this, std::string(val));
396
        }
397
        return std::make_pair(this, val);
1,185,946✔
398
    }
399
};
400

401
extern const string_attr_type<void> SA_ORIGINAL_LINE;
402
extern const string_attr_type<void> SA_BODY;
403
extern const string_attr_type<void> SA_SRC_FILE;
404
extern const string_attr_type<void> SA_SRC_LINE;
405
extern const string_attr_type<void> SA_THREAD_ID;
406
extern const string_attr_type<void> SA_EXTRA_CONTENT;
407
extern const string_attr_type<ui_icon_t> SA_HIDDEN;
408
extern const string_attr_type<void> SA_REPLACED;
409
extern const string_attr_type<intern_string_t> SA_FORMAT;
410
extern const string_attr_type<void> SA_REMOVED;
411
extern const string_attr_type<void> SA_PREFORMATTED;
412
extern const string_attr_type<std::string> SA_INVALID;
413
extern const string_attr_type<std::string> SA_ERROR;
414
extern const string_attr_type<int64_t> SA_LEVEL;
415
extern const string_attr_type<int64_t> SA_ORIGIN_OFFSET;
416
extern const string_attr_type<text_format_t> SA_QUOTED_TEXT;
417

418
extern const string_attr_type<std::string> VC_ANCHOR;
419
extern const string_attr_type<role_t> VC_ROLE;
420
extern const string_attr_type<role_t> VC_ROLE_FG;
421
extern const string_attr_type<text_attrs> VC_STYLE;
422
extern const string_attr_type<const char*> VC_GRAPHIC;
423
extern const string_attr_type<block_elem_t> VC_BLOCK_ELEM;
424
extern const string_attr_type<styling::color_unit> VC_FOREGROUND;
425
extern const string_attr_type<styling::color_unit> VC_BACKGROUND;
426
extern const string_attr_type<std::string> VC_HYPERLINK;
427
extern const string_attr_type<ui_icon_t> VC_ICON;
428
extern const string_attr_type<ui_command> VC_COMMAND;
429

430
namespace lnav {
431

432
namespace string::attrs {
433

434
template<typename S>
435
std::pair<S, string_attr_pair>
436
preformatted(S str)
437
{
438
    return std::make_pair(std::move(str), SA_PREFORMATTED.value());
439
}
440

441
template<typename S>
442
std::pair<S, string_attr_pair>
443
href(S str, std::string href)
16✔
444
{
445
    return std::make_pair(std::move(str), VC_HYPERLINK.value(std::move(href)));
16✔
446
}
447

448
}  // namespace string::attrs
449

450
namespace roles {
451

452
template<typename S>
453
std::pair<S, string_attr_pair>
UNCOV
454
for_flag(S str, bool flag)
×
455
{
456
    return std::make_pair(
UNCOV
457
        std::move(str),
×
UNCOV
458
        VC_ROLE.value(flag ? role_t::VCR_OK : role_t::VCR_ERROR));
×
459
}
460

461
template<typename S>
462
std::pair<S, string_attr_pair>
463
error(S str)
519✔
464
{
465
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_ERROR));
519✔
466
}
467

468
template<typename S>
469
std::pair<S, string_attr_pair>
470
warning(S str)
317✔
471
{
472
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_WARNING));
317✔
473
}
474

475
template<typename S>
476
std::pair<S, string_attr_pair>
477
status(S str)
478
{
479
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_STATUS));
480
}
481

482
template<typename S>
483
std::pair<S, string_attr_pair>
484
inactive_status(S str)
485
{
486
    return std::make_pair(std::move(str),
487
                          VC_ROLE.value(role_t::VCR_INACTIVE_STATUS));
488
}
489

490
template<typename S>
491
std::pair<S, string_attr_pair>
492
status_title(S str)
40✔
493
{
494
    return std::make_pair(std::move(str),
40✔
495
                          VC_ROLE.value(role_t::VCR_STATUS_TITLE));
80✔
496
}
497

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

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

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

520
template<typename S>
521
std::pair<S, string_attr_pair>
522
file(S str)
372✔
523
{
524
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_FILE));
372✔
525
}
526

527
template<typename S>
528
std::pair<S, string_attr_pair>
529
symbol(S str)
16,027✔
530
{
531
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_SYMBOL));
16,027✔
532
}
533

534
template<typename S>
535
std::pair<S, string_attr_pair>
536
keyword(S str)
150✔
537
{
538
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_KEYWORD));
150✔
539
}
540

541
template<typename S>
542
std::pair<S, string_attr_pair>
543
variable(S str)
2,577✔
544
{
545
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_VARIABLE));
2,577✔
546
}
547

548
template<typename S>
549
std::pair<S, string_attr_pair>
550
number(S str)
3,960✔
551
{
552
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_NUMBER));
3,960✔
553
}
554

555
template<typename S>
556
std::pair<S, string_attr_pair>
557
comment(S str)
5✔
558
{
559
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_COMMENT));
5✔
560
}
561

562
template<typename S>
563
std::pair<S, string_attr_pair>
564
identifier(S str)
2,590✔
565
{
566
    return std::make_pair(std::move(str),
2,590✔
567
                          VC_ROLE.value(role_t::VCR_IDENTIFIER));
5,180✔
568
}
569

570
template<typename S>
571
std::pair<S, string_attr_pair>
572
string(S str)
1✔
573
{
574
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_STRING));
1✔
575
}
576

577
template<typename S>
578
std::pair<S, string_attr_pair>
579
hr(S str)
×
580
{
581
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HR));
×
582
}
583

584
template<typename S>
585
std::pair<S, string_attr_pair>
586
hyperlink(S str)
323✔
587
{
588
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_HYPERLINK));
323✔
589
}
590

591
template<typename S>
592
std::pair<S, string_attr_pair>
593
list_glyph(S str)
360✔
594
{
595
    return std::make_pair(std::move(str),
360✔
596
                          VC_ROLE.value(role_t::VCR_LIST_GLYPH));
720✔
597
}
598

599
template<typename S>
600
std::pair<S, string_attr_pair>
601
breadcrumb(S str)
602
{
603
    return std::make_pair(std::move(str),
604
                          VC_ROLE.value(role_t::VCR_BREADCRUMB));
605
}
606

607
template<typename S>
608
std::pair<S, string_attr_pair>
609
quoted_code(S str)
2,641✔
610
{
611
    return std::make_pair(std::move(str),
2,641✔
612
                          VC_ROLE.value(role_t::VCR_QUOTED_CODE));
5,282✔
613
}
614

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

623
template<typename S>
624
std::pair<S, string_attr_pair>
625
snippet_border(S str)
1✔
626
{
627
    return std::make_pair(std::move(str),
1✔
628
                          VC_ROLE.value(role_t::VCR_SNIPPET_BORDER));
2✔
629
}
630

631
template<typename S>
632
std::pair<S, string_attr_pair>
633
table_border(S str)
913✔
634
{
635
    return std::make_pair(std::move(str),
913✔
636
                          VC_ROLE.value(role_t::VCR_TABLE_BORDER));
1,826✔
637
}
638

639
template<typename S>
640
std::pair<S, string_attr_pair>
641
table_header(S str)
×
642
{
643
    return std::make_pair(std::move(str),
×
644
                          VC_ROLE.value(role_t::VCR_TABLE_HEADER));
×
645
}
646

647
template<typename S>
648
std::pair<S, string_attr_pair>
649
quote_border(S str)
650
{
651
    return std::make_pair(std::move(str),
652
                          VC_ROLE.value(role_t::VCR_QUOTE_BORDER));
653
}
654

655
template<typename S>
656
std::pair<S, string_attr_pair>
657
quoted_text(S str)
658
{
659
    return std::make_pair(std::move(str),
660
                          VC_ROLE.value(role_t::VCR_QUOTED_TEXT));
661
}
662

663
template<typename S>
664
std::pair<S, string_attr_pair>
665
footnote_border(S str)
666
{
667
    return std::make_pair(std::move(str),
668
                          VC_ROLE.value(role_t::VCR_FOOTNOTE_BORDER));
669
}
670

671
template<typename S>
672
std::pair<S, string_attr_pair>
673
footnote_text(S str)
642✔
674
{
675
    return std::make_pair(std::move(str),
642✔
676
                          VC_ROLE.value(role_t::VCR_FOOTNOTE_TEXT));
1,284✔
677
}
678

679
template<typename S>
680
std::pair<S, string_attr_pair>
681
h1(S str)
682
{
683
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H1));
684
}
685

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

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

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

707
template<typename S>
708
std::pair<S, string_attr_pair>
709
h5(S str)
×
710
{
711
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H5));
×
712
}
713

714
template<typename S>
715
std::pair<S, string_attr_pair>
716
h6(S str)
717
{
718
    return std::make_pair(std::move(str), VC_ROLE.value(role_t::VCR_H6));
719
}
720

721
template<typename S>
722
std::pair<S, string_attr_pair>
723
suggestion(S str)
724
{
725
    return std::make_pair(std::move(str),
726
                          VC_ROLE.value(role_t::VCR_SUGGESTION));
727
}
728

729
namespace literals {
730

731
constexpr std::pair<string_fragment, role_t> operator"" _ok(const char* str,
6✔
732
                                                            std::size_t len)
733
{
734
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_OK);
6✔
735
}
736

737
constexpr std::pair<string_fragment, role_t> operator"" _error(const char* str,
8✔
738
                                                               std::size_t len)
739
{
740
    return std::make_pair(string_fragment{str, 0, (int) len},
8✔
741
                          role_t::VCR_ERROR);
16✔
742
}
743

744
constexpr std::pair<string_fragment, role_t> operator"" _warning(
7✔
745
    const char* str, std::size_t len)
746
{
747
    return std::make_pair(string_fragment{str, 0, (int) len},
7✔
748
                          role_t::VCR_WARNING);
14✔
749
}
750

751
constexpr std::pair<string_fragment, role_t> operator"" _info(const char* str,
119✔
752
                                                              std::size_t len)
753
{
754
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_INFO);
119✔
755
}
756

757
constexpr std::pair<string_fragment, role_t> operator"" _status_title(
758
    const char* str, std::size_t len)
759
{
760
    return std::make_pair(string_fragment{str, 0, (int) len},
761
                          role_t::VCR_STATUS_TITLE);
762
}
763

764
constexpr std::pair<string_fragment, role_t> operator"" _status_subtitle(
×
765
    const char* str, std::size_t len)
766
{
767
    return std::make_pair(string_fragment{str, 0, (int) len},
×
768
                          role_t::VCR_STATUS_SUBTITLE);
×
769
}
770

771
constexpr std::pair<string_fragment, role_t> operator"" _symbol(const char* str,
39✔
772
                                                                std::size_t len)
773
{
774
    return std::make_pair(string_fragment{str, 0, (int) len},
39✔
775
                          role_t::VCR_SYMBOL);
78✔
776
}
777

778
constexpr std::pair<string_fragment, role_t> operator"" _keyword(
7✔
779
    const char* str, std::size_t len)
780
{
781
    return std::make_pair(string_fragment{str, 0, (int) len},
7✔
782
                          role_t::VCR_KEYWORD);
14✔
783
}
784

785
constexpr std::pair<string_fragment, role_t> operator"" _variable(
211✔
786
    const char* str, std::size_t len)
787
{
788
    return std::make_pair(string_fragment{str, 0, (int) len},
211✔
789
                          role_t::VCR_VARIABLE);
422✔
790
}
791

792
constexpr std::pair<string_fragment, role_t> operator"" _comment(
44✔
793
    const char* str, std::size_t len)
794
{
795
    return std::make_pair(string_fragment{str, 0, (int) len},
44✔
796
                          role_t::VCR_COMMENT);
88✔
797
}
798

799
constexpr std::pair<string_fragment, role_t> operator"" _hotkey(const char* str,
739✔
800
                                                                std::size_t len)
801
{
802
    return std::make_pair(string_fragment{str, 0, (int) len},
739✔
803
                          role_t::VCR_STATUS_HOTKEY);
1,478✔
804
}
805

806
constexpr std::pair<string_fragment, role_t> operator"" _h1(const char* str,
50✔
807
                                                            std::size_t len)
808
{
809
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H1);
50✔
810
}
811

812
constexpr std::pair<string_fragment, role_t> operator"" _h2(const char* str,
108✔
813
                                                            std::size_t len)
814
{
815
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H2);
108✔
816
}
817

UNCOV
818
constexpr std::pair<string_fragment, role_t> operator"" _h3(const char* str,
×
819
                                                            std::size_t len)
820
{
UNCOV
821
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H3);
×
822
}
823

824
constexpr std::pair<string_fragment, role_t> operator"" _h4(const char* str,
1,875✔
825
                                                            std::size_t len)
826
{
827
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_H4);
1,875✔
828
}
829

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

836
constexpr std::pair<string_fragment, role_t> operator"" _hr(const char* str,
837
                                                            std::size_t len)
838
{
839
    return std::make_pair(string_fragment{str, 0, (int) len}, role_t::VCR_HR);
840
}
841

842
constexpr std::pair<string_fragment, role_t> operator"" _hyperlink(
1✔
843
    const char* str, std::size_t len)
844
{
845
    return std::make_pair(string_fragment{str, 0, (int) len},
1✔
846
                          role_t::VCR_HYPERLINK);
2✔
847
}
848

849
constexpr std::pair<string_fragment, role_t> operator"" _list_glyph(
743✔
850
    const char* str, std::size_t len)
851
{
852
    return std::make_pair(string_fragment{str, 0, (int) len},
743✔
853
                          role_t::VCR_LIST_GLYPH);
1,486✔
854
}
855

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

863
constexpr std::pair<string_fragment, role_t> operator"" _quoted_code(
1✔
864
    const char* str, std::size_t len)
865
{
866
    return std::make_pair(string_fragment{str, 0, (int) len},
1✔
867
                          role_t::VCR_QUOTED_CODE);
2✔
868
}
869

870
constexpr std::pair<string_fragment, role_t> operator"" _code_border(
305✔
871
    const char* str, std::size_t len)
872
{
873
    return std::make_pair(string_fragment{str, 0, (int) len},
305✔
874
                          role_t::VCR_CODE_BORDER);
610✔
875
}
876

877
constexpr std::pair<string_fragment, role_t> operator"" _table_header(
65✔
878
    const char* str, std::size_t len)
879
{
880
    return std::make_pair(string_fragment{str, 0, (int) len},
65✔
881
                          role_t::VCR_TABLE_HEADER);
130✔
882
}
883

884
constexpr std::pair<string_fragment, role_t> operator"" _table_border(
885
    const char* str, std::size_t len)
886
{
887
    return std::make_pair(string_fragment{str, 0, (int) len},
888
                          role_t::VCR_TABLE_BORDER);
889
}
890

891
constexpr std::pair<string_fragment, role_t> operator"" _quote_border(
85✔
892
    const char* str, std::size_t len)
893
{
894
    return std::make_pair(string_fragment{str, 0, (int) len},
85✔
895
                          role_t::VCR_QUOTE_BORDER);
170✔
896
}
897

898
constexpr std::pair<string_fragment, role_t> operator"" _quoted_text(
899
    const char* str, std::size_t len)
900
{
901
    return std::make_pair(string_fragment{str, 0, (int) len},
902
                          role_t::VCR_QUOTED_TEXT);
903
}
904

905
constexpr std::pair<string_fragment, role_t> operator"" _footnote_border(
325✔
906
    const char* str, std::size_t len)
907
{
908
    return std::make_pair(string_fragment{str, 0, (int) len},
325✔
909
                          role_t::VCR_FOOTNOTE_BORDER);
650✔
910
}
911

912
constexpr std::pair<string_fragment, role_t> operator"" _footnote_text(
913
    const char* str, std::size_t len)
914
{
915
    return std::make_pair(string_fragment{str, 0, (int) len},
916
                          role_t::VCR_FOOTNOTE_BORDER);
917
}
918

919
constexpr std::pair<string_fragment, role_t> operator"" _snippet_border(
1,799✔
920
    const char* str, std::size_t len)
921
{
922
    return std::make_pair(string_fragment{str, 0, (int) len},
1,799✔
923
                          role_t::VCR_SNIPPET_BORDER);
3,598✔
924
}
925

926
inline std::pair<std::string, string_attr_pair> operator"" _link(
927
    const char* str, std::size_t len)
928
{
929
    return std::make_pair(std::string(str, len),
930
                          VC_HYPERLINK.value(std::string(str, len)));
931
}
932

933
}  // namespace literals
934

935
}  // namespace roles
936
}  // namespace lnav
937

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

© 2026 Coveralls, Inc