Skip to content

Commit

Permalink
close #75
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Pennebaker committed Apr 10, 2023
1 parent 74be985 commit 8e59587
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 22 deletions.
63 changes: 63 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Most text files
[*]
charset = utf-8
max_line_length = none
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4 # bash8

# Machine-generated files
[*.{scpt,plist,dot,db}]
trim_trailing_whitespace = false
insert_final_newline = none
indent_size = none

# Freeform text
[*.{txt,md,cob,emacs,el,lisp,lsp,scm,setup,meta,clj,rkt,ecl,sbcl,abcl,eclrc,sbclrc,asd,snusp}]
indent_size = none

# Fix cmake
[CMakeLists.txt]
indent_size = 4 # bash8

# Align keys
[*.{yaml,yml,reek,.yamllint}]
indent_size = 2

# Placeholder files
[*.{gitkeep,__init__.py}]
insert_final_newline = none

#
# Windows junk
#
[*.{cmd,bat,reg,ps1,vbs,cs,fs,fsx,ahk,psenvrc}]
end_of_line = crlf
insert_final_newline = false
[settings.json]
end_of_line = crlf
insert_final_newline = false

# Lexer restrictions
[{makefile,Makefile,GNUmakefile,BSDmakefile}]
indent_style = tab
[*.{makefile,Makefile,mk,GNUmakefile,BSDmakefile,go,gitmodules}]
indent_style = tab

# Natural HTML nesting
[*.js]
quote_type = single

# Compressed artifacts
[*.min.*]
insert_final_newline = false
[*-min.*]
insert_final_newline = false

# Potential mixed indentations
[*.patch]
trim_trailing_whitespace = false
indent_style = none
indent_size = none
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@

Work in progress

# ABOUT

`unmake` is a makefile linter that promotes extreme portability.

Too many makefiles online are restricted to building only as Works On My Machine^TM.

`unmake` bucks this trend, encouraging the makefile author to think more critically about what level of platform support they want for their software builds.

Do you want to be able to build your software on macOS? On Linux? On FreeBSD? On Windows (Command Prompt, PowerShell, *and/or* WSL)? On `fish` terminals?

All of the above?

`unmake` can help to catch vendor-lock issues earlier in the SDLC process. So that your apps can build more reliably, for more contributors to enjoy.

# EXAMPLES

```console
Expand Down Expand Up @@ -56,6 +70,31 @@ The `unmake` linter serves several purposes.

`make` is a natural candidate for working around limitations in provisioning scripts. For example, `go mod` / `cargo` do not track linters or other dev dependencies, and `sh` defaults to ignoring errors during provisioning. `make`'s default semantics prepare it well for provisioning and other activities. `make` can do many things! `unmake` helps it do them better.

# PARSING

`unmake` follows a stiff reading of the POSIX `make` standard:

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html

Briefly, characters in `makefiles` that are explicitly rejected by the standard, may be treated as parse errors. Implementation-defined behavior, undefined behavior, and certain ill-advised syntax, may be treated as parse errors.

Common examples of `makefile` syntax that

* Vintage macOS CR (`\r`) and Windows CRLF (`\r\n`) line endings are out of spec. If you have a need to contribute to projects with makefiles from a Windows machine, configure your text editor to use LF (`\n`) line endings (and a final LF as well).
* Spaces (` `) en lieu of hard tabs (`\t`) at the beginning of rule commands, are out of spec.
* Whitespace in the middle of a backslash escaped line feed sequence (`\\ \n`) is out of spec.
* makefiles that end on a cliffhanger backslash escaped line feed sequence with no accompanying followup line in the same file (`\\\n<eof>`), are out of spec.
* Macro assignments with no identifier (e.g., `=1`) are out of spec.
* Plain leftover macro identifiers with no assignment (e.g., `A`) are out of spec.
* Include paths with double-quotes (`"`) are out of spec.
* Backslash escaped line feed sequences in include lines (`include`...`\\\n`) are out of spec.

Certain extensions beyond the POSIX `make` subset, such as GNU-isms, or BSD-isms, etc., may also trigger parse errors. Repeat: This is a linter focusing on

# LINTER WARNINGS

Coming soon.

# CAVEATS

We do our best to catch POSIX make violations, but some may slip by. For example:
Expand Down
2 changes: 2 additions & 0 deletions examples/crlf/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
all:
@echo "Hello World!"
28 changes: 6 additions & 22 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ parser! {
rule eof() = ![_]

rule line_ending() -> String =
s:$("\r\n" / "\n") {
s:$("\n") {
s.to_string()
}

Expand Down Expand Up @@ -362,17 +362,12 @@ fn test_isolated_comment_lines() {
ns: Vec::new()
})
);
assert_eq!(
parse_posix("\r\n"),
Ok(Mk {
o: 0,
l: 1,
ns: Vec::new()
})
);

assert!(parse_posix("\r").is_err());
assert!(parse_posix("\r\n").is_err());
assert!(parse_posix("\r\n\r\n").is_err());

assert_eq!(parse_posix("\n\n").unwrap().ns, Vec::new());
assert_eq!(parse_posix("\r\n\r\n").unwrap().ns, Vec::new());
assert_eq!(parse_posix("#\n").unwrap().ns, Vec::new());
assert_eq!(parse_posix("#").unwrap().ns, Vec::new());
assert_eq!(parse_posix("# alphabet\n").unwrap().ns, Vec::new());
Expand Down Expand Up @@ -592,18 +587,7 @@ fn test_parse_macros() {
}]
);

assert_eq!(
parse_posix("A=1\r\n")
.unwrap()
.ns
.into_iter()
.map(|e| e.n)
.collect::<Vec<Ore>>(),
vec![Ore::Mc {
n: "A".to_string(),
v: "1".to_string(),
}]
);
assert!(parse_posix("A=1\r\n").is_err());

assert_eq!(
parse_posix("A=1\n\n")
Expand Down

0 comments on commit 8e59587

Please sign in to comment.