rust-analyzer format

This commit is contained in:
Noah Swerhun 2023-12-20 15:22:45 -06:00
parent 0c73dd3f56
commit 3eafbff7f9
4 changed files with 115 additions and 63 deletions

View file

@ -1,4 +1,4 @@
use std::{path::PathBuf, fs}; use std::{fs, path::PathBuf};
use path_clean::PathClean; use path_clean::PathClean;
use regex::Regex; use regex::Regex;
@ -15,7 +15,7 @@ pub enum BuildRuleKind<T> {
Convenience(T), Convenience(T),
} }
#[derive(Debug,Clone)] #[derive(Debug, Clone)]
pub struct BuildRule { pub struct BuildRule {
pub target: String, pub target: String,
pub prerequisites: Vec<String>, pub prerequisites: Vec<String>,
@ -40,7 +40,7 @@ impl BuildRule {
true => { true => {
headers.push(String::from(path.to_str().unwrap())); headers.push(String::from(path.to_str().unwrap()));
continue; continue;
}, }
false => (), false => (),
} }
@ -51,7 +51,7 @@ impl BuildRule {
true => { true => {
headers.push(String::from(path.to_str().unwrap())); headers.push(String::from(path.to_str().unwrap()));
continue 'fileloop; continue 'fileloop;
}, }
false => (), false => (),
} }
} }
@ -63,7 +63,6 @@ impl BuildRule {
headers headers
} }
pub fn new_from_c_file(path: &str, makefile: &Makefile) -> BuildRule { pub fn new_from_c_file(path: &str, makefile: &Makefile) -> BuildRule {
let mut prerequisites: Vec<String> = Vec::new(); let mut prerequisites: Vec<String> = Vec::new();
prerequisites.push((PathBuf::from(path)).clean().to_str().unwrap().to_string()); prerequisites.push((PathBuf::from(path)).clean().to_str().unwrap().to_string());
@ -82,7 +81,11 @@ impl BuildRule {
let compile_command = format!("$(CC) $(CFLAGS) $(INCS) -o {} -c {}", obj_path, path); let compile_command = format!("$(CC) $(CFLAGS) $(INCS) -o {} -c {}", obj_path, path);
BuildRule { target: String::from(obj_path), prerequisites, recipe_commands: vec![compile_command] } BuildRule {
target: String::from(obj_path),
prerequisites,
recipe_commands: vec![compile_command],
}
} }
} }

View file

