setup template project better

This commit is contained in:
Joe 2026-02-02 12:52:28 -06:00
parent 1bf32f0920
commit 10c73c60ea
12 changed files with 172 additions and 90 deletions

View file

@ -0,0 +1,7 @@
{
"languageMode": "strict",
"lint": { "*": true, "LocalUnused": false },
"lintErrors": false,
"typeErrors": true,
"globals": []
}

View file

@ -0,0 +1,7 @@
{
"recommendations": [
"evaera.vscode-rojo",
"johnnymorganz.stylua",
"johnnymorganz.luau-lsp"
]
}

View file

@ -0,0 +1,32 @@
{
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.rulers": [
80
],
"files.eol": "\n",
"files.encoding": "utf8",
"files.autoGuessEncoding": false,
"luau-lsp.plugin.maximumRequestBodySize": "500mb",
"luau-lsp.plugin.enabled": true,
"luau-lsp.completion.autocompleteEnd": true,
"luau-lsp.completion.imports.enabled": true,
"luau-lsp.completion.imports.separateGroupsWithLine": true,
"luau-lsp.completion.showPropertiesOnMethodCall": true,
"luau-lsp.hover.multilineFunctionDefinitions": true,
"luau-lsp.hover.showTableKinds": true,
"luau-lsp.inlayHints.makeInsertable": false,
"luau-lsp.inlayHints.hideHintsForMatchingParameterNames": false,
"luau-lsp.sourcemap.autogenerate": true,
"luau-lsp.sourcemap.includeNonScripts": true,
"luau-lsp.diagnostics.strictDatamodelTypes": true,
"luau-lsp.completion.imports.requireStyle": "alwaysAbsolute",
"luau-lsp.fflags.enableNewSolver": false,
"[luau]": {
"editor.defaultFormatter": "JohnnyMorganz.stylua"
},
"stylua.targetReleaseVersion": "latest",
"git.ignoreLimitWarning": true,
}

View file

