use std::str::FromStr;
pub trait LanguageConsts {
fn cc(&self) -> &'static str;
fn extension(&self) -> &'static str;
fn generate_helloworld_content(&self) -> String;
fn generate_makefile_content(&self, project_name: &str) -> String {
format!(
"# Compiler and flags\n\
CC = {}\n\
CFLAGS = -Wall -Wextra -Werror -O2 -g\n\
LDFLAGS =\n\
\n\
# Directories\n\
SRC_DIR = src\n\
BUILD_DIR = build\n\
\n\
# Source files\n\
SRCS = $(wildcard $(SRC_DIR)/*.{})\n\
OBJS = $(SRCS:$(SRC_DIR)/%.{}=$(BUILD_DIR)/%.o)\n\
\n\
# Target executable\n\
TARGET = {}\n\
\n\
# Default target\n\
all: $(TARGET)\n\
\n\
# Build target\n\
$(TARGET): $(OBJS)\n\
\t@mkdir -p $(BUILD_DIR)\n\
\t$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)\n\
\t@echo \"Build complete: $(TARGET)\"\n\
\n\
# Compile source files\n\
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.{}\n\
\t@mkdir -p $(BUILD_DIR)\n\
\t$(CC) $(CFLAGS) -c $< -o $@\n\
\n\
# Clean build artifacts\n\
clean:\n\
\t@rm -rf $(BUILD_DIR) $(TARGET)\n\
\t@echo \"Cleaned build artifacts\"\n\
\n\
# Run the program\n\
run: $(TARGET)\n\
\t./$(TARGET)\n\
\n\
# Rebuild\n\
rebuild: clean all\n\
\n\
.PHONY: all clean run rebuild\n",
self.cc(),
self.extension(),
self.extension(),
project_name,
self.extension()
)
}
}
#[derive(Debug, Clone, Copy)]
pub enum Language {
C,
Cpp,
}
impl std::fmt::Display for Language {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Language::C => write!(f, "C"),
Language::Cpp => write!(f, "C++"),
}
}
}
impl LanguageConsts for Language {
fn cc(&self) -> &'static str {
match self {
Language::C => "gcc",
Language::Cpp => "g++",
}
}
fn extension(&self) -> &'static str {
match self {
Language::C => "c",
Language::Cpp => "cpp",
}
}
fn generate_helloworld_content(&self) -> String {
match self {
Language::C => String::from(
"#include <stdio.h>\n\n\
int main() {\n\
\tprintf(\"Hello, World!\\n\");\n\
\treturn 0;\n\
}\n",
),
Language::Cpp => String::from(
"#include <iostream>\n\n\
int main() {\n\
\tstd::cout << \"Hello, World!\" << std::endl;\n\
\treturn 0;\n\
}\n",
),
}
}
}
impl FromStr for Language {
type Err = anyhow::Error;
fn from_str(input: &str) -> Result<Language, Self::Err> {
match input.to_lowercase().as_str() {
"c" => Ok(Language::C),
"cpp" => Ok(Language::Cpp),
_ => anyhow::bail!("Unsupported language: {}. Use 'c' or 'cpp'", input),
}
}
}