@ -1,5 +1,5 @@
use std::process::exit;
use clap::Parser; use clap::Parser;
use std::process::exit;
mod build_rule; mod build_rule;
mod makefile; mod makefile;
@ -52,9 +52,11 @@ fn main() {
let makefile = Makefile::new_from_path(&makefile_name); let makefile = Makefile::new_from_path(&makefile_name);
let mut rule_list = RuleList::new(); let mut rule_list = RuleList::new();
rule_list.recursively_gen_objects(".", &makefile).unwrap_or_else(|e| { rule_list
panic!("error: problem in recursive search: {e}"); .recursively_gen_objects(".", &makefile)
}); .unwrap_or_else(|e| {
panic!("error: problem in recursive search: {e}");
});
if rule_list.0.is_empty() { if rule_list.0.is_empty() {
eprintln!("no source files found, nothing to do. exiting..."); eprintln!("no source files found, nothing to do. exiting...");
@ -65,12 +67,12 @@ fn main() {
// Only include directory defaults if the user has not specified them // Only include directory defaults if the user has not specified them
let mut dirdefwritten = false; let mut dirdefwritten = false;
if ! makefile.contains_builddir_def() { if !makefile.contains_builddir_def() {
generated_content.push_str("BUILDDIR = build\n"); generated_content.push_str("BUILDDIR = build\n");
dirdefwritten = true; dirdefwritten = true;
} }
if ! makefile.contains_objdir_def() { if !makefile.contains_objdir_def() {
generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n"); generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n");
dirdefwritten = true; dirdefwritten = true;
} }
@ -81,8 +83,10 @@ fn main() {
ARGS.with(|args| { ARGS.with(|args| {
if args.dynamic_library { if args.dynamic_library {
generated_content.push_str("# dynamic library\nCFLAGS += -fPIC\nLDFLAGS += -shared\n\n"); generated_content
} else {} .push_str("# dynamic library\nCFLAGS += -fPIC\nLDFLAGS += -shared\n\n");
} else {
}
}); });
rule_list.add_target_rule(); rule_list.add_target_rule();
@ -101,7 +105,9 @@ fn main() {
generated_content.push_str(&rule_list.to_string()); generated_content.push_str(&rule_list.to_string());
// Write makefile // Write makefile
makefile.write_new_generated_content(generated_content).unwrap_or_else(|e| { makefile
panic!("error: could not write makefile at {}: {e}", makefile.path); .write_new_generated_content(generated_content)
}); .unwrap_or_else(|e| {
panic!("error: could not write makefile at {}: {e}", makefile.path);
});
} }

View file

@ -1,5 +1,5 @@
use std::{fs, io::ErrorKind};
use regex::Regex; use regex::Regex;
use std::{fs, io::ErrorKind};
const START_KEY: &str = "#=mgen_start=#\n"; const START_KEY: &str = "#=mgen_start=#\n";
const END_KEY: &str = "\n#=mgen_end=#"; const END_KEY: &str = "\n#=mgen_end=#";
@ -19,28 +19,37 @@ impl Makefile {
let contents = match fs::read_to_string(path) { let contents = match fs::read_to_string(path) {
Ok(v) => v, Ok(v) => v,
Err(e) => match e.kind() { Err(e) => match e.kind() {
// doesn't matter if the file doesn't exist, it will be created // doesn't matter if the file doesn't exist, it will be created
// later. // later.
ErrorKind::NotFound => return Makefile { ErrorKind::NotFound => {
path: String::from(path), prologue: String::from(""), return Makefile {
mgen_zone: String::from(""), epilogue: String::from(""), path: String::from(path),
include_dirs: vec![String::from("")] }, prologue: String::from(""),
_ => panic!("error: cannot read makefile: {e}") mgen_zone: String::from(""),
} epilogue: String::from(""),
include_dirs: vec![String::from("")],
}
}
_ => panic!("error: cannot read makefile: {e}"),
},
}; };
let contains_start = contents.find(START_KEY).is_some(); let contains_start = contents.find(START_KEY).is_some();
let contains_end = contents.find(END_KEY).is_some(); let contains_end = contents.find(END_KEY).is_some();
if (contains_start && !contains_end) || (!contains_start && if (contains_start && !contains_end) || (!contains_start && contains_end) {
contains_end) {
panic!("error: makefile contains one mgen guard but not the other. cannot continue."); panic!("error: makefile contains one mgen guard but not the other. cannot continue.");
} }
if !(contains_start && contains_end) { if !(contains_start && contains_end) {
let include_dirs = Makefile::get_include_dirs(&contents); let include_dirs = Makefile::get_include_dirs(&contents);
return Makefile { path: String::from(path), prologue: contents, return Makefile {
mgen_zone: String::from(""), epilogue: String::from(""), include_dirs }; path: String::from(path),
prologue: contents,
mgen_zone: String::from(""),
epilogue: String::from(""),
include_dirs,
};
} }
// contains the part before the start key and everything after // contains the part before the start key and everything after
@ -49,16 +58,16 @@ impl Makefile {
let gen_and_post: Vec<&str> = pre_and_after[1].split(END_KEY).collect(); let gen_and_post: Vec<&str> = pre_and_after[1].split(END_KEY).collect();
let include_dirs = Makefile::get_include_dirs(&contents); let include_dirs = Makefile::get_include_dirs(&contents);
Makefile { Makefile {
path: String::from(path), path: String::from(path),
prologue: String::from(pre_and_after[0]), prologue: String::from(pre_and_after[0]),
mgen_zone: String::from(gen_and_post[0]), mgen_zone: String::from(gen_and_post[0]),
epilogue: String::from(gen_and_post[1]), epilogue: String::from(gen_and_post[1]),
include_dirs include_dirs,
} }
} }
pub fn get_include_dirs(search: &String) -> Vec<String> { pub fn get_include_dirs(search: &String) -> Vec<String> {
let mut include_dirs: Vec<String> = Vec::new(); let mut include_dirs: Vec<String> = Vec::new();
@ -66,23 +75,18 @@ impl Makefile {
let caps = makefile_regex.captures_iter(search); let caps = makefile_regex.captures_iter(search);
let dirlist = match caps.map(|c| c.extract()).last() { let dirlist = match caps.map(|c| c.extract()).last() {
Some((_, [v])) => v, Some((_, [v])) => v,
None => { None => return include_dirs,
return include_dirs
}
,
}; };
let incdir_regex = Regex::new(r"\s*-I\s*(.*?)(?:[\s]|$)").unwrap(); let incdir_regex = Regex::new(r"\s*-I\s*(.*?)(?:[\s]|$)").unwrap();
let caps = incdir_regex.captures_iter(&dirlist); let caps = incdir_regex.captures_iter(&dirlist);
for (_, [dir]) in caps.map(|c| c.extract()) { for (_, [dir]) in caps.map(|c| c.extract()) {
include_dirs.push(String::from(dir)); include_dirs.push(String::from(dir));
} }
include_dirs include_dirs
} }
pub fn contains_builddir_def(&self) -> bool { pub fn contains_builddir_def(&self) -> bool {
let re = Regex::new(r"\s+BUILDDIR = ").unwrap(); let re = Regex::new(r"\s+BUILDDIR = ").unwrap();
re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue)) re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue))
@ -92,9 +96,16 @@ impl Makefile {
let re = Regex::new(r"\s+OBJDIR = ").unwrap(); let re = Regex::new(r"\s+OBJDIR = ").unwrap();
re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue)) re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue))
} }
pub fn write_new_generated_content(&self, generated_content: String) -> std::io::Result<()> { pub fn write_new_generated_content(&self, generated_content: String) -> std::io::Result<()> {
let content = [&self.prologue, START_KEY, &generated_content, END_KEY, &self.epilogue].concat(); let content = [
&self.prologue,
START_KEY,
&generated_content,
END_KEY,
&self.epilogue,
]
.concat();
fs::write(&self.path, &content)?; fs::write(&self.path, &content)?;

View file

@ -9,11 +9,15 @@ use crate::ARGS;
pub struct RuleList(pub Vec<BuildRuleKind<BuildRule>>); pub struct RuleList(pub Vec<BuildRuleKind<BuildRule>>);
impl RuleList { impl RuleList {
pub fn new() -> RuleList{ pub fn new() -> RuleList {
RuleList(vec![]) RuleList(vec![])
} }
pub fn recursively_gen_objects(&mut self, proj_dir_path: &str, makefile: &Makefile) -> std::io::Result<()>{ pub fn recursively_gen_objects(
&mut self,
proj_dir_path: &str,
makefile: &Makefile,
) -> std::io::Result<()> {
let files = fs::read_dir(proj_dir_path)?; let files = fs::read_dir(proj_dir_path)?;
for file in files { for file in files {
let file = file?; let file = file?;
@ -36,18 +40,21 @@ impl RuleList {
continue; continue;
} }
let path = path.to_str().unwrap(); let path = path.to_str().unwrap();
self.0.push(BuildRuleKind::Object(BuildRule::new_from_c_file(path, makefile))); self.0
}, .push(BuildRuleKind::Object(BuildRule::new_from_c_file(
path, makefile,
)));
}
None => { None => {
continue; continue;
}, }
} }
} }
} }
Ok(()) Ok(())
} }
pub fn get_obj_targets(&self) -> Vec<String>{ pub fn get_obj_targets(&self) -> Vec<String> {
let mut ret: Vec<String> = Vec::new(); let mut ret: Vec<String> = Vec::new();
for rule in &self.0 { for rule in &self.0 {
match rule { match rule {
@ -63,13 +70,15 @@ impl RuleList {
let mut target_comm = String::new(); let mut target_comm = String::new();
ARGS.with(|args| { ARGS.with(|args| {
if args.static_library { if args.static_library {
target_comm = String::from( target_comm = String::from(format!(
format!("$(AR) $(ARFLAGS) $(BUILDDIR)/$(TARGET) {}", objects.join(" ")) "$(AR) $(ARFLAGS) $(BUILDDIR)/$(TARGET) {}",
); objects.join(" ")
));
} else { } else {
target_comm = String::from( target_comm = String::from(format!(
format!("$(CC) $(LDFLAGS) $(INCS) -o $(BUILDDIR)/$(TARGET) {} $(LDLIBS)", objects.join(" ")) "$(CC) $(LDFLAGS) $(INCS) -o $(BUILDDIR)/$(TARGET) {} $(LDLIBS)",
); objects.join(" ")
));
} }
}); });
@ -87,7 +96,7 @@ impl RuleList {
self.0.push(BuildRuleKind::Directory(BuildRule { self.0.push(BuildRuleKind::Directory(BuildRule {
target: dir.to_string(), target: dir.to_string(),
prerequisites: vec![], prerequisites: vec![],
recipe_commands: vec![format!("mkdir -p {dir}").to_string()] recipe_commands: vec![format!("mkdir -p {dir}").to_string()],
})); }));
} }
@ -95,7 +104,10 @@ impl RuleList {
self.0.push(BuildRuleKind::Convenience(BuildRule { self.0.push(BuildRuleKind::Convenience(BuildRule {
target: String::from(".PHONY: clean\nclean"), target: String::from(".PHONY: clean\nclean"),
prerequisites: vec![], prerequisites: vec![],
recipe_commands: vec![String::from("rm -r $(OBJDIR)"), String::from("rm -r $(BUILDDIR)")] recipe_commands: vec![
String::from("rm -r $(OBJDIR)"),
String::from("rm -r $(BUILDDIR)"),
],
})); }));
} }
@ -103,7 +115,7 @@ impl RuleList {
self.0.push(BuildRuleKind::Convenience(BuildRule { self.0.push(BuildRuleKind::Convenience(BuildRule {
target: String::from(".PHONY: run\nrun"), target: String::from(".PHONY: run\nrun"),
prerequisites: vec![String::from("$(BUILDDIR)/$(TARGET)")], prerequisites: vec![String::from("$(BUILDDIR)/$(TARGET)")],
recipe_commands: vec![String::from("./$(BUILDDIR)/$(TARGET)")] recipe_commands: vec![String::from("./$(BUILDDIR)/$(TARGET)")],
})); }));
} }
@ -152,7 +164,7 @@ impl RuleList {
} }
} }
fn file_is_hidden(file: &DirEntry) -> bool{ fn file_is_hidden(file: &DirEntry) -> bool {
let file_name = file.file_name(); let file_name = file.file_name();
let str_name = file_name.to_str().unwrap(); let str_name = file_name.to_str().unwrap();
let first_char = str_name.chars().nth(0).unwrap(); let first_char = str_name.chars().nth(0).unwrap();
@ -165,10 +177,30 @@ fn file_is_hidden(file: &DirEntry) -> bool{
impl ToString for RuleList { impl ToString for RuleList {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let targets = &self.get_target_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n"); let targets = &self
let objects = &self.get_object_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n"); .get_target_rules()
let directories = &self.get_directory_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n"); .iter()
let conveniences = &self.get_convenience_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n"); .map(|v| v.to_string())
.collect::<Vec<_>>()
.join("\n");
let objects = &self
.get_object_rules()
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join("\n");
let directories = &self
.get_directory_rules()
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join("\n");
let conveniences = &self
.get_convenience_rules()
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join("\n");
let all = [targets, objects, directories, conveniences]; let all = [targets, objects, directories, conveniences];
let mut nonzero: Vec<String> = Vec::new(); let mut nonzero: Vec<String> = Vec::new();
@ -178,7 +210,7 @@ impl ToString for RuleList {
nonzero.push(category.clone()); nonzero.push(category.clone());
} }
} }
nonzero.join("\n\n") nonzero.join("\n\n")
} }
} }