This repository has no description
1use anyhow::anyhow;
2use cargo::{
3 core::{dependency::DepKind, EitherManifest, Package, SourceId, Workspace},
4 ops::{
5 self,
6 cargo_add::{self, AddOptions, DepOp},
7 NewOptions, VersionControl,
8 },
9 util::{
10 context::GlobalContext, toml::read_manifest, toml_mut::manifest::DepTable,
11 },
12};
13use std::{env, fs, path::Path};
14
15use crate::cli::run;
16
17pub fn new_project(name: String) -> anyhow::Result<()> {
18 let cargoctx = GlobalContext::default()?;
19 let package_path = Path::new(&env::current_dir()?).join(&name);
20 println!("Creating project at {:?}", package_path);
21
22 // Create a bin crate with the name of the directory
23 ops::new(
24 &NewOptions {
25 version_control: Some(VersionControl::NoVcs),
26 kind: ops::NewProjectKind::Bin,
27 auto_detect_kind: false,
28 path: package_path.clone(),
29 name: None,
30 edition: None,
31 registry: None,
32 },
33 &cargoctx,
34 )?;
35
36 println!("Reading manifest");
37
38 let manifest = read_manifest(
39 &package_path.clone().join("Cargo.toml"),
40 SourceId::crates_io(&cargoctx)?,
41 &cargoctx,
42 )?;
43
44 let manifest = match manifest {
45 EitherManifest::Real(manifest) => manifest,
46 EitherManifest::Virtual(_) => {
47 return Err(anyhow!("Virtual manifests not supported, run the command outside of a workspace, or create your project manually with cargo new <name> && cd <name> && cargo add shapemaker && cargo add rand"))
48 }
49 };
50
51 println!("Adding dependencies to Cargo.toml");
52
53 let workspace = Workspace::new(&package_path.join("Cargo.toml"), &cargoctx)?;
54 // Add deps
55 cargo_add::add(
56 &workspace,
57 &AddOptions {
58 dry_run: false,
59 honor_rust_version: None,
60 gctx: &cargoctx,
61 spec: &Package::new(manifest, &package_path.join("Cargo.toml")),
62 dependencies: vec![
63 DepOp {
64 crate_spec: Some("shapemaker".to_string()),
65 rename: None,
66 features: None,
67 default_features: Some(true),
68 optional: Some(false),
69 public: None,
70 registry: None,
71 path: None,
72 base: None,
73 git: Some(
74 "https://github.com/gwennlbh/shapemaker".to_string(),
75 ),
76 branch: None,
77 rev: None,
78 tag: match env::var("CARGO_PKG_VERSION") {
79 Ok(version) => Some(format!("v{version}")),
80 Err(_) => None,
81 },
82 },
83 DepOp {
84 crate_spec: Some("rand".to_string()),
85 rename: None,
86 features: None,
87 default_features: Some(true),
88 optional: Some(false),
89 public: None,
90 registry: None,
91 path: None,
92 base: None,
93 git: None,
94 branch: None,
95 rev: None,
96 tag: None,
97 },
98 ],
99 section: DepTable::new().set_kind(DepKind::Normal),
100 },
101 )?;
102
103 println!("Writing main.rs");
104
105 // Write template main.rs
106 fs::write(
107 package_path.join("src/main.rs"),
108 format!(
109 "
110use shapemaker::*;
111use rand;
112
113pub fn main() {{
114 let mut canvas = Canvas::new(vec![]);
115
116 // Make your canvas beautiful <3
117
118 canvas.render_to_png(\"{}.png\", 2000).unwrap();
119}}",
120 name
121 )
122 .trim(),
123 )?;
124
125 run::run_project(&package_path)?;
126
127 std::env::set_current_dir(&package_path)?;
128
129 std::process::Command::new(
130 std::env::var("SHAPEMAKER_EDITOR").unwrap_or_else(|_| {
131 std::env::var("EDITOR").unwrap_or_else(|_| "code".to_string())
132 }),
133 )
134 .arg(".")
135 .spawn()?;
136
137 return Ok(());
138}