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

Add shebang support for "cargo script" #15318

Open
victor-timofei opened this issue Jul 20, 2023 · 4 comments
Open

Add shebang support for "cargo script" #15318

victor-timofei opened this issue Jul 20, 2023 · 4 comments
Labels
A-cargo cargo related issues A-project-model project model and workspace related issues B-unstable unstable feature C-feature Category: feature request

Comments

@victor-timofei
Copy link

Add an initial shebang support for "cargo script".

Cargo script is an experimental feature for single-file packages described in eRFC-3424.

The initial support would require to recognize and parse the shebang and handle the entire file as a single-file package.

Parsing the manifest would be out of the scope for the moment since it hasn't been stabilized yet. So there would not be support for external packages from crates.io at the moment.

As an extra this initial support could be be beneficial also for other third party alternatives.

I am willing to help with this feature.

Cargo script tracking issue here.

Relates to: #9609

cc: @epage

@victor-timofei victor-timofei added the C-feature Category: feature request label Jul 20, 2023
@epage
Copy link

epage commented Jul 20, 2023

I think a little more generalized title / description is that rust-analyzer should recognize that a .rs file might also be the manifest path and not look for a Cargo.toml. Whether we use #! detection is one possible solution.

The big question is how. This was somewhat talked about during the Pre-RFC (summary, discussion).

While this is just at an eRFC phase, the cargo team is fairly positive about moving this forward towards stabilzation. I think collaboration between the cargo team and the rust-analyzer teams on how to recognize these files would be fit within the experiment and would be good preparation for stabilization discussions.

As was mentioned, edit capabilities for the inline manifest is out of scope for this issue as we haven't finalized the format yet. I'm assuming there wouldn't be enough learned by supporting it for us to do throwaway work for the current manifest syntax.

As for any other potential editor features that can be triggered for "cargo script" (and I assume be handled in subsequent issues), Some quick thoughts

  • Add #! and/or skeleton manifest
  • Depending on how configurable we make lockfile behavior, toggling that
  • Expanding to a multi-file package (we have talked about supporting this for cargo new but haven't defined the CLI for it yet)

@lowr lowr added A-cargo cargo related issues B-unstable unstable feature A-project-model project model and workspace related issues labels Jul 21, 2023
@gwpl
Copy link

gwpl commented Jul 26, 2023

Thanks for linking #9609 (comment) of compatibility with https://rust-script.org/ to this issue!

Yes, two issues are definitely related, and probably possible to be taken care off together at once.

Also I believe that operating on standalone Rust files, will help with LLM support (OpenAI GPT-4, LLaMA 2, Starcoder...) , ultimately helping rust adoption in organizations/projects... - if interested, cross linking related thread: https://community.openai.com/t/how-to-generate-modify-rust-scripts-sourcecode-with-openai-api/267190

@Veykril
Copy link
Member

Veykril commented Jul 30, 2023

Implementing this requires #14318

@NightMachinery
Copy link

NightMachinery commented Oct 29, 2023

I am currently using https://github.com/igor-petruk/scriptisto for creating Rust scripts, which works great, but first-party support would be better.

Here is an example script that I created today using GPT4:

#!/usr/bin/env scriptisto

// scriptisto-begin
// script_src: src/main.rs
// build_cmd: cargo build --release
// target_bin: ./target/release/script
// files:
//  - path: Cargo.toml
//    content: |
//     package = { name = "script", version = "0.1.0", edition = "2018"}
//     [dependencies]
//     walkdir = "2"
//     regex = "1"
//     clap = "2"
// scriptisto-end

use std::env;
use std::path::Path;
use walkdir::WalkDir;
use regex::Regex;
use clap::{App, Arg};

fn main() {
    // Set up CLI arguments using clap.
    let matches = App::new("Reminday script")
        .arg(
            Arg::with_name("end-pattern")
                .long("end-pattern")
                .takes_value(true)
                .help("Specifies the file end pattern."),
        )
        .get_matches();
    // Retrieve the --end-pattern CLI argument or use the default pattern.
    let end_pattern = matches.value_of("end-pattern").unwrap_or(r"\.(md|org|txt|zsh)");

    // Retrieve the remindayRootDir environment variable.
    let reminday_root_dir = env::var("remindayRootDir").expect("remindayRootDir is not set!");

    // Retrieve the directories to exclude from environment variables.
    let reminday_bak_c_dir = env::var("remindayBakCDir").expect("remindayBakCDir is not set!");
    let reminday_bak_dir = env::var("remindayBakDir").expect("remindayBakDir is not set!");

    // Retrieve today's date from the environment variable `datej`.
    let today = env::var("datej").expect("datej is not set!");
    let date_regex = Regex::new(r"(\d+)/(\d+)/(\d+)").unwrap();
    let caps = date_regex.captures(&today).unwrap();
    let year: i32 = caps[1].parse().unwrap();
    let month: i32 = caps[2].parse().unwrap();
    let day: i32 = caps[3].parse().unwrap();

    let file_regex_str = format!(r"/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)[^/]*{}", end_pattern);
    let file_regex = Regex::new(&file_regex_str).unwrap();

    for entry in WalkDir::new(reminday_root_dir).into_iter().filter_map(|e| e.ok()) {
        let path_str = entry.path().to_str().unwrap();

        if path_str.starts_with(&reminday_bak_c_dir) || path_str.starts_with(&reminday_bak_dir) {
            continue;  // Skip the excluded directories
        }

        if let Some(caps) = file_regex.captures(path_str) {
            let file_year: i32 = caps["year"].parse().unwrap();
            let file_month: i32 = caps["month"].parse().unwrap();
            let file_day: i32 = caps["day"].parse().unwrap();

            if file_year < year
                || (file_year == year && file_month < month)
                || (file_year == year && file_month == month && file_day < day) {
                println!("{}", path_str);
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cargo cargo related issues A-project-model project model and workspace related issues B-unstable unstable feature C-feature Category: feature request
Projects
None yet
Development

No branches or pull requests

6 participants