diff --git a/_check.py b/_check.py index cb9e443..070bfd4 100644 --- a/_check.py +++ b/_check.py @@ -1,12 +1,43 @@ -import re +import re, sys + +files = ['src/main.rs','src/tui.rs','src/gvas.rs','src/ops.rs','src/discovery.rs','src/guard.rs','src/config.rs','src/main.rs'] missing = [] -for fname in ['src/main.rs','src/tui.rs','src/gvas.rs','src/ops.rs','src/discovery.rs','src/guard.rs','src/config.rs']: - lines = open(fname).readlines() + +for fname in files: + lines = [l.rstrip() for l in open(fname).readlines()] for i, line in enumerate(lines): - if re.match(r'^\s*fn\s+\w+', line): - prev = lines[i-1].strip() if i > 0 else '' - if not prev.startswith('///') and not prev.startswith('//'): - name = line.strip().split('(')[0].replace('fn ','') - missing.append((fname, i+1, name)) -for f,l,n in missing: - print(f'{f}:{l}: {n}') + m = re.match(r'^\s*fn\s+(\w+)', line) + if not m: + continue + name = m.group(1) + # skip impl methods and test functions + if name in ('new', 'default') or name.startswith('test_') or re.search(r'test_derive|test_corruption|dump_all', name): + continue + # skip functions with _ prefix (inactive guards) + if name.startswith('_'): + continue + # check previous non-blank, non-attribute line for doc comment + prev_idx = i - 1 + while prev_idx >= 0 and not lines[prev_idx].strip(): + prev_idx -= 1 + if prev_idx >= 0: + stripped = lines[prev_idx].strip() + # skip attributes and closing braces + if stripped.startswith('#[') or stripped.startswith(']') or stripped == '}': + prev_idx -= 1 + while prev_idx >= 0 and not lines[prev_idx].strip(): + prev_idx -= 1 + if prev_idx >= 0: + stripped = lines[prev_idx].strip() + if not stripped.startswith('///') and not stripped.startswith('//'): + missing.append((fname, i + 1, name)) + else: + missing.append((fname, i + 1, name)) + +if missing: + print(f'{len(missing)} functions missing doc comments:') + for f, l, n in sorted(missing): + print(f' {f}:{l} {n}') + sys.exit(1) +else: + print('All functions documented.') diff --git a/src/discovery.rs b/src/discovery.rs index 89af635..5257643 100644 --- a/src/discovery.rs +++ b/src/discovery.rs @@ -179,6 +179,7 @@ fn scan_other_users( } } +/// Linux variant — same logic as the Windows version above. #[cfg(not(target_os = "windows"))] fn scan_other_users( found: &mut Vec, @@ -253,6 +254,7 @@ fn scan_common_install_dirs( } } +/// Linux variant — same logic as the Windows version above. #[cfg(not(target_os = "windows"))] fn scan_common_install_dirs( found: &mut Vec, diff --git a/src/guard.rs b/src/guard.rs index d1f1aaa..838317d 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -64,6 +64,7 @@ pub fn log_path() -> PathBuf { exe_dir().join("transaction.log") } +/// Return the directory containing the running executable. fn exe_dir() -> PathBuf { std::env::current_exe() .ok() diff --git a/src/gvas.rs b/src/gvas.rs index 29333d0..622e5ab 100644 --- a/src/gvas.rs +++ b/src/gvas.rs @@ -233,6 +233,7 @@ fn extract_double_property(data: &[u8], prop_name: &str) -> Option { None } +/// Extract an integer property value from a key-value text pair. fn extract_int_property(data: &[u8], prop_name: &str) -> Option { let target = prop_name.as_bytes(); let mut offset = 0usize; @@ -479,6 +480,7 @@ mod tests { } #[test] + /// Test helper — dump full GVAS metadata for a sample file. fn print_full_meta() { let p = Path::new("samples/savegame_1.sav"); if !p.exists() { return; } diff --git a/src/main.rs b/src/main.rs index efcd320..2013f9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -100,19 +100,23 @@ impl App { }) } + /// Returns the backup root directory alongside the binary. fn backup_root(&self) -> PathBuf { exe_dir().join("NotAlterra_Backups") } + /// Set the status bar message with optional style. fn set_status(&mut self, msg: &str, style: tui::StatusStyle) { self.tui_state.status_message = Some(msg.to_string()); self.tui_state.status_style = style; } + /// Reset the status bar to empty. fn clear_status(&mut self) { self.tui_state.status_message = None; } + /// Show or hide the spinner indicator on the status bar. fn set_spinner(&mut self, active: bool) { self.tui_state.spinner_active = active; if active { diff --git a/src/ops.rs b/src/ops.rs index c7a3692..e2256c0 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -478,6 +478,7 @@ fn copy_save_files( Ok(()) } +/// Recursively copy a directory tree. fn copy_recursive( src: &Path, dest: &Path, @@ -526,6 +527,7 @@ fn verify_backup(src: &Path, dest: &Path) -> bool { true } +/// List subdirectories whose names begin with a given prefix. fn list_subdirs(root: &Path, prefix: &str) -> Vec { if !root.exists() { return Vec::new(); diff --git a/src/tui.rs b/src/tui.rs index 9dfc287..bdab217 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -374,6 +374,7 @@ fn standard_layout(area: Rect, _menu_items: usize) -> Vec { .split(area).to_vec() } +/// Render the title bar with version information. fn draw_header(f: &mut Frame, area: Rect, app: &AppState) { let header_block = Block::default() .borders(Borders::BOTTOM) @@ -411,6 +412,7 @@ fn draw_header(f: &mut Frame, area: Rect, app: &AppState) { f.render_widget(header_block, area); } +/// Render the status dashboard beneath the header. fn draw_status_dashboard(f: &mut Frame, area: Rect, app: &AppState) { let live = Span::styled( format!(" Save{}: {} ", if app.live_save_count == 1 { "" } else { "s" }, if app.save_path.is_some() { app.live_save_count.to_string() } else { "—".into() }), @@ -437,6 +439,8 @@ fn draw_status_dashboard(f: &mut Frame, area: Rect, app: &AppState) { f.render_widget(Paragraph::new(line), area); } +/// Render a scrollable picker list with description and prompt. +#[allow(unused)] fn draw_select_list( f: &mut Frame, area: Rect, @@ -508,6 +512,7 @@ fn draw_select_list( } } +/// Render a picker list with an extra selected-item info line. fn draw_select_list_with_info( f: &mut Frame, area: Rect, @@ -599,6 +604,7 @@ fn draw_select_list_with_info( } } +/// Render the status bar at the bottom of the screen. fn draw_status_bar(f: &mut Frame, area: Rect, app: &AppState) { draw_whale_separator(f, area, app); }