Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3 Rework Contexts #7

Merged
merged 4 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading