use std::path::{Path, PathBuf};
use anyhow::{Context, Result, anyhow};
use console::style;
use directories::UserDirs;
use lune_utils::path::{LuauFilePath, LuauModulePath, get_current_dir};
const LUNE_COMMENT_PREFIX: &str = "-->";
pub fn discover_script_path(path: impl Into<PathBuf>, in_home_dir: bool) -> Result<PathBuf> {
let path = LuauModulePath::strip(path);
let path = if path.is_absolute() {
path
} else if in_home_dir {
UserDirs::new()
.context("Missing home directory")?
.home_dir()
.join(path)
} else {
get_current_dir().join(path)
};
match LuauModulePath::resolve(&path) {
Err(e) => Err(anyhow!(
"Failed to resolve script at path {} ({})",
style(path.display()).yellow(),
style(format!("{e:?}")).red()
)),
Ok(m) => match m.target() {
LuauFilePath::File(f) => Ok(f.clone()),
LuauFilePath::Directory(_) => Err(anyhow!(
"Failed to resolve script at path {}\
\nThe path is a directory without an init file",
style(path.display()).yellow()
)),
},
}
}
pub fn discover_script_path_including_lune_dirs(path: impl AsRef<Path>) -> Result<PathBuf> {
let path: &Path = path.as_ref();
match discover_script_path(path, false) {
Ok(path) => Ok(path),
Err(e) => {
if path.is_absolute() {
return Err(e);
}
let res = discover_script_path(Path::new("lune").join(path), false)
.or_else(|_| discover_script_path(Path::new(".lune").join(path), false))
.or_else(|_| discover_script_path(Path::new("lune").join(path), true))
.or_else(|_| discover_script_path(Path::new(".lune").join(path), true));
match res {
Err(_) => Err(e),
Ok(path) => Ok(path),
}
}
}
}
pub fn parse_lune_description_from_file(contents: &str) -> Option<String> {
let mut comment_lines = Vec::new();
for line in contents.lines() {
if let Some(stripped) = line.strip_prefix(LUNE_COMMENT_PREFIX) {
comment_lines.push(stripped);
} else {
break;
}
}
if comment_lines.is_empty() {
None
} else {
let shortest_indent = comment_lines.iter().fold(usize::MAX, |acc, line| {
let first_alphanumeric = line.find(char::is_alphanumeric).unwrap();
acc.min(first_alphanumeric)
});
let unindented_lines = comment_lines
.iter()
.map(|line| line[shortest_indent..].to_string())
.collect::<Vec<_>>()
.join(" ");
Some(unindented_lines)
}
}