use std::fs;
use std::path::PathBuf;
pub fn extract_current_token(file_path: &PathBuf, line: usize, column: usize) -> Option<String> {
let content = fs::read_to_string(file_path).ok()?;
let lines: Vec<&str> = content.lines().collect();
let line_content = lines.get(line.saturating_sub(1))?;
let col_index = column.saturating_sub(1);
let token_start = line_content[..col_index]
.rfind(|c: char| !c.is_alphanumeric() && c != '_')
.map(|i| i + 1)
.unwrap_or(0);
let token = &line_content[token_start..col_index];
if token.is_empty() {
None
} else {
Some(token.to_string())
}
}
pub fn is_completion_position(file_path: &PathBuf, line: usize, column: usize) -> bool {
let content = match fs::read_to_string(file_path) {
Ok(c) => c,
Err(_) => return false,
};
let lines: Vec<&str> = content.lines().collect();
let line_content = match lines.get(line.saturating_sub(1)) {
Some(l) => l,
None => return false,
};
if line_content.is_empty() {
return true;
}
let col_index = column.saturating_sub(1);
if col_index >= line_content.len() {
return true;
}
let char_at_cursor = match line_content.chars().nth(col_index) {
Some(c) => c,
None => return true,
};
matches!(
char_at_cursor,
' ' | '\t'
| '('
| '['
| '{'
| '='
| '+'
| '-'
| '*'
| '/'
| '%'
| '&'
| '|'
| '^'
| '!'
| '<'
| '>'
| ':'
| ';'
| ','
| '.'
)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
#[test]
fn test_extract_token() {
let mut file = tempfile::NamedTempFile::new().unwrap();
writeln!(file, "fn test() {{").unwrap();
writeln!(file, " let x = foobar").unwrap();
writeln!(file, "}}").unwrap();
let token = extract_current_token(&file.path().to_path_buf(), 2, 19);
assert_eq!(token.as_deref(), Some("foobar"));
}
}