Skip to main content

ninox_core/
lib.rs

1pub mod brain;
2pub mod client;
3pub mod config;
4pub mod embeddings;
5pub mod events;
6pub mod github;
7pub mod harness;
8pub mod hooks;
9pub mod lifecycle;
10pub mod plugin;
11pub mod pty;
12pub mod store;
13pub mod tmux;
14pub mod types;
15
16pub use brain::{BrainEntry, BrainIndex, QueryFilters};
17pub use config::{AppConfig, ThemeVariant};
18pub use events::{Engine, Event};
19pub use store::Store;
20pub use types::*;
21
22/// Convert a name into a tmux/URL-safe session ID.
23///
24/// Lowercases, maps non-alphanumeric chars to hyphens, and collapses consecutive
25/// hyphens. Returns an empty string if the input contains no alphanumeric chars.
26///
27/// Examples: `"ATH-123 auth fix"` → `"ath-123-auth-fix"`, `"my feature"` → `"my-feature"`
28pub fn slugify(s: &str) -> String {
29    s.to_lowercase()
30        .chars()
31        .map(|c| if c.is_ascii_alphanumeric() { c } else { '-' })
32        .collect::<String>()
33        .split('-')
34        .filter(|p| !p.is_empty())
35        .collect::<Vec<_>>()
36        .join("-")
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn slugify_ticket_id() {
45        assert_eq!(slugify("ATH-123"), "ath-123");
46    }
47
48    #[test]
49    fn slugify_spaced_name() {
50        assert_eq!(slugify("auth fix"), "auth-fix");
51    }
52
53    #[test]
54    fn slugify_ticket_with_description() {
55        assert_eq!(slugify("ATH-123 auth fix"), "ath-123-auth-fix");
56    }
57
58    #[test]
59    fn slugify_collapses_consecutive_separators() {
60        assert_eq!(slugify("my  feature!"), "my-feature");
61    }
62
63    #[test]
64    fn slugify_already_clean() {
65        assert_eq!(slugify("my-feature"), "my-feature");
66    }
67
68    #[test]
69    fn slugify_empty_returns_empty() {
70        assert_eq!(slugify(""), "");
71        assert_eq!(slugify("---"), "");
72    }
73}