use crate::types::Column;
use crate::{Instruction, TargetConfig};
use log::{error, info};
use lsp_types::{InitializeParams, TextDocumentPositionParams, Url};
use std::fs::File;
use std::io::BufRead;
use std::path::PathBuf;
pub fn find_word_at_pos(line: &str, col: Column) -> (Column, Column) {
let line_ = format!("{} ", line);
let is_ident_char = |c: char| c.is_alphanumeric() || c == '_';
let start = line_
.chars()
.enumerate()
.take(col)
.filter(|&(_, c)| !is_ident_char(c))
.last()
.map(|(i, _)| i + 1)
.unwrap_or(0);
#[allow(clippy::filter_next)]
let mut end = line_
.chars()
.enumerate()
.skip(col)
.filter(|&(_, c)| !is_ident_char(c));
let end = end.next();
(start, end.map(|(i, _)| i).unwrap_or(col))
}
pub fn get_word_from_file_params(
pos_params: &TextDocumentPositionParams,
) -> anyhow::Result<String> {
let uri = &pos_params.text_document.uri;
let line = pos_params.position.line as usize;
let col = pos_params.position.character as usize;
let filepath = uri.to_file_path();
match filepath {
Ok(file) => {
let file = File::open(file).unwrap_or_else(|_| panic!("Couldn't open file -> {}", uri));
let buf_reader = std::io::BufReader::new(file);
let line_conts = buf_reader.lines().nth(line).unwrap().unwrap();
let (start, end) = find_word_at_pos(&line_conts, col);
Ok(String::from(&line_conts[start..end]))
}
Err(_) => Err(anyhow::anyhow!("filepath get error")),
}
}
pub fn get_target_config(params: &InitializeParams) -> TargetConfig {
let mut root_path: Option<PathBuf> = None;
if let Some(folders) = ¶ms.workspace_folders {
let mut path = None;
for folder in folders.iter() {
if let Ok(parsed) = Url::parse(folder.uri.as_str()) {
if let Ok(parsed_path) = parsed.to_file_path() {
path = Some(parsed_path);
break;
}
}
}
root_path = path;
};
if root_path.is_none() {
if let Some(root_uri) = ¶ms.root_uri {
if let Ok(path) = root_uri.to_file_path() {
root_path = Some(path)
}
}
};
if let Some(mut path) = root_path {
path.push(".asm-lsp.toml");
if let Ok(config) = std::fs::read_to_string(path.clone()) {
let path_s = path.display();
match toml::from_str::<TargetConfig>(&config) {
Ok(config) => {
info!("Parsing asm-lsp config from file -> {path_s}\n");
return config;
}
Err(e) => {
error!("Failed to parse config file {path_s} - Error: {e}\n");
} }
}
}
TargetConfig::default()
}
pub fn filter_targets(instr: &Instruction, config: &TargetConfig) -> Instruction {
let mut instr = instr.clone();
let forms = instr
.forms
.iter()
.filter(|form| {
(form.gas_name.is_some() && config.assemblers.gas)
|| (form.go_name.is_some() && config.assemblers.go)
})
.map(|form| {
let mut filtered = form.clone();
if !config.assemblers.gas {
filtered.gas_name = None;
}
if !config.assemblers.go {
filtered.go_name = None;
}
filtered
})
.collect();
instr.forms = forms;
instr
}