Skip to content

Commit

Permalink
Merge pull request #7 from hlafaille/feat/3
Browse files Browse the repository at this point in the history
#3 Rework Contexts
  • Loading branch information
hlafaille authored Mar 12, 2024
2 parents 34f292b + f8ffcd5 commit 41652dd
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 165 deletions.
121 changes: 113 additions & 8 deletions src/backend/context.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,124 @@
use crate::backend::project::Config;
use std::{
cell::{Cell, RefCell},
env, fs, io,
};

use crate::{backend::project::Config, frontend::terminal::print_err};

use super::project::get_config_from_fs;

/**
* Represents the currently loaded project
*/
/// Represents the context of the currently loaded project.
pub struct ProjectContext {
/// Project config (espresso.toml)
pub config: Config,
/// Absolute paths (with suffixes known at compile time) that're relavent to this project (ex: path to src)
pub absolute_paths: AbsoltuePaths,
/// Absolute paths (with suffixes NOT known at compile time) that're relavent to this project (ex: path to base package)
pub dynamic_absolute_paths: DynamicAbsolutePaths,
/// If we're running in debug mode (ESPRESSO_DEBUG=1)
pub debug_mode: bool,
}

/// Contains absolute paths to critical resources within the currently loaded project.
pub struct AbsoltuePaths {
/// Path to the currently loaded projects directory. Should be the current working directory.
pub project: String,
/// Path to the src/ directory within the currently loaded project.
pub source: String,
/// Path to the config file within the currently loaded project.
pub config: String,
}

/// Contains absolute paths to critical resources within the currently loaded project. Determined at runtime.
pub struct DynamicAbsolutePaths {
/// Path to the base package. Should be {source}/package/path/here. The Main.java file will live here.
pub base_package: String,
}

/// Get if debug mode is active. You can enable debug mode by setting the `ESPRESSO_DEBUG`
/// environment variable to `1`.
///
/// # Returns
///
/// `true` if `ESPRESSO_DEBUG=1`, `false` if `ESPRESSO_DEBUG=0` or not set
pub fn get_debug_mode() -> bool {
match env::var("ESPRESSO_DEBUG") {
Ok(v) => {
if v == "1" {
return true;
} else if v == "0" {
return false;
} else {
return false;
}
}
Err(_) => return false,
};
}

/// Get an AbsolutePaths struct
///
/// # Arguments
///
/// * `config`: Reference to a Config
/// * `debug_mode`: Reference to a bool if we're in debug mode
///
/// # Returns
///
/// AbsolutePaths
pub fn get_absolute_paths(debug_mode: &bool) -> AbsoltuePaths {
let mut cwd = env::current_dir()
.expect("Failed to read the current working directory; are you in a shell?")
.to_string_lossy()
.into_owned();

if *debug_mode {
cwd += "/espresso_debug"
}

AbsoltuePaths {
project: cwd.clone(),
source: cwd.clone() + "/src/java",
config: cwd.clone() + "/espresso.toml",
}
}

/// Get a DynamicAbsolutePaths struct.
///
/// # Arguments
/// * `ap`: Reference to an `AbsolutePaths` struct. Used to get the `src/` directory.
/// * `config`: Reference to a `Config` struct. used to get the current `base_package`.
/// * `debug_mode`: Reference to a bool if we're in debug mode
///
/// # Returns
///
/// DynamicAbsolutePaths
pub fn get_dynamic_absolute_paths(ap: &AbsoltuePaths, config: &Config) -> DynamicAbsolutePaths {
let base_package = ap.source.clone()
+ "/" + config
.project
.base_package
.clone()
.replace(".", "/")
.as_str();
DynamicAbsolutePaths { base_package }
}

/**
* Get the Project Context
*/
/// Get context about the currently loaded project.
///
/// # Returns
///
/// ProjectContext
pub fn get_project_context() -> ProjectContext {
let debug_mode = get_debug_mode();
let absolute_paths = get_absolute_paths(&debug_mode);
let config = get_config_from_fs(&absolute_paths);
let dynamic_absolute_paths = get_dynamic_absolute_paths(&absolute_paths, &config);

ProjectContext {
config: get_config_from_fs()
config,
absolute_paths,
debug_mode,
dynamic_absolute_paths,
}
}
2 changes: 1 addition & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod context;
pub mod project;
pub mod toolchain;
pub mod context;
144 changes: 48 additions & 96 deletions src/backend/project.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{collections::HashMap, env, fs::{self, create_dir_all}, path::Path};
use crate::util::pathutil;

use super::context::{AbsoltuePaths, ProjectContext};
use serde::{Deserialize, Serialize};
use super::context::ProjectContext;
use std::{collections::HashMap, fs, io};

