-
-
Notifications
You must be signed in to change notification settings - Fork 390
Feat: Add PHPStorm to the IDE selection and add CSS to stretch out command output block to full width for larger screens #566
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
Changes from 12 commits
afcb970
3861093
f6c9b1b
41d8bb3
387f0b9
c1b4a01
1d84967
3f18662
0732034
026ffc9
97969f4
5035fde
d372eed
742857c
363d2fa
44bae44
18b2755
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ use super::helpers::resolve_workspace_root; | |
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
| enum LineAwareLaunchStrategy { | ||
| GotoFlag, | ||
| JetBrainsLineColumnFlags, | ||
| PathWithLineColumn, | ||
| } | ||
|
|
||
|
|
@@ -53,6 +54,9 @@ fn command_launch_strategy(command: &str) -> Option<LineAwareLaunchStrategy> { | |
| { | ||
| return Some(LineAwareLaunchStrategy::GotoFlag); | ||
| } | ||
| if identifier == "phpstorm" || identifier == "phpstorm64" { | ||
| return Some(LineAwareLaunchStrategy::JetBrainsLineColumnFlags); | ||
| } | ||
| if identifier == "zed" || identifier == "zed-preview" { | ||
| return Some(LineAwareLaunchStrategy::PathWithLineColumn); | ||
| } | ||
|
|
@@ -64,6 +68,9 @@ fn app_launch_strategy(app: &str) -> Option<LineAwareLaunchStrategy> { | |
| if normalized.contains("visual studio code") || normalized.starts_with("cursor") { | ||
| return Some(LineAwareLaunchStrategy::GotoFlag); | ||
| } | ||
| if normalized == "phpstorm" { | ||
| return Some(LineAwareLaunchStrategy::JetBrainsLineColumnFlags); | ||
|
aolin480 marked this conversation as resolved.
Outdated
|
||
| } | ||
| if normalized == "zed" || normalized.starts_with("zed ") { | ||
| return Some(LineAwareLaunchStrategy::PathWithLineColumn); | ||
| } | ||
|
|
@@ -81,28 +88,15 @@ fn app_cli_command(app: &str) -> Option<&'static str> { | |
| if normalized.starts_with("cursor") { | ||
| return Some("cursor"); | ||
| } | ||
| if normalized == "phpstorm" { | ||
| return Some("phpstorm"); | ||
|
Comment on lines
+91
to
+92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For macOS file links with a line/column, every recognized PhpStorm app name/path is collapsed to the global Useful? React with 👍 / 👎. |
||
| } | ||
| if normalized == "zed" || normalized.starts_with("zed ") { | ||
| return Some("zed"); | ||
| } | ||
| None | ||
| } | ||
|
|
||
| fn normalize_app_identifier(app: &str) -> String { | ||
| app.trim() | ||
| .chars() | ||
| .map(|value| { | ||
| if value.is_ascii_alphanumeric() { | ||
| value.to_ascii_lowercase() | ||
| } else { | ||
| ' ' | ||
| } | ||
| }) | ||
| .collect::<String>() | ||
| .split_whitespace() | ||
| .collect::<Vec<_>>() | ||
| .join(" ") | ||
| } | ||
|
|
||
| fn find_executable_in_path(program: &str) -> Option<PathBuf> { | ||
| let trimmed = program.trim(); | ||
| if trimmed.is_empty() { | ||
|
|
@@ -125,6 +119,22 @@ fn find_executable_in_path(program: &str) -> Option<PathBuf> { | |
| None | ||
| } | ||
|
|
||
| fn normalize_app_identifier(app: &str) -> String { | ||
| app.trim() | ||
| .chars() | ||
| .map(|value| { | ||
| if value.is_ascii_alphanumeric() { | ||
| value.to_ascii_lowercase() | ||
| } else { | ||
| ' ' | ||
| } | ||
| }) | ||
| .collect::<String>() | ||
| .split_whitespace() | ||
| .collect::<Vec<_>>() | ||
| .join(" ") | ||
| } | ||
|
|
||
| fn build_launch_args( | ||
| path: &str, | ||
| args: &[String], | ||
|
|
@@ -141,6 +151,15 @@ fn build_launch_args( | |
| launch_args.push("--goto".to_string()); | ||
| launch_args.push(located_path); | ||
| } | ||
| Some(LineAwareLaunchStrategy::JetBrainsLineColumnFlags) => { | ||
| launch_args.push("--line".to_string()); | ||
| launch_args.push(line.to_string()); | ||
| if let Some(column) = column { | ||
| launch_args.push("--column".to_string()); | ||
| launch_args.push(column.to_string()); | ||
| } | ||
| launch_args.push(path.to_string()); | ||
|
aolin480 marked this conversation as resolved.
Outdated
|
||
| } | ||
| Some(LineAwareLaunchStrategy::PathWithLineColumn) => { | ||
| let sanitized_path = normalize_windows_namespace_path(path); | ||
| let located_path = format_path_with_location(&sanitized_path, line, column); | ||
|
|
@@ -323,6 +342,10 @@ mod tests { | |
| command_launch_strategy("zed"), | ||
| Some(LineAwareLaunchStrategy::PathWithLineColumn) | ||
| ); | ||
| assert_eq!( | ||
| command_launch_strategy("phpstorm64.exe"), | ||
| Some(LineAwareLaunchStrategy::JetBrainsLineColumnFlags) | ||
| ); | ||
| assert_eq!(command_launch_strategy("vim"), None); | ||
| } | ||
|
|
||
|
|
@@ -490,6 +513,28 @@ mod tests { | |
| assert_eq!(args, vec!["/tmp/project/src/App.tsx:33".to_string()]); | ||
| } | ||
|
|
||
| #[test] | ||
| fn builds_line_and_column_flags_for_phpstorm_targets() { | ||
| let args = build_launch_args( | ||
| "/tmp/project/src/App.tsx", | ||
| &[], | ||
| Some(33), | ||
| Some(7), | ||
| Some(LineAwareLaunchStrategy::JetBrainsLineColumnFlags), | ||
| ); | ||
|
|
||
| assert_eq!( | ||
| args, | ||
| vec![ | ||
| "--line".to_string(), | ||
| "33".to_string(), | ||
| "--column".to_string(), | ||
| "7".to_string(), | ||
| "/tmp/project/src/App.tsx".to_string(), | ||
| ] | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn falls_back_to_plain_path_for_unknown_targets() { | ||
| let args = build_launch_args( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,11 +31,13 @@ pub(crate) fn read_settings(path: &PathBuf) -> Result<AppSettings, String> { | |
| let data = std::fs::read_to_string(path).map_err(|e| e.to_string())?; | ||
| let mut value: Value = serde_json::from_str(&data).map_err(|e| e.to_string())?; | ||
| migrate_follow_up_message_behavior(&mut value); | ||
| migrate_open_app_targets(&mut value); | ||
| match serde_json::from_value(value.clone()) { | ||
| Ok(settings) => Ok(settings), | ||
| Err(_) => { | ||
| sanitize_remote_settings_for_tcp_only(&mut value); | ||
| migrate_follow_up_message_behavior(&mut value); | ||
| migrate_open_app_targets(&mut value); | ||
| serde_json::from_value(value).map_err(|e| e.to_string()) | ||
| } | ||
| } | ||
|
|
@@ -92,6 +94,39 @@ fn migrate_follow_up_message_behavior(value: &mut Value) { | |
| ); | ||
| } | ||
|
|
||
| fn migrate_open_app_targets(value: &mut Value) { | ||
| let Value::Object(root) = value else { | ||
| return; | ||
| }; | ||
| let Some(Value::Array(existing_targets)) = root.get_mut("openAppTargets") else { | ||
| return; | ||
| }; | ||
|
|
||
| let has_phpstorm = existing_targets | ||
| .iter() | ||
| .any(|target| target.get("id").and_then(Value::as_str) == Some("phpstorm")); | ||
| if has_phpstorm { | ||
| return; | ||
| } | ||
|
|
||
| let phpstorm_target = match serde_json::to_value(AppSettings::default().open_app_targets) { | ||
| Ok(Value::Array(targets)) => targets | ||
| .into_iter() | ||
| .find(|target| target.get("id").and_then(Value::as_str) == Some("phpstorm")), | ||
| _ => None, | ||
| }; | ||
| let Some(phpstorm_target) = phpstorm_target else { | ||
| return; | ||
| }; | ||
|
|
||
| let insert_at = existing_targets | ||
| .iter() | ||
| .position(|target| target.get("id").and_then(Value::as_str) == Some("finder")) | ||
| .unwrap_or(existing_targets.len()); | ||
|
|
||
| existing_targets.insert(insert_at, phpstorm_target); | ||
|
Comment on lines
+123
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::{read_settings, read_workspaces, write_workspaces}; | ||
|
|
@@ -251,4 +286,48 @@ mod tests { | |
| let settings = read_settings(&path).expect("read settings"); | ||
| assert_eq!(settings.follow_up_message_behavior, "queue"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn read_settings_migrates_missing_open_app_targets() { | ||
| let temp_dir = std::env::temp_dir().join(format!("codex-monitor-test-{}", Uuid::new_v4())); | ||
| std::fs::create_dir_all(&temp_dir).expect("create temp dir"); | ||
| let path = temp_dir.join("settings.json"); | ||
|
|
||
| std::fs::write( | ||
| &path, | ||
| r#"{ | ||
| "theme": "dark", | ||
| "selectedOpenAppId": "vscode", | ||
| "openAppTargets": [ | ||
| { "id": "vscode", "label": "VS Code", "kind": "command", "appName": null, "command": "code", "args": [] }, | ||
| { "id": "cursor", "label": "Cursor", "kind": "command", "appName": null, "command": "cursor", "args": [] }, | ||
| { "id": "zed", "label": "Zed", "kind": "command", "appName": null, "command": "zed", "args": [] }, | ||
| { "id": "ghostty", "label": "Ghostty", "kind": "command", "appName": null, "command": "ghostty", "args": [] }, | ||
| { "id": "antigravity", "label": "Antigravity", "kind": "command", "appName": null, "command": "antigravity", "args": [] }, | ||
| { "id": "finder", "label": "File Manager", "kind": "finder", "appName": null, "command": null, "args": [] } | ||
| ] | ||
| }"#, | ||
| ) | ||
| .expect("write settings"); | ||
|
|
||
| let settings = read_settings(&path).expect("read settings"); | ||
| let ids: Vec<&str> = settings | ||
| .open_app_targets | ||
| .iter() | ||
| .map(|target| target.id.as_str()) | ||
| .collect(); | ||
|
|
||
| assert_eq!( | ||
| ids, | ||
| vec![ | ||
| "vscode", | ||
| "cursor", | ||
| "zed", | ||
| "ghostty", | ||
| "antigravity", | ||
| "phpstorm", | ||
| "finder" | ||
| ] | ||
| ); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.