microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
164.62k stars 29.42k forks source link

Terminal doesn't handle multiple OSC 1337 or OSC 7 escape sequences correctly #234332

Open rzhw opened 1 day ago

rzhw commented 1 day ago

Type: Bug

From VSCode:

  1. Create either of the following scripts as test.py, and follow the below instructions:

OSC 1337:

import os
import sys

script_dir = os.path.dirname(os.path.realpath(__file__))

if not os.path.exists("foo"):
    print("make a folder called foo first")
    quit()

new_cwd = os.path.join(script_dir, "foo")
print(f"changing cwd OSC 1337 to {new_cwd}", flush=True)
sys.stdout.write(f"\033]1337;CurrentDir={new_cwd}\007")
print("../test.py:37:1: error: use of undeclared identifier 'sdfsfds'")
print("delay...")

# print(f"changing cwd OSC 1337 to {script_dir}", flush=True)
# sys.stdout.write(f"\033]1337;CurrentDir={script_dir}\007")
# print("./test.py:37:1: error: use of undeclared identifier 'sdfsfds'")
# print("delay...")

OSC 7:

import os
import sys

script_dir = os.path.dirname(os.path.realpath(__file__))

if not os.path.exists("foo"):
    print("make a folder called foo first")
    quit()

new_cwd = os.path.join(script_dir, "foo")
print(f"changing cwd OSC 7 to {new_cwd}", flush=True)
sys.stdout.write(f"\033]7;file://localhost{new_cwd}\007")
print("../test.py:37:1: error: use of undeclared identifier 'sdfsfds'")
print("delay...")

# print(f"changing cwd OSC 7 to {script_dir}", flush=True)
# sys.stdout.write(f"\033]7;file://localhost{script_dir}\007")
# print("./test.py:37:1: error: use of undeclared identifier 'sdfsfds'")
# print("delay...")
  1. Run python3 test.py from the inbuilt terminal.

  2. Observe that Ctrl/Cmd+Click on ../test.py opens test.py as expected.

  3. Uncomment the commented lines.

  4. Run python3 test.py.

  5. Observe that Ctrl/Cmd+Click on ../test.py does not open it. Instead, VSCode spins a while and then pops a file picker.

  6. Observe that Ctrl/Cmd+Click on ./test.py opens test.py as expected.

From iTerm2:

  1. Run python3 test.py, with the lines either commented out or not.

  2. Observe that in both cases, Cmd+Click on ../test.py and ./test.py open test.py as expected.

This seems particularly notable as OSC 1337 is an iTerm2 proprietary escape sequence.

VS Code version: Code 1.95.3 (Universal) (f1a4fb101478ce6ec82fe9627c43efbf9e98c813, 2024-11-13T14:50:04.152Z) OS version: Darwin arm64 24.2.0

Tyriar commented 1 day ago

I think the problem here is that we tie the cwd to the command being run, not the line range. Changing cwd inside a command like this isn't supported and I'm a little surprised to see it works in iTerm2, but I guess they just went the line route instead of linking it to the full execution. @rzhw have you read somewhere official that this is supposed to work? I think you stumbled upon some largely undefined behavior here.

rzhw commented 1 day ago

Ah, I wondered if the similar behavior with OSC 633 ; P ; Cwd was due to OSC 633 being designed for shell integration, and the OSC 1337 and OSC 7 implementations being potentially based off of that and so working off the same assumptions?

I haven't seen anything explicitly saying OSC 7 and OSC 1337 should support multiple subsequent calls, though my naive reading of iTerm2's docs for OSC 1337 and OSC 7:

CurrentDir

OSC 1337 ; CurrentDir=[Ps1] ST

Reports the current directory.

[PS1] is the current directory.

The following synonym is available as a combination of RemoteHost and CurrentDir:

OSC 7 ; [Ps] ST

where [Ps] is a file URL with a hostname and a path, like file://example.com/usr/bin.

And WezTerm's docs for OSC 7:

OSC 7 Escape sequence to set the working directory

OSC 7 means Operating System Command number 7. This is an escape sequence that originated in the macOS Terminal application that is used to advise the terminal of the current working directory.

An application (usually your shell) can be configured to emit this escape sequence when the current directory changes, or just to emit it each time it prints the prompt.

The current working directory can be specified as a URL like this:

printf "\033]7;file://HOSTNAME/CURRENT/DIR\033\\"

When the current working directory has been set via OSC 7, spawning a new tab will use the current working directory of the current tab, so that you don't have to manually change the directory.

If you are on a modern Fedora installation, the defaults for bash and zsh source a vte.sh script that configures the shell to emit this sequence. On other systems you will likely need to configure this for yourself.

Seems to suggest nothing should prevent subsequent calls from working.

rzhw commented 9 hours ago

Thinking about this a bit more, macOS Terminal also doesn't seem to suggest there's limitations on how often OSC 7 can be sent. Rather, it's just for programs to "notify Terminal of the current working directory ... by sending it commands":

Screenshot 2024-11-21 at 14 37 01