Skip to content

Commit 9535f64

Browse files
committed
refactor editor detection to use .internal/editor.port over port/process scanning, fix #46
1 parent 25ca77a commit 9535f64

13 files changed

Lines changed: 238 additions & 744 deletions

File tree

Cargo.lock

Lines changed: 61 additions & 576 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bridge/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "defold-nvim-bridge"
3-
version = "0.1.4"
3+
version = "0.2.0"
44
edition = "2024"
55

66
[dependencies]

crates/bridge/src/main.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,16 @@ enum Commands {
8181
game_root_dir: String,
8282
},
8383
/// Finds the open editor port
84-
FindEditorPort,
84+
FindEditorPort {
85+
#[clap(value_name = "GAME_ROOT_DIR", index = 1)]
86+
game_root_dir: String,
87+
},
8588
/// Sends a command to the editor
8689
SendCommand {
87-
#[clap(long = "port")]
88-
port: Option<u16>,
90+
#[clap(value_name = "GAME_ROOT_DIR", index = 1)]
91+
game_root_dir: String,
8992

90-
#[clap(value_name = "COMMAND", index = 1)]
93+
#[clap(value_name = "COMMAND", index = 2)]
9194
command: String,
9295
},
9396
/// Compile `.script_api` file and return the resulting `.lua` in stdout
@@ -186,15 +189,20 @@ fn main() -> Result<()> {
186189
tracing::info!("{}", dir.display());
187190
}
188191
}
189-
Commands::FindEditorPort => {
190-
if let Some(port) = editor::find_port() {
192+
Commands::FindEditorPort { game_root_dir } => {
193+
if let Some(port) = editor::find_port(&absolute(game_root_dir)?) {
191194
println!("Editor is running at port {port}");
192195
} else {
193196
println!("Could not find editor port, is the editor open?");
194197
}
195198
}
196-
Commands::SendCommand { port, command } => {
197-
editor::send_command(port, &command)?;
199+
Commands::SendCommand {
200+
game_root_dir,
201+
command,
202+
} => {
203+
if let Some(port) = editor::find_port(&absolute(game_root_dir)?) {
204+
editor::send_command(port, &command)?;
205+
}
198206
}
199207
Commands::CompileScriptApi { input } => {
200208
if !input.exists() {

crates/core/Cargo.toml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "defold-nvim-core"
3-
version = "0.1.4"
3+
version = "0.2.0"
44
edition = "2024"
55

66
[dependencies]
@@ -10,23 +10,20 @@ version-compare = "0.2.1"
1010
flate2 = "1.1.5"
1111
zip = "7.0.0"
1212
dirs = "6.0.0"
13-
reqwest = { version = "0.12.28", default-features = false, features = [
13+
reqwest = { version = "0.13.1", default-features = false, features = [
1414
"blocking",
1515
"json",
16-
"rustls-tls",
1716
] }
1817
rust-ini = "0.21.3"
1918
serde = { version = "1.0.228", features = ["derive"] }
20-
serde_json = "1.0.147"
19+
serde_json = "1.0.148"
2120
sha3 = "0.10.8"
2221
strum = { version = "0.27.2", features = ["derive"] }
2322
tracing = "0.1.44"
2423
which = "8.0.0"
2524
url = "2.5.7"
2625
walkdir = "2.5.0"
2726
edn-rs = "0.18.0"
28-
netstat2 = "0.11.2"
29-
sysinfo = "0.37.2"
3027
serde_yaml = "0.9.34"
3128
textwrap = "0.16.2"
3229
fs_extra = "1.3.0"

crates/core/src/editor.rs

Lines changed: 19 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
use std::collections::HashMap;
1+
use std::{collections::HashMap, fs, path::Path};
22

3-
use crate::cache;
4-
use anyhow::{Context, Result, bail};
5-
use netstat2::{AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo, iterate_sockets_info};
6-
use sysinfo::System;
3+
use anyhow::{Result, bail};
74

85
fn command_url(port: u16, command: Option<String>) -> String {
96
format!(
@@ -12,97 +9,36 @@ fn command_url(port: u16, command: Option<String>) -> String {
129
)
1310
}
1411

15-
pub fn find_port() -> Option<u16> {
16-
const CACHE: &str = "editor-port";
12+
#[must_use]
13+
pub fn find_port(game_root: &Path) -> Option<u16> {
14+
let editor_port = game_root.join(".internal").join("editor.port");
1715

18-
if let Some(port) = cache::get(CACHE)
19-
&& let Some(port) = port.parse::<u16>().ok()
20-
&& is_editor_port(port)
21-
{
22-
return Some(port);
16+
// editor port file doesnt exist? Editor isn't open
17+
if !editor_port.exists() {
18+
return None;
2319
}
2420

25-
tracing::debug!("Looking for editor port...");
21+
let content = fs::read_to_string(editor_port).ok()?;
2622

27-
let sys = System::new_all();
23+
let port: u16 = content.parse().ok()?;
2824

29-
for (pid, proc) in sys.processes() {
30-
if !proc
31-
.name()
32-
.to_ascii_lowercase()
33-
.to_str()
34-
.unwrap_or_default()
35-
.contains("java")
36-
{
37-
continue;
38-
}
39-
40-
let ports = ports_for_pid(pid.as_u32());
41-
42-
if ports.is_err() {
43-
continue;
44-
}
45-
46-
let ports = ports.unwrap();
47-
if ports.is_empty() {
48-
continue;
49-
}
50-
51-
tracing::debug!("Pid {} has ports: {:?}", pid.as_u32(), ports);
52-
53-
for port in ports {
54-
if is_editor_port(port) {
55-
tracing::debug!("Found editor at {port}");
56-
57-
if let Err(err) = cache::set(CACHE, &port.to_string()) {
58-
tracing::error!("Could not cache editor key because: {err:?}");
59-
}
60-
61-
return Some(port);
62-
}
63-
}
64-
}
65-
66-
None
67-
}
68-
69-
fn ports_for_pid(pid: u32) -> Result<Vec<u16>> {
70-
let mut ports = Vec::new();
71-
72-
let af_flags = AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6;
73-
let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
74-
75-
for socket in iterate_sockets_info(af_flags, proto_flags)? {
76-
let socket = socket?;
77-
78-
if socket.associated_pids.contains(&pid) {
79-
match &socket.protocol_socket_info {
80-
ProtocolSocketInfo::Tcp(tcp) => {
81-
ports.push(tcp.local_port);
82-
}
83-
ProtocolSocketInfo::Udp(udp) => {
84-
ports.push(udp.local_port);
85-
}
86-
}
87-
}
25+
if is_editor_port(port) {
26+
Some(port)
27+
} else {
28+
None
8829
}
89-
90-
Ok(ports)
9130
}
9231

32+
#[must_use]
9333
pub fn is_editor_port(port: u16) -> bool {
9434
reqwest::blocking::Client::new()
9535
.head(command_url(port, None))
9636
.send()
9737
.is_ok_and(|r| r.status().is_success())
9838
}
9939

100-
pub fn list_commands(port: Option<u16>) -> Result<HashMap<String, String>> {
101-
let url = command_url(
102-
port.or_else(find_port)
103-
.context("could not determine editor port")?,
104-
None,
105-
);
40+
pub fn list_commands(port: u16) -> Result<HashMap<String, String>> {
41+
let url = command_url(port, None);
10642

10743
let res = reqwest::blocking::get(url)?;
10844

@@ -115,12 +51,8 @@ pub fn list_commands(port: Option<u16>) -> Result<HashMap<String, String>> {
11551
serde_json::from_str(&content).map_err(anyhow::Error::from)
11652
}
11753

118-
pub fn send_command(port: Option<u16>, cmd: &str) -> Result<()> {
119-
let url = command_url(
120-
port.or_else(find_port)
121-
.context("could not determine editor port")?,
122-
Some(cmd.to_string()),
123-
);
54+
pub fn send_command(port: u16, cmd: &str) -> Result<()> {
55+
let url = command_url(port, Some(cmd.to_string()));
12456

12557
let res = reqwest::blocking::Client::new().post(url).send()?;
12658

crates/sidecar/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "defold-nvim-sidecar"
3-
version = "0.1.4"
3+
version = "0.2.0"
44
edition = "2024"
55

66
[lib]

crates/sidecar/src/lib.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ fn register_exports(lua: &Lua) -> LuaResult<LuaTable> {
8383
exports.set("version", lua.create_string(utils::version())?)?;
8484
exports.set("set_log_level", lua.create_function(set_log_level)?)?;
8585
exports.set("read_game_project", lua.create_function(read_game_project)?)?;
86-
exports.set("find_editor_port", lua.create_function(find_editor_port)?)?;
8786
exports.set("is_editor_port", lua.create_function(is_editor_port)?)?;
8887
exports.set("list_commands", lua.create_function(list_commands)?)?;
8988
exports.set("send_command", lua.create_function(send_command)?)?;
@@ -134,27 +133,21 @@ fn read_game_project(lua: &Lua, path: String) -> LuaResult<Value> {
134133
Ok(val)
135134
}
136135

137-
#[instrument(level = "debug", err(Debug), skip_all)]
138-
fn find_editor_port(_lua: &Lua, _: ()) -> LuaResult<u16> {
139-
let port = editor::find_port().context("could not find port")?;
140-
Ok(port)
141-
}
142-
143136
#[allow(clippy::unnecessary_wraps)]
144137
#[instrument(level = "debug", err(Debug), skip_all)]
145138
fn is_editor_port(_lua: &Lua, port: u16) -> LuaResult<bool> {
146139
Ok(editor::is_editor_port(port))
147140
}
148141

149142
#[instrument(level = "debug", err(Debug), skip_all)]
150-
fn list_commands(lua: &Lua, port: Option<u16>) -> LuaResult<LuaTable> {
143+
fn list_commands(lua: &Lua, port: u16) -> LuaResult<LuaTable> {
151144
let commands = editor::list_commands(port)?;
152145

153146
lua.create_table_from(commands)
154147
}
155148

156149
#[instrument(level = "debug", err(Debug), skip_all)]
157-
fn send_command(_lua: &Lua, (port, cmd): (Option<u16>, String)) -> LuaResult<()> {
150+
fn send_command(_lua: &Lua, (port, cmd): (u16, String)) -> LuaResult<()> {
158151
editor::send_command(port, &cmd)?;
159152

160153
Ok(())

lua/defold/editor.lua

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
local M = {}
22

33
---List all available Defold commands
4-
---@param port integer|nil
54
---@return table|nil
6-
function M.list_commands(port)
5+
function M.list_commands()
76
local log = require "defold.service.logger"
7+
local project = require "defold.project"
8+
9+
local port = project.editor_port()
10+
11+
if not port then
12+
log.error "Could not find Defold editor, is it running?"
13+
return
14+
end
15+
816
local sidecar = require "defold.sidecar"
917

1018
local ok, res = pcall(sidecar.list_commands, port)
@@ -19,11 +27,23 @@ function M.list_commands(port)
1927
end
2028

2129
---Sends a command to the Defold editor
22-
---@param port integer|nil
2330
---@param command string
2431
---@param dont_report_error boolean|nil
25-
function M.send_command(port, command, dont_report_error)
32+
function M.send_command(command, dont_report_error)
2633
local log = require "defold.service.logger"
34+
local project = require "defold.project"
35+
36+
local port = project.editor_port()
37+
38+
if not port then
39+
if dont_report_error then
40+
return
41+
end
42+
43+
log.error "Could not find Defold editor, is it running?"
44+
return
45+
end
46+
2747
local sidecar = require "defold.sidecar"
2848

2949
local _, err = pcall(sidecar.send_command, port, command)

0 commit comments

Comments
 (0)