Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@
# Build
target/
src/data/*
.nxfs
.nxfs
plugins/*
# Include plugins README.md
!plugins/README.md

# misc
.DS_Store
plugins/.DS_Store
src/.DS_Store
src/*/.DS_Store
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nyx"
version = "2.11.0"
version = "2.12.0"
edition = "2021"
authors = ["Elouan DA COSTA PEIXOTO <elouandacostapeixoto@gmail.com>"]
description = "A CLI tool for managing your projects."
Expand Down
28 changes: 28 additions & 0 deletions plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Here's the plugins directory used for plugin system

## Usage

Add as many plugins as you want and add the name of it to the nyx's config file. The name of the plugin must match the name of the file without file extension.

## Exampled

Simple example for a plugin file:

```toml
[plugin]
name = "rust"
plugin_type = "Simple"
version = "0.1.0"
enabled = true

[core]
build_command = true
clean_command = true
run_command = true

[commands]
init_command = ["cargo", "init", "--bin"]
build_command = []
clean_command = []
run_command = []
```
16 changes: 16 additions & 0 deletions src/init/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use std::env;

use crate::{nxfs, utils::log::log_from_log_level};

pub fn init_command() {
let args: Vec<String> = env::args().collect();
if args.len() <= 2 {
init_nyx();
}
}

// Basic init of NYX
fn init_nyx() {
log_from_log_level(crate::nxfs::config::LogLevel::Info, "Initialize NYX..");
nxfs::nxs::create_data();
}
10 changes: 8 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ pub mod nxfs;
use std::env;
mod health;
mod hello;
mod init;
pub mod plugins;

