Skip to content

Commit d462cc4

Browse files
committed
Improve robustness
1 parent 93ebfbe commit d462cc4

File tree

3 files changed

+83
-16
lines changed

3 files changed

+83
-16
lines changed

README.md

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ from tempfile import gettempdir
4444

4545

4646
port_file_path = Path(gettempdir()) / "vscode-port"
47-
port = port_file_path.read_text()
47+
contents = json.loads(port_file_path.read_text())
48+
port = contents["port"]
4849

4950
response = requests.post(
5051
f"http://localhost:{port}/execute-command",
@@ -57,6 +58,50 @@ response = requests.post(
5758
response.raise_for_status()
5859
```
5960

61+
## Troubleshooting
62+
63+
If you're running into issues with commands interleaving with keystrokes, or the extension not responding, the server supports a command `command-server.writePort`, which will cause the extension to update the port and write a monotonically increasing counter variable to the port file. You can run this command (via keyboard shortcut) and then wait for the file to update to ensure you're talking to the right vscode instance and to ensure that the command will not interleave with other keyboard shortcuts issued to VSCode.
64+
65+
Here's some example code for this mode of operation. Note that this assumes
66+
that you have a function `actions.key` that presses the given key (eg
67+
[talon](https://talonvoice.com/)):
68+
69+
```py
70+
port_file_path = Path(gettempdir()) / "vscode-port"
71+
original_contents = port_file_path.read_text()
72+
73+
# Issue command to VSCode telling it to update the port file. Because only
74+
# the active VSCode instance will accept keypresses, we can be sure that
75+
# the active VSCode instance will be the one to write the port.
76+
if is_mac:
77+
actions.key("cmd-shift-alt-p")
78+
else:
79+
actions.key("ctrl-shift-alt-p")
80+
81+
# Wait for the VSCode instance to update the port file. This generally
82+
# happens within the first millisecond, but we give it 3 seconds just in
83+
# case.
84+
start_time = time.monotonic()
85+
new_contents = port_file_path.read_text()
86+
while original_contents == new_contents:
87+
time.sleep(0.001)
88+
if time.monotonic() - start_time > 3.0:
89+
raise Exception("Timed out waiting for VSCode to update port file")
90+
new_contents = port_file_path.read_text()
91+
92+
port = json.loads(new_contents)["port"]
93+
94+
response = requests.post(
95+
f"http://localhost:{port}/execute-command",
96+
json={
97+
"commandId": "some-command-id",
98+
"args": ["some-argument"],
99+
},
100+
timeout=(0.05, 3.05),
101+
)
102+
response.raise_for_status()
103+
```
104+
60105
## Known issues
61106

62107
- The server won't respond until the extension is loaded. This may be obvious,

package.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"type": "git",
99
"url": "https://github.com/pokey/command-server"
1010
},
11-
"version": "0.2.2",
11+
"version": "0.3.2",
1212
"engines": {
1313
"vscode": "^1.53.0"
1414
},
@@ -19,7 +19,21 @@
1919
"*"
2020
],
2121
"main": "./out/extension.js",
22-
"contributes": {},
22+
"contributes": {
23+
"commands": [
24+
{
25+
"command": "command-server.writePort",
26+
"title": "Write port to file"
27+
}
28+
],
29+
"keybindings": [
30+
{
31+
"command": "command-server.writePort",
32+
"key": "ctrl+shift+alt+p",
33+
"mac": "cmd+shift+alt+p"
34+
}
35+
]
36+
},
2337
"scripts": {
2438
"vscode:prepublish": "yarn run compile",
2539
"compile": "tsc -p ./",

src/extension.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,6 @@ export function activate(context: vscode.ExtensionContext) {
5858
}
5959
});
6060

61-
setInterval(() => {
62-
const path = getPortPath();
63-
64-
if (
65-
vscode.window.state.focused &&
66-
(!existsSync(path) || parseInt(readFileSync(path).toString()) !== port)
67-
) {
68-
writePort();
69-
}
70-
}, 500);
71-
7261
const windowStateDisposable = vscode.window.onDidChangeWindowState(
7362
(event) => {
7463
if (event.focused && port !== null) {
@@ -77,13 +66,32 @@ export function activate(context: vscode.ExtensionContext) {
7766
}
7867
);
7968

69+
// We keep a monotonically increasing write counter so that the port file is
70+
// guaranteed to change every time we write to it. This way a client can use
71+
// the `command-server.writePort` command to request us to update the port
72+
// file, and then wait for it to change.
73+
var fileWriteCounter = 0;
74+
8075
function writePort() {
8176
const path = getPortPath();
8277
console.log(`Saving port ${port} to path ${path}`);
83-
writeFileSync(path, `${port}`);
78+
79+
const portInfo = {
80+
port,
81+
fileWriteCounter,
82+
};
83+
84+
fileWriteCounter++;
85+
86+
writeFileSync(path, JSON.stringify(portInfo));
8487
}
8588

86-
context.subscriptions.push(windowStateDisposable, {
89+
let disposable = vscode.commands.registerCommand(
90+
"command-server.writePort",
91+
writePort
92+
);
93+
94+
context.subscriptions.push(disposable, windowStateDisposable, {
8795
dispose() {
8896
server.close();
8997
},

0 commit comments

Comments
 (0)