mirror of
https://github.com/dexoron/dcr.git
synced 2026-10-21 17:19:37 +00:00
Rewrite project from Python to Rust and add Windows/MacOS supports
This commit is contained in:
82
src/cli/build.rs
Normal file
82
src/cli/build.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use crate::config::{PROFILE, PROJECT_COMPILER, flags};
|
||||
use crate::utils::fs::check_dir;
|
||||
use crate::utils::text::{BOLD, BRIGHT_GREEN, BRIGHT_RED, colored};
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
use std::time::Instant;
|
||||
|
||||
pub fn build(args: &[String]) -> i32 {
|
||||
let mut active_profile = PROFILE.to_string();
|
||||
let red_bold = BRIGHT_RED.to_owned() + BOLD;
|
||||
let green_bold = BRIGHT_GREEN.to_owned() + BOLD;
|
||||
let project_name = std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|p| p.file_name().map(|v| v.to_string_lossy().to_string()))
|
||||
.unwrap_or_else(|| "project".to_string());
|
||||
|
||||
let items = check_dir(None).unwrap_or_default();
|
||||
if !items.contains(&"dcr.toml".to_string()) {
|
||||
println!("{}: не найден файл dcr.toml", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if let Some(first_arg) = args.first() {
|
||||
if first_arg.starts_with("--") {
|
||||
let candidate = first_arg.trim_start_matches("--");
|
||||
if flags(candidate).is_some() {
|
||||
active_profile = candidate.to_string();
|
||||
} else {
|
||||
println!("{}: неизвестный флаг сборки", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
println!("{}: неизвестный аргумент", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
" Сборка проекта `{}`\n Профиль: {}\n Компилятор: {}\n",
|
||||
colored(&project_name, &green_bold),
|
||||
colored(&active_profile, &green_bold),
|
||||
colored(PROJECT_COMPILER, &green_bold)
|
||||
);
|
||||
|
||||
if !items.contains(&"target".to_string()) {
|
||||
let _ = fs::create_dir("./target");
|
||||
}
|
||||
let target_items = check_dir(Some("target")).unwrap_or_default();
|
||||
if !target_items.contains(&active_profile) {
|
||||
let _ = fs::create_dir(format!("./target/{active_profile}"));
|
||||
}
|
||||
|
||||
let src_items = check_dir(Some("src")).unwrap_or_default();
|
||||
if src_items.contains(&"main.c".to_string()) {
|
||||
let compile_flags = flags(&active_profile).unwrap_or(&[]);
|
||||
let start_time = Instant::now();
|
||||
let mut cmd = Command::new(PROJECT_COMPILER);
|
||||
cmd.arg("./src/main.c");
|
||||
for flag in compile_flags {
|
||||
cmd.arg(flag);
|
||||
}
|
||||
cmd.arg("-o").arg(format!("./target/{active_profile}/main"));
|
||||
|
||||
match cmd.status() {
|
||||
Ok(status) if status.success() => {
|
||||
let times = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||
println!(
|
||||
" {} Сборка завершена успешно, за {} секунд",
|
||||
colored("✔", &green_bold),
|
||||
colored(×.to_string(), &green_bold)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
_ => {
|
||||
println!("{}: сборка не удалась", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
72
src/cli/clean.rs
Normal file
72
src/cli/clean.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use crate::config::flags;
|
||||
use crate::utils::fs::check_dir;
|
||||
use crate::utils::text::{BOLD, BRIGHT_GREEN, BRIGHT_RED, BRIGHT_YELLOW, colored};
|
||||
use std::fs;
|
||||
|
||||
pub fn clean(args: &[String]) -> i32 {
|
||||
let red_bold = BRIGHT_RED.to_owned() + BOLD;
|
||||
let green_bold = BRIGHT_GREEN.to_owned() + BOLD;
|
||||
let yellow_bold = BRIGHT_YELLOW.to_owned() + BOLD;
|
||||
|
||||
let project_name = std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|p| p.file_name().map(|v| v.to_string_lossy().to_string()))
|
||||
.unwrap_or_else(|| "project".to_string());
|
||||
let items = check_dir(None).unwrap_or_default();
|
||||
|
||||
if args.len() > 1 {
|
||||
println!("{}: неизвестный аргумент", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
if !items.contains(&"dcr.toml".to_string()) {
|
||||
println!("{}: не найден файл dcr.toml", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
|
||||
println!(
|
||||
" Очистка проекта `{}`",
|
||||
colored(&project_name, &green_bold)
|
||||
);
|
||||
if !items.contains(&"target".to_string()) {
|
||||
println!(
|
||||
"{}: директория target не найдена",
|
||||
colored("warn", &yellow_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if let Some(arg) = args.first() {
|
||||
let mut profile = arg.clone();
|
||||
if profile.starts_with("--") {
|
||||
profile = profile.trim_start_matches("--").to_string();
|
||||
}
|
||||
if flags(&profile).is_none() {
|
||||
println!("{}: неизвестный профиль", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
|
||||
let target_items = check_dir(Some("target")).unwrap_or_default();
|
||||
if !target_items.contains(&profile) {
|
||||
println!(
|
||||
"{}: директория target/{profile} не найдена",
|
||||
colored("warn", &yellow_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
println!(" Профиль: {}", colored(&profile, &green_bold));
|
||||
let _ = fs::remove_dir_all(format!("target/{profile}"));
|
||||
println!(
|
||||
"{} Удалена директория target/{profile}",
|
||||
colored("\n ✔", &green_bold)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
let _ = fs::remove_dir_all("target");
|
||||
println!(
|
||||
"{} Удалена директория target",
|
||||
colored("\n ✔", &green_bold)
|
||||
);
|
||||
0
|
||||
}
|
||||
161
src/cli/flag_update.rs
Normal file
161
src/cli/flag_update.rs
Normal file
@@ -0,0 +1,161 @@
|
||||
use reqwest::blocking::Client;
|
||||
use serde::Deserialize;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
const LATEST_RELEASE_URL: &str = "https://api.github.com/repos/dexoron/dcr/releases/latest";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Release {
|
||||
tag_name: String,
|
||||
assets: Vec<ReleaseAsset>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ReleaseAsset {
|
||||
name: String,
|
||||
browser_download_url: String,
|
||||
}
|
||||
|
||||
pub fn flag_update(args: &[String]) -> i32 {
|
||||
if !args.is_empty() {
|
||||
println!("Ошибка: команда не поддежривает аргументы");
|
||||
return 1;
|
||||
}
|
||||
|
||||
let current_version = env!("CARGO_PKG_VERSION");
|
||||
let target = env!("DCR_TARGET");
|
||||
let client = match Client::builder().user_agent("dcr-updater").build() {
|
||||
Ok(client) => client,
|
||||
Err(_) => {
|
||||
println!("Ошибка: не удалось инициализировать HTTP клиент");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
let release = match fetch_latest_release(&client) {
|
||||
Ok(release) => release,
|
||||
Err(err) => {
|
||||
println!("Ошибка: не удалось проверить обновления: {err}");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
let latest_version = release.tag_name.trim_start_matches('v');
|
||||
if latest_version == current_version {
|
||||
println!("Установлена последняя версия: {current_version}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
let candidate_names = asset_candidates(target);
|
||||
let Some(asset) = release
|
||||
.assets
|
||||
.iter()
|
||||
.find(|asset| candidate_names.iter().any(|name| name == &asset.name))
|
||||
else {
|
||||
println!("Ошибка: не найден бинарник для таргета {target}");
|
||||
return 1;
|
||||
};
|
||||
|
||||
let bytes = match download_asset(&client, &asset.browser_download_url) {
|
||||
Ok(bytes) => bytes,
|
||||
Err(err) => {
|
||||
println!("Ошибка: не удалось скачать обновление: {err}");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
let current_exe = match std::env::current_exe() {
|
||||
Ok(path) => path,
|
||||
Err(_) => {
|
||||
println!("Ошибка: не удалось определить путь текущего бинарника");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
let temp_path = temp_binary_path(¤t_exe);
|
||||
|
||||
if fs::write(&temp_path, &bytes).is_err() {
|
||||
println!("Ошибка: не удалось записать временный бинарник");
|
||||
return 1;
|
||||
}
|
||||
set_executable_permissions(&temp_path);
|
||||
|
||||
if self_replace::self_replace(&temp_path).is_err() {
|
||||
let _ = fs::remove_file(&temp_path);
|
||||
println!("Ошибка: не удалось заменить текущий бинарник");
|
||||
return 1;
|
||||
}
|
||||
|
||||
let _ = fs::remove_file(&temp_path);
|
||||
println!("Обновление завершено: {current_version} -> {latest_version}");
|
||||
0
|
||||
}
|
||||
|
||||
fn fetch_latest_release(client: &Client) -> Result<Release, String> {
|
||||
let response = client
|
||||
.get(LATEST_RELEASE_URL)
|
||||
.send()
|
||||
.map_err(|_| "запрос к GitHub API завершился ошибкой".to_string())?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("GitHub API вернул статус {}", response.status()));
|
||||
}
|
||||
|
||||
response
|
||||
.json::<Release>()
|
||||
.map_err(|_| "ответ GitHub API имеет неожиданный формат".to_string())
|
||||
}
|
||||
|
||||
fn download_asset(client: &Client, url: &str) -> Result<Vec<u8>, String> {
|
||||
let response = client
|
||||
.get(url)
|
||||
.send()
|
||||
.map_err(|_| "запрос на скачивание завершился ошибкой".to_string())?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("скачивание вернуло статус {}", response.status()));
|
||||
}
|
||||
|
||||
response
|
||||
.bytes()
|
||||
.map(|bytes| bytes.to_vec())
|
||||
.map_err(|_| "не удалось прочитать скачанные данные".to_string())
|
||||
}
|
||||
|
||||
fn asset_candidates(target: &str) -> Vec<String> {
|
||||
let mut names = vec![format!("dcr-{target}")];
|
||||
|
||||
match target {
|
||||
"x86_64-pc-windows-msvc" => {
|
||||
names.push("dcr-x86_64-pc-windows-msvc.exe".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
names
|
||||
}
|
||||
|
||||
fn temp_binary_path(current_exe: &Path) -> PathBuf {
|
||||
let stamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|value| value.as_millis())
|
||||
.unwrap_or(0);
|
||||
let mut extension = format!("new-{stamp}");
|
||||
if cfg!(windows) {
|
||||
extension.push_str(".exe");
|
||||
}
|
||||
current_exe.with_extension(extension)
|
||||
}
|
||||
|
||||
fn set_executable_permissions(path: &Path) {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
if let Ok(meta) = fs::metadata(path) {
|
||||
let mut perms = meta.permissions();
|
||||
perms.set_mode(0o755);
|
||||
let _ = fs::set_permissions(path, perms);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/cli/help.rs
Normal file
36
src/cli/help.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use crate::utils::text::{BOLD, BRIGHT_CYAN, BRIGHT_GREEN, colored};
|
||||
|
||||
pub fn help() -> i32 {
|
||||
let green_bold = BRIGHT_GREEN.to_owned() + BOLD;
|
||||
let cyan_bold = BRIGHT_CYAN.to_owned() + BOLD;
|
||||
|
||||
println!("DCR (Dexoron Cargo Realization)");
|
||||
println!("Менеджер C-проектов, вдохновленный Cargo.");
|
||||
println!();
|
||||
println!("{}", colored("ИСПОЛЬЗОВАНИЕ:", &green_bold));
|
||||
println!("{}", colored(" dcr <команда> [опции]", &cyan_bold));
|
||||
println!();
|
||||
println!("{}", colored("КОМАНДЫ:", &green_bold));
|
||||
println!(" new <name> Создать новый проект");
|
||||
println!(" init Инициализировать текущую директорию как проект");
|
||||
println!(" build [--profile] Собрать проект (по умолчанию: --debug)");
|
||||
println!(" run [--profile] Собрать и запустить (по умолчанию: --debug)");
|
||||
println!(" clean Удалить директорию target");
|
||||
println!("{}", colored("ФЛАГИ:", &green_bold));
|
||||
println!(" --help Показать справку по команде");
|
||||
println!(" --update Обновить dcr до актуальной версии");
|
||||
println!(" --version Показать версию dcr");
|
||||
println!();
|
||||
println!("{}", colored("ОПЦИИ:", &green_bold));
|
||||
println!(" --debug Сборка с профилем debug");
|
||||
println!(" --release Сборка с профилем release");
|
||||
println!();
|
||||
println!("{}", colored("ПРИМЕРЫ:", &green_bold));
|
||||
println!("{}", colored(" dcr new hello", &cyan_bold));
|
||||
println!("{}", colored(" dcr build --release", &cyan_bold));
|
||||
println!("{}", colored(" dcr run --debug", &cyan_bold));
|
||||
println!();
|
||||
println!("{}", colored("ПОДСКАЗКА:", &green_bold));
|
||||
println!(" Запусти 'dcr <команда> --help' для справки по команде.");
|
||||
0
|
||||
}
|
||||
96
src/cli/init.rs
Normal file
96
src/cli/init.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use crate::config::{FILE_MAIN_C, file_dcr_toml};
|
||||
use crate::utils::fs::check_dir;
|
||||
use crate::utils::text::{BOLD, BRIGHT_CYAN, BRIGHT_GREEN, BRIGHT_RED, colored, printc};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
|
||||
pub fn init(args: &[String]) -> i32 {
|
||||
let red_bold = BRIGHT_RED.to_owned() + BOLD;
|
||||
let green_bold = BRIGHT_GREEN.to_owned() + BOLD;
|
||||
let cyan_bold = BRIGHT_CYAN.to_owned() + BOLD;
|
||||
|
||||
if !args.is_empty() {
|
||||
println!(
|
||||
"{}: команда не поддерживает доп. аргументы",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
let items = check_dir(None).unwrap_or_default();
|
||||
let project_name = std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|p| p.file_name().map(|v| v.to_string_lossy().to_string()))
|
||||
.unwrap_or_else(|| "project".to_string());
|
||||
|
||||
if !items.is_empty() {
|
||||
println!("{}: директория не пуста", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
|
||||
let cwd = std::env::current_dir()
|
||||
.map(|v| v.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|_| ".".to_string());
|
||||
println!("Инициализация проекта в {cwd}");
|
||||
|
||||
let mut dcr_toml = match fs::File::create("./dcr.toml") {
|
||||
Ok(file) => file,
|
||||
Err(_) => {
|
||||
println!(
|
||||
"{}: не удалось создать dcr.toml",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
if dcr_toml
|
||||
.write_all(file_dcr_toml(&project_name).as_bytes())
|
||||
.is_err()
|
||||
{
|
||||
println!(
|
||||
"{}: не удалось записать dcr.toml",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
println!(
|
||||
" {} Создан файл {}",
|
||||
colored("✔", &green_bold),
|
||||
colored("dcr.toml", &cyan_bold)
|
||||
);
|
||||
|
||||
if fs::create_dir("src").is_err() {
|
||||
println!("{}: не удалось создать src", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
let mut main_c = match fs::File::create("./src/main.c") {
|
||||
Ok(file) => file,
|
||||
Err(_) => {
|
||||
println!(
|
||||
"{}: не удалось создать src/main.c",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
if main_c.write_all(FILE_MAIN_C.as_bytes()).is_err() {
|
||||
println!(
|
||||
"{}: не удалось записать src/main.c",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
println!(
|
||||
" {} Создан файл {}\n",
|
||||
colored("✔", &green_bold),
|
||||
colored("src/main.c", &cyan_bold)
|
||||
);
|
||||
|
||||
println!(
|
||||
"Проект `{}` успешно создан\n",
|
||||
colored(&project_name, &green_bold)
|
||||
);
|
||||
printc("Следуюший шаг:", &green_bold);
|
||||
printc(" dcr run", &cyan_bold);
|
||||
0
|
||||
}
|
||||
7
src/cli/mod.rs
Normal file
7
src/cli/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
pub mod build;
|
||||
pub mod clean;
|
||||
pub mod flag_update;
|
||||
pub mod help;
|
||||
pub mod init;
|
||||
pub mod new;
|
||||
pub mod run;
|
||||
123
src/cli/new.rs
Normal file
123
src/cli/new.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use crate::config::{FILE_MAIN_C, file_dcr_toml};
|
||||
use crate::utils::fs::check_dir;
|
||||
use crate::utils::text::{BOLD, BRIGHT_CYAN, BRIGHT_GREEN, BRIGHT_RED, colored, printc};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
|
||||
pub fn new(args: &[String]) -> i32 {
|
||||
let items = check_dir(None).unwrap_or_default();
|
||||
let red_bold = BRIGHT_RED.to_owned() + BOLD;
|
||||
let green_bold = BRIGHT_GREEN.to_owned() + BOLD;
|
||||
let cyan_bold = BRIGHT_CYAN.to_owned() + BOLD;
|
||||
|
||||
if args.is_empty() {
|
||||
println!(
|
||||
"{}: не указанно название проекта",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
if args.len() > 1 {
|
||||
println!(
|
||||
"{}: команда не поддерживает доп. аргументы",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
let project_name = &args[0];
|
||||
println!(
|
||||
"Создание проекта `{}`...",
|
||||
colored(project_name, &green_bold)
|
||||
);
|
||||
|
||||
if items.contains(project_name) {
|
||||
println!(
|
||||
"{}: директория `{}` уже существует\n",
|
||||
colored("error", &red_bold),
|
||||
colored(project_name, &green_bold)
|
||||
);
|
||||
printc("Подсказка:", &green_bold);
|
||||
println!(
|
||||
" Используй `{}` для инициализации существующего проекта\n или задай другое имя проекта",
|
||||
colored("dcr init", &cyan_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if fs::create_dir(project_name).is_err() {
|
||||
println!(
|
||||
"{}: не удалось создать директорию",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
println!(
|
||||
" {} Создана директория {}",
|
||||
colored("✔", &green_bold),
|
||||
project_name
|
||||
);
|
||||
|
||||
let toml_path = format!("./{project_name}/dcr.toml");
|
||||
let mut dcr_toml = match fs::File::create(&toml_path) {
|
||||
Ok(file) => file,
|
||||
Err(_) => {
|
||||
println!(
|
||||
"{}: не удалось создать dcr.toml",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
if dcr_toml
|
||||
.write_all(file_dcr_toml(project_name).as_bytes())
|
||||
.is_err()
|
||||
{
|
||||
println!(
|
||||
"{}: не удалось записать dcr.toml",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
println!(
|
||||
" {} Создан файл {}",
|
||||
colored("✔", &green_bold),
|
||||
colored("dcr.toml", &cyan_bold)
|
||||
);
|
||||
|
||||
if fs::create_dir_all(format!("./{project_name}/src")).is_err() {
|
||||
println!("{}: не удалось создать src", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
let main_c_path = format!("./{project_name}/src/main.c");
|
||||
let mut main_c = match fs::File::create(&main_c_path) {
|
||||
Ok(file) => file,
|
||||
Err(_) => {
|
||||
println!(
|
||||
"{}: не удалось создать src/main.c",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
if main_c.write_all(FILE_MAIN_C.as_bytes()).is_err() {
|
||||
println!(
|
||||
"{}: не удалось записать src/main.c",
|
||||
colored("error", &red_bold)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
println!(
|
||||
" {} Создан файл {}\n",
|
||||
colored("✔", &green_bold),
|
||||
colored("src/main.c", &cyan_bold)
|
||||
);
|
||||
|
||||
println!(
|
||||
"Проект `{}` успешно создан\n",
|
||||
colored(project_name, &green_bold)
|
||||
);
|
||||
printc("Следуюший шаг:", &green_bold);
|
||||
printc(&format!(" cd {project_name}\n dcr run"), &cyan_bold);
|
||||
0
|
||||
}
|
||||
55
src/cli/run.rs
Normal file
55
src/cli/run.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use crate::cli::build::build;
|
||||
use crate::config::{PROFILE, flags};
|
||||
use crate::utils::fs::check_dir;
|
||||
use crate::utils::text::{BOLD, BRIGHT_RED, colored};
|
||||
use std::process::Command;
|
||||
|
||||
pub fn run(args: &[String]) -> i32 {
|
||||
let red_bold = BRIGHT_RED.to_owned() + BOLD;
|
||||
let mut active_profile = PROFILE.to_string();
|
||||
|
||||
let items = check_dir(None).unwrap_or_default();
|
||||
if !items.contains(&"dcr.toml".to_string()) {
|
||||
println!("{}: не найден файл dcr.toml", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if let Some(first_arg) = args.first() {
|
||||
if first_arg.starts_with("--") {
|
||||
let candidate = first_arg.trim_start_matches("--");
|
||||
if flags(candidate).is_some() {
|
||||
active_profile = candidate.to_string();
|
||||
} else {
|
||||
println!("{}: неизвестный флаг сборки", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
println!("{}: неизвестный аргумент", colored("error", &red_bold));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
let build_status = build(args);
|
||||
if build_status == 0 {
|
||||
println!("\n Запуск target/{active_profile}/main");
|
||||
println!("--------------------------------");
|
||||
return Command::new(format!("./target/{active_profile}/main"))
|
||||
.status()
|
||||
.map(|status| status.code().unwrap_or(1))
|
||||
.unwrap_or(1);
|
||||
}
|
||||
|
||||
if check_dir(Some(&format!("target/{active_profile}")))
|
||||
.unwrap_or_default()
|
||||
.contains(&active_profile)
|
||||
{
|
||||
println!("Запуск последнего релиза");
|
||||
return Command::new(format!("./target/{active_profile}/main"))
|
||||
.status()
|
||||
.map(|status| status.code().unwrap_or(1))
|
||||
.unwrap_or(1);
|
||||
}
|
||||
|
||||
println!("Исправьте ошибки в коде для запуска проекта");
|
||||
0
|
||||
}
|
||||
43
src/config.rs
Normal file
43
src/config.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
pub const PROJECT_VERSION: &str = "0.1.0";
|
||||
pub const PROJECT_LANGUAGE: &str = "c";
|
||||
pub const PROJECT_COMPILER: &str = "clang";
|
||||
pub const PROFILE: &str = "debug";
|
||||
|
||||
pub fn file_dcr_toml(project_name: &str) -> String {
|
||||
format!(
|
||||
r#"[package]
|
||||
name = "{project_name}"
|
||||
version = "{project_version}"
|
||||
language = "{project_language}"
|
||||
compiler = "{project_compiler}"
|
||||
|
||||
[dependencies]
|
||||
"#,
|
||||
project_version = PROJECT_VERSION,
|
||||
project_language = PROJECT_LANGUAGE,
|
||||
project_compiler = PROJECT_COMPILER
|
||||
)
|
||||
}
|
||||
|
||||
pub const FILE_MAIN_C: &str = r#"#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
printf("Hello World!\n");
|
||||
return 0;
|
||||
}
|
||||
"#;
|
||||
|
||||
pub fn flags(profile: &str) -> Option<&'static [&'static str]> {
|
||||
match profile {
|
||||
"release" => Some(&["-O3", "-DNDEBUG", "-march=native"]),
|
||||
"debug" => Some(&[
|
||||
"-O0",
|
||||
"-g",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-fno-omit-frame-pointer",
|
||||
"-DDEBUG",
|
||||
]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
from .help import help
|
||||
from .init import init
|
||||
from .new import new
|
||||
from .run import run
|
||||
from .build import build
|
||||
from .clean import clean
|
||||
from .flag_update import flag_update
|
||||
|
||||
|
||||
__all__ = [
|
||||
"help",
|
||||
"init",
|
||||
"new",
|
||||
"run",
|
||||
"build",
|
||||
"clean",
|
||||
"flag_update",
|
||||
]
|
||||
@@ -1,70 +0,0 @@
|
||||
import time
|
||||
import os
|
||||
import subprocess
|
||||
from ..config import flags, profile, project_compiler
|
||||
from ..utils.fs import check_dir
|
||||
from ..utils.text import colored, BRIGHT_GREEN, BOLD, BRIGHT_RED
|
||||
|
||||
|
||||
def build(args: list[str] | None = None) -> int:
|
||||
active_profile: str = profile
|
||||
project_name = os.path.basename(os.getcwd())
|
||||
if "dcr.toml" not in check_dir():
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": не найден файл dcr.toml")
|
||||
return 1
|
||||
if args:
|
||||
if len(args) >= 1 and args[0].startswith("--"):
|
||||
candidate: str = args[0][2:]
|
||||
if candidate in flags:
|
||||
active_profile: str = candidate
|
||||
else:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": неизвестный флаг сборки")
|
||||
return 1
|
||||
else:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": неизвестный аргумент")
|
||||
return 1
|
||||
|
||||
print(
|
||||
" Сборка проекта `"
|
||||
+ colored(project_name, BRIGHT_GREEN + BOLD)
|
||||
+ "`\n Профиль: "
|
||||
+ colored(active_profile, BRIGHT_GREEN + BOLD)
|
||||
+ "\n Компилятор: "
|
||||
+ colored(project_compiler, BRIGHT_GREEN + BOLD)
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
if "target" not in check_dir():
|
||||
os.mkdir("./target")
|
||||
if active_profile not in check_dir("target"):
|
||||
os.mkdir(f"./target/{active_profile}")
|
||||
if "main.c" in check_dir("src"):
|
||||
compile_flags = flags[active_profile]
|
||||
start_time: float = time.time()
|
||||
try:
|
||||
subprocess.run(
|
||||
[
|
||||
project_compiler,
|
||||
"./src/main.c",
|
||||
*compile_flags,
|
||||
"-o",
|
||||
f"./target/{active_profile}/main",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
end_time: float = time.time()
|
||||
times: float = end_time - start_time
|
||||
times: float = int(times * 100) / 100
|
||||
print(
|
||||
" "
|
||||
+ colored("✔", BRIGHT_GREEN + BOLD)
|
||||
+ " Сборка завершена успешно, за "
|
||||
+ colored(str(times), BRIGHT_GREEN + BOLD)
|
||||
+ " секунд"
|
||||
)
|
||||
return 0
|
||||
except: # noqa: E722
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": сборка не удалась")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -1,53 +0,0 @@
|
||||
import os
|
||||
import shutil
|
||||
from ..utils.fs import check_dir
|
||||
from ..utils.text import colored, BRIGHT_RED, BOLD, BRIGHT_GREEN, BRIGHT_YELLOW
|
||||
from ..config import flags
|
||||
|
||||
|
||||
def clean(args: list[str] | None = None) -> int:
|
||||
project_name = os.path.basename(os.getcwd())
|
||||
items: list[str] = check_dir()
|
||||
|
||||
if args and len(args) > 1:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": неизвестный аргумент")
|
||||
return 1
|
||||
|
||||
if "dcr.toml" not in items:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": не найден файл dcr.toml")
|
||||
return 1
|
||||
|
||||
print(" Очистка проекта `" + colored(project_name, BRIGHT_GREEN + BOLD) + "`")
|
||||
|
||||
if "target" not in items:
|
||||
print(colored("warn", BRIGHT_YELLOW + BOLD) + ": директория target не найдена")
|
||||
return 1
|
||||
|
||||
if args:
|
||||
profile = args[0]
|
||||
|
||||
if profile.startswith("--"):
|
||||
profile = profile[2:]
|
||||
|
||||
if profile not in flags:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": неизвестный профиль")
|
||||
return 1
|
||||
|
||||
if profile not in check_dir("target"):
|
||||
print(
|
||||
colored("warn", BRIGHT_YELLOW + BOLD)
|
||||
+ f": директория target/{profile} не найдена"
|
||||
)
|
||||
return 1
|
||||
|
||||
print(" Профиль: " + colored(profile, BRIGHT_GREEN + BOLD))
|
||||
shutil.rmtree(os.path.join("target", profile))
|
||||
print(
|
||||
colored("\n ✔", BRIGHT_GREEN + BOLD)
|
||||
+ f" Удалена директория target/{profile}"
|
||||
)
|
||||
return 0
|
||||
|
||||
shutil.rmtree("target")
|
||||
print(colored("\n ✔", BRIGHT_GREEN + BOLD) + " Удалена директория target")
|
||||
return 0
|
||||
@@ -1,23 +0,0 @@
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
|
||||
def flag_update(args: list[str] | None = None) -> int:
|
||||
if args and len(args) > 0:
|
||||
print("Ошибка: команда не поддежривает аргументы")
|
||||
return 1
|
||||
if platform.system() != "Linux":
|
||||
print("Ошибка: обновление поддерживается только на Linux")
|
||||
return 1
|
||||
if shutil.which("curl") is None:
|
||||
print("Ошибка: не найден curl")
|
||||
return 1
|
||||
try:
|
||||
subprocess.run(
|
||||
["bash", "-c", "curl -fsSL dcr.zov.tatar | bash"], check=True
|
||||
)
|
||||
return 0
|
||||
except subprocess.CalledProcessError:
|
||||
print("Ошибка: не удалось выполнить обновление")
|
||||
return 1
|
||||
@@ -1,39 +0,0 @@
|
||||
from ..utils.text import colored, BRIGHT_GREEN, BRIGHT_CYAN, BOLD
|
||||
|
||||
|
||||
def help() -> int:
|
||||
print(
|
||||
"\n".join(
|
||||
[
|
||||
"DCR (Dexoron Cargo Realization)",
|
||||
"Менеджер C-проектов, вдохновленный Cargo.",
|
||||
"",
|
||||
colored("ИСПОЛЬЗОВАНИЕ:", BRIGHT_GREEN + BOLD),
|
||||
colored(" dcr <команда> [опции]", BRIGHT_CYAN + BOLD),
|
||||
"",
|
||||
colored("КОМАНДЫ:", BRIGHT_GREEN + BOLD),
|
||||
" new <name> Создать новый проект",
|
||||
" init Инициализировать текущую директорию как проект",
|
||||
" build [--profile] Собрать проект (по умолчанию: --debug)",
|
||||
" run [--profile] Собрать и запустить (по умолчанию: --debug)",
|
||||
" clean Удалить директорию target",
|
||||
colored("ФЛАГИ:", BRIGHT_GREEN + BOLD),
|
||||
" --help Показать справку по команде",
|
||||
" --update Обновить dcr до актуальной версии",
|
||||
" --version Показать версию dcr",
|
||||
"",
|
||||
colored("ОПЦИИ:", BRIGHT_GREEN + BOLD),
|
||||
" --debug Сборка с профилем debug",
|
||||
" --release Сборка с профилем release",
|
||||
"",
|
||||
colored("ПРИМЕРЫ:", BRIGHT_GREEN + BOLD),
|
||||
colored(" dcr new hello", BRIGHT_CYAN + BOLD),
|
||||
colored(" dcr build --release", BRIGHT_CYAN + BOLD),
|
||||
colored(" dcr run --debug", BRIGHT_CYAN + BOLD),
|
||||
"",
|
||||
colored("ПОДСКАЗКА:", BRIGHT_GREEN + BOLD),
|
||||
" Запусти 'dcr <команда> --help' для справки по команде.",
|
||||
]
|
||||
)
|
||||
)
|
||||
return 0
|
||||
@@ -1,61 +0,0 @@
|
||||
from ..utils.text import colored, BRIGHT_RED, BOLD, printc, BRIGHT_GREEN, BRIGHT_CYAN
|
||||
from ..config import (
|
||||
file_dcr_toml,
|
||||
file_main_c,
|
||||
project_version,
|
||||
project_language,
|
||||
project_compiler,
|
||||
)
|
||||
import os
|
||||
from ..utils.fs import check_dir
|
||||
|
||||
|
||||
def init(args: list[str] | None = None) -> int:
|
||||
if args:
|
||||
print(
|
||||
colored("error", BRIGHT_RED + BOLD)
|
||||
+ ": команда не поддерживает доп. аргументы"
|
||||
)
|
||||
return 1
|
||||
items: list[str] = check_dir()
|
||||
project_name = os.path.basename(os.getcwd())
|
||||
|
||||
if items:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": директория не пуста")
|
||||
return 1
|
||||
|
||||
print("Инициализация проекта в " + os.getcwd())
|
||||
|
||||
with open("./dcr.toml", "w") as file:
|
||||
file.write(
|
||||
file_dcr_toml.format(
|
||||
project_name=project_name,
|
||||
project_version=project_version,
|
||||
project_language=project_language,
|
||||
project_compiler=project_compiler,
|
||||
)
|
||||
)
|
||||
print(
|
||||
" "
|
||||
+ colored("✔", BRIGHT_GREEN + BOLD)
|
||||
+ " Создан файл "
|
||||
+ colored("dcr.toml", BRIGHT_CYAN + BOLD)
|
||||
)
|
||||
|
||||
os.mkdir("src")
|
||||
with open("./src/main.c", "w") as file:
|
||||
file.write(file_main_c)
|
||||
print(
|
||||
" "
|
||||
+ colored("✔", BRIGHT_GREEN + BOLD)
|
||||
+ " Создан файл "
|
||||
+ colored("src/main.c\n", BRIGHT_CYAN + BOLD)
|
||||
)
|
||||
|
||||
print(
|
||||
"Проект `" + colored(project_name, BRIGHT_GREEN + BOLD) + "` успешно создан\n"
|
||||
)
|
||||
printc("Следуюший шаг:", BRIGHT_GREEN + BOLD)
|
||||
printc(" dcr run", BRIGHT_CYAN + BOLD)
|
||||
|
||||
return 0
|
||||
@@ -1,89 +0,0 @@
|
||||
from ..utils.text import (
|
||||
colored,
|
||||
printc,
|
||||
BRIGHT_GREEN,
|
||||
BOLD,
|
||||
BRIGHT_CYAN,
|
||||
BRIGHT_RED,
|
||||
)
|
||||
from ..config import (
|
||||
file_dcr_toml,
|
||||
file_main_c,
|
||||
project_version,
|
||||
project_language,
|
||||
project_compiler,
|
||||
)
|
||||
import os
|
||||
from ..utils.fs import check_dir
|
||||
|
||||
|
||||
def new(args: list[str]) -> int:
|
||||
items: list[str] = check_dir()
|
||||
if len(args) == 0:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": не указанно название проекта")
|
||||
return 1
|
||||
if len(args) > 1:
|
||||
print(
|
||||
colored("error", BRIGHT_RED + BOLD)
|
||||
+ ": команда не поддерживает доп. аргументы"
|
||||
)
|
||||
return 1
|
||||
project_name: str = args[0]
|
||||
print("Создание проекта `" + colored(project_name, BRIGHT_GREEN + BOLD) + "`...")
|
||||
|
||||
if project_name in items:
|
||||
print(
|
||||
colored("error", BRIGHT_RED + BOLD)
|
||||
+ ": директория `"
|
||||
+ colored(project_name, BRIGHT_GREEN + BOLD)
|
||||
+ "` уже существует\n"
|
||||
)
|
||||
printc("Подсказка:", BRIGHT_GREEN + BOLD)
|
||||
print(
|
||||
" Используй `"
|
||||
+ colored("dcr init", BRIGHT_CYAN + BOLD)
|
||||
+ "` для инициализации существующего проекта\n или задай другое имя проекта"
|
||||
)
|
||||
return 1
|
||||
|
||||
os.mkdir(project_name)
|
||||
print(
|
||||
" "
|
||||
+ colored("✔", BRIGHT_GREEN + BOLD)
|
||||
+ " Создана директория "
|
||||
+ project_name
|
||||
)
|
||||
|
||||
with open(f"./{project_name}/dcr.toml", "w") as file:
|
||||
file.write(
|
||||
file_dcr_toml.format(
|
||||
project_name=project_name,
|
||||
project_version=project_version,
|
||||
project_language=project_language,
|
||||
project_compiler=project_compiler,
|
||||
)
|
||||
)
|
||||
print(
|
||||
" "
|
||||
+ colored("✔", BRIGHT_GREEN + BOLD)
|
||||
+ " Создан файл "
|
||||
+ colored("dcr.toml", BRIGHT_CYAN + BOLD)
|
||||
)
|
||||
|
||||
os.makedirs(f"./{project_name}/src")
|
||||
with open(f"./{project_name}/src/main.c", "w") as file:
|
||||
file.write(file_main_c)
|
||||
print(
|
||||
" "
|
||||
+ colored("✔", BRIGHT_GREEN + BOLD)
|
||||
+ " Создан файл "
|
||||
+ colored("src/main.c\n", BRIGHT_CYAN + BOLD)
|
||||
)
|
||||
|
||||
print(
|
||||
"Проект `" + colored(project_name, BRIGHT_GREEN + BOLD) + "` успешно создан\n"
|
||||
)
|
||||
printc("Следуюший шаг:", BRIGHT_GREEN + BOLD)
|
||||
printc(" cd " + project_name + "\n dcr run", BRIGHT_CYAN + BOLD)
|
||||
|
||||
return 0
|
||||
@@ -1,37 +0,0 @@
|
||||
import subprocess
|
||||
|
||||
from ..utils.fs import check_dir
|
||||
from ..utils.text import colored, BRIGHT_RED, BOLD
|
||||
from ..config import flags, profile
|
||||
from .build import build
|
||||
|
||||
|
||||
def run(args: list[str] | None = None) -> int:
|
||||
active_profile: str = profile
|
||||
if "dcr.toml" not in check_dir():
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": не найден файл dcr.toml")
|
||||
return 1
|
||||
if args:
|
||||
if len(args) >= 1 and args[0].startswith("--"):
|
||||
candidate: str = args[0][2:]
|
||||
if candidate in flags:
|
||||
active_profile: str = candidate
|
||||
else:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": неизвестный флаг сборки")
|
||||
return 1
|
||||
else:
|
||||
print(colored("error", BRIGHT_RED + BOLD) + ": неизвестный аргумент")
|
||||
return 1
|
||||
|
||||
build_status: int = build(args)
|
||||
if build_status == 0:
|
||||
print("\n Запуск " + "target/" + active_profile + "/main")
|
||||
print("--------------------------------")
|
||||
return subprocess.run([f"./target/{active_profile}/main"]).returncode
|
||||
else:
|
||||
if active_profile in check_dir("target/" + active_profile):
|
||||
print("Запуск последнего релиза")
|
||||
return subprocess.run([f"./target/{active_profile}/main"]).returncode
|
||||
else:
|
||||
print("Исправьте ошибки в коде для запуска проекта")
|
||||
return 0
|
||||
@@ -1,43 +0,0 @@
|
||||
file_dcr_toml: str = """[package]
|
||||
name = "{project_name}"
|
||||
version = "{project_version}"
|
||||
language = "{project_language}"
|
||||
compiler = "{project_compiler}"
|
||||
|
||||
[dependencies]
|
||||
"""
|
||||
file_main_c: str = """#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
printf("Hello World!\\n");
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
|
||||
file_dcr_lock: str = """# This file is automatically @generated by dcr.
|
||||
# It is not intended for manual editing.
|
||||
version = 1
|
||||
|
||||
[[package]]
|
||||
name = "{project_name}"
|
||||
version = "{project_version}"
|
||||
"""
|
||||
|
||||
"""[[package]]
|
||||
name = "{package_name}"
|
||||
version = "{package_version}"
|
||||
source = "{{package_source}"
|
||||
checksum = "{package_checksum}"
|
||||
dependencies = [{package_dependencies}]"""
|
||||
|
||||
project_version: str = "0.1.0"
|
||||
project_language: str = "c"
|
||||
project_compiler: str = "clang"
|
||||
|
||||
profile: str = "debug"
|
||||
flags: dict[str, list[str]] = {
|
||||
"release": ["-O3", "-DNDEBUG", "-march=native"],
|
||||
"debug": ["-O0", "-g", "-Wall", "-Wextra", "-fno-omit-frame-pointer", "-DDEBUG"],
|
||||
}
|
||||
|
||||
VERSION = "v0.1.1"
|
||||
@@ -1,38 +0,0 @@
|
||||
from .config import VERSION
|
||||
import dcr.cli as cli # ty:ignore[unresolved-import]
|
||||
import sys
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) < 2:
|
||||
cli.help()
|
||||
return 0
|
||||
|
||||
cmd: str = sys.argv[1]
|
||||
args: str | list[str] = sys.argv[2:]
|
||||
|
||||
match cmd:
|
||||
case "new":
|
||||
cli.new(args)
|
||||
case "init":
|
||||
cli.init(args)
|
||||
case "build":
|
||||
cli.build(args)
|
||||
case "run":
|
||||
cli.run(args)
|
||||
case "clean":
|
||||
cli.clean(args)
|
||||
case "--version":
|
||||
print(f"dcr {VERSION} (GNU/Linux)")
|
||||
case "--help":
|
||||
cli.help()
|
||||
case "--update":
|
||||
cli.flag_update(args)
|
||||
case _:
|
||||
print("Неизвестная команда или аргумент")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,8 +0,0 @@
|
||||
import os
|
||||
|
||||
|
||||
def check_dir(dir: str | None = None) -> list[str]:
|
||||
if dir in (None, ".", "./"):
|
||||
return os.listdir(os.getcwd())
|
||||
else:
|
||||
return os.listdir(os.getcwd() + "/" + dir)
|
||||
@@ -1,40 +0,0 @@
|
||||
# RESET
|
||||
RESET = "\033[0m"
|
||||
|
||||
# TEXT STYLES
|
||||
BOLD = "\033[1m"
|
||||
DIM = "\033[2m"
|
||||
ITALIC = "\033[3m"
|
||||
UNDERLINE = "\033[4m"
|
||||
BLINK = "\033[5m"
|
||||
REVERSE = "\033[7m"
|
||||
HIDDEN = "\033[8m"
|
||||
STRIKETHROUGH = "\033[9m"
|
||||
|
||||
# STANDARD COLORS (Foreground)
|
||||
BLACK = "\033[30m"
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
BLUE = "\033[34m"
|
||||
MAGENTA = "\033[35m"
|
||||
CYAN = "\033[36m"
|
||||
WHITE = "\033[37m"
|
||||
|
||||
# BRIGHT COLORS
|
||||
BRIGHT_BLACK = "\033[90m"
|
||||
BRIGHT_RED = "\033[91m"
|
||||
BRIGHT_GREEN = "\033[92m"
|
||||
BRIGHT_YELLOW = "\033[93m"
|
||||
BRIGHT_BLUE = "\033[94m"
|
||||
BRIGHT_MAGENTA = "\033[95m"
|
||||
BRIGHT_CYAN = "\033[96m"
|
||||
BRIGHT_WHITE = "\033[97m"
|
||||
|
||||
|
||||
def colored(msg: str, style: str) -> str:
|
||||
return style + msg + RESET
|
||||
|
||||
|
||||
def printc(msg: str, style: str) -> None:
|
||||
print(style + msg + RESET)
|
||||
34
src/main.rs
Normal file
34
src/main.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
mod cli;
|
||||
mod config;
|
||||
mod utils;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
if args.len() < 2 {
|
||||
std::process::exit(cli::help::help());
|
||||
}
|
||||
|
||||
let cmd = args[1].as_str();
|
||||
let rest = &args[2..];
|
||||
|
||||
let code = match cmd {
|
||||
"new" => cli::r#new::new(rest),
|
||||
"init" => cli::init::init(rest),
|
||||
"build" => cli::build::build(rest),
|
||||
"run" => cli::run::run(rest),
|
||||
"clean" => cli::clean::clean(rest),
|
||||
"--version" => {
|
||||
println!("dcr {} ({})", env!("CARGO_PKG_VERSION"), env!("DCR_TARGET"));
|
||||
0
|
||||
}
|
||||
"--help" => cli::help::help(),
|
||||
"--update" => cli::flag_update::flag_update(rest),
|
||||
_ => {
|
||||
println!("Неизвестная команда или аргумент");
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
std::process::exit(code);
|
||||
}
|
||||
17
src/utils/fs.rs
Normal file
17
src/utils/fs.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn check_dir(dir: Option<&str>) -> io::Result<Vec<String>> {
|
||||
let path: PathBuf = match dir {
|
||||
None | Some(".") | Some("./") => std::env::current_dir()?,
|
||||
Some(value) => std::env::current_dir()?.join(value),
|
||||
};
|
||||
|
||||
let mut items = Vec::new();
|
||||
for entry in std::fs::read_dir(path)? {
|
||||
let entry = entry?;
|
||||
items.push(entry.file_name().to_string_lossy().to_string());
|
||||
}
|
||||
|
||||
Ok(items)
|
||||
}
|
||||
30
src/utils/log.rs
Normal file
30
src/utils/log.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use crate::utils::text::{BOLD, BRIGHT_GREEN, BRIGHT_RED, BRIGHT_YELLOW, colored};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn error(msg: &str) {
|
||||
println!(
|
||||
"{}: {msg}",
|
||||
colored("error", &(BRIGHT_RED.to_owned() + BOLD))
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn warn(msg: &str) {
|
||||
println!(
|
||||
"{}: {msg}",
|
||||
colored("warn", &(BRIGHT_YELLOW.to_owned() + BOLD))
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn info(msg: &str) {
|
||||
println!("{}: {msg}", colored("info", BOLD));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn ok(msg: &str) {
|
||||
println!(
|
||||
"{}: {msg}",
|
||||
colored("ok", &(BRIGHT_GREEN.to_owned() + BOLD))
|
||||
);
|
||||
}
|
||||
3
src/utils/mod.rs
Normal file
3
src/utils/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod fs;
|
||||
pub mod log;
|
||||
pub mod text;
|
||||
16
src/utils/text.rs
Normal file
16
src/utils/text.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
pub const RESET: &str = "\x1b[0m";
|
||||
|
||||
pub const BOLD: &str = "\x1b[1m";
|
||||
|
||||
pub const BRIGHT_RED: &str = "\x1b[91m";
|
||||
pub const BRIGHT_GREEN: &str = "\x1b[92m";
|
||||
pub const BRIGHT_YELLOW: &str = "\x1b[93m";
|
||||
pub const BRIGHT_CYAN: &str = "\x1b[96m";
|
||||
|
||||
pub fn colored(msg: &str, style: &str) -> String {
|
||||
format!("{style}{msg}{RESET}")
|
||||
}
|
||||
|
||||
pub fn printc(msg: &str, style: &str) {
|
||||
println!("{style}{msg}{RESET}");
|
||||
}
|
||||
Reference in New Issue
Block a user