advanced: attempt to open a REPL on linux/macOS (#571)

Fixes #85

---------

Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
This commit is contained in:
Tyler Wilding 2024-09-22 13:47:37 -04:00 committed by GitHub
parent 135f200f4a
commit 465092d965
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 93 additions and 49 deletions

View file

@ -6,12 +6,14 @@ Our attempt at distributing the [OpenGOAL](https://github.com/open-goal/jak-proj
The launcher uses the [Tauri](https://tauri.app/) framework.
- [Usage](#usage)
- [Asking for help](#asking-for-help)
- [Development](#development)
- [Windows](#windows)
- [Linux (Ubuntu 22.04)](#linux-ubuntu-2204)
- [Building and Running](#building-and-running)
- [OpenGOAL Launcher](#opengoal-launcher)
- [Usage](#usage)
- [Asking for help](#asking-for-help)
- [Development](#development)
- [Windows](#windows)
- [Linux (Ubuntu 22.04)](#linux-ubuntu-2204)
- [macOS](#macos)
- [Building and Running](#building-and-running)
## Usage
@ -53,6 +55,12 @@ nvm install lts/hydrogen # installs latest nodejs 18.X
npm install -g yarn
```
### macOS
```bash
npm install -g yarn
```
### Building and Running
To build and run the application locally, all you have to do is run:

View file

@ -1,5 +1,6 @@
use std::{
collections::HashMap,
io::ErrorKind,
path::{Path, PathBuf},
process::Stdio,
time::Instant,
@ -37,6 +38,12 @@ struct CommonConfigData {
tooling_version: Version,
}
#[derive(Clone, serde::Serialize)]
struct ToastPayload {
toast: String,
level: String,
}
fn common_prelude(
config: &tokio::sync::MutexGuard<LauncherConfig>,
) -> Result<CommonConfigData, CommandError> {
@ -574,33 +581,66 @@ pub async fn run_compiler(
#[tauri::command]
pub async fn open_repl(
config: tauri::State<'_, tokio::sync::Mutex<LauncherConfig>>,
app_handle: tauri::AppHandle,
game_name: String,
) -> Result<(), CommandError> {
// TODO - explore a linux option though this is very annoying because without doing a ton of research
// we seem to have to handle various terminals. Which honestly we should probably do on windows too
//
// So maybe we can make a menu where the user will specify what terminal to use / what launch-options to use
let config_lock = config.lock().await;
let config_info = common_prelude(&config_lock)?;
let data_folder = get_data_dir(&config_info, &game_name, false)?;
let exec_info = get_exec_location(&config_info, "goalc")?;
let mut command = Command::new("cmd");
command
.args([
"/K",
"start",
&bin_ext("goalc"),
"--proj-path",
&data_folder.to_string_lossy(),
])
.current_dir(exec_info.executable_dir);
let mut command;
#[cfg(windows)]
{
command.creation_flags(0x08000000);
command = Command::new("cmd");
command
.args([
"/K",
"start",
&bin_ext("goalc"),
"--proj-path",
&data_folder.to_string_lossy(),
])
.current_dir(exec_info.executable_dir)
.creation_flags(0x08000000);
}
#[cfg(target_os = "linux")]
{
command = Command::new("xdg-terminal-exec");
command
.args(["./goalc", "--proj-path", &data_folder.to_string_lossy()])
.current_dir(exec_info.executable_dir);
}
#[cfg(target_os = "macos")]
{
command = Command::new("osascript");
command
.args([
"-e",
"'tell app \"Terminal\" to do script",
format!("\"cd {:?}\" &&", exec_info.executable_dir).as_str(),
"./goalc",
"--proj-path",
&data_folder.to_string_lossy(),
])
.current_dir(exec_info.executable_dir);
}
match command.spawn() {
Ok(_) => Ok(()),
Err(e) => {
if let ErrorKind::NotFound = e.kind() {
let _ = app_handle.emit_all(
"toast_msg",
ToastPayload {
toast: format!("'{:?}' not found in PATH!", command.get_program()),
level: "error".to_string(),
},
);
}
return Err(CommandError::BinaryExecution(
"Unable to launch REPL".to_owned(),
));
}
}
command.spawn()?;
Ok(())
}
#[derive(Debug, Serialize, Deserialize)]
@ -748,12 +788,6 @@ pub async fn get_launch_game_string(
))
}
#[derive(Clone, serde::Serialize)]
struct ToastPayload {
toast: String,
level: String,
}
#[tauri::command]
pub async fn launch_game(
config: tauri::State<'_, tokio::sync::Mutex<LauncherConfig>>,

View file

@ -195,9 +195,17 @@ pub async fn is_avx_requirement_met(
}
match config_lock.requirements.avx {
None => {
if is_x86_feature_detected!("avx") || is_x86_feature_detected!("avx2") {
config_lock.requirements.avx = Some(true);
} else {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
if is_x86_feature_detected!("avx") || is_x86_feature_detected!("avx2") {
config_lock.requirements.avx = Some(true);
} else {
config_lock.requirements.avx = Some(false);
}
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
// TODO - macOS check if on atleast sequoia and rosetta 2 is installed
config_lock.requirements.avx = Some(false);
}
config_lock.save_config().map_err(|err| {

View file

@ -1,7 +1,6 @@
<script lang="ts">
import { getInternalName, SupportedGame } from "$lib/constants";
import { openDir } from "$lib/rpc/window";
import IconArrowLeft from "~icons/mdi/arrow-left";
import IconCog from "~icons/mdi/cog";
import { configDir, join } from "@tauri-apps/api/path";
import { createEventDispatcher, onMount } from "svelte";
@ -27,7 +26,6 @@
import { navigate } from "svelte-navigator";
import { listen } from "@tauri-apps/api/event";
import { toastStore } from "$lib/stores/ToastStore";
import { launchMod } from "$lib/rpc/features";
export let activeGame: SupportedGame;
@ -167,13 +165,11 @@
launchGame(getInternalName(activeGame), true);
}}>{$_("gameControls_button_playInDebug")}</DropdownItem
>
{#if !isLinux}
<DropdownItem
on:click={async () => {
openREPL(getInternalName(activeGame));
}}>{$_("gameControls_button_openREPL")}</DropdownItem
>
{/if}
<DropdownItem
on:click={async () => {
openREPL(getInternalName(activeGame));
}}>{$_("gameControls_button_openREPL")}</DropdownItem
>
<DropdownDivider />
<DropdownItem
on:click={async () => {

View file

@ -330,13 +330,11 @@
launchMod(getInternalName(activeGame), true, modName, modSource);
}}>{$_("gameControls_button_playInDebug")}</DropdownItem
>
{#if !isLinux}
<DropdownItem
on:click={async () => {
openREPLForMod(getInternalName(activeGame), modName, modSource);
}}>{$_("gameControls_button_openREPL")}</DropdownItem
>
{/if}
<DropdownItem
on:click={async () => {
openREPLForMod(getInternalName(activeGame), modName, modSource);
}}>{$_("gameControls_button_openREPL")}</DropdownItem
>
<DropdownDivider />
<DropdownItem
on:click={async () => {