Skip to content

Commit

Permalink
Add a file to define global variables (#92)
Browse files Browse the repository at this point in the history
Adds a vars.ini file to define global replacements.
  • Loading branch information
MysteryBlokHed authored Jul 30, 2021
1 parent 7de1b0d commit 48f59dd
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 8 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
target/
testing/
_build/
databind.toml
45 changes: 45 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ clap = "2.33"
glob = "0.3"
rand = "0.8"
regex = "1.5"
rust-ini = "0.17"
same-file = "1.0"
serde = { version="1.0", features=["derive"] }
serde_json = "1.0"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ page on the docs.
- Shorthand to call functions without namespace prefix (`func_1` instead of `namespace:func_1`)
- Subcommand to create new projects easily
- While loops
- A file to define variables that can be used anywhere
- Variable definitions via scoreboards
- Shorthand for objective creation
- Shorthand for testing variables in `if` commands
Expand Down
55 changes: 55 additions & 0 deletions docs/global_vars.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Global Vars
===========

You can define global variables with a file called ``vars.ini`` in the project root.
Keys and values aren't put in a section of the ``.ini``, they're just in the file. For example:

.. code-block:: ini
name=World
This defines a global variable ``name`` that can be used in your code.

Using Global Vars
-----------------

To use a global variable in your code, use an ``&`` symbol followed
by the variable name. Like this:

.. code-block:: databind
say Hello, &name!
Which, with the ``vars.ini`` defined above, becomes:

.. code-block:: mcfunction
say Hello, World!
Instances of ``&varname`` are directly replaced, meaning that
escaping them with a ``%`` symbol doesn't work. This means that
the following code:

.. code-block:: databind
say Hello, %&name!
Just becomes:

.. code-block:: databind
say Hello, %World!
``%World`` is effectively the same as ``World``, so the ``%`` symbol
won't appear in the compiled output.

When to use
-----------

Global variables are useful to let users more easily configure aspects
of your datapack. This does mean that the project must be recompiled
whenever the configuration is changed, and that users must have Databind
downloaded to use the project. If you are only configuring number values,
eg. an amount of time to wait for something, then it might be easier for
people using your datapack to have a ``config.mcfunction`` file somewhere in the
project that sets scoreboard values.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ Contents:
cli.rst
config.rst
macros.rst
global_vars.rst
folder_structure.rst
examples.rst
45 changes: 38 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
#![warn(clippy::all)]

use glob::glob;
use ini::Ini;
use same_file::is_same_file;
use serde::Serialize;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::{
collections::HashMap,
env, fs,
path::{Path, PathBuf},
};
use walkdir::WalkDir;

mod cli;
Expand Down Expand Up @@ -221,6 +223,27 @@ fn main() -> std::io::Result<()> {
src_dir.as_path()
};

// Read vars.ini if present
let vars = {
let path = format!("{}/vars.ini", datapack);
let vars_ini = Path::new(&path);
if vars_ini.exists() && vars_ini.is_file() {
let i = Ini::load_from_file(vars_ini).unwrap();
let vars: HashMap<String, String> = i
.iter()
.next()
.unwrap()
.1
.iter()
// Replace each mapping of `"var": "value"` with `"&var": "value"`
.map(|x| (format!("&{}", x.0), x.1.into()))
.collect();
Some(vars)
} else {
None
}
};

for entry in WalkDir::new(&src_dir).into_iter().filter_map(|e| e.ok()) {
if entry.path().is_file() {
// Do not add config file to output folder
Expand Down Expand Up @@ -264,9 +287,17 @@ fn main() -> std::io::Result<()> {
}

if compile {
let content = fs::read_to_string(entry.path())
.expect(&format!("Failed to read file {}", entry.path().display())[..]);
let mut compile = compiler::Compiler::new(content);
let contents = {
let mut file_contents = fs::read_to_string(entry.path())
.expect(&format!("Failed to read file {}", entry.path().display())[..]);
if let Some(vars_map) = &vars {
for (k, v) in vars_map.iter() {
file_contents = file_contents.replace(k, v);
}
}
file_contents
};
let mut compile = compiler::Compiler::new(contents);
let tokens = compile.tokenize();

let mut compiled = if entry
Expand Down
31 changes: 31 additions & 0 deletions tests/file_contents_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,34 @@ fn test_macro_recursion() {
let contents = fs::read_to_string(&out_path).unwrap();
assert!(contents.contains("say Macro 1 - Test"));
}

/// Test that global variables are properly read and replaced
#[test]
fn test_global_vars() {
let mut path = tests::resources();
path.push("test_global_vars");

let out = TempDir::new("test_global_vars").expect("Could not create tempdir for test");

tests::run_with_args(
"cargo",
&[
"run",
"--",
path.to_str().unwrap(),
"--ignore-config",
"--out",
out.path().to_str().unwrap(),
],
None,
);

let out_path = format!(
"{}/data/test/functions/main.mcfunction",
out.path().display()
);
let contents = fs::read_to_string(&out_path).unwrap();

assert!(contents.contains("say Variable 1"));
assert!(contents.contains("tellraw @a \"Variable 2\""));
}
1 change: 1 addition & 0 deletions tests/resources/test_global_vars/databind.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
func main
say &var1
tellraw @a "&var2"
end
2 changes: 2 additions & 0 deletions tests/resources/test_global_vars/vars.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var1=Variable 1
var2 = Variable 2

0 comments on commit 48f59dd

Please sign in to comment.