Skip to content

Commit ca3be18

Browse files
committed
Option to show line ending on received lines
1 parent 237df9b commit ca3be18

6 files changed

Lines changed: 86 additions & 54 deletions

File tree

src/app.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -315,25 +315,6 @@ impl App {
315315
Duration::from_secs(1),
316316
);
317317

318-
// let serial_signal_tick_handle = serial_handle.clone();
319-
// let mut cache = arc_swap::Cache::new(std::sync::Arc::clone(
320-
// &serial_signal_tick_handle.port_status,
321-
// ));
322-
// event_carousel.add_repeating(
323-
// "SerialSignals",
324-
// Box::new(move || {
325-
// let port_status = cache.load();
326-
// if port_status.state.is_healthy() {
327-
// serial_signal_tick_handle
328-
// .read_signals()
329-
// .map_err(|e| e.to_string())
330-
// } else {
331-
// Ok(())
332-
// }
333-
// }),
334-
// Duration::from_millis(100),
335-
// );
336-
337318
let line_ending = settings.last_port_settings.rx_line_ending.as_bytes();
338319
let buffer = Buffer::new(
339320
line_ending,

src/buffer/buf_line.rs

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::borrow::Cow;
22

3+
use bstr::ByteSlice;
34
use chrono::{DateTime, Local};
45
use compact_str::{CompactString, ToCompactString, format_compact};
56
use ratatui::{
@@ -11,6 +12,7 @@ use ratatui_macros::{line, span};
1112
use tracing::debug;
1213

1314
use crate::{
15+
buffer::LineEnding,
1416
settings::Rendering,
1517
traits::{ByteSuffixCheck, FirstChars, LineHelpers},
1618
};
@@ -60,7 +62,9 @@ pub struct BufLine {
6062

6163
#[derive(Debug, Clone, PartialEq, Eq)]
6264
pub(super) enum LineType {
63-
Port,
65+
Port {
66+
escaped_line_ending: Option<CompactString>,
67+
},
6468
User {
6569
is_bytes: bool,
6670
is_macro: bool,
@@ -92,6 +96,7 @@ impl BufLine {
9296
raw_buffer_index: usize,
9397
area_width: u16,
9498
rendering: &Rendering,
99+
line_ending: &LineEnding,
95100
now: DateTime<Local>,
96101
line_type: LineType,
97102
) -> Self {
@@ -115,20 +120,42 @@ impl BufLine {
115120
rendered_line_height: 0,
116121
line_type,
117122
};
123+
bufline.populate_line_ending(raw_value, line_ending);
118124
bufline.update_line_height(area_width, rendering);
119125
bufline
120126
}
127+
pub fn populate_line_ending(&mut self, full_line_slice: &[u8], line_ending: &LineEnding) {
128+
match &mut self.line_type {
129+
LineType::Port {
130+
escaped_line_ending,
131+
} => {
132+
if escaped_line_ending.is_some() {
133+
unreachable!();
134+
}
135+
if full_line_slice.has_line_ending(line_ending) {
136+
_ = escaped_line_ending
137+
.insert(line_ending.as_bytes().escape_bytes().to_compact_string());
138+
}
139+
}
140+
// TODO?
141+
LineType::User { .. } => (),
142+
}
143+
}
121144
pub fn update_line(
122145
&mut self,
123146
line: Line<'static>,
124147
full_line_slice: &[u8],
125148
area_width: u16,
126149
rendering: &Rendering,
150+
line_ending: &LineEnding,
127151
) {
128152
self.index_info = make_index_info(full_line_slice, self.raw_buffer_index, &self.line_type);
129153

130154
self.value = line;
131155
self.value.remove_unsavory_chars();
156+
157+
self.populate_line_ending(full_line_slice, line_ending);
158+
132159
self.update_line_height(area_width, rendering);
133160
}
134161

@@ -150,21 +177,36 @@ impl BufLine {
150177
pub fn as_line(&self, rendering: &Rendering) -> Line {
151178
let borrowed_spans = self.value.borrowed_spans_iter();
152179

153-
let indices_span_iter = std::iter::once(Span::styled(
180+
let indices_and_len = std::iter::once(Span::styled(
154181
Cow::Borrowed(self.index_info.as_ref()),
155182
Style::new().dark_gray(),
156183
))
157184
.filter(|_| rendering.show_indices);
158185

159-
let spans = std::iter::once(Span::styled(
186+
let timestamp = std::iter::once(Span::styled(
160187
Cow::Borrowed(self.timestamp_str.as_ref()),
161188
Style::new().dark_gray(),
162189
))
163190
.filter(|_| rendering.timestamps);
164191

165-
let spans = spans.chain(indices_span_iter);
166-
167-
let spans = spans.chain(borrowed_spans);
192+
let line_ending = std::iter::once(&self.line_type).filter_map(|lt| match lt {
193+
_ if !rendering.show_line_ending => None,
194+
LineType::Port {
195+
escaped_line_ending: Some(line_ending),
196+
} => Some(Span::styled(
197+
Cow::Borrowed(line_ending.as_str()),
198+
Style::new().dark_gray(),
199+
)),
200+
LineType::Port {
201+
escaped_line_ending: None,
202+
} => None,
203+
LineType::User { .. } => None,
204+
});
205+
206+
let spans = timestamp
207+
.chain(indices_and_len)
208+
.chain(borrowed_spans)
209+
.chain(line_ending);
168210

169211
Line::from_iter(spans)
170212
}

src/buffer/mod.rs

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ impl Buffer {
366366
self.raw.inner.len(), // .max(1)
367367
self.last_terminal_size.width,
368368
&self.rendering,
369+
&self.line_ending,
369370
now,
370371
LineType::User {
371372
is_bytes: true,
@@ -438,6 +439,7 @@ impl Buffer {
438439
self.raw.inner.len(), // .max(1)
439440
self.last_terminal_size.width,
440441
&self.rendering,
442+
&self.line_ending,
441443
now,
442444
LineType::User {
443445
is_bytes: false,
@@ -484,6 +486,8 @@ impl Buffer {
484486
return;
485487
}
486488

489+
let this_rx_completed = self.raw.inner.has_line_ending(&self.line_ending);
490+
487491
if append_to_last {
488492
let last_line = self
489493
.styled_lines
@@ -492,18 +496,19 @@ impl Buffer {
492496
.expect("can't append to nothing");
493497
let last_index = last_line.index_in_buffer();
494498

495-
let slice = &self.raw.inner[last_index..start_index + trunc.len()];
499+
let trunc = &self.raw.inner[last_index..start_index + trunc.len()];
500+
let orig = &self.raw.inner[last_index..start_index + orig.len()];
496501
// info!("AAAFG: {:?}", slice);
497502
let lossy_flavor = if self.rendering.escape_invalid_bytes {
498503
LossyFlavor::escaped_bytes_styled(Style::new().dark_gray())
499504
} else {
500505
LossyFlavor::replacement_char()
501506
};
502-
let mut line = match slice.into_line_lossy(Style::new(), lossy_flavor) {
507+
let mut line = match trunc.into_line_lossy(Style::new(), lossy_flavor) {
503508
Ok(line) => line,
504509
Err(_) => {
505510
error!("ansi-to-tui failed to parse input! Using unstyled text.");
506-
Line::from(String::from_utf8_lossy(slice).to_string())
511+
Line::from(String::from_utf8_lossy(trunc).to_string())
507512
}
508513
};
509514
// debug!(
@@ -520,10 +525,16 @@ impl Buffer {
520525
// line.style_slice(1..3, Style::new().red().italic());
521526
// }
522527

523-
let line_opt = self.color_rules.apply_onto(slice, line);
528+
let line_opt = self.color_rules.apply_onto(trunc, line);
524529

525530
if let Some(line) = line_opt {
526-
last_line.update_line(line, slice, self.last_terminal_size.width, &self.rendering);
531+
last_line.update_line(
532+
line,
533+
orig,
534+
self.last_terminal_size.width,
535+
&self.rendering,
536+
&self.line_ending,
537+
);
527538
} else {
528539
_ = self.styled_lines.rx.pop();
529540
self.styled_lines.last_rx_completed = true;
@@ -545,39 +556,23 @@ impl Buffer {
545556

546557
let line_opt = self.color_rules.apply_onto(trunc, line);
547558

548-
// if line.width() >= 5 {
549-
// line.style_slice(1..3, Style::new().red().italic());
550-
// }
551-
552-
// if !line.is_styled() {
553-
// assert!(line.spans.len() <= 1);
554-
// }
555-
556-
// debug!(
557-
// "buf_index: {start_index}, new: {line}",
558-
// line = line
559-
// .spans
560-
// .iter()
561-
// .map(|s| s.content.as_ref())
562-
// .join("")
563-
// .escape_default()
564-
// );
565-
566-
// let line = line_opt.unwrap_or_default();
567559
if let Some(line) = line_opt {
568560
self.styled_lines.rx.push(BufLine::new_with_line(
569561
line,
570562
orig,
571563
start_index,
572564
self.last_terminal_size.width,
573565
&self.rendering,
566+
&self.line_ending,
574567
known_time.unwrap_or_else(Local::now),
575-
LineType::Port,
568+
LineType::Port {
569+
escaped_line_ending: None,
570+
},
576571
));
577572
}
578573
};
579-
let last_rx_completed = self.raw.inner.has_line_ending(&self.line_ending);
580-
self.styled_lines.last_rx_completed = last_rx_completed;
574+
575+
self.styled_lines.last_rx_completed = this_rx_completed;
581576
}
582577

583578
// Forced to use Vec<u8> for now
@@ -737,8 +732,9 @@ impl Buffer {
737732
let should_reconsume =
738733
changed!(old, new, echo_user_input) || changed!(old, new, escape_invalid_bytes);
739734

740-
let should_rewrap_lines =
741-
changed!(old, new, timestamps) || changed!(old, new, show_indices);
735+
let should_rewrap_lines = changed!(old, new, timestamps)
736+
|| changed!(old, new, show_indices)
737+
|| changed!(old, new, show_line_ending);
742738

743739
if changed!(old, new, bytes_per_line) {
744740
self.determine_bytes_per_line(new.bytes_per_line.into());

src/cli.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@
1111
// - or instead, show an error and drop on port selection screen, but an --option can skip that and just close?
1212
// - both should skip scanning for serial ports and try to directly connect to the given port
1313
// - maybe also allow USB PID+VID as an "address"? would prefer to accept same formats as usb ignore configs
14+
15+
// option to print out all possible AppActions then exit?

src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
fn main() -> color_eyre::Result<()> {
22
yap::run()
33
}
4+
5+
// TODO defmt support
6+
// TODO mouse select in line mode?
7+
8+
// Far future TODOs:
9+
// TODO Forwarding + Loopback support
10+
// TODO TCP Socket support

src/settings/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ pub struct Rendering {
106106
/// Wrap text longer than the screen.
107107
pub wrap_text: bool,
108108

109+
#[serde(default)]
110+
/// Show line ending at end of recieved lines.
111+
pub show_line_ending: bool,
112+
109113
#[serde(default)]
110114
/// Show invalid byte sequences in \xFF notation.
111115
pub escape_invalid_bytes: bool,

0 commit comments

Comments
 (0)