#[derive(Deserialize, Serialize, Debug)]
pub struct Config {
Expand All @@ -21,80 +23,22 @@ pub struct Toolchain {
pub path: String,
}

/**
* Get if ESPRESSO_DEBUG=1
*/
pub fn get_debug_mode() -> bool {
match env::var("ESPRESSO_DEBUG") {
Ok(v) => {
if v == "1" {
return true
} else if v == "0" {
return false
} else {
return false
}
}
Err(_) => return false,
};
}

/**
* Get the config path. Note, this value changes if ESPRESSO_DEBUG=1
*/
pub fn get_config_path() -> String {
let debug_mode = get_debug_mode();
if debug_mode {
"espresso_debug/espresso.toml".to_string()
} else {
"espresso.toml".to_string()
}
}

pub fn get_absolute_project_path() -> String {
let debug_mode = get_debug_mode();
let current_dir = env::current_dir().unwrap().to_string_lossy().into_owned();
if debug_mode {
current_dir + "/espresso_debug"
} else {
current_dir
}
}

/**
* Get the source path. Note, this value is prefixed with `espresso_debug` if ESPRESSO_DEBUG=1
*/
pub fn get_source_path() -> String {
(get_absolute_project_path() + "/src/java").to_string()
}

/**
* Ensure development directory exists
*/
pub fn ensure_debug_directory_exists_if_debug(){
if !get_debug_mode() {
return;
}
if !Path::exists(Path::new("espresso_debug")) {
create_dir_all("espresso_debug").expect("Failed to ensure debug directory exists");
}
}

/**
* Load the project at the current working directory
*/
pub fn get_config_from_fs() -> Config {
let contents = fs::read_to_string(get_config_path()).expect("Unable to read conig file");
pub fn get_config_from_fs(ap: &AbsoltuePaths) -> Config {
let contents = fs::read_to_string(ap.config.clone()).expect("Unable to read conig file");
toml::from_str(&contents).unwrap()
}


/**
* If a project exists. A project is deemed existing if it has a source directory
* and a config file.
*/
pub fn does_exist() -> bool {
let source_exists = does_source_exist();
let config_exists = does_config_exist();
pub fn does_exist(ap: &AbsoltuePaths) -> bool {
let source_exists = pathutil::does_path_exist(&ap.source);
let config_exists = pathutil::does_path_exist(&ap.config);

// Return false if either source or config does not exist
if !source_exists || !config_exists {
Expand All @@ -105,32 +49,16 @@ pub fn does_exist() -> bool {
true
}

/**
* If the source path (ex: src) exists
*/
pub fn does_source_exist() -> bool {
Path::exists(Path::new(get_source_path().as_str()))
}

/**
* Checks if the config exists
*/
pub fn does_config_exist() -> bool {
Path::exists(Path::new(get_config_path().as_str()))
}

/**
* Get the base package path. This value is the `location of src + base_package`
*/
pub fn get_full_base_package_path(p_ctx: &ProjectContext) -> String{
format!("{}/{}", get_source_path(), p_ctx.config.project.base_package.replace(".", "/"))
}

/**
* Initialize the source tree
*/
pub fn initialize_source_tree(p_ctx: &ProjectContext) {
std::fs::create_dir_all(get_full_base_package_path(p_ctx)).expect("failed to create main package directories in file system");
pub fn initialize_source_tree(p_ctx: &ProjectContext) -> io::Result<()>{
// get the base backage (dot notation) and the base package path on the fs
let base_package_path = p_ctx.dynamic_absolute_paths.base_package.clone();
let base_package = p_ctx.config.project.base_package.clone();

// ensure the base package path exists
std::fs::create_dir_all(&base_package_path)?;

// create the Main.java file (textwrap doesn't work????)
let base_java_content = r#"package ${BASE_PACKAGE};
Expand All @@ -140,9 +68,16 @@ public class Main {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}"#.replace("${BASE_PACKAGE}", &p_ctx.config.project.base_package);

std::fs::write(get_full_base_package_path(p_ctx) + "/Main.java", base_java_content);
}"#
.replace("${BASE_PACKAGE}", &base_package);

// write an example java file
std::fs::write(
base_package_path.clone() + "/Main.java",
base_java_content,
)?;

Ok(())
}

fn process_input(x: String, default: String) -> String {
Expand All @@ -156,8 +91,8 @@ fn process_input(x: String, default: String) -> String {
/**
* Initialize a config
*/
pub fn initialize_config(name: String, base_package: String) {
// process the name
pub fn initialize_config(name: String, base_package: String, ap: &AbsoltuePaths) -> io::Result<()> {

// populate a base_config struct
let base_config = Config {
project: Project {
Expand All @@ -173,5 +108,22 @@ pub fn initialize_config(name: String, base_package: String) {

// write it to a toml string, then write it to the config file
let toml_string = toml::to_string(&base_config).expect("Failed to serialize struct");
fs::write(get_config_path(), toml_string).expect("Failed to write config file")
}
fs::write(ap.config.clone(), toml_string)?;
Ok(())
}


/// Ensure the project environment is properly setup
///
/// # Arguments
/// * `ap`: Reference to an `AbsolutePaths` struct
/// * `debug_mode`: Reference to a bool that defines if we're in debug mode or not
///
/// # Returns
/// `io::Result`, propagated from `fs::create_dir`
pub fn ensure_environment(ap: &AbsoltuePaths, debug_mode: &bool) -> io::Result<()>{
if *debug_mode {
fs::create_dir(&ap.project)?
}
Ok(())
}
Loading

0 comments on commit 41652dd

Please sign in to comment.