nils_common/lib.rs
1//! # nils-common public API contracts (Task 1.2)
2//!
3//! This crate keeps runtime behavior stable. The items below are contract specifications for
4//! planned cross-CLI modules; this step is documentation-only and does not implement/export all
5//! modules yet.
6//!
7//! ## Planned module contracts (spec only)
8//!
9//! ```text
10//! // env
11//! pub fn is_truthy(input: &str) -> bool;
12//! pub fn env_truthy(name: &str) -> bool;
13//! pub fn env_truthy_or(name: &str, default: bool) -> bool;
14//! pub fn env_or_default(name: &str, default: &str) -> String;
15//! pub fn env_non_empty(name: &str) -> Option<String>;
16//! pub fn no_color_enabled() -> bool;
17//!
18//! // shell
19//! pub enum AnsiStripMode { CsiSgrOnly, CsiAnyTerminator }
20//! pub fn quote_posix_single(input: &str) -> String;
21//! pub fn strip_ansi(input: &str, mode: AnsiStripMode) -> std::borrow::Cow<'_, str>;
22//!
23//! // process (expansion on top of existing path lookup helpers)
24//! pub struct ProcessOutput {
25//! pub status: std::process::ExitStatus,
26//! pub stdout: Vec<u8>,
27//! pub stderr: Vec<u8>,
28//! }
29//! pub enum ProcessError { Io(std::io::Error), NonZero(ProcessOutput) }
30//! pub fn run_output(program: &str, args: &[&str]) -> Result<ProcessOutput, ProcessError>;
31//! pub fn run_checked(program: &str, args: &[&str]) -> Result<(), ProcessError>;
32//! pub fn run_stdout_trimmed(program: &str, args: &[&str]) -> Result<String, ProcessError>;
33//!
34//! // git
35//! pub fn is_inside_work_tree(cwd: &std::path::Path) -> Result<bool, ProcessError>;
36//! pub fn repo_root(cwd: &std::path::Path) -> Result<Option<std::path::PathBuf>, ProcessError>;
37//! pub fn rev_parse(cwd: &std::path::Path, args: &[&str]) -> Result<String, ProcessError>;
38//! pub fn rev_parse_opt(cwd: &std::path::Path, args: &[&str]) -> Result<Option<String>, ProcessError>;
39//! pub fn staged_name_only() -> std::io::Result<String>;
40//! pub fn suggested_scope_from_staged_paths(staged: &str) -> String;
41//!
42//! // clipboard
43//! pub enum ClipboardTool { Pbcopy, WlCopy, Xclip, Xsel, Clip }
44//! pub struct ClipboardPolicy<'a> {
45//! pub tool_order: &'a [ClipboardTool],
46//! pub warn_on_failure: bool,
47//! }
48//! pub enum ClipboardOutcome { Copied(ClipboardTool), SkippedNoTool, SkippedFailure }
49//! pub fn copy_best_effort(text: &str, policy: &ClipboardPolicy<'_>) -> ClipboardOutcome;
50//! ```
51//!
52//! ## Compatibility rules
53//! - `nils-common` returns structured results only; user-facing warning/error text stays in
54//! caller adapters.
55//! - Exit-code mapping stays in caller crates.
56//! - APIs stay domain-neutral and must not encode crate-specific UX policies.
57//! - Quoting and ANSI differences are expressed via explicit mode/policy parameters.
58//!
59pub mod clipboard;
60pub mod env;
61pub mod fs;
62pub mod git;
63pub mod markdown;
64pub mod process;
65pub mod provider_runtime;
66pub mod shell;
67
68pub fn greeting(name: &str) -> String {
69 format!("Hello, {name}!")
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use pretty_assertions::assert_eq;
76
77 #[test]
78 fn greeting_formats_name() {
79 let result = greeting("Nils");
80 assert_eq!(result, "Hello, Nils!");
81 }
82}