use std::path::Path;
#[derive(Debug, Clone, PartialEq)]
pub enum CommentStyle {
Line(String),
Block(String, String),
BlockTriple(String),
}
impl CommentStyle {
pub fn prefix(&self) -> &str {
match self {
CommentStyle::Line(p) => p,
CommentStyle::Block(o, _) => o,
CommentStyle::BlockTriple(d) => d,
}
}
}
pub fn comment_style_for(path: &Path) -> Option<CommentStyle> {
let ext = path.extension().and_then(|s| s.to_str()).unwrap_or("");
let fname = path.file_name().and_then(|s| s.to_str()).unwrap_or("");
match fname {
"Makefile" | "makefile" | "Dockerfile" | "Containerfile" => {
return Some(CommentStyle::Line("#".to_string()));
}
"CMakeLists.txt" => return Some(CommentStyle::Line("#".to_string())),
"Rakefile" | "Gemfile" => return Some(CommentStyle::Line("#".to_string())),
_ => {}
}
match ext {
"rs" | "go" | "c" | "h" | "cpp" | "hpp" | "cc" | "cxx" | "hh" | "java" | "js" | "ts"
| "jsx" | "tsx" | "kt" | "kts" | "swift" | "zig" | "dart" | "php" | "m" | "mm" | "cs"
| "scala" | "groovy" | "vala" | "v" | "nu" | "svelte" | "vue" => {
Some(CommentStyle::Line("//".to_string()))
}
"py" | "rb" | "pl" | "pm" | "sh" | "bash" | "zsh" | "fish" | "yaml" | "yml" | "toml"
| "r" | "R" | "rake" | "gemspec" | "erb" | "el" | "ex" | "exs" | "jl" | "coffee"
| "csh" | "awk" | "tcl" | "mk" | "ninja" | "bzl" | "BUILD" | "WORKSPACE" | "dhall"
| "nix" | "conf" | "cfg" | "ini" | "desktop" | "service" | "timer" | "diff" | "patch"
| "ziggy" | "ziggy-schema" => Some(CommentStyle::Line("#".to_string())),
"sql" | "hs" | "lhs" | "lua" | "ada" | "adb" | "ads" | "sqlite" | "sqlite3" | "vhd"
| "vhdl" => Some(CommentStyle::Line("--".to_string())),
"tex" | "sty" | "cls" | "ltx" | "bib" | "matlab" | "maxima" | "prolog" => {
Some(CommentStyle::Line("%".to_string()))
}
"lisp" | "lsp" | "clj" | "cljs" | "cljc" | "edn" | "scm" | "ss" => {
Some(CommentStyle::Line(";".to_string()))
}
"html" | "htm" | "xhtml" | "xml" | "xsl" | "xslt" | "xsd" | "svg" | "rmd" | "mdown"
| "mkdn" | "mdx" => Some(CommentStyle::Block("<!--".into(), "-->".into())),
"css" | "scss" | "sass" | "less" | "graphql" | "gql" | "proto" | "flatbuffers" | "fbs"
| "solidity" | "sol" => Some(CommentStyle::Block("/*".to_string(), "*/".to_string())),
_ => None,
}
}
pub fn format_as_comment(lines: &[String], style: &CommentStyle) -> String {
match style {
CommentStyle::Line(prefix) => lines
.iter()
.map(|l| {
if l.trim().is_empty() {
prefix.clone()
} else {
format!("{} {}", prefix, l.trim())
}
})
.collect::<Vec<_>>()
.join("\n"),
CommentStyle::Block(open, close) => {
let mut result = open.clone();
result.push('\n');
for line in lines {
if line.trim().is_empty() {
result.push_str(open);
result.push('\n');
} else {
result.push_str(&format!("{} {}", open, line.trim()));
result.push('\n');
}
}
result.push_str(close);
result.push('\n');
result
}
CommentStyle::BlockTriple(delim) => {
let mut result = delim.clone();
result.push('\n');
for line in lines {
result.push_str(line.trim());
result.push('\n');
}
result.push_str(delim);
result.push('\n');
result
}
}
}