mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Add filter functionality to PatchVisualizer and ConfirmingPage
- Implemented a case-insensitive wildcard matching function in PatchVisualizer to filter visible nodes based on user input. - Enhanced the ConfirmingPage to include a TextInput for filtering, allowing users to search for specific nodes in the PatchVisualizer. - Updated the rendering logic to display appropriate messages based on the filter state, improving user experience and clarity.
This commit is contained in:
parent
ff96d98d79
commit
c092bb975c
6 changed files with 295 additions and 30 deletions
42
src/cli/cursor.rs
Normal file
42
src/cli/cursor.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use std::path::PathBuf;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
|
||||
use super::resolve_path;
|
||||
|
||||
/// Open the project directory in Cursor IDE.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct CursorCommand {
|
||||
/// Path to open. Defaults to the current directory.
|
||||
#[clap(default_value = ".")]
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl CursorCommand {
|
||||
pub fn run(self) -> anyhow::Result<()> {
|
||||
let path = resolve_path(&self.path);
|
||||
|
||||
// Use cmd /c to run cursor through the shell (cursor is a shell command, not an exe)
|
||||
#[cfg(windows)]
|
||||
Command::new("cmd")
|
||||
.args(["/c", "cursor", &path.to_string_lossy()])
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
.context("Failed to launch Cursor IDE. Is 'cursor' in your PATH?")?;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
Command::new("cursor")
|
||||
.arg(&*path)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
.context("Failed to launch Cursor IDE. Is 'cursor' in your PATH?")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
//! Defines Rojo's CLI through clap types.
|
||||
|
||||
mod build;
|
||||
mod cursor;
|
||||
mod doc;
|
||||
mod fmt_project;
|
||||
mod init;
|
||||
mod plugin;
|
||||
mod serve;
|
||||
mod sourcemap;
|
||||
mod studio;
|
||||
mod syncback;
|
||||
mod upload;
|
||||
|
||||
|
|
@ -16,12 +18,14 @@ use clap::Parser;
|
|||
use thiserror::Error;
|
||||
|
||||
pub use self::build::BuildCommand;
|
||||
pub use self::cursor::CursorCommand;
|
||||
pub use self::doc::DocCommand;
|
||||
pub use self::fmt_project::FmtProjectCommand;
|
||||
pub use self::init::{InitCommand, InitKind};
|
||||
pub use self::plugin::{PluginCommand, PluginSubcommand};
|
||||
pub use self::serve::ServeCommand;
|
||||
pub use self::sourcemap::SourcemapCommand;
|
||||
pub use self::studio::StudioCommand;
|
||||
pub use self::syncback::SyncbackCommand;
|
||||
pub use self::upload::UploadCommand;
|
||||
|
||||
|
|
@ -46,8 +50,10 @@ impl Options {
|
|||
Subcommand::Upload(subcommand) => subcommand.run(),
|
||||
Subcommand::Sourcemap(subcommand) => subcommand.run(),
|
||||
Subcommand::FmtProject(subcommand) => subcommand.run(),
|
||||
Subcommand::Cursor(subcommand) => subcommand.run(),
|
||||
Subcommand::Doc(subcommand) => subcommand.run(),
|
||||
Subcommand::Plugin(subcommand) => subcommand.run(),
|
||||
Subcommand::Studio(subcommand) => subcommand.run(),
|
||||
Subcommand::Syncback(subcommand) => subcommand.run(self.global),
|
||||
}
|
||||
}
|
||||
|
|
@ -120,8 +126,10 @@ pub enum Subcommand {
|
|||
Upload(UploadCommand),
|
||||
Sourcemap(SourcemapCommand),
|
||||
FmtProject(FmtProjectCommand),
|
||||
Cursor(CursorCommand),
|
||||
Doc(DocCommand),
|
||||
Plugin(PluginCommand),
|
||||
Studio(StudioCommand),
|
||||
Syncback(SyncbackCommand),
|
||||
}
|
||||
|
||||
|
|
|
|||
79
src/cli/studio.rs
Normal file
79
src/cli/studio.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use memofs::Vfs;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::project::Project;
|
||||
|
||||
use super::resolve_path;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UniverseResponse {
|
||||
#[serde(rename = "universeId")]
|
||||
universe_id: u64,
|
||||
}
|
||||
|
||||
/// Open a Rojo project in Roblox Studio.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct StudioCommand {
|
||||
/// Path to the project. Defaults to the current directory.
|
||||
#[clap(default_value = ".")]
|
||||
pub project: PathBuf,
|
||||
}
|
||||
|
||||
impl StudioCommand {
|
||||
pub fn run(self) -> anyhow::Result<()> {
|
||||
let vfs = Vfs::new_oneshot();
|
||||
|
||||
let base_path = resolve_path(&self.project);
|
||||
let project = Project::load_fuzzy(&vfs, &base_path)?
|
||||
.context("A project file is required to run 'rojo studio'")?;
|
||||
|
||||
let serve_place_ids = project
|
||||
.serve_place_ids
|
||||
.as_ref()
|
||||
.context("No servePlaceIds in project file. Add servePlaceIds to your project file.")?;
|
||||
|
||||
let place_id = serve_place_ids
|
||||
.iter()
|
||||
.min()
|
||||
.copied()
|
||||
.context("servePlaceIds is empty in project file")?;
|
||||
|
||||
let universe_id = get_universe_id(place_id)?;
|
||||
|
||||
let url = format!(
|
||||
"roblox-studio:1+launchmode:edit+task:EditPlace+placeId:{}+universeId:{}",
|
||||
place_id, universe_id
|
||||
);
|
||||
|
||||
// Use cmd /c start to fully detach the process on Windows
|
||||
#[cfg(windows)]
|
||||
Command::new("cmd")
|
||||
.args(["/c", "start", "", &url])
|
||||
.spawn()
|
||||
.context("Failed to launch Roblox Studio")?;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
opener::open(&url).context("Failed to open Roblox Studio")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_universe_id(place_id: u64) -> anyhow::Result<u64> {
|
||||
let url = format!(
|
||||
"https://apis.roblox.com/universes/v1/places/{}/universe",
|
||||
place_id
|
||||
);
|
||||
|
||||
let response: UniverseResponse = reqwest::blocking::get(&url)
|
||||
.context("Failed to fetch universe ID from Roblox API")?
|
||||
.json()
|
||||
.context("Failed to parse universe ID response")?;
|
||||
|
||||
Ok(response.universe_id)
|
||||
}
|
||||
|
|
@ -83,6 +83,9 @@ impl SyncbackCommand {
|
|||
// Determine if we need to download the input file
|
||||
let resolved_input = resolve_path(&self.input);
|
||||
let _temp_file: Option<NamedTempFile>;
|
||||
// Track if we should delete the input file after successful syncback
|
||||
// (when using default Project.rbxl and file exists locally)
|
||||
let delete_input_after_syncback: Option<PathBuf>;
|
||||
|
||||
// Logic:
|
||||
// - If --download=PLACEID: always download that specific place
|
||||
|
|
@ -100,11 +103,18 @@ impl SyncbackCommand {
|
|||
);
|
||||
let temp_path = temp.path().to_path_buf();
|
||||
_temp_file = Some(temp);
|
||||
delete_input_after_syncback = None;
|
||||
temp_path
|
||||
}
|
||||
None if resolved_input.exists() => {
|
||||
// No --download flag, input file exists: use it
|
||||
_temp_file = None;
|
||||
// If using default input path, mark for deletion after success
|
||||
delete_input_after_syncback = if self.input.as_os_str() == "Project.rbxl" {
|
||||
Some(resolved_input.clone().into_owned())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
resolved_input.into_owned()
|
||||
}
|
||||
None => {
|
||||
|
|
@ -123,6 +133,7 @@ impl SyncbackCommand {
|
|||
);
|
||||
let temp_path = temp.path().to_path_buf();
|
||||
_temp_file = Some(temp);
|
||||
delete_input_after_syncback = None;
|
||||
temp_path
|
||||
}
|
||||
};
|
||||
|
|
@ -251,6 +262,18 @@ impl SyncbackCommand {
|
|||
|
||||
// Refresh git index if in a git repository
|
||||
refresh_git_index(base_path);
|
||||
|
||||
// Delete input file if using default Project.rbxl location
|
||||
if let Some(input_path) = &delete_input_after_syncback {
|
||||
match std::fs::remove_file(input_path) {
|
||||
Ok(()) => log::info!("Deleted input file: {}", input_path.display()),
|
||||
Err(e) => log::warn!(
|
||||
"Failed to delete input file {}: {}",
|
||||
input_path.display(),
|
||||
e
|
||||
),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::info!(
|
||||
"Would write {} files/folders and remove {} files/folders.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue