diff --git a/examples/bench.rs b/examples/bench.rs index 603dbd5..d4481fb 100644 --- a/examples/bench.rs +++ b/examples/bench.rs @@ -1,5 +1,5 @@ -//! In-process benchmarks mirroring the Go `go test -bench` suite -//! (internal/tui/bench_test.go, internal/treemap/treemap_test.go): +//! In-process benchmarks of the TUI model (render, navigation, filtering) +//! and the treemap layout: //! //! cargo run --release --example bench //! diff --git a/src/app.rs b/src/app.rs index 2cd420b..21dcd65 100644 --- a/src/app.rs +++ b/src/app.rs @@ -100,7 +100,7 @@ fn start_source( Ok((Some(s), t)) } -/// Cancels on SIGINT for report mode, like Go's signal.NotifyContext. +/// A token cancelled by SIGINT (Ctrl+C), for report mode. fn interrupt_cancel() -> Cancel { static CANCEL: std::sync::OnceLock = std::sync::OnceLock::new(); extern "C" fn on_sigint(_: libc::c_int) { diff --git a/src/cancel.rs b/src/cancel.rs index c529f9b..2ccd3be 100644 --- a/src/cancel.rs +++ b/src/cancel.rs @@ -1,4 +1,5 @@ -//! A clonable cancellation token, the equivalent of a Go context's Done. +//! A clonable cancellation token: a flag to poll plus a channel that is +//! closed on cancellation, so it can also be waited on in a select. use crossbeam_channel::{Receiver, Sender}; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/src/export.rs b/src/export.rs index 0673681..aecc55b 100644 --- a/src/export.rs +++ b/src/export.rs @@ -213,7 +213,11 @@ pub fn summary(w: &mut dyn Write, t: &Tree) -> io::Result<()> { textutil::size(r.tot_alloc), r.tot_alloc )?; - writeln!(w, "Elapsed {}", textutil::go_duration(st.elapsed()))?; + writeln!( + w, + "Elapsed {}", + textutil::fmt_duration(st.elapsed()) + )?; for (k, &c) in st.err_counts.iter().enumerate() { if c > 0 { writeln!( diff --git a/src/filter/lexer.rs b/src/filter/lexer.rs index f733893..b38e5bb 100644 --- a/src/filter/lexer.rs +++ b/src/filter/lexer.rs @@ -24,7 +24,7 @@ fn tok(kind: TokKind, val: &str, pos: usize) -> Token { } } -/// ASCII white space as Go's unicode.IsSpace sees it. +/// ASCII white space: space, \t, \n, \v, \f, \r. fn is_space(c: u8) -> bool { matches!(c, b' ' | b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r') } diff --git a/src/filter/mod.rs b/src/filter/mod.rs index 094c015..2980d97 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -150,7 +150,7 @@ mod tests { ); } assert!(names(&tr, "[").is_empty()); // malformed bare glob matches nothing - assert!(names(&tr, "voilà\u{a0}x").is_empty()); // Go's lexer hangs on byte 0xA0 + assert!(names(&tr, "voilà\u{a0}x").is_empty()); // regression: a lexer once hung on byte 0xA0 (NBSP) } #[test] diff --git a/src/filter/parser.rs b/src/filter/parser.rs index 4de7ccb..c02110d 100644 --- a/src/filter/parser.rs +++ b/src/filter/parser.rs @@ -309,7 +309,7 @@ fn has_glob(s: &str) -> bool { pub(super) fn name_match(v: &str) -> Expr { let lv = v.to_lowercase(); if has_glob(v) { - // Go's filepath.Match never matches a malformed pattern. + // A malformed glob never matches. return if glob_ok(lv.as_bytes()) { Expr::Glob(Field::Name, lv) } else { @@ -319,8 +319,9 @@ pub(super) fn name_match(v: &str) -> Expr { Expr::Contains(Field::Name, lv) } -/// Reports whether pattern is well formed by Go's filepath.Match rules -/// (fnmatch, which does the matching, accepts anything). +/// Reports whether pattern is a well-formed glob (see +/// `platform::glob_match`): every `[` class is closed and non-empty, ranges +/// have both ends, and no escape is dangling. fn glob_ok(p: &[u8]) -> bool { // One possibly escaped character of a range; None if malformed. let esc = |mut i: usize| -> Option { @@ -461,13 +462,12 @@ pub fn parse_age(s: &str) -> Result { )) } }; - // Saturates where Go's time.Duration would overflow. + // Saturates beyond u64 nanoseconds (about 584 years). Ok(Duration::from_nanos((v * secs * 1e9) as u64)) } /// Parses "2006-01-02", "2006-01-02T15:04", "2006-01-02 15:04" (local time) -/// or RFC 3339, as Go's time.ParseInLocation with time.Local would, into unix -/// nanoseconds. +/// or RFC 3339 (with its own offset) into unix nanoseconds. fn parse_date(s: &str) -> Option { let b = s.as_bytes(); let fixed = |i: usize, n: usize| -> Option { @@ -492,7 +492,7 @@ fn parse_date(s: &str) -> Option { if sep != b'T' && sep != b' ' { return None; } - // Go's "15" hour accepts one or two digits. + // The hour may have one or two digits. let mut i = 11; let hl = if fixed(i, 2).is_some() { 2 } else { 1 }; let h = fixed(i, hl)?; diff --git a/src/inventory/mod.rs b/src/inventory/mod.rs index cda018b..eff8b1d 100644 --- a/src/inventory/mod.rs +++ b/src/inventory/mod.rs @@ -80,7 +80,7 @@ pub struct Node { pub files: u32, // recursive counts beneath (dirs excludes self) pub dirs: u32, pub errors: u32, // recursive error count beneath and including self - pub mode: u32, // Go fs.FileMode bit layout (see platform::mode) + pub mode: u32, // portable mode bits (see platform::mode) pub uid: u32, pub gid: u32, pub nlink: u32, diff --git a/src/lib.rs b/src/lib.rs index 2a8cf38..6fc0975 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -//! mapsize: interactive terminal disk usage analyser (Rust port). +//! mapsize: interactive terminal disk usage analyser. pub mod app; pub mod brand; diff --git a/src/main.rs b/src/main.rs index 0642318..7b3056d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use mapsize::inventory::SizeMode; use mapsize::{brand, config, scan, snapshot, textutil}; use std::path::Path; -/// Flags taking a value (Go's flag package: `-f v`, `-f=v`, `--f v`, `--f=v`). +/// Flags taking a value, written `-f v`, `-f=v`, `--f v` or `--f=v`. const VALUE_FLAGS: &[&str] = &[ "workers", "follow-symlinks", @@ -71,8 +71,8 @@ Flags: --theme NAME colour theme: default, dark, high-contrast, mono --color MODE colour support: auto, truecolor, 256, 16, none --no-mouse disable mouse support - --log FILE write a debug log to FILE - --log-level LEVEL log level: error, warn, info, debug, trace + --log FILE accepted for compatibility; ignored + --log-level LEVEL accepted for compatibility (error, warn, info, debug, trace); ignored --version print version and exit " ); @@ -171,7 +171,7 @@ fn run(args: Vec) -> i32 { return fail(format!("invalid --log-level {l:?}")); } } - // ponytail: --log is accepted for CLI compatibility; the Rust port has no debug logging yet. + // ponytail: --log and --log-level are accepted for compatibility and ignored; there is no debug logging. let (depth, top, largest) = match (int("depth", -1), int("top", 0), int("largest-files", 0)) { (Ok(d), Ok(t), Ok(l)) => (d, t.max(0) as usize, l.max(0) as usize), diff --git a/src/scan.rs b/src/scan.rs index 812c565..760493d 100644 --- a/src/scan.rs +++ b/src/scan.rs @@ -651,7 +651,8 @@ impl Controller { } } -/// The OS error text without Rust's " (os error N)" suffix, matching Go. +/// The OS error text, lower-cased and without the " (os error N)" suffix, +/// e.g. "permission denied". fn err_msg(e: &io::Error) -> String { let s = e.to_string(); match s.rfind(" (os error ") { diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index cd5abf5..3c4efab 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -21,10 +21,22 @@ //! sha256 32 bytes over the uncompressed body //! ``` //! -//! Varints are Go's encoding/binary (zig-zag for signed). Nodes are written -//! in ID order; a parent always precedes its children, so a reader can -//! rebuild the tree in one pass and malformed input cannot create cycles. -//! Aggregates are recomputed on load, never trusted. +//! A uvarint is unsigned LEB128: 7 bits per byte, least significant group +//! first, the high bit set on every byte but the last; at most 10 bytes for +//! 64 bits. A varint (signed) is zig-zag encoded first, (v << 1) ^ (v >> 63), +//! so small magnitudes of either sign stay short: 0, -1, 1, -2 → 0, 1, 2, 3. +//! +//! In the meta JSON, timestamps are RFC 3339 strings with nanoseconds +//! (trailing zeros trimmed) and the writer's UTC offset, or "Z" for UTC, +//! e.g. "2026-10-08T10:40:00.123456789+01:00". An unset time is +//! "0001-01-01T00:00:00Z"; null is read as unset. +//! +//! Compatibility: snapshots written by mapsize 1.x load unchanged, and the +//! mode bits (see `platform::mode`) mean the same on every OS. +//! +//! Nodes are written in ID order; a parent always precedes its children, so +//! a reader can rebuild the tree in one pass and malformed input cannot +//! create cycles. Aggregates are recomputed on load, never trusted. mod compare; @@ -65,9 +77,9 @@ const FLAG_GZIPPED: u16 = 1; #[serde(default)] struct Meta { root: String, - created: GoTime, - start: GoTime, - end: GoTime, + created: JsonTime, + start: JsonTime, + end: JsonTime, complete: bool, cancelled: bool, files: i64, @@ -131,7 +143,7 @@ impl Writer { self.bytes(&b[..=i]) } fn varint(&mut self, v: i64) -> io::Result<()> { - self.uvarint(((v << 1) ^ (v >> 63)) as u64) // zig-zag, as encoding/binary.PutVarint + self.uvarint(((v << 1) ^ (v >> 63)) as u64) // zig-zag } fn str(&mut self, s: &[u8]) -> io::Result<()> { self.uvarint(s.len() as u64)?; @@ -154,11 +166,11 @@ pub fn save(out: &mut dyn Write, t: &Tree) -> io::Result<()> { let st = &t.stats; let m = Meta { root: String::from_utf8_lossy(&st.root).into_owned(), - created: GoTime::from_system(SystemTime::now()), - start: GoTime::from_system(st.start).local(), + created: JsonTime::from_system(SystemTime::now()), + start: JsonTime::from_system(st.start).local(), end: st .end - .map(|e| GoTime::from_system(e).local()) + .map(|e| JsonTime::from_system(e).local()) .unwrap_or_default(), complete: st.complete, cancelled: st.cancelled, @@ -233,7 +245,8 @@ pub fn save_file(path: &Path, t: &Tree) -> io::Result<()> { res } -/// Creates a new 0600 file named .mapsize-*.tmp in dir (like os.CreateTemp). +/// Creates a new private (0600 on Unix) file named .mapsize-.tmp in +/// dir, retrying on name collisions. fn create_temp(dir: &Path) -> io::Result<(PathBuf, File)> { let seed = SystemTime::now() .duration_since(UNIX_EPOCH) @@ -303,7 +316,8 @@ impl Body { Ok(self.buf[self.pos - 1]) } - /// Fills out completely (errors like io.ReadFull). + /// Fills out completely: "EOF" if the stream ends before the first byte, + /// "unexpected EOF" if it ends part way. fn read_full(&mut self, out: &mut [u8]) -> Result<(), String> { let mut done = 0; while done < out.len() { @@ -332,7 +346,7 @@ impl Body { fn varint(&mut self, what: &str) -> Result { let ux = read_uvarint(self).map_err(|e| format!("snapshot: bad {what}: {e}"))?; - let v = (ux >> 1) as i64; // zig-zag, as encoding/binary.PutVarint + let v = (ux >> 1) as i64; // undo zig-zag Ok(if ux & 1 != 0 { !v } else { v }) } @@ -349,7 +363,7 @@ impl Body { } } -/// encoding/binary.ReadUvarint over the body. +/// Reads a uvarint (LEB128) from the body; more than 64 bits is an error. fn read_uvarint(b: &mut Body) -> Result { let (mut x, mut s) = (0u64, 0u32); for i in 0..10 { @@ -611,32 +625,32 @@ fn valid_name(s: &[u8]) -> bool { !s.is_empty() && s != b"." && s != b".." && !s.iter().any(|&c| c == b'/' || c == 0) } -/// A Go time.Time as JSON carries it: unix seconds plus nanoseconds, and -/// the UTC offset it is written with. The default is Go's zero time -/// (0001-01-01T00:00:00Z). +/// A timestamp as the meta JSON carries it (see the module docs): unix +/// seconds plus nanoseconds, and the UTC offset it is written with. The +/// default is the unset time, 0001-01-01T00:00:00Z. #[derive(Clone, Copy, PartialEq, Eq, Debug)] -struct GoTime { +struct JsonTime { secs: i64, nanos: u32, off: i32, // seconds east of UTC; presentation only } -const GO_ZERO_SECS: i64 = -62_135_596_800; +const ZERO_SECS: i64 = -62_135_596_800; -impl Default for GoTime { +impl Default for JsonTime { fn default() -> Self { - GoTime { - secs: GO_ZERO_SECS, + JsonTime { + secs: ZERO_SECS, nanos: 0, off: 0, } } } -impl GoTime { - fn from_system(t: SystemTime) -> GoTime { +impl JsonTime { + fn from_system(t: SystemTime) -> JsonTime { match t.duration_since(UNIX_EPOCH) { - Ok(d) => GoTime { + Ok(d) => JsonTime { secs: d.as_secs() as i64, nanos: d.subsec_nanos(), off: 0, @@ -649,7 +663,7 @@ impl GoTime { } else { (-s - 1, 1_000_000_000 - n) }; - GoTime { + JsonTime { secs, nanos, off: 0, @@ -658,14 +672,14 @@ impl GoTime { } } - /// The same instant in the local time zone (as Go's time.Now()). - fn local(self) -> GoTime { + /// The same instant, presented in the local time zone. + fn local(self) -> JsonTime { let off = crate::platform::local_time(self.secs).off; - GoTime { off, ..self } + JsonTime { off, ..self } } fn is_zero(self) -> bool { - (self.secs, self.nanos) == (GO_ZERO_SECS, 0) + (self.secs, self.nanos) == (ZERO_SECS, 0) } fn to_system(self) -> SystemTime { @@ -677,7 +691,7 @@ impl GoTime { } } - /// RFC 3339 with trimmed nanoseconds, like Go's MarshalJSON. + /// RFC 3339 with nanoseconds (trailing zeros trimmed) and "Z" for UTC. fn format(self) -> String { let secs = self.secs + self.off as i64; let (y, mo, d) = civil_from_days(secs.div_euclid(86400)); @@ -704,7 +718,7 @@ impl GoTime { } /// Parses RFC 3339 ("2026-10-08T10:40:00.123456789+01:00"). - fn parse(s: &str) -> Option { + fn parse(s: &str) -> Option { let b = s.as_bytes(); let num = |r: std::ops::Range| -> Option { let p = b.get(r)?; @@ -762,7 +776,7 @@ impl GoTime { _ => return None, }; let secs = days_from_civil(y, mo, d) * 86400 + h * 3600 + mi * 60 + se - off; - Some(GoTime { + Some(JsonTime { secs, nanos, off: off as i32, @@ -779,18 +793,18 @@ impl GoTime { } } -impl Serialize for GoTime { +impl Serialize for JsonTime { fn serialize(&self, s: S) -> Result { s.serialize_str(&self.format()) } } -impl<'de> Deserialize<'de> for GoTime { +impl<'de> Deserialize<'de> for JsonTime { fn deserialize>(d: D) -> Result { - // null leaves the zero time, as in Go. + // null leaves the time unset. match Option::::deserialize(d)? { - None => Ok(GoTime::default()), - Some(s) => GoTime::parse(&s) + None => Ok(JsonTime::default()), + Some(s) => JsonTime::parse(&s) .ok_or_else(|| serde::de::Error::custom(format!("parsing time {s:?}"))), } } @@ -914,7 +928,7 @@ mod tests { } #[test] - fn read_uvarint_matches_go() { + fn varint_encoding() { for v in [0, 1, 127, 128, 300, 1 << 35, u64::MAX] { assert_eq!(read_uvarint(&mut body(&put_uvarint(v))), Ok(v)); } @@ -923,7 +937,7 @@ mod tests { read_uvarint(&mut body(&[0xff; 11])).is_err(), "overflow not detected" ); - // Zig-zag as Go's PutVarint. + // Zig-zag. for (v, enc) in [(0i64, 0u64), (-1, 1), (1, 2), (-2, 3), (i64::MIN, u64::MAX)] { assert_eq!(((v << 1) ^ (v >> 63)) as u64, enc); assert_eq!(body(&put_uvarint(enc)).varint("v"), Ok(v)); @@ -931,16 +945,16 @@ mod tests { } #[test] - fn go_time_json() { - let t = GoTime::parse("2026-10-08T10:40:00.123456789+01:00").unwrap(); + fn json_time() { + let t = JsonTime::parse("2026-10-08T10:40:00.123456789+01:00").unwrap(); assert_eq!((t.secs, t.nanos, t.off), (1_791_452_400, 123_456_789, 3600)); assert_eq!(t.format(), "2026-10-08T10:40:00.123456789+01:00"); assert_eq!( - GoTime { off: 0, ..t }.format(), + JsonTime { off: 0, ..t }.format(), "2026-10-08T09:40:00.123456789Z" ); assert_eq!( - GoTime { + JsonTime { off: -5 * 3600 - 1800, ..t } @@ -948,17 +962,17 @@ mod tests { "2026-10-08T04:10:00.123456789-05:30" ); assert_eq!( - GoTime::parse("2026-10-08T09:40:00.1Z").unwrap().format(), + JsonTime::parse("2026-10-08T09:40:00.1Z").unwrap().format(), "2026-10-08T09:40:00.1Z" ); assert_eq!( - GoTime::parse("0001-01-01T00:00:00Z"), - Some(GoTime::default()) + JsonTime::parse("0001-01-01T00:00:00Z"), + Some(JsonTime::default()) ); - assert_eq!(GoTime::default().format(), "0001-01-01T00:00:00Z"); + assert_eq!(JsonTime::default().format(), "0001-01-01T00:00:00Z"); assert_eq!( - GoTime::from_system(GoTime::default().to_system()), - GoTime::default() + JsonTime::from_system(JsonTime::default().to_system()), + JsonTime::default() ); for bad in [ "", @@ -967,17 +981,17 @@ mod tests { "2026-10-08T00:00:00", "2026-10-08T00:00:00.Z", ] { - assert_eq!(GoTime::parse(bad), None, "{bad}"); + assert_eq!(JsonTime::parse(bad), None, "{bad}"); } } - /// A tiny tree saved by the Go binary + /// A snapshot written by mapsize 1.2.0 of a tiny tree /// (tree/{a/x.iso 10000 B, a/b/note.txt, c/y.log 3000 B, c/link -> ../a}). #[test] - fn loads_go_snapshot() { + fn loads_1_2_snapshot() { let t = load_file(Path::new(concat!( env!("CARGO_MANIFEST_DIR"), - "/src/snapshot/testdata/go.msz" + "/src/snapshot/testdata/v1.2.0.msz" ))) .unwrap(); let r = t.node(0); @@ -997,7 +1011,7 @@ mod tests { assert_eq!(t.node(iso).size, 10000); assert_eq!(t.ext_name(t.node(iso)), "iso"); assert!(t.path_string(iso).ends_with("/tree/a/x.iso")); - // And it survives a Rust round trip unchanged. + // And it survives a save/load round trip unchanged. let again = load(&saved(&t)[..]).unwrap(); assert_eq!( (again.node(0).tot_size, again.len(), again.stats.start), diff --git a/src/snapshot/testdata/go.msz b/src/snapshot/testdata/v1.2.0.msz similarity index 100% rename from src/snapshot/testdata/go.msz rename to src/snapshot/testdata/v1.2.0.msz diff --git a/src/textutil.rs b/src/textutil.rs index 82c822d..6df1c2f 100644 --- a/src/textutil.rs +++ b/src/textutil.rs @@ -357,9 +357,9 @@ pub fn rfc3339_utc(unix_nanos: i64) -> String { ) } -/// Formats a duration like Go's time.Duration.String after rounding to -/// milliseconds, e.g. "1.234s", "250ms", "2m3.5s". -pub fn go_duration(d: Duration) -> String { +/// Formats a duration rounded to milliseconds: "0s", "250ms", "1.234s", +/// "2m3.5s", "1h0m5s" (trailing zeros of the seconds trimmed). +pub fn fmt_duration(d: Duration) -> String { let ms = (d.as_nanos() + 500_000) / 1_000_000; if ms == 0 { return "0s".into(); @@ -393,8 +393,8 @@ mod time_tests { rfc3339_utc(1_791_456_000 * 1_000_000_000), "2026-10-08T10:40:00Z" ); - assert_eq!(go_duration(Duration::from_micros(1_234_400)), "1.234s"); - assert_eq!(go_duration(Duration::from_millis(250)), "250ms"); - assert_eq!(go_duration(Duration::from_millis(123_500)), "2m3.5s"); + assert_eq!(fmt_duration(Duration::from_micros(1_234_400)), "1.234s"); + assert_eq!(fmt_duration(Duration::from_millis(250)), "250ms"); + assert_eq!(fmt_duration(Duration::from_millis(123_500)), "2m3.5s"); } } diff --git a/src/treemap/mod.rs b/src/treemap/mod.rs index eea578b..4e704dc 100644 --- a/src/treemap/mod.rs +++ b/src/treemap/mod.rs @@ -326,7 +326,7 @@ pub(crate) mod tests { } } - /// The Go fuzz target's property, run over fixed seeds. + /// Squarify invariants over random partitions, from fixed seeds. #[test] fn squarify_random_partitions() { let mut rng = Rng::new(1); diff --git a/src/tui/bench.rs b/src/tui/bench.rs index 35a0d3f..0706ee7 100644 --- a/src/tui/bench.rs +++ b/src/tui/bench.rs @@ -1,5 +1,5 @@ //! Benchmark hooks: the model driven with no terminal, rendering in -//! true colour, as the Go benchmarks do. +//! true colour. use super::model::{Key, Model, Msg, Options, Profile}; use crate::cancel::Cancel; diff --git a/src/tui/model.rs b/src/tui/model.rs index fbba738..d6d154c 100644 --- a/src/tui/model.rs +++ b/src/tui/model.rs @@ -58,7 +58,7 @@ pub(crate) enum Profile { Ascii, } -/// A key press. name follows Bubble Tea's keystroke names ("a", "G", +/// A key press. name is the keystroke name ("a", "G", /// "ctrl+c", "shift+tab", "space", "pgdown", …); text is the inserted /// text for printable keys. #[derive(Clone, Debug, Default)] @@ -69,7 +69,7 @@ pub(crate) struct Key { } impl Key { - /// A key from its keystroke name, as the Go tests build them: single + /// A key from its keystroke name, as tests build them: single /// characters insert themselves, "space" inserts " ". pub fn from_name(s: &str) -> Key { let text = match s { diff --git a/src/tui/run.rs b/src/tui/run.rs index b14e4e5..0dd0187 100644 --- a/src/tui/run.rs +++ b/src/tui/run.rs @@ -162,7 +162,7 @@ fn enter_terminal(mouse: bool) -> io::Result<()> { Ok(()) } -/// Bubble Tea keystroke name for a key event. +/// The keystroke name (see `Key`) for a key event. fn convert_key(ev: KeyEvent) -> Option { if ev.kind == KeyEventKind::Release { return None; @@ -251,7 +251,7 @@ fn convert(ev: Event) -> Option { _ => None, } } - // Pastes are ignored, as in the Go version. + // Pastes are ignored. _ => None, } } diff --git a/src/tui/tests.rs b/src/tui/tests.rs index c36ccc5..fa762a8 100644 --- a/src/tui/tests.rs +++ b/src/tui/tests.rs @@ -1,4 +1,5 @@ -//! Headless model tests (ports of tui_test.go, nest_test.go, live_test.go). +//! Headless model tests: rendering and navigation, nested directories, +//! and a model driven by a live scan. use super::bench::opts_for; use super::canvas::rgb; @@ -536,7 +537,7 @@ fn copy_refuses_control_characters() { ); } -// ---- nest_test.go ----------------------------------------------------------- +// ---- Nested directories ----------------------------------------------------- fn root_tree() -> Tree { let mut t = Tree::new(b"/", Kind::Dir); @@ -611,7 +612,7 @@ fn reveal_headless_zooms_map() { ); } -// ---- live_test.go ----------------------------------------------------------- +// ---- Live scan -------------------------------------------------------------- /// Renders, navigates, filters and resizes while the scanner mutates the /// inventory, verifying the locking discipline.