Skip to main content

ninox_core/
lib.rs

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