1pub fn bounded(bytes: &[u8], max: usize) -> (String, bool) {
6 if bytes.len() <= max {
7 return (String::from_utf8_lossy(bytes).into_owned(), false);
8 }
9 let head_len = max * 2 / 3;
10 let tail_len = max - head_len;
11 let head = String::from_utf8_lossy(&bytes[..head_len]);
12 let tail = String::from_utf8_lossy(&bytes[bytes.len() - tail_len..]);
13 let omitted = bytes.len() - head_len - tail_len;
14 (
15 format!(
16 "{head}\n\n[... {omitted} bytes omitted; output limit is {max} bytes ...]\n\n{tail}"
17 ),
18 true,
19 )
20}
21
22pub fn numbered_window(text: &str, offset: usize, limit: usize) -> (String, usize, bool) {
26 let start = offset.max(1) - 1;
27 let total = text.lines().count();
28 let mut out = String::new();
29 let mut shown = 0;
30 for (i, line) in text.lines().enumerate().skip(start).take(limit) {
31 out.push_str(&format!("{:>6}\t{}\n", i + 1, line));
32 shown += 1;
33 }
34 let more = start + shown < total;
35 (out, total, more)
36}
37
38pub fn shell_quote(s: &str) -> String {
40 if !s.is_empty()
41 && s.bytes()
42 .all(|b| b.is_ascii_alphanumeric() || b"-_./=:@%+,".contains(&b))
43 {
44 return s.to_string();
45 }
46 format!("'{}'", s.replace('\'', "'\\''"))
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn bounded_keeps_head_and_tail() {
55 let data: Vec<u8> = (0..1000).map(|i| b'a' + (i % 26) as u8).collect();
56 let (s, cut) = bounded(&data, 300);
57 assert!(cut);
58 assert!(s.starts_with("abcdefghij"));
59 assert!(s.contains("omitted"));
60 assert!(s.ends_with(std::str::from_utf8(&data[900..]).unwrap()));
61 let (s, cut) = bounded(b"short", 300);
62 assert!(!cut);
63 assert_eq!(s, "short");
64 }
65
66 #[test]
67 fn window_numbers_from_offset() {
68 let (s, total, more) = numbered_window("a\nb\nc\nd", 2, 2);
69 assert_eq!(s, " 2\tb\n 3\tc\n");
70 assert_eq!(total, 4);
71 assert!(more);
72 let (_, _, more) = numbered_window("a\nb", 1, 10);
73 assert!(!more);
74 }
75
76 #[test]
77 fn quoting() {
78 assert_eq!(shell_quote("abc/def.txt"), "abc/def.txt");
79 assert_eq!(shell_quote("it's here"), "'it'\\''s here'");
80 assert_eq!(shell_quote(""), "''");
81 }
82}