// Current version of NYX
// if modified and then running update command it will replace
// your current nyx installation with the newer version
const VERSION: &str = "2.11.0";
const VERSION: &str = "2.12.0";
enum Commands {
Init,
CatNxs,
Expand All @@ -31,6 +33,7 @@ enum Commands {
Hello,
Update,
Config,
Plugins,
Upgrade,
Help,
Version,
Expand All @@ -55,6 +58,7 @@ Commands:
hello Display helpful information about today
upgrade Update the current version of NYX
config Manage nyx configuration
plugins Manage plugins
help Show this help message

Options:
Expand Down Expand Up @@ -93,6 +97,7 @@ fn main() {
Some("hello") => Commands::Hello,
Some("update") => Commands::Update,
Some("config") => Commands::Config,
Some("plugins") => Commands::Plugins,
Some("upgrade") => Commands::Upgrade,
Some("help") => Commands::Help,
Some("version") => Commands::Version,
Expand All @@ -103,7 +108,7 @@ fn main() {
};

match command {
Commands::Init => nxfs::nxs::create_data(),
Commands::Init => init::init_command(),
Commands::CatNxs => nxfs::nxs::cat_nxs(),
Commands::CatNxp { hash } => nxfs::nxp::cat_nxp(hash.as_deref()),
Commands::Project => projects::project_command(),
Expand All @@ -113,6 +118,7 @@ fn main() {
Commands::Health => health::health_command(),
Commands::Hello => hello::hello_command(),
Commands::Config => nxfs::config::config_command(),
Commands::Plugins => plugins::plugins_command(),
Commands::Update => update::update_command(),
Commands::Upgrade => upgrade::upgrade_bin(),
Commands::Help => command_usage(nyx_usage()),
Expand Down
9 changes: 9 additions & 0 deletions src/nxfs/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Options:
pub struct Config {
pub config: ConfigHeader,
pub user: ConfigUser,
pub plugins: ConfigPlugins,
pub git: ConfigGit,
pub behavior: ConfigBehavior,
pub ui: ConfigUi,
Expand All @@ -51,6 +52,11 @@ pub struct ConfigUser {
pub update_list: Vec<UserUpdateEntry>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ConfigPlugins {
pub list: Vec<String>
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct UserUpdateEntry {
pub command: String,
Expand Down Expand Up @@ -118,6 +124,9 @@ name = ''
health_list = []
update_list = []

[plugins]
list = []

[git]
profile_url = ''

Expand Down
2 changes: 1 addition & 1 deletion src/nxfs/nxs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub fn create_data() {
create_nxs_file()
}

/// The function `create_nxs_file` creates a NXS file with a NXSHeader and project list.
/// The function `create_nxs_file` creates NXS file with a NXSHeader and project list.
fn create_nxs_file() {
// NXSHeader
let header: NXSHeader = NXSHeader {
Expand Down
122 changes: 122 additions & 0 deletions src/plugins/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use std::{
env, fs, path::PathBuf, process::{Child, Command}
};

use lrncore::{path::change_work_dir, usage_exit::command_usage};
use parser::parse_plugin_file;
use serde::Deserialize;

use crate::{
nxfs::config::{parse_config_file, LogLevel},
utils::log::log_from_log_level,
};

pub mod parser;

#[derive(Deserialize, Debug)]
pub struct Plugin {
pub plugin: PluginSection,
pub core: CoreSection,
pub commands: CommandsSection,
}

#[derive(Deserialize, Debug)]
pub struct PluginSection {
pub name: String,
pub version: String,
pub enabled: bool,
}

#[derive(Deserialize, Debug)]
pub struct CoreSection {
pub build_command: bool,
pub clean_command: bool,
pub run_command: bool,
}

#[derive(Deserialize, Debug)]
pub struct CommandsSection {
pub init_command: Vec<String>,
pub build_command: Vec<String>,
pub clean_command: Vec<String>,
pub run_command: Vec<String>,
}

fn plugins_help() -> &'static str {
(r"
Usage: nyx plugins [subcommand] [arguments] [options]

Subcommands:
health Check plugins health

Options:
-h, --help Show this help message
") as _
}

pub fn plugins_command() {
let args: Vec<String> = env::args().collect();
if args.len() <= 2 {
command_usage(plugins_help());
}
match args[2].as_str() {
"health" => health_plugins(),
_ => {
command_usage(plugins_help());
}
}
}

// Check plugins installed
fn health_plugins() {
// Load config file
let config = parse_config_file().expect("Failed to parse config file");
let mut invalid_plugins_number: u8 = 0;
// Iterate over plugins list
for each in config.plugins.list {
let file_path: &str = &format!("plugins/{each}.toml");
if !fs::exists(file_path).expect("Failed to check path") {
invalid_plugins_number += 1;
log_from_log_level(
LogLevel::Warn,
format!("Failed to load plugin: {each}").as_str(),
);
} else {
match parse_plugin_file(&each) {
Ok(_) => (),
Err(e) => {
log_from_log_level(
LogLevel::Warn,
format!("Failed to parse plugin: {each}").as_str(),
);
eprintln!("{e}");
}
}
}
}
// Log depending on number of invalid plugins
if invalid_plugins_number != 0 {
log_from_log_level(
LogLevel::Warn,
format!("Plugin unabled to be load: {invalid_plugins_number}").as_str(),
);
} else {
log_from_log_level(LogLevel::Info, "Successfully load all plugins");
}
}

/// Run init command from given plugin
pub fn run_init_command(plugin: Plugin, _name: &str, path: PathBuf) {
change_work_dir(path.as_os_str().to_str().expect("Failed to cast pathbuf to os_str to str"));
let mut init_commands_vec: Vec<String> = plugin.commands.init_command;
let bin = init_commands_vec.remove(0);
let mut command: Child = Command::new(bin)
.args(init_commands_vec)
.spawn()
.expect("Failed to fork process");
let wait_command = command.wait().expect("Failed to wait forked process");
if !wait_command.success() {
log_from_log_level(LogLevel::Error, "Failed to run init command");
}
log_from_log_level(LogLevel::Info, "Successfully run init command");
}
22 changes: 22 additions & 0 deletions src/plugins/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use lrncore::path::change_work_dir;
use toml::de::Error as toml_error;

use crate::utils;

use super::Plugin;

/// Parse given plugin and return struct
pub fn parse_plugin_file(name: &str) -> Result<Plugin, toml_error> {
change_work_dir(&utils::env::get_nyx_env_var());
let file_path: &str = &format!("plugins/{name}.toml");
let file =
std::fs::read_to_string(file_path).expect("Failed to read the plugin file to string");
let plugin: Plugin = match toml::from_str(&file) {
Ok(p) => p,
Err(e) => {
println!("Failed to parse the configuration file: {e:?}");
return Err(e);
}
};
Ok(plugin)
}
24 changes: 12 additions & 12 deletions src/projects/list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::utils::get_select_project_option;
use crate::utils::log;
use lrncore::usage_exit::command_usage;
use std::env;
use std::env::current_dir;
use std::process::exit;
use tabled::settings::Style;
use tabled::Table;
Expand Down Expand Up @@ -55,13 +56,14 @@ pub fn list_projects() {
pub fn add_existing_project_to_list() {
inquire::set_global_render_config(utils::get_render_config());
let ans = get_select_project_option("Which tech your project is using ?");
let path = current_dir().expect("Failed to get pwd");
match ans {
Ok(choice) => create_repo_or_not(&choice),
Ok(choice) => create_repo_or_not(&choice, path.as_os_str().to_str().expect("Failed to cast pathbuf to os_str to str")),
Err(_) => println!("There was an error, please try again"),
}
}

pub fn create_repo_or_not(tech: &str) {
pub fn create_repo_or_not(tech: &str, path: &str) {
inquire::set_global_render_config(utils::get_render_config());
let choice: Vec<&str> = vec!["Yes", "No"];
let options = utils::get_select_option(
Expand All @@ -70,17 +72,16 @@ pub fn create_repo_or_not(tech: &str) {
)
.unwrap();
match options.as_str() {
"Yes" => create_repo_add_to_list(tech),
"No" => add_project_to_list(tech),
"Yes" => create_repo_add_to_list(tech, path),
"No" => add_project_to_list(tech, path),
_ => {
println!("There was an error, please try again")
}
}
}

pub fn add_project_to_list(tech: &str) {
let current_dir = lrncore::path::get_current_path();
let app_name = current_dir.split("/").last().unwrap().to_lowercase();
pub fn add_project_to_list(tech: &str, path: &str) {
let app_name = path.split("/").last().unwrap().to_lowercase();
let mut repository_user_input: String;
repository_user_input = utils::prompt_message(
"Enter the url of the github's repository of the project: ",
Expand Down Expand Up @@ -115,17 +116,16 @@ pub fn add_project_to_list(tech: &str) {
let new_app: nxp::NXPContent = nxp::NXPContent {
name: (app_name.to_owned()),
tech: (tech.to_owned()),
location: (current_dir),
location: (path.to_owned()),
repository: repository_user_input,
github_project,
version,
};
nxp::create_new_nxp(new_app);
}

fn create_repo_add_to_list(tech: &str) {
let current_dir = lrncore::path::get_current_path();
let app_name = current_dir.split("/").last().unwrap();
fn create_repo_add_to_list(tech: &str, path: &str) {
let app_name = path.split("/").last().unwrap();
let choice = vec!["public", "private", "internal"];
let repository_visibility: String =
utils::get_select_option("Select the repository visibility:", choice).unwrap();
Expand Down Expand Up @@ -164,7 +164,7 @@ fn create_repo_add_to_list(tech: &str) {
let new_app: NXPContent = NXPContent {
name: (app_name.to_owned()),
tech: (tech.to_owned()),
location: (current_dir),
location: (path.to_owned()),
repository,
github_project,
version,
Expand Down
Loading