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

Blightmud / Blightmud / 23965955605

03 Apr 2026 11:26PM UTC coverage: 74.122%. First build
23965955605

Pull #1406

github

web-flow
Merge 4d2eeb87b into abbfa3d0f
Pull Request #1406: Adds tag support to lines through lua.

474 of 608 new or added lines in 12 files covered. (77.96%)

10168 of 13718 relevant lines covered (74.12%)

672.53 hits per line

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

38.24
/src/ui/ui_wrapper.rs
1
use std::{
2
    io::{stdout, Write},
3
    sync::{Arc, Mutex},
4
};
5

6
use crate::{
7
    io::SaveData,
8
    model::{Settings, MOUSE_ENABLED, READER_MODE},
9
    session::Session,
10
    tts::TTSController,
11
};
12

13
use super::{history::History, HeadlessScreen, ReaderScreen, SplitScreen, UserInterface};
14
use anyhow::Result;
15
use termion::{input::MouseTerminal, raw::IntoRawMode, screen::IntoAlternateScreen};
16

17
/// Creates the io::Write terminal handler we draw to.
18
fn create_screen_writer(mouse_support: bool) -> Result<Box<dyn Write>> {
×
19
    let screen = stdout().into_raw_mode()?.into_alternate_screen()?;
×
20
    if mouse_support {
×
21
        Ok(Box::new(MouseTerminal::from(screen)))
×
22
    } else {
23
        Ok(Box::new(screen))
×
24
    }
25
}
×
26

27
pub struct UiWrapper {
28
    screen: Box<dyn UserInterface>,
29
    tts_ctrl: Arc<Mutex<TTSController>>,
30
}
31

32
impl UiWrapper {
33
    pub fn new(session: &Session) -> Result<Self> {
×
34
        let settings = Settings::try_load()?;
×
35
        let reader_mode = settings.get(READER_MODE)?;
×
36
        let screen: Box<dyn UserInterface> = if reader_mode {
×
37
            Box::new(ReaderScreen::new(
×
38
                create_screen_writer(false)?,
×
39
                History::new(),
×
40
            )?)
×
41
        } else {
42
            Box::new(SplitScreen::new(
×
43
                create_screen_writer(settings.get(MOUSE_ENABLED)?)?,
×
44
                History::new(),
×
45
            )?)
×
46
        };
47
        let tts_ctrl = session.tts_ctrl.clone();
×
48

49
        Ok(Self { screen, tts_ctrl })
×
50
    }
×
51

52
    pub fn new_from(
×
53
        screen: Box<dyn UserInterface>,
×
54
        session: &Session,
×
55
        reader_mode: bool,
×
56
    ) -> Result<Self> {
×
57
        let (writer, history) = screen.destroy()?;
×
58
        let mut screen: Box<dyn UserInterface> = if reader_mode {
×
59
            Box::new(ReaderScreen::new(writer, history)?)
×
60
        } else {
61
            Box::new(SplitScreen::new(writer, history)?)
×
62
        };
63
        screen.setup()?;
×
64
        Ok(Self {
×
65
            screen,
×
66
            tts_ctrl: session.tts_ctrl.clone(),
×
67
        })
×
68
    }
×
69

70
    pub fn headless(session: &Session) -> Result<Self> {
136✔
71
        Ok(Self {
136✔
72
            screen: Box::new(HeadlessScreen {}),
136✔
73
            tts_ctrl: session.tts_ctrl.clone(),
136✔
74
        })
136✔
75
    }
136✔
76
}
77

