Skip to content

Commit

Permalink
feat: ✨ added support for default template (#21)
Browse files Browse the repository at this point in the history
* feat(init): ✨ Add default templates

This is used for `bonnie --init`. It fetches the file at `$BONNIE_TEMPLATE_PATH`, falling back to `~/.bonnie/template.toml` if necessary.  The `home` crate was introduced to handle the finding of the user's home directory on Windows, which is surprisingly complicated and **can fail**.

* feat(init): ✨ Add edit template file flag

Using the `-e` or `--edit-template` flag, the user can now open the template file using the editor in the `EDITOR` environment variable or, on Windows, `start`.

* docs(help): 📝 Update help text to add `-e`

* fix(init): 🐛 Change template environment variable

It is now `BONNIE_TEMPLATE` to match `BONNIE_CONFIG`.

This breaks with the previous implementation.

* docs(help): 📝 Update help with new env var

* docs(wiki): 📝 Update docs with new env var

Changed `BONNIE_TEMPLATE_PATH` to `BONNIE_TEMPLATE`.

* Update src/help.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* Update src/help.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* Update src/init.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* Update src/init.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* Update src/bin/main.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* Update src/bin/main.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* refactor(init): ♻️ use `String`s as errors

* refactor: ♻️ Extract `-e` into function

* refactor(init): ♻️ Remove "Initialising..." text

Copying a file doesn't take that long.

* refactor(init): ♻️ Remove needles format\

It added quotes around a string.

* refactor(init): ♻️ Remove unclear names

* fix: 🐛 Add error message if template not found

* docs(wiki): 📝 Add info about `-e`

* fix: 🐛 Add more descriptive error

* fix(init): 🐛 Add actual path to error message

* Update src/template.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* Update src/template.rs

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>

* style: 🎨 Run `cargo fmt`

Co-authored-by: arctic_hen7 <arctic_hen7@pm.me>
  • Loading branch information
ostev and arctic-hen7 committed Jul 12, 2021
1 parent 8c56d3e commit 7c3eec6
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 16 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"conventionalCommits.scopes": [
"install_scripts",
"wiki"
"wiki",
"init",
"help"
]
}
32 changes: 32 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ edition = "2018"

[dependencies]
toml = "0.5.8"
serde = { version = "1.0.125", features = ["derive"] }
serde = { version="1.0.125", features=["derive"] }
serde_json = "1.0.64"
dotenv = "0.15.0"
regex = "1.5.4"
home = "0.5.3"

[lib]
name = "lib"
Expand Down
9 changes: 8 additions & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use lib::{cache, cache_exists, get_cfg, help, init, load_from_cache, Config, BONNIE_VERSION};
use lib::{
cache, cache_exists, get_cfg, help, init, load_from_cache, template, Config, BONNIE_VERSION,
};
use std::env;
use std::io::Write;

Expand Down Expand Up @@ -50,12 +52,17 @@ fn core() -> Result<i32, String> {
_ => None,
},
)?;

println!("A new Bonnie configuration file has been initialized at ./bonnie.toml!");

return Ok(0);
} else if prog_args[0] == "-h" || prog_args[0] == "--help" {
help(stdout);
return Ok(0);
} else if prog_args[0] == "-c" || prog_args[0] == "--cache" {
should_cache = true;
} else if prog_args[0] == "-e" || prog_args[0] == "--edit-template" {
return template::edit().map(|_| 0);
}
}
// Check if there's a cache we should read from
Expand Down
4 changes: 3 additions & 1 deletion src/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ This just summarizes the functionality of this command, not the syntax of Bonnie
-h, --help prints this help page
-v, --version prints the current version of Bonnie
-i, --init [-t, --template <template-file>] creates a new `bonnie.toml` configuration, potentially taking a template file to use
-i, --init [-t, --template <template-file>] creates a new `bonnie.toml` configuration, using the specified template file if provided.
-e, --edit-template opens the default template in your default cli editor
-c, --cache caches the Bonnie configuration file to `.bonnie.cache.json` for performance (this cache must be MANUALLY updated by re-running this command!)
The expected location of a Bonnie configuration file can be changed from the default `./bonnie.toml` by setting the `BONNIE_CONF` environment variable.
The expected location of a Bonnie cache file can be changed from the default `./.bonnie.cache.json` by setting the `BONNIE_CACHE` environment variable.
The expected location of your default template can be changed from the default `~/.bonnie/template.toml` by setting the `BONNIE_TEMPLATE` environment variable.
Further information can be found at https://github.com/arctic-hen7/bonnie/wiki.
",
Expand Down
30 changes: 19 additions & 11 deletions src/init.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::template;
use crate::version::BONNIE_VERSION;

