mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-20 12:45:05 +00:00
Add brand new rojo init command
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
## Unreleased Changes for 0.6.x
|
||||
* Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284))
|
||||
* Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241))
|
||||
* Added a revamped `rojo init` command, which will now create more complete projects.
|
||||
* Added the `rojo doc` command, which opens Rojo's documentation in your browser.
|
||||
* Simplified filesystem access code dramatically.
|
||||
* Improved error reporting and logging across the board.
|
||||
|
||||
5
assets/default-model.lua
Normal file
5
assets/default-model.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
return {
|
||||
hello = function()
|
||||
print("Hello world, from {project_name}!")
|
||||
end,
|
||||
}
|
||||
6
assets/model.project.json
Normal file
6
assets/model.project.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "{project_name}",
|
||||
"tree": {
|
||||
"$path": "src"
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,36 @@
|
||||
{
|
||||
"name": "[placeholder]",
|
||||
"name": "{project_name}",
|
||||
"tree": {
|
||||
"$className": "DataModel",
|
||||
"HttpService": {
|
||||
"$className": "HttpService",
|
||||
"$properties": {
|
||||
"HttpEnabled": true
|
||||
}
|
||||
},
|
||||
"Lighting": {
|
||||
"$className": "Lighting",
|
||||
"$properties": {
|
||||
"Ambient": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"Brightness": 2,
|
||||
"GlobalShadows": true,
|
||||
"Outlines": false,
|
||||
"Technology": "Voxel"
|
||||
}
|
||||
},
|
||||
|
||||
"ReplicatedStorage": {
|
||||
"$className": "ReplicatedStorage",
|
||||
"Source": {
|
||||
"$path": "src"
|
||||
|
||||
"Common": {
|
||||
"$path": "src/common"
|
||||
}
|
||||
},
|
||||
"SoundService": {
|
||||
"$className": "SoundService",
|
||||
"$properties": {
|
||||
"RespectFilteringEnabled": true
|
||||
|
||||
"ServerScriptService": {
|
||||
"$className": "ServerScriptService",
|
||||
|
||||
"Server": {
|
||||
"$path": "src/server"
|
||||
}
|
||||
},
|
||||
|
||||
"StarterPlayer": {
|
||||
"$className": "StarterPlayer",
|
||||
|
||||
"StarterPlayerScripts": {
|
||||
"$className": "StarterPlayerScripts",
|
||||
|
||||
"Client": {
|
||||
"$path": "src/client"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"Workspace": {
|
||||
"$className": "Workspace",
|
||||
"$properties": {
|
||||
@@ -61,6 +58,32 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Lighting": {
|
||||
"$className": "Lighting",
|
||||
"$properties": {
|
||||
"Ambient": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"Brightness": 2,
|
||||
"GlobalShadows": true,
|
||||
"Outlines": false,
|
||||
"Technology": "Voxel"
|
||||
}
|
||||
},
|
||||
"SoundService": {
|
||||
"$className": "SoundService",
|
||||
"$properties": {
|
||||
"RespectFilteringEnabled": true
|
||||
}
|
||||
},
|
||||
"HttpService": {
|
||||
"$className": "HttpService",
|
||||
"$properties": {
|
||||
"HttpEnabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
147
src/cli/init.rs
147
src/cli/init.rs
@@ -1,17 +1,156 @@
|
||||
use std::{
|
||||
fs::{self, OpenOptions},
|
||||
io::{self, Write},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use snafu::Snafu;
|
||||
|
||||
use crate::cli::InitCommand;
|
||||
use crate::cli::{InitCommand, InitKind};
|
||||
|
||||
static DEFAULT_PLACE_PROJECT: &str = include_str!("../../assets/place.project.json");
|
||||
|
||||
static DEFAULT_MODEL_PROJECT: &str = include_str!("../../assets/model.project.json");
|
||||
static DEFAULT_MODEL_INIT: &str = include_str!("../../assets/default-model.lua");
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
pub struct InitError(Error);
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
enum Error {}
|
||||
enum Error {
|
||||
#[snafu(display("A project file named default.project.json already exists in this folder"))]
|
||||
AlreadyExists,
|
||||
|
||||
#[snafu(display("I/O error"))]
|
||||
Io { source: io::Error },
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(source: io::Error) -> Self {
|
||||
Self::Io { source }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(options: InitCommand) -> Result<(), InitError> {
|
||||
Ok(init_inner(options)?)
|
||||
}
|
||||
|
||||
fn init_inner(_options: InitCommand) -> Result<(), Error> {
|
||||
unimplemented!("init command");
|
||||
fn init_inner(options: InitCommand) -> Result<(), Error> {
|
||||
let base_path = options.absolute_path();
|
||||
let canonical = fs::canonicalize(&base_path)?;
|
||||
let project_name = canonical
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.unwrap_or("new-project");
|
||||
|
||||
let project_params = ProjectParams {
|
||||
name: project_name.to_owned(),
|
||||
};
|
||||
|
||||
match options.kind {
|
||||
InitKind::Place => init_place(&base_path, project_params),
|
||||
InitKind::Model => init_model(&base_path, project_params),
|
||||
}
|
||||
}
|
||||
|
||||
fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> {
|
||||
let project_file = project_params.render_template(DEFAULT_PLACE_PROJECT);
|
||||
try_create_project(base_path, &project_file)?;
|
||||
|
||||
let src = base_path.join("src");
|
||||
fs::create_dir_all(&src)?;
|
||||
|
||||
let src_common = src.join("common");
|
||||
fs::create_dir_all(src.join(&src_common))?;
|
||||
|
||||
let src_server = src.join("server");
|
||||
fs::create_dir_all(src.join(&src_server))?;
|
||||
|
||||
let src_client = src.join("client");
|
||||
fs::create_dir_all(src.join(&src_client))?;
|
||||
|
||||
write_if_not_exists(
|
||||
&src_common.join("Hello.lua"),
|
||||
"return function()\n\tprint(\"Hello, world!\")\nend",
|
||||
)?;
|
||||
|
||||
write_if_not_exists(
|
||||
&src_server.join("init.server.lua"),
|
||||
"print(\"Hello world, from server!\")",
|
||||
)?;
|
||||
|
||||
write_if_not_exists(
|
||||
&src_client.join("init.client.lua"),
|
||||
"print(\"Hello world, from client!\")",
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_model(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> {
|
||||
let project_file = project_params.render_template(DEFAULT_MODEL_PROJECT);
|
||||
try_create_project(base_path, &project_file)?;
|
||||
|
||||
let src = base_path.join("src");
|
||||
fs::create_dir_all(&src)?;
|
||||
|
||||
let init = project_params.render_template(DEFAULT_MODEL_INIT);
|
||||
write_if_not_exists(&src.join("init.lua"), &init)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Contains parameters used in templates to create a project.
|
||||
struct ProjectParams {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl ProjectParams {
|
||||
/// Render a template by replacing variables with project parameters.
|
||||
fn render_template(&self, template: &str) -> String {
|
||||
template.replace("{project_name}", &self.name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a file if it does not exist yet, otherwise, leave it alone.
|
||||
fn write_if_not_exists(path: &Path, contents: &str) -> Result<(), Error> {
|
||||
let file_res = OpenOptions::new().write(true).create_new(true).open(path);
|
||||
|
||||
let mut file = match file_res {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
return match err.kind() {
|
||||
io::ErrorKind::AlreadyExists => return Ok(()),
|
||||
_ => Err(err.into()),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
file.write_all(contents.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Try to create a project file and fail if it already exists.
|
||||
fn try_create_project(base_path: &Path, contents: &str) -> Result<(), Error> {
|
||||
let project_path = base_path.join("default.project.json");
|
||||
|
||||
let file_res = OpenOptions::new()
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(project_path);
|
||||
|
||||
let mut file = match file_res {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
return match err.kind() {
|
||||
io::ErrorKind::AlreadyExists => Err(Error::AlreadyExists),
|
||||
_ => Err(err.into()),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
file.write_all(contents.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user