Repository: fornwall/rust-script (Rust)

Issue:
Main function recognition
## Description
If I add a space after the function identifier `main` rust-script will not use the function.  

## Example
- This example was taken from the example script in this repository's main readme.  
- The _only_ change was that I added a space between `main` and `()`:

```rust
#!/usr/bin/env rust-script
//! Dependencies can be specified in the script file itself as follows:
//!
//! ```cargo
//! [dependencies]
//! rand = "0.8.0"
//! ```

use rand::prelude::*;

fn main () {
    let x: u64 = random();
    println!("A random number: {}", x);
}

```

This can be seen this in the following compiler warnings:

```bash
» rust-script script2.rs
warning: unused doc comment
  --> script2.rs:3:5
   |
2  | /      {
3  | |      //! Dependencies can be specified in the script file itself as follows:
   | | _____^
4  | || //!
5  | || //! ```cargo
6  | || //! [dependencies]
7  | || //! rand = "0.8.0"
8  | || //! ```
   | ||_______^
...  |
15 | |  }
16 | |      }
   | |______- rustdoc does not generate documentation for expressions
   |
   = help: use `//` for a plain comment
   = note: `#[warn(unused_doc_comments)]` on by default

warning: function `main` is never used
  --> script2.rs:12:4
   |
12 | fn main () {
   |    ^^^^
   |
   = note: `#[warn(dead_code)]` on by default

```

## Why is this an issue?
In my case, I generate rust scripts externally using [`quote`](https://crates.io/crates/quote), which injects these errant spaces into the output TokenStream. 

As seen above, this is valid Rust code. I am opening this issue here because I assume it's relevant, but please let me know if I should close it and look somewhere else.

## Notes
If you feel this is worth changing, I can try to fix it and open a PR. I'm not sure where to look for this problem though, tbh.


Discussion:
@plasticartsshow Thanks! This should be fixed by https://github.com/fornwall/rust-script/pull/96, which is a part of the just released 0.25.0 version.

Let me know how it works!



Patch:
diff --git a/src/manifest.rs b/src/manifest.rs
index 46f1797..2c8a1aa 100644
--- a/src/manifest.rs
+++ b/src/manifest.rs
@@ -26,12 +26,9 @@ pub fn split_input(
     script_name: &str,
     toolchain: Option<String>,
 ) -> MainResult<(String, String)> {
-    fn contains_main_method(line: &str) -> bool {
-        let line = line.trim_start();
-        line.starts_with("fn main(")
-            || line.starts_with("pub fn main(")
-            || line.starts_with("async fn main(")
-            || line.starts_with("pub async fn main(")
+    fn contains_main_method(source: &str) -> bool {
+        let re_shebang: Regex = Regex::new(r"(?m)^ *(pub )?(async )?fn main *\(").unwrap();
+        re_shebang.is_match(source)
     }
 
     let (part_mani, source, template, sub_prelude) = match input {
@@ -41,7 +38,7 @@ pub fn split_input(
             let (manifest, source) =
                 find_embedded_manifest(content).unwrap_or((Manifest::Toml(""), content));
 
-            let source = if source.lines().any(contains_main_method) {
+            let source = if contains_main_method(source) {
                 source.to_string()
             } else {
                 format!("fn main() -> Result<(), Box<dyn std::error::Error+Sync+Send>> {{\n    {{\n    {}    }}\n    Ok(())\n}}", source)


Test patch:
diff --git a/tests/data/script-main-with-spaces.rs b/tests/data/script-main-with-spaces.rs
new file mode 100644
index 0000000..d18903b
--- /dev/null
+++ b/tests/data/script-main-with-spaces.rs
@@ -0,0 +1,4 @@
+fn main  () {
+    println!("--output--");
+    println!("Hello, World!");
+}
diff --git a/tests/tests/script.rs b/tests/tests/script.rs
index bdfa523..08ad4c2 100644
--- a/tests/tests/script.rs
+++ b/tests/tests/script.rs
@@ -34,6 +34,15 @@ fn test_script_full_line_without_main() {
     .unwrap()
 }
 
+#[test]
+fn test_script_main_with_space() {
+    let out = rust_script!("tests/data/script-main-with-spaces.rs").unwrap();
+    scan!(out.stdout_output();
+        ("Hello, World!") => ()
+    )
+    .unwrap()
+}
+
 #[test]
 fn test_script_invalid_doc_comment() {
     let out = rust_script!("tests/data/script-invalid-doc-comment.rs").unwrap();