@ -1,17 +1,10 @@
# {project_name}
Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}.
## Getting Started
To build the place from scratch, use:
Generated by [Atlas](https://github.com/UserGeneratedLLC/rojo).
```bash
rojo build -o "{project_name}.rbxlx"
```
Next, open `{project_name}.rbxlx` in Roblox Studio and start the Rojo server:
## Commands
```bash
rojo serve
rojo syncback
```
For more help, check out [the Rojo documentation](https://rojo.space/docs).

View file

@ -1,72 +1,9 @@
{
"name": "{project_name}",
"tree": {
"$className": "DataModel",
"ReplicatedStorage": {
"Shared": {
"$path": "src/shared"
}
},
"ServerScriptService": {
"Server": {
"$path": "src/server"
}
},
"StarterPlayer": {
"StarterPlayerScripts": {
"Client": {
"$path": "src/client"
}
}
},
"Workspace": {
"$properties": {
"FilteringEnabled": true
},
"Baseplate": {
"$className": "Part",
"$properties": {
"Anchored": true,
"Color": [
0.38823,
0.37254,
0.38823
],
"Locked": true,
"Position": [
0,
-10,
0
],
"Size": [
512,
20,
512
]
}
}
},
"Lighting": {
"$properties": {
"Ambient": [
0,
0,
0
],
"Brightness": 2,
"GlobalShadows": true,
"Outlines": false,
"Technology": "Voxel"
}
},
"SoundService": {
"$properties": {
"RespectFilteringEnabled": true
}
}
name: "{project_name}",
servePlaceIds: [{place_id}],
syncScriptsOnly: true,
tree: {
$className: "DataModel",
$path: "src"
}
}

View file

@ -1,8 +1,10 @@
# Project place file
/{project_name}.rbxlx
/*.rbxlx
/*.rbxl
# Roblox Studio lock files
/*.rbxlx.lock
/*.rbxl.lock
sourcemap.json
# Sourcemap
/sourcemap.json

View file

@ -1 +0,0 @@
print("Hello world, from client!")

View file

@ -1 +0,0 @@
print("Hello world, from server!")

View file

@ -1,3 +0,0 @@
return function()
print("Hello, world!")
end

View file

@ -0,0 +1,12 @@
syntax = "Luau"
column_width = 80
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
collapse_simple_statement = "FunctionOnly"
space_after_function_names = "Never"
[sort_requires]
enabled = true

View file

@ -28,7 +28,7 @@ static TEMPLATE_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/templ
#[derive(Debug, Parser)]
pub struct InitCommand {
/// Path to the place to create the project. Defaults to the current directory.
#[clap(default_value = "")]
#[clap(long, default_value = ".")]
pub path: PathBuf,
/// The kind of project to create, 'place', 'plugin', or 'model'.
@ -38,6 +38,13 @@ pub struct InitCommand {
/// Skips the initialization of a git repository.
#[clap(long)]
pub skip_git: bool,
/// Place ID to use for servePlaceIds.
pub placeid: Option<u64>,
/// Skip cloning cursor rules into .cursor directory.
#[clap(long)]
pub skip_rules: bool,
}
impl InitCommand {
@ -45,6 +52,18 @@ impl InitCommand {
let template = self.kind.template();
let base_path = resolve_path(&self.path);
// Check if directory exists and is non-empty
if base_path.exists() {
let is_empty = base_path.read_dir()?.next().is_none();
if !is_empty {
bail!(
"Directory '{}' is not empty. Please use an empty directory.",
base_path.display()
);
}
}
fs::create_dir_all(&base_path)?;
let canonical = fs::canonicalize(&base_path)?;
@ -55,6 +74,7 @@ impl InitCommand {
let project_params = ProjectParams {
name: project_name.to_owned(),
place_id: self.placeid,
};
println!(
@ -95,7 +115,7 @@ impl InitCommand {
}
}
if !self.skip_git && should_git_init(&base_path) {
let did_git_init = if !self.skip_git && should_git_init(&base_path) {
log::debug!("Initializing Git repository...");
let status = Command::new("git")
@ -106,6 +126,76 @@ impl InitCommand {
if !status.success() {
bail!("git init failed: status code {:?}", status.code());
}
true
} else {
!self.skip_git
};
if !self.skip_rules {
if did_git_init {
log::debug!("Adding cursor rules as submodule...");
let result = Command::new("git")
.args([
"submodule",
"add",
"https://github.com/jrmelsha/cursor-rules.git",
".cursor",
])
.current_dir(&base_path)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
match result {
Ok(status) if status.success() => {
println!("Added cursor rules as submodule.");
}
_ => {
log::debug!("Failed to add cursor rules submodule, skipping.");
}
}
} else {
log::debug!("Cloning cursor rules (no git repo)...");
let result = Command::new("git")
.args([
"clone",
"https://github.com/jrmelsha/cursor-rules.git",
".cursor",
])
.current_dir(&base_path)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
match result {
Ok(status) if status.success() => {
println!("Cloned cursor rules successfully.");
}
_ => {
log::debug!("Failed to clone cursor rules, skipping.");
}
}
}
}
if did_git_init {
log::debug!("Committing initial project...");
let _ = Command::new("git")
.args(["add", "."])
.current_dir(&base_path)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
let _ = Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(&base_path)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
}
println!("Created project successfully.");
@ -172,14 +262,21 @@ impl FromStr for InitKind {
/// Contains parameters used in templates to create a project.
struct ProjectParams {
name: String,
place_id: Option<u64>,
}
impl ProjectParams {
/// Render a template by replacing variables with project parameters.
fn render_template(&self, template: &str) -> String {
let place_id_str = self
.place_id
.map(|id| id.to_string())
.unwrap_or_else(|| "0".to_string());
template
.replace("{project_name}", &self.name)
.replace("{rojo_version}", env!("CARGO_PKG_VERSION"))
.replace("{place_id}", &place_id_str)
}
}