pub struct TxtView { /* private fields */ }Expand description
A terminal text viewer.
Wrap any text with TxtView::new, optionally tweak it with
TxtView::with_config, and show it with TxtView::run:
use txtview::{TxtView, TxtViewConfig};
let mut viewer = TxtView::new("hello world")
.with_config(TxtViewConfig::default());ANSI styling is preserved: SGR color, style codes and OSC8 hyperlinks
pass through, and the active style is re-emitted compactly when a styled
line wraps. Control bytes and other escape sequences are shown as visible
caret notation. See TxtViewConfig for the available display options.
Implementations§
Source§impl TxtView
impl TxtView
Sourcepub fn run(&mut self) -> Result<()>
pub fn run(&mut self) -> Result<()>
Show the viewer and block until the user quits.
This takes over the terminal: it enters raw mode, switches to an
alternate screen, hides the cursor, and enables mouse capture. The
terminal is always restored before returning, including on errors or
a panic (cleanup runs from a Drop guard).
§Errors
Returns io::Error with io::ErrorKind::NotConnected when stdin
or stdout is not a terminal (for example when output is piped), and
propagates I/O errors from the terminal itself or the event loop.
§Keybindings
| Key | Action |
|---|---|
q, Esc, Ctrl+C | Quit |
↑/↓, j/k | Scroll one line |
PgUp/PgDn | Scroll one page |
Home/g, End/G | Jump to start / end |
| Mouse wheel | Scroll one line per tick |
| Scrollbar track/thumb | Click to jump to position, drag to scroll |
Examples found in repository?
More examples
3fn main() -> std::io::Result<()> {
4 let text = (1..=100)
5 .map(|i| format!("Line {:>3}: The quick brown fox jumps over the lazy dog", i))
6 .collect::<Vec<String>>()
7 .join("\n");
8
9 let config = TxtViewConfig {
10 show_line_numbers: true,
11 ..TxtViewConfig::default()
12 };
13
14 let mut viewer = TxtView::new(&text).with_config(config);
15 viewer.run()
16}3fn main() -> std::io::Result<()> {
4 // Fixed 20-column viewport so wrapping always happens at the same place,
5 // independent of the terminal size.
6 let doc = vec![
7 "Grapheme cluster wrapping demo".to_string(),
8 "".to_string(),
9 "Every cluster wraps as one unit, never split at a row boundary:".to_string(),
10 "".to_string(),
11 "skin-tone modifier: 123456789012345678👍🏿xyz".to_string(),
12 "ZWJ family emoji: 123456789012345678👨\u{200d}👩\u{200d}👧x".to_string(),
13 "flag pair: 1234567890123456789🇺🇸x".to_string(),
14 "".to_string(),
15 "combining marks stay with their base char:".to_string(),
16 " na\u{303}i\u{303}ve cafe\u{301} re\u{301}sume\u{301}".to_string(),
17 "".to_string(),
18 "keycap and variation-selector sequences:".to_string(),
19 " \u{23}\u{fe0f}\u{20e3} \u{31}\u{fe0f}\u{20e3} vs plain 3 and a ❤\u{fe0f} heart"
20 .to_string(),
21 "".to_string(),
22 "All of these stay intact even when a row boundary".to_string(),
23 "lands in the middle of one.".to_string(),
24 ];
25
26 let text = doc.join("\n");
27
28 let config = TxtViewConfig {
29 viewport_width: Some(20),
30 show_line_numbers: false,
31 show_scrollbar: false,
32 ..TxtViewConfig::default()
33 };
34
35 let mut viewer = TxtView::new(&text).with_config(config);
36 viewer.run()
37}3fn main() {
4 let lines = vec![
5 "Visual width demo".to_string(),
6 "".to_string(),
7 "CJK characters take 2 columns each:".to_string(),
8 " 中文测试 ABC abc 123".to_string(),
9 " 日本語テスト ABC abc 123".to_string(),
10 " 한국어테스트 ABC abc 123".to_string(),
11 "".to_string(),
12 "Mixed ASCII and CJK:".to_string(),
13 " Hello你好World世界!".to_string(),
14 " Helloあなたは元気です!".to_string(),
15 " Hello안녕하세요!".to_string(),
16 " Price: ¥100 ($15 USD)".to_string(),
17 "".to_string(),
18 "Full-width punctuation:".to_string(),
19 " 「引用符」《书名号》【括号】".to_string(),
20 "".to_string(),
21 "Emoji (often 2 columns):".to_string(),
22 " Hello 👋 World 🌍".to_string(),
23 "".to_string(),
24 "Wrapping counts visual columns, not characters:".to_string(),
25 " 12345678901234567890 (20 chars, 20 cols)".to_string(),
26 " 一二三四五六七八九十 (10 chars, 20 cols)".to_string(),
27 "".to_string(),
28 "Both lines above wrap at 20 columns:".to_string(),
29 " 一二三四五六七八九十十一二 (12 CJK chars, 24 cols)".to_string(),
30 "".to_string(),
31 "24 CJK chars = 48 cols, wraps into rows at column boundaries:".to_string(),
32 " 一二三四五六七八九十".to_string(),
33 " 一二三四五六七八九十".to_string(),
34 " 一二三四五六七八九十".to_string(),
35 ];
36
37 let mut viewer = TxtView::new(lines.join("\n"));
38 viewer.run().unwrap();
39}16fn main() {
17 let lines = vec![
18 "Welcome to TxtView".bold().underlined().to_string(),
19 "".to_string(),
20 "What is this?".bold().to_string(),
21 " A lightweight terminal text viewer for Rust, built on".to_string(),
22 format!(
23 " {} with no heavy dependencies.",
24 "crossterm".cyan().bold()
25 ),
26 "".to_string(),
27 "Supported features".bold().to_string(),
28 bullet("Scrolling", "line-by-line or page-by-page", |s| {
29 s.cyan().bold().to_string()
30 }),
31 bullet("Wrapping", "reflows text to the viewport width", |s| {
32 s.yellow().to_string()
33 }),
34 bullet("Scrollbar", "shows the reading position", |s| {
35 s.red().bold().to_string()
36 }),
37 bullet("Line numbers", "optional left-hand column", |s| {
38 s.italic().to_string()
39 }),
40 bullet("Mouse support", "wheel and button scrolling", |s| {
41 s.green().to_string()
42 }),
43 "".to_string(),
44 "Keybindings".bold().to_string(),
45 binding("j / k", "scroll one line"),
46 binding("PgUp / PgDn", "scroll one page"),
47 binding("g / G", "jump to start / end"),
48 binding("q / Esc", "quit"),
49 "".to_string(),
50 "Configuration".bold().to_string(),
51 " Everything is set through TxtViewConfig:".to_string(),
52 setting("show_line_numbers", "toggles the line number column"),
53 setting("show_scrollbar", "toggles the interactive scrollbar"),
54 setting("show_help_bar", "toggles this help section"),
55 "".to_string(),
56 ];
57
58 let mut viewer = TxtView::new(lines.join("\n")).with_config(TxtViewConfig::default());
59 viewer.run().unwrap();
60}3fn main() -> std::io::Result<()> {
4 let doc = vec![
5 "Control character & tab handling demo".to_string(),
6 "".to_string(),
7 "Tabs are measured and wrapped at their 8-column terminal stop:".to_string(),
8 "\tone tab of indentation".to_string(),
9 "\t\ttwo tabs".to_string(),
10 "\t\t\tthree tabs".to_string(),
11 "no\tgap\tor\twider".to_string(),
12 "".to_string(),
13 "Mixed tab and space indentation:".to_string(),
14 " four spaces then\tone tab".to_string(),
15 "\tone tab then four spaces".to_string(),
16 "".to_string(),
17 "Control bytes are shown as caret notation instead of being executed:".to_string(),
18 "backspace \x08 BEL \x07 CR \r DEL \x7f end".to_string(),
19 "solo control bytes: ^not caret, actual: \x01 \x02 \x03 \x04".to_string(),
20 "field separators: US \x1f RS \x1e GS \x1d FS \x1c".to_string(),
21 "".to_string(),
22 "SGR and OSC8 hyperlinks pass through; other escapes show as text:".to_string(),
23 "cursor moves and clears never execute: \x1b[2A \x1b[2J \x1b[K".to_string(),
24 "OSC8 hyperlink stays live and is never split: \x1b]8;;https://example.com/about\x07example.com\x1b]8;;\x07".to_string(),
25 "an OSC title is escaped text, never a live title: \x1b]0;window title\x07".to_string(),
26 "two-byte escapes too: \x1b7 saved cursor \x1b8 restore".to_string(),
27 "".to_string(),
28 "An empty line and a tab-only line both occupy a row:".to_string(),
29 "".to_string(),
30 "\t".to_string(),
31 "".to_string(),
32 "Long content so wrapping kicks in, note how tabs keep 8-column alignment:".to_string(),
33 "\tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.".to_string(),
34 "a shorter line\t\t\twith long tab gaps and trailing spaces".to_string(),
35 "".to_string(),
36 "A very long unbroken\t\t\ttoken-heavy line that wraps several times across the viewport width to exercise the wrap-with-tab path:".to_string(),
37 "".to_string(),
38 ];
39
40 let text = doc.join("\n");
41
42 let config = TxtViewConfig {
43 show_line_numbers: true,
44 show_scrollbar: true,
45 show_help_bar: true,
46 ..TxtViewConfig::default()
47 };
48
49 let mut viewer = TxtView::new(&text).with_config(config);
50 viewer.run()
51}Source§impl TxtView
impl TxtView
Sourcepub fn new(input: impl AsRef<str>) -> Self
pub fn new(input: impl AsRef<str>) -> Self
Create a viewer for the given text.
The text is split into lines. Blank lines are preserved and a single trailing newline is ignored. Both borrowed and owned text are accepted:
use txtview::TxtView;
let viewer = TxtView::new("line one\nline two");
assert_eq!(viewer.line_count(), 2);
let owned = String::from("line one\nline two");
let viewer = TxtView::new(owned);
assert_eq!(viewer.line_count(), 2);Examples found in repository?
More examples
3fn main() -> std::io::Result<()> {
4 let text = (1..=100)
5 .map(|i| format!("Line {:>3}: The quick brown fox jumps over the lazy dog", i))
6 .collect::<Vec<String>>()
7 .join("\n");
8
9 let config = TxtViewConfig {
10 show_line_numbers: true,
11 ..TxtViewConfig::default()
12 };
13
14 let mut viewer = TxtView::new(&text).with_config(config);
15 viewer.run()
16}3fn main() -> std::io::Result<()> {
4 // Fixed 20-column viewport so wrapping always happens at the same place,
5 // independent of the terminal size.
6 let doc = vec![
7 "Grapheme cluster wrapping demo".to_string(),
8 "".to_string(),
9 "Every cluster wraps as one unit, never split at a row boundary:".to_string(),
10 "".to_string(),
11 "skin-tone modifier: 123456789012345678👍🏿xyz".to_string(),
12 "ZWJ family emoji: 123456789012345678👨\u{200d}👩\u{200d}👧x".to_string(),
13 "flag pair: 1234567890123456789🇺🇸x".to_string(),
14 "".to_string(),
15 "combining marks stay with their base char:".to_string(),
16 " na\u{303}i\u{303}ve cafe\u{301} re\u{301}sume\u{301}".to_string(),
17 "".to_string(),
18 "keycap and variation-selector sequences:".to_string(),
19 " \u{23}\u{fe0f}\u{20e3} \u{31}\u{fe0f}\u{20e3} vs plain 3 and a ❤\u{fe0f} heart"
20 .to_string(),
21 "".to_string(),
22 "All of these stay intact even when a row boundary".to_string(),
23 "lands in the middle of one.".to_string(),
24 ];
25
26 let text = doc.join("\n");
27
28 let config = TxtViewConfig {
29 viewport_width: Some(20),
30 show_line_numbers: false,
31 show_scrollbar: false,
32 ..TxtViewConfig::default()
33 };
34
35 let mut viewer = TxtView::new(&text).with_config(config);
36 viewer.run()
37}3fn main() {
4 let lines = vec![
5 "Visual width demo".to_string(),
6 "".to_string(),
7 "CJK characters take 2 columns each:".to_string(),
8 " 中文测试 ABC abc 123".to_string(),
9 " 日本語テスト ABC abc 123".to_string(),
10 " 한국어테스트 ABC abc 123".to_string(),
11 "".to_string(),
12 "Mixed ASCII and CJK:".to_string(),
13 " Hello你好World世界!".to_string(),
14 " Helloあなたは元気です!".to_string(),
15 " Hello안녕하세요!".to_string(),
16 " Price: ¥100 ($15 USD)".to_string(),
17 "".to_string(),
18 "Full-width punctuation:".to_string(),
19 " 「引用符」《书名号》【括号】".to_string(),
20 "".to_string(),
21 "Emoji (often 2 columns):".to_string(),
22 " Hello 👋 World 🌍".to_string(),
23 "".to_string(),
24 "Wrapping counts visual columns, not characters:".to_string(),
25 " 12345678901234567890 (20 chars, 20 cols)".to_string(),
26 " 一二三四五六七八九十 (10 chars, 20 cols)".to_string(),
27 "".to_string(),
28 "Both lines above wrap at 20 columns:".to_string(),
29 " 一二三四五六七八九十十一二 (12 CJK chars, 24 cols)".to_string(),
30 "".to_string(),
31 "24 CJK chars = 48 cols, wraps into rows at column boundaries:".to_string(),
32 " 一二三四五六七八九十".to_string(),
33 " 一二三四五六七八九十".to_string(),
34 " 一二三四五六七八九十".to_string(),
35 ];
36
37 let mut viewer = TxtView::new(lines.join("\n"));
38 viewer.run().unwrap();
39}16fn main() {
17 let lines = vec![
18 "Welcome to TxtView".bold().underlined().to_string(),
19 "".to_string(),
20 "What is this?".bold().to_string(),
21 " A lightweight terminal text viewer for Rust, built on".to_string(),
22 format!(
23 " {} with no heavy dependencies.",
24 "crossterm".cyan().bold()
25 ),
26 "".to_string(),
27 "Supported features".bold().to_string(),
28 bullet("Scrolling", "line-by-line or page-by-page", |s| {
29 s.cyan().bold().to_string()
30 }),
31 bullet("Wrapping", "reflows text to the viewport width", |s| {
32 s.yellow().to_string()
33 }),
34 bullet("Scrollbar", "shows the reading position", |s| {
35 s.red().bold().to_string()
36 }),
37 bullet("Line numbers", "optional left-hand column", |s| {
38 s.italic().to_string()
39 }),
40 bullet("Mouse support", "wheel and button scrolling", |s| {
41 s.green().to_string()
42 }),
43 "".to_string(),
44 "Keybindings".bold().to_string(),
45 binding("j / k", "scroll one line"),
46 binding("PgUp / PgDn", "scroll one page"),
47 binding("g / G", "jump to start / end"),
48 binding("q / Esc", "quit"),
49 "".to_string(),
50 "Configuration".bold().to_string(),
51 " Everything is set through TxtViewConfig:".to_string(),
52 setting("show_line_numbers", "toggles the line number column"),
53 setting("show_scrollbar", "toggles the interactive scrollbar"),
54 setting("show_help_bar", "toggles this help section"),
55 "".to_string(),
56 ];
57
58 let mut viewer = TxtView::new(lines.join("\n")).with_config(TxtViewConfig::default());
59 viewer.run().unwrap();
60}3fn main() -> std::io::Result<()> {
4 let doc = vec![
5 "Control character & tab handling demo".to_string(),
6 "".to_string(),
7 "Tabs are measured and wrapped at their 8-column terminal stop:".to_string(),
8 "\tone tab of indentation".to_string(),
9 "\t\ttwo tabs".to_string(),
10 "\t\t\tthree tabs".to_string(),
11 "no\tgap\tor\twider".to_string(),
12 "".to_string(),
13 "Mixed tab and space indentation:".to_string(),
14 " four spaces then\tone tab".to_string(),
15 "\tone tab then four spaces".to_string(),
16 "".to_string(),
17 "Control bytes are shown as caret notation instead of being executed:".to_string(),
18 "backspace \x08 BEL \x07 CR \r DEL \x7f end".to_string(),
19 "solo control bytes: ^not caret, actual: \x01 \x02 \x03 \x04".to_string(),
20 "field separators: US \x1f RS \x1e GS \x1d FS \x1c".to_string(),
21 "".to_string(),
22 "SGR and OSC8 hyperlinks pass through; other escapes show as text:".to_string(),
23 "cursor moves and clears never execute: \x1b[2A \x1b[2J \x1b[K".to_string(),
24 "OSC8 hyperlink stays live and is never split: \x1b]8;;https://example.com/about\x07example.com\x1b]8;;\x07".to_string(),
25 "an OSC title is escaped text, never a live title: \x1b]0;window title\x07".to_string(),
26 "two-byte escapes too: \x1b7 saved cursor \x1b8 restore".to_string(),
27 "".to_string(),
28 "An empty line and a tab-only line both occupy a row:".to_string(),
29 "".to_string(),
30 "\t".to_string(),
31 "".to_string(),
32 "Long content so wrapping kicks in, note how tabs keep 8-column alignment:".to_string(),
33 "\tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.".to_string(),
34 "a shorter line\t\t\twith long tab gaps and trailing spaces".to_string(),
35 "".to_string(),
36 "A very long unbroken\t\t\ttoken-heavy line that wraps several times across the viewport width to exercise the wrap-with-tab path:".to_string(),
37 "".to_string(),
38 ];
39
40 let text = doc.join("\n");
41
42 let config = TxtViewConfig {
43 show_line_numbers: true,
44 show_scrollbar: true,
45 show_help_bar: true,
46 ..TxtViewConfig::default()
47 };
48
49 let mut viewer = TxtView::new(&text).with_config(config);
50 viewer.run()
51}Sourcepub fn with_config(self, config: TxtViewConfig) -> Self
pub fn with_config(self, config: TxtViewConfig) -> Self
Apply configuration and rebuild the display layout.
Consumes the viewer and returns it so callers can chain:
use txtview::{TxtView, TxtViewConfig};
let viewer = TxtView::new("hello")
.with_config(TxtViewConfig {
show_line_numbers: true,
..TxtViewConfig::default()
});Examples found in repository?
3fn main() -> std::io::Result<()> {
4 let text = (1..=100)
5 .map(|i| format!("Line {:>3}: The quick brown fox jumps over the lazy dog", i))
6 .collect::<Vec<String>>()
7 .join("\n");
8
9 let config = TxtViewConfig {
10 show_line_numbers: true,
11 ..TxtViewConfig::default()
12 };
13
14 let mut viewer = TxtView::new(&text).with_config(config);
15 viewer.run()
16}More examples
3fn main() -> std::io::Result<()> {
4 // Fixed 20-column viewport so wrapping always happens at the same place,
5 // independent of the terminal size.
6 let doc = vec![
7 "Grapheme cluster wrapping demo".to_string(),
8 "".to_string(),
9 "Every cluster wraps as one unit, never split at a row boundary:".to_string(),
10 "".to_string(),
11 "skin-tone modifier: 123456789012345678👍🏿xyz".to_string(),
12 "ZWJ family emoji: 123456789012345678👨\u{200d}👩\u{200d}👧x".to_string(),
13 "flag pair: 1234567890123456789🇺🇸x".to_string(),
14 "".to_string(),
15 "combining marks stay with their base char:".to_string(),
16 " na\u{303}i\u{303}ve cafe\u{301} re\u{301}sume\u{301}".to_string(),
17 "".to_string(),
18 "keycap and variation-selector sequences:".to_string(),
19 " \u{23}\u{fe0f}\u{20e3} \u{31}\u{fe0f}\u{20e3} vs plain 3 and a ❤\u{fe0f} heart"
20 .to_string(),
21 "".to_string(),
22 "All of these stay intact even when a row boundary".to_string(),
23 "lands in the middle of one.".to_string(),
24 ];
25
26 let text = doc.join("\n");
27
28 let config = TxtViewConfig {
29 viewport_width: Some(20),
30 show_line_numbers: false,
31 show_scrollbar: false,
32 ..TxtViewConfig::default()
33 };
34
35 let mut viewer = TxtView::new(&text).with_config(config);
36 viewer.run()
37}16fn main() {
17 let lines = vec![
18 "Welcome to TxtView".bold().underlined().to_string(),
19 "".to_string(),
20 "What is this?".bold().to_string(),
21 " A lightweight terminal text viewer for Rust, built on".to_string(),
22 format!(
23 " {} with no heavy dependencies.",
24 "crossterm".cyan().bold()
25 ),
26 "".to_string(),
27 "Supported features".bold().to_string(),
28 bullet("Scrolling", "line-by-line or page-by-page", |s| {
29 s.cyan().bold().to_string()
30 }),
31 bullet("Wrapping", "reflows text to the viewport width", |s| {
32 s.yellow().to_string()
33 }),
34 bullet("Scrollbar", "shows the reading position", |s| {
35 s.red().bold().to_string()
36 }),
37 bullet("Line numbers", "optional left-hand column", |s| {
38 s.italic().to_string()
39 }),
40 bullet("Mouse support", "wheel and button scrolling", |s| {
41 s.green().to_string()
42 }),
43 "".to_string(),
44 "Keybindings".bold().to_string(),
45 binding("j / k", "scroll one line"),
46 binding("PgUp / PgDn", "scroll one page"),
47 binding("g / G", "jump to start / end"),
48 binding("q / Esc", "quit"),
49 "".to_string(),
50 "Configuration".bold().to_string(),
51 " Everything is set through TxtViewConfig:".to_string(),
52 setting("show_line_numbers", "toggles the line number column"),
53 setting("show_scrollbar", "toggles the interactive scrollbar"),
54 setting("show_help_bar", "toggles this help section"),
55 "".to_string(),
56 ];
57
58 let mut viewer = TxtView::new(lines.join("\n")).with_config(TxtViewConfig::default());
59 viewer.run().unwrap();
60}3fn main() -> std::io::Result<()> {
4 let doc = vec![
5 "Control character & tab handling demo".to_string(),
6 "".to_string(),
7 "Tabs are measured and wrapped at their 8-column terminal stop:".to_string(),
8 "\tone tab of indentation".to_string(),
9 "\t\ttwo tabs".to_string(),
10 "\t\t\tthree tabs".to_string(),
11 "no\tgap\tor\twider".to_string(),
12 "".to_string(),
13 "Mixed tab and space indentation:".to_string(),
14 " four spaces then\tone tab".to_string(),
15 "\tone tab then four spaces".to_string(),
16 "".to_string(),
17 "Control bytes are shown as caret notation instead of being executed:".to_string(),
18 "backspace \x08 BEL \x07 CR \r DEL \x7f end".to_string(),
19 "solo control bytes: ^not caret, actual: \x01 \x02 \x03 \x04".to_string(),
20 "field separators: US \x1f RS \x1e GS \x1d FS \x1c".to_string(),
21 "".to_string(),
22 "SGR and OSC8 hyperlinks pass through; other escapes show as text:".to_string(),
23 "cursor moves and clears never execute: \x1b[2A \x1b[2J \x1b[K".to_string(),
24 "OSC8 hyperlink stays live and is never split: \x1b]8;;https://example.com/about\x07example.com\x1b]8;;\x07".to_string(),
25 "an OSC title is escaped text, never a live title: \x1b]0;window title\x07".to_string(),
26 "two-byte escapes too: \x1b7 saved cursor \x1b8 restore".to_string(),
27 "".to_string(),
28 "An empty line and a tab-only line both occupy a row:".to_string(),
29 "".to_string(),
30 "\t".to_string(),
31 "".to_string(),
32 "Long content so wrapping kicks in, note how tabs keep 8-column alignment:".to_string(),
33 "\tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.".to_string(),
34 "a shorter line\t\t\twith long tab gaps and trailing spaces".to_string(),
35 "".to_string(),
36 "A very long unbroken\t\t\ttoken-heavy line that wraps several times across the viewport width to exercise the wrap-with-tab path:".to_string(),
37 "".to_string(),
38 ];
39
40 let text = doc.join("\n");
41
42 let config = TxtViewConfig {
43 show_line_numbers: true,
44 show_scrollbar: true,
45 show_help_bar: true,
46 ..TxtViewConfig::default()
47 };
48
49 let mut viewer = TxtView::new(&text).with_config(config);
50 viewer.run()
51}Sourcepub fn line_count(&self) -> usize
pub fn line_count(&self) -> usize
The number of logical lines in the input.
Sourcepub fn config(&self) -> &TxtViewConfig
pub fn config(&self) -> &TxtViewConfig
Returns a reference to the current configuration of this TxtView.
Use it to inspect the active settings or to build a modified config
and apply it via TxtView::with_config.
use txtview::{TxtView, TxtViewConfig};
let viewer = TxtView::new("hello");
let config = viewer.config();
assert!(!config.show_line_numbers);