Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big refactor and various improvements #39

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
71 changes: 14 additions & 57 deletions Cargo.lock

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

6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "lightmon"
version = "0.2.0"
version = "0.3.0"
authors = ["Reagan McFarland <me@reaganmcf.com>", "Alay Shah"]
description = "A lightweight, cross-platform, language-agnostic 'run code on file change' tool, inspired by Nodemon"
homepage = "https://github.com/reaganmcf/lightmon"
Expand All @@ -17,9 +17,7 @@ exclude = [
notify = "4.0.12"
clap = {version = "~2.27.0", features = ["yaml"]}
walkdir = "2"
log = "0.4.0"
env_logger = "0.8.3"
termcolor = "1.1.2"
colored = "2"
serde_json = "1.0"

[dev-dependencies]
Expand Down
45 changes: 11 additions & 34 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use clap::{App, AppSettings, ArgMatches};
use env_logger::Builder;
use log::LevelFilter;
use clap::{load_yaml, App, AppSettings, ArgMatches};
use serde_json::Value;
use std::fs::File;
use std::io::BufReader;
Expand All @@ -17,8 +15,8 @@ pub(crate) enum SupportedLanguage {
impl std::fmt::Display for SupportedLanguage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SupportedLanguage::Rust => write!(f, "rust"),
SupportedLanguage::Node => write!(f, "node"),
SupportedLanguage::Rust => write!(f, "🦀 Rust"),
SupportedLanguage::Node => write!(f, "Node.js"),
SupportedLanguage::Shell => write!(f, "shell"),
}
}
Expand All @@ -41,12 +39,6 @@ impl Cli {
.global_setting(AppSettings::AllowExternalSubcommands)
.get_matches();

if matches.is_present("verbose") {
Builder::new().filter_level(LevelFilter::Debug).init();
} else {
Builder::new().filter_level(LevelFilter::Info).init();
}

let config: Option<Cli> = match matches.subcommand() {
("rust", Some(sub_matcher)) => Some(Self::build_rust_config(Some(sub_matcher))),
("node", Some(_)) => Some(Self::build_node_config()),
Expand All @@ -56,7 +48,7 @@ impl Cli {
// again that a subcommand was passed in. This is because an unsupported lang would
// still match to this branch.
if matches.subcommand_name().is_some() {
error!(
eprintln!(
"{} is not supported. Consider using `lightmon shell` instead.",
matches.subcommand_name().unwrap()
);
Expand All @@ -74,7 +66,7 @@ impl Cli {
} else if Path::new("Cargo.toml").exists() {
Some(Self::build_rust_config(None))
} else {
error!("Unable to resolve configuration automatically. Consider using `lightmon shell` instead.");
eprintln!("Unable to resolve configuration automatically. Consider using `lightmon shell` instead.");
None
}
}
Expand All @@ -83,6 +75,7 @@ impl Cli {
if config.is_none() {
std::process::exit(1);
}

config.unwrap()
}

Expand All @@ -97,7 +90,6 @@ impl Cli {
// 1. The value at `scripts.start`
// 2. `node main` where `main` is the value of the `main` key in `package.json` (the entry point of the project).
fn build_node_config() -> Self {
debug!("Configuring for node mode...");
let watch_patterns: Vec<String> = vec![
"*.jsx".to_string(),
"*.js".to_string(),
Expand All @@ -113,23 +105,14 @@ impl Cli {

if values.is_object() {
if let Some(scripts) = values.get("scripts") {
debug!("scripts found! Value is = {}", scripts);
if let Some(scripts_start) = scripts.get("start") {
debug!(
"scripts.start found! Resolving exec_commands as '{}'",
scripts_start
);
exec_commands.push(scripts_start.as_str().unwrap().to_string());
}
}

// If scripts resolution failed, try getting main entry point
if exec_commands.is_empty() {
if let Some(main_entry_point) = values.get("main") {
debug!(
"main found! Resolving exec_commands as '{}'",
main_entry_point
);
// main_entry_point has a " on either end, so we need to trim
exec_commands.push(format!("node {}", main_entry_point.as_str().unwrap()));
}
Expand All @@ -139,7 +122,6 @@ impl Cli {

// exec commands resolution fallback
if exec_commands.is_empty() {
debug!("Failed to resolve exec command using package.json, falling back to 'node index.js'");
exec_commands.push("node index.js".to_string());
}

Expand Down Expand Up @@ -168,14 +150,12 @@ impl Cli {
// Will resolve the exec command to `cargo build --bin my_bin --all-targets`
fn build_rust_config(sub_matcher: Option<&ArgMatches>) -> Self {
let mut exec_commands: Vec<String> = Vec::new();
debug!("Configuring for rust mode...");

// attempt to match subcommand
if let Some(sub_matcher) = sub_matcher {
debug!("build_rust_config received subcommand override!");
if let (external_name, Some(external_args)) = sub_matcher.subcommand() {
if external_args.values_of("").is_some() {
let ext_args: Vec<&str> = external_args.values_of("").unwrap().collect();
debug!("External commands = {:?}", ext_args);
exec_commands.push(format!("cargo {} {}", external_name, ext_args.join(" ")));
} else {
exec_commands.push(format!("cargo {}", external_name));
Expand All @@ -185,13 +165,11 @@ impl Cli {
// Since no subcommand was given, resolve via project type
// 1. Check if src/main.rs exists
if Path::new("src/main.rs").exists() {
debug!("Cargo bin project detected");
exec_commands.push(format!("cargo {}", "run"));
} else if Path::new("src/lib.rs").exists() {
debug!("Cargo lib project detected");
exec_commands.push(format!("cargo {}", "test"));
} else {
error!("Could not find which type of rust project this is. Consider overriding using a cargo subcommand. Run `lightmon help rust` for more information.");
eprintln!("Could not find which type of rust project this is. Consider overriding using a cargo subcommand. Run `lightmon help rust` for more information.");
std::process::exit(1);
}
}
Expand All @@ -208,15 +186,14 @@ impl Cli {
fn build_shell_config(sub_matcher: &ArgMatches) -> Self {
let mut watch_patterns: Vec<String> = Vec::new();
let mut exec_commands: Vec<String> = Vec::new();
debug!("Configuring for shell mode...");
debug!("Script Path = {:?}", sub_matcher.value_of("script"));
debug!("Watch Pattern = {:?}", sub_matcher.value_of("watch"));

let split = sub_matcher.value_of("watch").unwrap().split(',');
for s in split {
watch_patterns.push(format!("*{}", s.to_string()));
}

exec_commands.push(format!("bash {}", sub_matcher.value_of("script").unwrap()));
debug!("{:?}", exec_commands);

Cli {
watch_patterns,
project_language: SupportedLanguage::Shell,
Expand Down
5 changes: 0 additions & 5 deletions src/cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ name: lightmon
version: "v0.2.0"
author: Reagan McFarland <me@reaganmcf.com>, Alay Shah
about: A light-weight, cross-platform, language agnostic \"run code on file change\" tool, inspired by Nodemon
args:
- verbose:
short: v
long: verbose
help: Use verbose output
subcommands:
- rust:
about: "Use rust preset for lightmon. Lightmon will detect the type of rust project you are working in automatically.\n Note: if you want to use a custom cargo command, you can provide the subcommand and any arguments and the exec command will get resolved accordingly."
Expand Down
58 changes: 26 additions & 32 deletions src/exec.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// Contains the method for starting a thread that will run the exec commands in parallel.

use std::process::Command;
use std::sync::mpsc::Sender;
use std::sync::Arc;
use std::thread;
use std::{io, process::Child};
use colored::*;
use std::sync::{mpsc::Sender, Arc};
use std::{
io,
process::{Child, Command},
thread,
};

use crate::cli::Cli;
use crate::LightmonEvent;
Expand All @@ -18,8 +20,6 @@ pub(crate) fn start(
exec_child_process_sender: Sender<Child>,
) -> std::thread::JoinHandle<()> {
thread::spawn(move || {
debug!("thread started");

// Build commands from exec commands
for exec_command in &cli_args.exec_commands {
// split into components
Expand All @@ -28,32 +28,26 @@ pub(crate) fn start(
for argument in split.iter().skip(1) {
cmd.arg(argument);
}
debug!("final cmd = {:?}", cmd);
let child = cmd.spawn().unwrap();
debug!("child process pid = {:?}", child.id());
match exec_child_process_sender.send(child) {
Ok(_) => {}
Err(_) => {
error!("Unable to send event to main loop. Something seriously went wrong!");
std::process::exit(1);
}
}

println!(
"{}",
format!(
"[lightmon] starting `{}`",
&cli_args.exec_commands.join(" ")
)
.green()
);

let child = cmd.spawn().expect("Unable to spawn process");

exec_child_process_sender
.send(child)
.expect("Unable to send event to main loop. Something seriously went wrong!");

let mut input = String::new();
loop {
let mut input = String::new();
if let Ok(n) = io::stdin().read_line(&mut input) {
if input.eq("rs\n") {
debug!("rs RECEIEVED");
match lightmon_event_sender.send(LightmonEvent::KillAndRestartChild) {
Ok(_) => {}
Err(_) => {
error!("Unable to kill and restart the process. Something seriously went wrong!");
std::process::exit(1);
}
}
} else {
debug!("unknown input, bits read from input {:?}", n);
debug!("input = {:?}", input);
}
if io::stdin().read_line(&mut input).is_ok() && input.eq("rs\n") {
lightmon_event_sender.send(LightmonEvent::KillAndRestartChild).expect("Unable to kill and restart the process. Something seriously went wrong!");
}
}
}
Expand Down
Loading