Skip to main content

ninox_core/
lib.rs

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