use super::context_tree::ContextId;
use std::cmp::Ordering;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Completion {
pub term: String,
pub distance: usize,
pub is_draft: bool,
pub contexts: Vec<ContextId>,
}
impl Completion {
pub fn finalized(term: String, distance: usize, contexts: Vec<ContextId>) -> Self {
Self {
term,
distance,
is_draft: false,
contexts,
}
}
pub fn draft(term: String, distance: usize, context: ContextId) -> Self {
Self {
term,
distance,
is_draft: true,
contexts: vec![context],
}
}
pub fn is_visible_in(&self, context: ContextId) -> bool {
self.contexts.contains(&context)
}
}
impl Ord for Completion {
fn cmp(&self, other: &Self) -> Ordering {
self.distance
.cmp(&other.distance)
.then_with(|| self.is_draft.cmp(&other.is_draft))
.then_with(|| self.term.cmp(&other.term))
}
}
impl PartialOrd for Completion {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl std::fmt::Display for Completion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let status = if self.is_draft { "draft" } else { "finalized" };
write!(
f,
"{} (distance: {}, {}, contexts: {:?})",
self.term, self.distance, status, self.contexts
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_finalized_creation() {
let completion = Completion::finalized("test".to_string(), 1, vec![0, 1]);
assert_eq!(completion.term, "test");
assert_eq!(completion.distance, 1);
assert!(!completion.is_draft);
assert_eq!(completion.contexts, vec![0, 1]);
}
#[test]
fn test_draft_creation() {
let completion = Completion::draft("draft".to_string(), 2, 5);
assert_eq!(completion.term, "draft");
assert_eq!(completion.distance, 2);
assert!(completion.is_draft);
assert_eq!(completion.contexts, vec![5]);
}
#[test]
fn test_is_visible_in() {
let completion = Completion::finalized("test".to_string(), 0, vec![0, 1, 2]);
assert!(completion.is_visible_in(0));
assert!(completion.is_visible_in(1));
assert!(completion.is_visible_in(2));
assert!(!completion.is_visible_in(3));
}
#[test]
fn test_sorting_by_distance() {
let mut completions = vec![
Completion::finalized("c".to_string(), 2, vec![0]),
Completion::finalized("b".to_string(), 1, vec![0]),
Completion::finalized("a".to_string(), 0, vec![0]),
];
completions.sort();
assert_eq!(completions[0].term, "a"); assert_eq!(completions[1].term, "b"); assert_eq!(completions[2].term, "c"); }
#[test]
fn test_sorting_by_draft_status() {
let mut completions = vec![
Completion::draft("draft".to_string(), 1, 0),
Completion::finalized("finalized".to_string(), 1, vec![0]),
];
completions.sort();
assert_eq!(completions[0].term, "finalized");
assert!(!completions[0].is_draft);
assert_eq!(completions[1].term, "draft");
assert!(completions[1].is_draft);
}
#[test]
fn test_sorting_by_term() {
let mut completions = vec![
Completion::finalized("z".to_string(), 0, vec![0]),
Completion::finalized("a".to_string(), 0, vec![0]),
Completion::finalized("m".to_string(), 0, vec![0]),
];
completions.sort();
assert_eq!(completions[0].term, "a");
assert_eq!(completions[1].term, "m");
assert_eq!(completions[2].term, "z");
}
#[test]
fn test_sorting_combined() {
let mut completions = vec![
Completion::draft("z".to_string(), 2, 0),
Completion::finalized("a".to_string(), 1, vec![0]),
Completion::draft("b".to_string(), 1, 0),
Completion::finalized("c".to_string(), 0, vec![0]),
Completion::draft("d".to_string(), 0, 0),
Completion::finalized("e".to_string(), 2, vec![0]),
];
completions.sort();
assert_eq!(completions[0].term, "c");
assert!(!completions[0].is_draft);
assert_eq!(completions[1].term, "d");
assert!(completions[1].is_draft);
assert_eq!(completions[2].term, "a");
assert!(!completions[2].is_draft);
assert_eq!(completions[3].term, "b");
assert!(completions[3].is_draft);
assert_eq!(completions[4].term, "e");
assert!(!completions[4].is_draft);
assert_eq!(completions[5].term, "z");
assert!(completions[5].is_draft);
}
#[test]
fn test_equality() {
let c1 = Completion::finalized("test".to_string(), 1, vec![0]);
let c2 = Completion::finalized("test".to_string(), 1, vec![0]);
let c3 = Completion::draft("test".to_string(), 1, 0);
assert_eq!(c1, c2);
assert_ne!(c1, c3); }
#[test]
fn test_display() {
let completion = Completion::finalized("hello".to_string(), 2, vec![0, 1]);
let display = format!("{}", completion);
assert!(display.contains("hello"));
assert!(display.contains("distance: 2"));
assert!(display.contains("finalized"));
assert!(display.contains("[0, 1]"));
let draft = Completion::draft("world".to_string(), 0, 5);
let display = format!("{}", draft);
assert!(display.contains("world"));
assert!(display.contains("draft"));
assert!(display.contains("[5]"));
}
}