use super::input::InputSession;
use crate::local::command::{RESULT_LIMIT, TEXT_UTF16_LIMIT};
use crate::types::{CandidateSource, LocalInputMode, PluginCommandQuery, WordItem};
impl InputSession {
pub(super) fn plugin_command_query(&self) -> Option<PluginCommandQuery> {
if self.dedicated_english || self.local_mode != LocalInputMode::Command {
return None;
}
if self
.plugin_rows
.as_ref()
.is_some_and(|(preedit, _)| *preedit == self.local_preedit)
{
return None;
}
let code = self.local_preedit.get(1..)?;
let (trigger, argument) = self.queries.plugin_command_source(code)?;
Some(PluginCommandQuery {
session_id: self.online_requests.session_id,
preedit: self.local_preedit.clone(),
trigger: trigger.to_owned(),
argument: argument.to_owned(),
})
}
pub(super) fn apply_plugin_command_rows(
&mut self,
query: &PluginCommandQuery,
rows: &[(String, String)],
) -> bool {
if self.plugin_command_query().as_ref() != Some(query) {
return false;
}
let mut texts: [Option<&str>; RESULT_LIMIT] = [None; RESULT_LIMIT];
let mut text_count = 0;
for (text, _) in rows {
if text_count == RESULT_LIMIT {
break;
}
if !text.trim().is_empty()
&& !text.chars().any(char::is_control)
&& text.encode_utf16().count() <= TEXT_UTF16_LIMIT
&& !texts[..text_count]
.iter()
.flatten()
.any(|existing| *existing == text)
{
texts[text_count] = Some(text);
text_count += 1;
}
}
let count = text_count;
let items = texts
.into_iter()
.take(count)
.flatten()
.enumerate()
.map(|(index, text)| {
WordItem::new(
query.trigger.clone(),
text,
(count - index) as i64,
CandidateSource::Plugin,
"",
)
})
.collect::<Vec<_>>();
if !items.is_empty() {
self.local_candidates.retain(|item| {
item.source != CandidateSource::Fallback
&& !items.iter().any(|row| row.word == item.word)
});
self.local_candidates.splice(0..0, items.iter().cloned());
}
self.plugin_rows = Some((query.preedit.clone(), items));
true
}
}