diff --git a/justfile b/justfile index 67dd6e1..564b979 100644 --- a/justfile +++ b/justfile @@ -7,12 +7,21 @@ test-quine: backtrace: RUST_BACKTRACE=1 cargo test --lib -publish: +publish: clippy # make sure version is up to date grep 'version("'`sed -En 's/version = "([^"]+)"/\1/p' Cargo.toml`'")' src/app.rs - git push github master + git push github master:master cargo publish +clippy: + rustup run nightly cargo clippy + +install-clippy: + rustup run nightly cargo install clippy + +install-nightly: + rustup install nightly + # make a quine, compile it, and verify it quine: create cc tmp/gen0.c -o tmp/gen0 diff --git a/notes b/notes index b81e134..4a95877 100644 --- a/notes +++ b/notes @@ -9,16 +9,20 @@ notes although maybe only after a '--': j build -- a=hello - parse lines into {{fragments}} and allow argument substitution - change error messages to underline problem token -- should i use // comments, since that's what's used in rust? - allow calling recipes in a justfile in a different directory: - just ../foo # ../justfile:foo - just xyz/foo # xyz/justfile:foo - just xyz/ # xyz/justfile:DEFAULT + - this is going to be hard. should a single recipe with a slash + require that all recipes have slashes? + or should non-slash recipes still run in this directory? + will need to change things a great deal - assignment . export environment variables . no barewords - indentation is line continuation - static errors when variables are missing {{}}, even if recipe isn't run +- write some tests to test the binary itself and all command line flags - change name back to 'just' . suggest j as alias @@ -58,8 +62,3 @@ later: may be nice to allow all recipes in a given langauge to share functions, variables, etc. could have a "prelude" recipe which was included as a prefix to other recipes -- windows support: currently calling 'sh', which won't work on windows - the answer will probably be to write a 'sh' clone and to only - call binaries from cargo -- run recipes asyncronously -- lint with clippy once it runs on stable diff --git a/src/lib.rs b/src/lib.rs index d08b010..9d65679 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,7 +72,7 @@ enum Fragment<'a> { */ #[cfg(unix)] -fn error_from_signal<'a>(recipe: &'a str, exit_status: process::ExitStatus) -> RunError<'a> { +fn error_from_signal(recipe: &str, exit_status: process::ExitStatus) -> RunError { use std::os::unix::process::ExitStatusExt; match exit_status.signal() { Some(signal) => RunError::Signal{recipe: recipe, signal: signal}, @@ -81,7 +81,7 @@ fn error_from_signal<'a>(recipe: &'a str, exit_status: process::ExitStatus) -> R } #[cfg(windows)] -fn error_from_signal<'a>(recipe: &'a str, exit_status: process::ExitStatus) -> RunError<'a> { +fn error_from_signal(recipe: &str, exit_status: process::ExitStatus) -> RunError { RunError::UnknownFailure{recipe: recipe} } @@ -147,7 +147,7 @@ impl<'a> Recipe<'a> { } else { for command in &self.lines { let mut command = *command; - if !command.starts_with("@") { + if !command.starts_with('@') { warn!("{}", command); } else { command = &command[1..]; @@ -369,7 +369,7 @@ struct Justfile<'a> { impl<'a> Justfile<'a> { fn first(&self) -> Option<&'a str> { let mut first: Option<&Recipe<'a>> = None; - for (_, recipe) in self.recipes.iter() { + for recipe in self.recipes.values() { if let Some(first_recipe) = first { if recipe.line_number < first_recipe.line_number { first = Some(recipe) @@ -409,7 +409,7 @@ impl<'a> Justfile<'a> { missing.push(*recipe); } } - if missing.len() > 0 { + if !missing.is_empty() { return Err(RunError::UnknownRecipes{recipes: missing}); } let recipes = names.iter().map(|name| self.recipes.get(name).unwrap()).collect::>(); @@ -437,31 +437,31 @@ enum RunError<'a> { impl<'a> Display for RunError<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self { - &RunError::UnknownRecipes{ref recipes} => { + match *self { + RunError::UnknownRecipes{ref recipes} => { if recipes.len() == 1 { try!(write!(f, "Justfile does not contain recipe: {}", recipes[0])); } else { try!(write!(f, "Justfile does not contain recipes: {}", recipes.join(" "))); }; }, - &RunError::Code{recipe, code} => { + RunError::Code{recipe, code} => { try!(write!(f, "Recipe \"{}\" failed with code {}", recipe, code)); }, - &RunError::Signal{recipe, signal} => { + RunError::Signal{recipe, signal} => { try!(write!(f, "Recipe \"{}\" wast terminated by signal {}", recipe, signal)); } - &RunError::UnknownFailure{recipe} => { + RunError::UnknownFailure{recipe} => { try!(write!(f, "Recipe \"{}\" failed for an unknown reason", recipe)); }, - &RunError::IoError{recipe, ref io_error} => { + RunError::IoError{recipe, ref io_error} => { try!(match io_error.kind() { io::ErrorKind::NotFound => write!(f, "Recipe \"{}\" could not be run because j could not find `sh` the command:\n{}", recipe, io_error), io::ErrorKind::PermissionDenied => write!(f, "Recipe \"{}\" could not be run because j could not run `sh`:\n{}", recipe, io_error), _ => write!(f, "Recipe \"{}\" could not be run because of an IO error while launching the `sh`:\n{}", recipe, io_error), }); }, - &RunError::TmpdirIoError{recipe, ref io_error} => + RunError::TmpdirIoError{recipe, ref io_error} => try!(write!(f, "Recipe \"{}\" could not be run because of an IO error while trying to create a temporary directory or write a file to that directory`:\n{}", recipe, io_error)), } Ok(()) @@ -572,15 +572,12 @@ fn tokenize(text: &str) -> Result, Error> { if column == 0 { if let Some(class) = match (indent, indentation(rest)) { // ignore: was no indentation and there still isn't - (None, Some("")) => { - None - } - // ignore: current line is blank - (_, None) => { + // or current line is blank + (None, Some("")) | (_, None) => { None } // indent: was no indentation, now there is - (None, Some(current @ _)) => { + (None, Some(current)) => { if mixed_whitespace(current) { return error!(ErrorKind::MixedLeadingWhitespace{whitespace: current}) } @@ -688,7 +685,7 @@ fn tokenize(text: &str) -> Result, Error> { Ok(tokens) } -fn parse<'a>(text: &'a str) -> Result { +fn parse(text: &str) -> Result { let tokens = try!(tokenize(text)); let filtered: Vec<_> = tokens.into_iter().filter(|token| token.class != Comment).collect(); if let Some(token) = filtered.iter().find(|token| { @@ -790,11 +787,11 @@ impl<'a> Parser<'a> { if self.accepted(Indent) { while !self.peek(Dedent) { if let Some(line) = self.accept(Line) { - if lines.len() == 0 { + if lines.is_empty() { if line.lexeme.starts_with("#!") { shebang = true; } - } else if !shebang && (line.lexeme.starts_with(" ") || line.lexeme.starts_with("\t")) { + } else if !shebang && (line.lexeme.starts_with(' ') || line.lexeme.starts_with('\t')) { return Err(line.error(ErrorKind::ExtraLeadingWhitespace)); }