use std::fs;

// Creates a new Bonnie configuration file using a template, or from the default
pub fn init(template: Option<String>) -> Result<(), String> {
// Check if there's already a config file in this directory
if fs::metadata("./bonnie.toml").is_ok() {
if fs::metadata("bonnie.toml").is_ok() {
Err(String::from("A Bonnie configuration file already exists in this directory. If you want to create a new one, please delete the old one first."))
} else {
// Check if a template has been given
Expand All @@ -22,19 +24,25 @@ pub fn init(template: Option<String>) -> Result<(), String> {
// We have a template file that doesn't exist
return Err(format!("The given template file at '{}' does not exist or can't be read. Please make sure the file exists and you have the permissions necessary to read from it.", template.as_ref().unwrap()));
} else {
// Create a new `bonnie.toml` file using the default
// TODO read the default from `~/.bonnie/template.toml` if it exists
output = fs::write(
"./bonnie.toml",
format!(
"version=\"{version}\"
// Try to get the default template file from `~/.bonnie/template.toml`
// If it's not available, we'll use a pre-programmed default
let template = match template::get_default() {
Ok(template) => Ok(template),
// Not ideal, but...
Err(err) if err == "The system cannot find the file specified. (os error 2)" => {
Ok(format!(
"version=\"{version}\"
[scripts]
start = \"echo \\\"No start script yet!\\\"\"
",
version = BONNIE_VERSION
),
);
",
version = BONNIE_VERSION
))
}
Err(err) => Err(err),
}?;

output = fs::write("bonnie.toml", template)
}

match output {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod help;
mod init;
mod raw_schema;
mod schema;
pub mod template;
mod version;

pub use crate::cache::{cache, cache_exists, load_from_cache};
Expand Down
88 changes: 88 additions & 0 deletions src/template.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use home::home_dir;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command as OsCommand;

pub fn get_template_path() -> Result<PathBuf, String> {
let default_template_path = home_dir()
.map(|path| path.join(".bonnie").join("template.toml"))
.ok_or(String::from(
"Your home directory couldn't be found. Please check your system configuration.",
))?;

Ok(env::var("BONNIE_TEMPLATE")
.map(|value| PathBuf::from(value))
.unwrap_or(default_template_path))
}

pub fn get_default() -> Result<String, String> {
let path = get_template_path()?;

let template = fs::read_to_string(path);

template.map_err(|err| err.to_string())
}

pub fn edit() -> Result<(), String> {
// This can take a little while with with `start` on Windows
println!("Opening template file...");

let template_path: String = match get_template_path() {
Ok(path) => path
.to_str()
.map(String::from)
.ok_or(String::from("The path provided is not valid Unicode.")),
Err(err) => Err(format!(
"Failed to get template path with the following error: {}",
err
)),
}?;

let template_exists = fs::metadata(&template_path).is_ok();

if !template_exists {
return Err(format!(
"I could not find a template file to edit at {}.",
template_path
));
}

let child;

let command;

if cfg!(target_os = "windows") {
// We need to spawn a `powershell` process to make `start` available.
child = OsCommand::new("powershell")
.arg(format!("start '{}'", template_path))
.spawn()
.map(|mut x| x.wait());

command = format!("powershell -command 'start {}'", template_path);
} else {
let editor = PathBuf::from(env::var("EDITOR").unwrap_or("nano".to_string()));

let safe_editor = editor.to_str().ok_or(
"The value given in the 'EDITOR' environment variable couldn't be parsed as a valid path.",
)?;

child = OsCommand::new(safe_editor)
.arg(&template_path)
.spawn()
.map(|mut x| x.wait());

command = format!("{} {}", safe_editor, template_path);
}

let result = match child {
Ok(_) => Ok(()),
Err(err) => Err(format!(
"The specified editor failed to start with the following error: '{}' when the command '{}' was run.",
err, command
)),
};

return result;
}
2 changes: 1 addition & 1 deletion wiki
Submodule wiki updated from b772fd to 5cdd38

0 comments on commit 7c3eec6

Please sign in to comment.