Skip to content

Commit 4a4dca5

Browse files
committed
fix(main): robust docker fallback for LSP spawn
- Check Docker container existence before spawning LSP - Use local executable if container is missing or check fails - Remove redundant error handling and fallback logic - Improve debug and warn tracing for process selection - Ensure consistent argument handling for both modes
1 parent 0ee8c8f commit 4a4dca5

File tree

4 files changed

+56
-40
lines changed

4 files changed

+56
-40
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

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

66
[dependencies]

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,17 @@ Logs are written to a temporary directory. On Unix systems, this is located at `
215215
tail -f /tmp/lspdock_rust-analyzer.log
216216
```
217217

218-
219218
## CLI Arguments <a id="cli-arguments"></a>
220219

221220
The following arguments can be used. These arguments take precedence over the config file. If an argument is provided, the config file field (if it exists) will be overridden. All arguments passed after `--` will be forwarded to the LSP. If any of these arguments are included, and the LSP arguments are passed directly, e.g. `lspdock --stdio`, all arguments will be sent directly to the LSP.
222221

222+
**Variable Expansion:** CLI arguments support the same variable expansion as the config file (`$CWD`, `$PARENT`, `$HOME`). Use single quotes to prevent shell expansion:
223+
```bash
224+
lspdock --container '$PARENT-web' --docker-path /app --local-path '$HOME/dev'
225+
```
226+
227+
Without single quotes, your shell will expand the variables before lspdock receives them.
228+
223229
```text
224230
Usage: lspdock [OPTIONS] [-- <ARGS>...]
225231
@@ -238,6 +244,12 @@ Options:
238244
-V, --version Print version
239245
```
240246

247+
**Why single quotes matter:**
248+
- `"$HOME"` → Shell expands to `/home/user` → lspdock receives `/home/user`
249+
- `'$HOME'` → Shell doesn't expand → lspdock receives `$HOME` → lspdock expands it
250+
251+
Single quotes preserve the literal `$` so lspdock can do the expansion.
252+
241253
### When to Use `--`
242254

243255
Use the `--` separator to avoid ambiguity when your LSP server has flags that conflict with lspdock:

src/main.rs

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::process::Stdio;
22
use tokio::process::Command;
3-
use tracing::{debug, error, info};
3+
use tracing::{debug, error, info, warn};
44
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
55
mod config;
66
mod lsp;
@@ -47,8 +47,38 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4747

4848
debug!(?config, "configuration file");
4949

50-
// Call docker only if the pattern matches.
51-
let (cmd, mut cmd_args) = if config.use_docker {
50+
info!("Initializing LSP");
51+
52+
let mut using_docker = config.use_docker;
53+
54+
// Check if Docker container exists before trying to use it
55+
if using_docker {
56+
let container_check = Command::new("docker")
57+
.args(["inspect", "-f", "{{.State.Running}}", &config.container])
58+
.output();
59+
60+
match container_check.await {
61+
Ok(output) if output.status.success() => {
62+
let running = String::from_utf8_lossy(&output.stdout).trim() == "true";
63+
if !running {
64+
warn!(container=%config.container, "Container exists but is not running, falling back to local");
65+
using_docker = false;
66+
} else {
67+
debug!(container=%config.container, "Container is running");
68+
}
69+
}
70+
Ok(_) => {
71+
warn!(container=%config.container, "Container not found, falling back to local");
72+
using_docker = false;
73+
}
74+
Err(e) => {
75+
warn!(%e, "Failed to check Docker, falling back to local");
76+
using_docker = false;
77+
}
78+
}
79+
}
80+
81+
let (cmd, cmd_args) = if using_docker {
5282
let cmd = vec![
5383
"exec".into(),
5484
"-i".into(),
@@ -59,55 +89,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5989
];
6090
("docker".into(), cmd)
6191
} else {
62-
(config.executable.clone(), vec![])
92+
(get_fallback_exec(&config), vec![])
6393
};
6494

65-
debug!(%config.container, ?cmd_args, "Connecting to LSP");
66-
debug!(?cli.args, "args received");
67-
cmd_args.extend(cli.args.clone());
68-
debug!(?cmd_args, "full command");
95+
let mut final_args = cmd_args;
96+
final_args.extend(cli.args.clone());
6997

70-
info!("Initializing LSP");
98+
debug!(?cmd, ?final_args, "Spawning LSP");
7199

72-
let mut using_docker = config.use_docker;
73-
let mut child = match Command::new(&cmd)
74-
.args(cmd_args)
100+
let mut child = Command::new(&cmd)
101+
.args(&final_args)
75102
.stdin(Stdio::piped())
76103
.stdout(Stdio::piped())
77104
.stderr(Stdio::null())
78105
.spawn()
79-
{
80-
Ok(ch) => ch,
81-
Err(_) if config.use_docker => {
82-
// Fallback to local lsp
83-
let exec = get_fallback_exec(&config);
84-
using_docker = false;
85-
86-
info!("Cannot connect to container, falling back to local");
87-
88-
// Last try, panic if cannot initialize
89-
Command::new(&exec)
90-
.args(cli.args)
91-
.stdin(Stdio::piped())
92-
.stdout(Stdio::piped())
93-
.stderr(Stdio::null())
94-
.spawn()
95-
.expect("failed to initialize in Docker and local")
96-
}
97-
98-
Err(err) => {
99-
error!(%err, "initializing lsp");
100-
std::process::exit(1);
101-
}
102-
};
106+
.expect("failed to spawn LSP process");
103107

104108
let stdout = BufReader::new(child.stdout.take().unwrap());
105109
let stdin = BufWriter::new(child.stdin.take().unwrap());
106110

107111
if using_docker {
108112
info!(%config.container, "Attached to stdout/stdin");
109113
} else {
110-
info!(%config.executable, "Attached to stdout/stdin");
114+
info!(%config.executable, "Attached to stdout/stdin (local)");
111115
}
112116

113117
// Main proxy handler

0 commit comments

Comments
 (0)