78
impl UserInterface for UiWrapper {
79
    fn setup(&mut self) -> Result<()> {
136✔
80
        self.screen.setup()
136✔
81
    }
136✔
82

83
    fn print_error(&mut self, output: &str) {
48✔
84
        self.tts_ctrl.lock().unwrap().speak_error(output);
48✔
85
        self.screen.print_error(output);
48✔
86
    }
48✔
87

88
    fn print_info(&mut self, output: &str) {
496✔
89
        self.tts_ctrl.lock().unwrap().speak_info(output);
496✔
90
        self.screen.print_info(output);
496✔
91
    }
496✔
92

93
    fn print_output(&mut self, line: &crate::model::Line) {
232✔
94
        self.tts_ctrl.lock().unwrap().speak_line(line);
232✔
95
        self.screen.print_output(line);
232✔
96
    }
232✔
97

98
    fn print_prompt(&mut self, prompt: &crate::model::Line) {
152✔
99
        self.tts_ctrl.lock().unwrap().speak_line(prompt);
152✔
100
        self.screen.print_prompt(prompt);
152✔
101
    }
152✔
102

103
    fn print_prompt_input(&mut self, input: &str, pos: usize) {
×
104
        self.screen.print_prompt_input(input, pos);
×
105
    }
×
106

107
    fn print_send(&mut self, send: &crate::model::Line) {
64✔
108
        if let Some(line) = send.print_line() {
64✔
109
            self.tts_ctrl.lock().unwrap().speak_input(line);
64✔
110
        }
64✔
111
        self.screen.print_send(send);
64✔
112
    }
64✔
113

114
    fn reset(&mut self) -> Result<()> {
136✔
115
        self.screen.reset()
136✔
116
    }
136✔
117

118
    fn reset_scroll(&mut self) -> Result<()> {
×
119
        self.screen.reset_scroll()
×
120
    }
×
121

122
    fn clear_output_area(&mut self) -> Result<()> {
×
123
        self.screen.clear_output_area()
×
124
    }
×
125

126
    fn scroll_down(&mut self) -> Result<()> {
×
127
        self.screen.scroll_down()
×
128
    }
×
129

130
    fn scroll_lock(&mut self, lock: bool) -> Result<()> {
×
131
        self.screen.scroll_lock(lock)
×
132
    }
×
133

134
    fn scroll_to(&mut self, row: usize) -> Result<()> {
×
135
        self.screen.scroll_to(row)
×
136
    }
×
137

138
    fn scroll_top(&mut self) -> Result<()> {
×
139
        self.screen.scroll_top()
×
140
    }
×
141

142
    fn scroll_up(&mut self) -> Result<()> {
×
143
        self.screen.scroll_up()
×
144
    }
×
145

146
    fn find_up(&mut self, pattern: &crate::model::Regex) -> Result<()> {
×
147
        self.screen.find_up(pattern)
×
148
    }
×
149

150
    fn find_down(&mut self, pattern: &crate::model::Regex) -> Result<()> {
×
151
        self.screen.find_down(pattern)
×
152
    }
×
153

154
    fn set_host(&mut self, host: &str, port: u16) -> Result<()> {
192✔
155
        self.screen.set_host(host, port)
192✔
156
    }
192✔
157

158
    fn add_tag(&mut self, proto: &str) -> Result<()> {
32✔
159
        self.screen.add_tag(proto)
32✔
160
    }
32✔
161

162
    fn remove_tag(&mut self, proto: &str) -> Result<()> {
×
163
        self.screen.remove_tag(proto)
×
164
    }
×
165

166
    fn clear_tags(&mut self) -> Result<()> {
96✔
167
        self.screen.clear_tags()
96✔
168
    }
96✔
169

170
    fn set_status_area_height(&mut self, height: u16) -> Result<()> {
×
171
        self.screen.set_status_area_height(height)
×
172
    }
×
173

NEW
174
    fn set_show_tags(&mut self, show: bool) -> Result<()> {
×
NEW
175
        self.screen.set_show_tags(show)
×
NEW
176
    }
×
177

NEW
178
    fn set_tag_mask(&mut self, mask: crate::model::TagMask) {
×
NEW
179
        self.screen.set_tag_mask(mask);
×
NEW
180
    }
×
181

182
    fn set_status_line(&mut self, line: usize, info: String) -> Result<()> {
×
183
        self.screen.set_status_line(line, info)
×
184
    }
×
185

186
    fn flush(&mut self) {
3,136✔
187
        self.screen.flush();
3,136✔
188
    }
3,136✔
189

190
    fn width(&self) -> u16 {
32✔
191
        self.screen.width()
32✔
192
    }
32✔
193

194
    fn height(&self) -> u16 {
32✔
195
        self.screen.height()
32✔
196
    }
32✔
197

198
    fn destroy(self: Box<Self>) -> Result<(Box<dyn Write>, History)> {
×
199
        self.screen.destroy()
×
200
    }
×
201
}
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