Open edencorbin opened 5 years ago
There's a "standard" escape sequence (OSC 7 ; URI ST) to set the terminal emulator's belief about the current directory. It originates from macOS Terminal.app, and was later adopted by some other ones, including GNOME Terminal and as far as I know Konsole too.
Another possible approach is to do some OS-specific hacks to examine the inner state of the child process (or even further down to descendents).
Yet another possibility is to mix the two, e.g. go to the directory set via OSC 7 if it was ever emitted, otherwise dig into the process.
The advantage of the OSC 7 approach is that it's clever regarding when to and when not to follow a child process. E.g. you start another nested subshell, it'll be the subdirectory of that subshell that's taken into account because that one also emits this sequence. However, launch an app that internally changes directory (e.g. make) and it – luckily – won't be make's internal subdir that's used.
The disadvantage of OSC 7 is that it requires cooperation from the shell, or other apps that matter.
I've been rejecting this feature request for as long as this project has been open-source, and I never learned about OSC 7. This is very exciting.
I'm not happy to crawl through the process tree to dig up the leafmost process's CWD, but I am extremely happy to support OSC 7.
FYI I asked about OSC 7 handling for Alacritty, which eventually led to this issue being created in the "Terminal WG" on gitlab: https://gitlab.freedesktop.org/terminal-wg/specifications/issues/20
There's not been much movement on that ticket, but you may be interested to follow it. Especially if you guys have any opinions regarding what a "formal" specification for OSC 7 might look like.
So for the record, the thread at https://github.com/jwilm/alacritty/pull/2937 has a pretty great discussion.
Honestly, I'm pretty okay using the de-facto standard that's already in place, the OSC 7 ; <URI> ST
mechanism. I'm not really sure there needs to be anything more formal than that.
Wait no I had a terrible thought. Say bash
is configured to emit that, and someone runs bash
in WSL. What are we supposed to do when someone tries to set the working directory to /home/zadjii
? How we:
Do we need to add some property on our side that indicates "this is a WSL distro, not a Windows exe"? What happens to users who don't set that, does the duplicate tab functionality just not work (effectively silently)?
Then the next part gets harder. What happens when this command is output over SSH? The terminal can't know that the path isn't on this machine anymore, right? How does Terminal.app handle this?
Maybe this does need more specification 😨
(Off: How long is it going to be until I mix up the two of you, D Howett and D Hewitt? :))
This is a crucial missing feature.
This should be a config option for the different commands. For example, I'd like this for duplicateTab
and splitPane
, but not for newTab
.
the escape sequence is documented in mac os terminal.app preferences as shown by this comment alacritty/alacritty#2937(comment)
On macOS, the escape sequences are actually specified in Terminal.app > Preferences... > Profiles > Tab
For the record, there's heated debate over in https://gitlab.freedesktop.org/terminal-wg/specifications/merge_requests/7 about the specification of exactly this feature. I doubt that we'll support any subset of this feature until there's an actually accepted proposal there - we'd rather not introduce another disparate implementation until there's an actual standard.
I'd recommend you to do the opposite :)
Quite a few terminals have successfully implemented OSC 7, copying from each other, resulting in happy users.
And there is somebody out there currently who thinks it isn't good enough, he thinks a formal specification is needed; comes up with a draft that is full of problems, and what I cannot understand at all, is only willing to document one of two siblings. (Note: I stopped following that thread a couple of days ago.)
Terminal-WG is not a formal authority, its documents aren't "official", aren't "standards" in any de jure way. It doesn't even have proper procedures, people with responsibilities, voting rights, whatever; no one knows what it takes to get a document "accepted" there, whatever this status means at all. It's just a collection of random unorganized folks trying to come up with something useful. Don't let those unofficial pending debates stop you from implementing a long-proven feature.
For the record, there's heated debate over in https://gitlab.freedesktop.org/terminal-wg/specifications/merge_requests/7
i commented it on the issue referenced in that pr too 😉
For anybody using Bash (from Git for Windows), a temporary workaround which has been saving me, is to store the new path every time you change dir (aliasing the cd
command), then cd there when a new shell is started; this is in my .bashrc:
if [ "${PWD,,}" = "/c/windows/system32" ]; then
if [ -f /tmp/pwd ]; then
cd "$(< /tmp/pwd)"
else
cd ~
fi
fi
cd() {
command cd "$@"
pwd > /tmp/pwd
}
I'm actually testing if I start in System32 (my terminal default start location), so that I can still type wt
in the Explorer address bar and start somewhere else, but this bit is optional and should be customized if your shell starts in a different folder.
I'm not fluent enough with the PowerShell or other shells, but I guess you can do something alike.
Ctrl+T should open a new tab with the same shell and the same directory.
Not everybody agrees with that assertion.
Not everybody agrees with that assertion.
Maybe many aggree. That's how terminal app works on most Linux desktop.
Atleast it can be made as an option.
Hi, I believe it is already clear in this thread that many agree this is a useful feature, and the Windows Terminal team is also ware of this. And it is also clear that the problem here is not they don’t want to make this configurable, but they need to first figure out some technical stuff that prevents the feature from being possible.
I follow this thread to keep up to date on this feature and related discussions, but the messages like this only clutter the interface and do not help. I want to ask people to please refrain from posting messages that do little other than reiterating points that are already known.
Atleast it can be made as an option
This is what I don't get about the stubbornness. If you want to go against how most terminals behave, cool. Not even giving an option though? Where's the logic in that? Even Ctrl+Shit+D that represents duplicating a tab doesn't actually duplicate it as it sticks you in the default directory. Like you have a duplicate feature that doesn't even duplicate.
What's the "technical stuff" that prevents this feature from being possible? The code already exists. There's already a duplicate tab in Ctrl+Shift+D. It just needs to be fed the current working directory and you have the behaviour that most people are used to and that people are requesting. So I'm confused at how this has "technical stuff" blocking it.
I appreciate this type of discussion because it's quite clear that there is stubbornness involved which means this type of discussion is necessary.
Ah you're right, the original discussion is lost, because it didn't ever get linked to this thread. I'm copying the content of another post (https://github.com/microsoft/terminal/issues/2427#issuecomment-521307534) here for reference:
Just chiming in;
(profile,working dir, environment var, etc).
Anything about the actual process on the other end is, in the general case, impossible to replicate. The connected process could be
ssh.exe
, whose environment variables and working directory have no bearing on the detectable environment and working directory from the terminal side. The same actually, weirdly enough, applies to WSL. It doesn't use "working directory" and it doesn't expose its environment variables to interested Windows processes in any way.Powershell doesn't even set the current working directory, so its directory can't be detected (!) either.
This is one of those things that is impossible in the general case but technically possible. There's a lot of intricacies here, like:
cmd powershell cd d:\users
well, powershell isn't the first process we launched. we'd ignore the path
d:\users
(in powershell) cd d:\users
we'd ignore
d:\users
because powershell doesn't actually set the current working directory (!!)If your "shell" is
ssh dustin@example.com
(where we strictly define shell to be "the first process Terminal spawns on your behalf"), its working directory is always going to beC:\windows\system32
regardless of what the remote working directory is.I'd rather not provide the feature than provide the feature with so many caveats that they'd fill a documentation page. ☹️ sorry.
No, because that would likely be neigh impossible to do in a general sense. How would we duplicate an instance of vim for example? What if the foreground process has opened some sort of file for exclusive access - how could we duplicate that process?
If there's a way this can be done safely and generally I'm all ears for proposed technical solutions, but I don't think it's something that's possible, so I'm not going to be investigating it.
Even if Powershell did set the working directory, we're still not positive that it's technically possible on Windows to get the CWD of another process. So that's the "technical" stuff that's preventing this from working. I'd love to add this as a setting. But there are definitely still technical questions that need answering.
The solution that's being discussed in this thread involves adding support for another VT sequence to the Terminal, that the shell would be able to emit to clue the Terminal in to what path it's in. This VT sequence isn't super well defined, and has edge cases that still need solving. Namely:
/home/foo
? There's no way for the Terminal to know that path is a WSL path, or even which distro it belongs to, so duplicating this tab would likely end up in C:\home\foo
(if it exists)You're trying to duplicate the running processes? Let's look at Linux for example. If you're running SSH in your terminal and open a new tab, the new tab doesn't open an SSH connection and browse to where you are in the SSH connection. It opens up a new tab where you are on your machine. Even if the process was local and not SSH it doesn't run the process. All that's being duplicated is the tab, not the running processes.
It sounds like this is being overly complicated. You aren't duplicating VIM or SSH or any other application that's running. You're duplicating the terminal and that answers the edge cases:
There's nothing wrong with duplicating the processes. I'm sure some would love that. It's just that would be another option on top of the option to duplicate the tabs. It shouldn't be a road-block. That's extra and optional.
@PandaClone it might surprise you to learn that some people set ssh.exe as the first thing that a profile launches, without running it from a shell.
Like as not, there really isn’t a way for the Terminal to interrogate wsl.exe
, the wrapper application that communicates with Linux processes, to get it to say what the current working directory is of the first process in its process tree.
Because it doesn’t use the windows working directory infrastructure, which stores the WD in the process environment block, just using the boring old Windows APIs is not sufficient to tell what its working directory is.
These are technical problems that we have to solve. Otherwise, we write a feature that only works for, like, 25% of people.
If it proves to be easy: we are always willing to accept community contributions.
- For WSL you aren't browsing your local. If the return is /home/foo that's the location. If the location was C:\home\foo it would return /mnt/c/home/foo.
Ah but see, the way this feature works as spec'd, the Terminal doesn't know who or what said "The current working directory is /home/foo
". This could be cmd.exe
- then yea, the user wants C:\home\foo
. This could be their Ubuntu distro, or their Fedora distro, or this could be ssh connected to centos or any other possibility. All the terminal gets is a string saying "this is the working directory now".
- I'm not sure what the user would have to customize, but since when is customization an issue?
Pretty much every shell the user runs is going to need to manually be configured to enable sending this sequence. For cmd
users, they'll need to manually configure their %PROMPT% to include the sequence $e]7;$P$e
. bash
users will need to set it up in their PS1
. PowerShell will certainly have another way to do it. The fundamental issue here though is that the shells don't emit this sequence by default.
SSH isn't a shell. You can set your profile to run it first, but it's still being run from the shell. It's just your profile is being instructed to run an application immediately. That application can be anything. It doesn't have to SSH. You can instruct your profile to run another shell if you wanted to.
And even in the case that there is no terminal, how is that a problem? There are always exceptions. Defaulting to the home directory when there is no directory to go to is fine. That's not a problem where you just "oh this can't be done".
Also, this is a feature that's standard in the majority terminals with tabs. Run any Linux distro which has their own terminal flavours and they all exhibit this behaviour of opening a new tab. This isn't a feature that's going to be ground breaking magic for Windows Terminal. It's a standard feature.
Terminal doesn’t just spawn shells. It literally calls CreateProcess
on the thing you provide in the profile config. SSH isn’t running in, or spawned by, a shell.
Look, we’re arguing about how possible this feature is. Can we just agree that we want this, everyone wants it, and if we had a reasonable way forward that worked in the vast majority of the use cases users care about that we would have done it already? I’m trying to reduce the number of times we have to say “on that can’t be done” with some upfront planning and design work.
It’s not groundbreaking magic, it’s just complicated by the Windows and WSL process model and we think it’ll fall over in some circumstances. Nobody’s saying anything more than that.
- For WSL you aren't browsing your local. If the return is /home/foo that's the location. If the location was C:\home\foo it would return /mnt/c/home/foo.
Ah but see, the way this feature works as spec'd, the Terminal doesn't know who or what said "The current working directory is
/home/foo
". This could becmd.exe
- then yea, the user wantsC:\home\foo
. This could be their Ubuntu distro, or their Fedora distro, or this could be ssh connected to centos or any other possibility. All the terminal gets is a string saying "this is the working directory now".
How doesn't it know who or what said the current working directory is? You're the one asking for it. You know whether it's a Command Prompt or a WSL or a PowerShell. You know where it's coming from so you know how to format the location.
- I'm not sure what the user would have to customize, but since when is customization an issue?
Pretty much every shell the user runs is going to need to manually be configured to enable sending this sequence. For
cmd
users, they'll need to manually configure their %PROMPT% to include the sequence$e]7;$P$e
.bash
users will need to set it up in theirPS1
. PowerShell will certainly have another way to do it. The fundamental issue here though is that the shells don't emit this sequence by default.
How is that a problem? This wouldn't be the first application to require configuration and it won't be the last. Not everything is plug and play and that's understandable. If the only way to make this work is for the user to require a configuration, how is that stopping point?
What happens when a WSL shell says "my CWD is /home/foo? There's no way for the Terminal to know that path is a WSL path, or even which distro it belongs to, so duplicating this tab would likely end up in C:\home\foo (if it exists)
I can only really speak for myself, but if I had a tab open using one profile, navigated somewhere specific, and then opened a new tab in a different profile, it would not surprise or disappoint me in the slightest if the working dir did not carry over, and the default was used instead.
I think you understand that most people asking for this feature are missing the behaviour in terminals such as those included with GNOME and macOS. Those terminals don't have to deal with the same complexities that this does, but at the same time, I don't think anyone is expecting you to try and smartly handle edge cases that simply don't exist in the software they're using as a reference point.
It sounds like a pretty hairy task even if you reduce the scope somewhat though. I hope a way can be found to include some version of this feature, as it is a nice time saver.
Could this use case be handled by #4472 in the short term? I'd personally be content with some variant of cmd.exe /c "wt.exe" new-tab -p "Ubuntu-20.04" -d $(pwd)
(probably bound to a Bash macro) that would open up a new tab in the most recently focused window (which is almost certainly the window that I typed the command in).
Gonna go out on a limb and say that implementing detection for the root process's current directory is easier than implementing commandline remoting and IPC to get WT to open tabs in the same window :smile:
wow, i just came here and realize that it seems need a long journey :)
We found that in windows terminal we could split the shell windows by press shortcut alt+shift+D, but it doesn't set to same directory
I've come with a workaround: change the starting directory.
Put this function into $PROFILE
(make sure to adjust $path
)
function sd {
$path = 'C:\Users\Admin\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'
((Get-Content -path $path) -replace '"startingDirectory":.*', ("`"startingDirectory`": `"$pwd`"") -replace "\\", "\\") | Set-Content -Path $path
}
.. and you'll be able to a open new tab in the same directory almost with no hassle, just make sure to type sd
before opening a new tab.
Of course, the drawback is that startingDirectory
is changed every time the function is called.
It would be best to use this approach with a key re-mapper, so that when Ctrl+T
is pressed the function is called automatically, and when Ctrl+F4
is pressed startingDirectory
is reverted back to its original value.
Inside whatever profile you are using example profile.sh or .zshrc create a ~/paths.sh file located within your $HOME directory. Paths will be updated whenever you call setCWD
This solution overrides the startingDirectory completely. Whenever you spawn a new terminal call setCWD before spawning the terminal and it will always start in the directly you last called setCWD in.
Note that I did this within .zshrc
Code:
source ~/paths.sh
if [[ $SAVED_PWD != $PWD ]]
then
cd $SAVED_PWD
fi
function setCWD(){
echo export SAVED_PWD=$(pwd) > ~/paths.sh
}
You may need to create an initial file so just call setCWD.
BTW if you are using autohotkey, here's a nice and quick script to get things working
Make a file called windows-terminal.ahk
and then paste this code below. Run the file and you are all set. (I recommend moving this file into the startup section so that when you restart this functionality is re-applied.
#IfWinActive, ahk_exe WindowsTerminal.exe
^t::
Send, setCWD {enter}
Send, ^t
Guys, this is very important for productivity, almost like it's above everything else. Please fix this, me and my friends will happily abandon all of the other inferior terminal emulators.
It looks like the attempt to 'standardise' OSC 7 at terminal-wg has stalled.
Is there still interest in implementing OSC 7 basically as it stands in Terminal.app?
Given that, we'd have "current host and CWD" for a given terminal, which just blats the 'process hacking' discussion; and then can decide/implement the user behaviours to make use of that information, e.g.,:
This discussion was very focused on the first part (getting the current CWD) but I suspect the second part is the one that will need more consideration, based on the existing comments so far above. Even for that list of ideas, I'm sure a reasonable objection exists to every one of them.
For those who are still intersted in this topic, I made a early PR in #7668 . This is a a friendly ping. I'd really love to hear from everyone about it.
What is the point of multiple tabs, especially fast duplication, if they don't inherit the current directory? This is such an important feature. Why not add a "hacky" workaround for now? I really don't see a problem extracting CWD from a process on Windows if it increases productivity for all the users, considering Windows itself has contained multiple such solutions for more than 20 years.
I can't understand why this feature isn't the default. I truly am boggled as to why there isn't even a way to enable this feature. This is the biggest user experience detractor I have with Terminal: from an expedience perspective I am better served by not using Terminal and instead using explorer and right clicking in the directory I want to open the shell and selecting "Open PowerShell window here" because it's faster than hitting alt+shift+d
then having to cd
to the right place.
Terminal adds a lot of quality of life for Windows devs. This feature would be huge jump forward for me (and I suspect others). I'll add my voice in advocating for this feature be a top priority.
I can't understand why this feature isn't the default.
I can't understand why people can't be bothered to read all the investigation that's been done in this thread, in #7668, #8214, #8166, and the other linked threads, to understand why this is actually a hard problem to solve. It turns out you can't just have a client app emit it's path - because the Terminal won't necessarily know whether that's a Windows or a WSL or a cygwin path.
It's a good thing we've got a bunch of talented contributors who are hard at work finding out the right way of implementing support for this feature, without breaking backwards-compatibility for other apps. We've just this week come up with a solution we're happy with, shouldn't be long before it's implemented.
Thanks @zadjii-msft !
In rereading my comment I'm realizing it comes off super accusatory and that was not my intent. I came here to say this:
Terminal adds a lot of quality of life for Windows devs. This feature would be huge jump forward for me (and I suspect others). I'll add my voice in advocating for this feature be a top priority.
And that my user experience so far has been this:
I can't understand why this feature isn't the default. I truly am boggled as to why there isn't even a way to enable this feature. This is the biggest user experience...etc
I probably should have put "as a user," at the beginning of my first paragraph.
I apologize for any offense I've given.
Happy new year :D I hope this feature so so much
I've found a very simple solution to this. What you need to do is execute a function on every cd command and save that somewhere so that it can be read on new instance.
To achieve this, you will modify your shell config file. I am using Fish shell on my machine (that uses ruby-like syntax), but you may convert this syntax to make it work for others. (tested on Zsh)
Add following to the /root/.config/fish/config.fish
or your shell's equivalent.
function cd
builtin cd $argv
pwd > ~/.last_dir
end
if test -f ~/.last_dir
cd ( cat ~/.last_dir )
end
⭐As a bonus, if I shutdown/restart my PC and open terminal again I automatically cd into my last project directory. Cool! 😎
I've found a very simple solution to this. What you need to do is execute a function on every cd command and save that somewhere so that it can be read on new instance.
To achieve this, you will modify your shell config file. I am using Fish shell on my machine (that uses ruby-like syntax), but you may convert this syntax to make it work for others. (tested on Zsh)
Add following to the
/root/.config/fish/config.fish
or your shell's equivalent.function cd builtin cd $argv pwd > ~/.last_dir end if test -f ~/.last_dir cd ( cat ~/.last_dir ) end
⭐As a bonus, if I shutdown/restart my PC and open terminal again I automatically cd into my last project directory. Cool! 😎
Nice, thanks!
The shell script version if this:
cd() {
builtin cd $argv
pwd > ~/.last_dir
}
if [ -f ~/.last_dir ]; then
cd `cat ~/.last_dir`
fi
I've tried a similar solution to @azterizm's one in the past. Always opening a terminal in the previous cd
location can be inconvenient in some situations :
I've tried a similar solution to @azterizm's one in the past. Always opening a terminal in the previous
cd
location can be inconvenient in some situations :
- When we open a terminal from a custom location (for instance, in an explorer with a "Open a terminal here" option
- When PowerShell is embedded in another tool (e.g. in an IDE)
About the option in the context menu "Open a terminal here", we can make a script for this.
A script that takes the directory of where the context menu was called from, then we convert the slashes to what Linux uses (C:\
to /mnt/c
) then run the Linux command from Powershell that updates ~/.last_dir
. Finally in the same script, open the terminal normally. It will be exactly what you want.
The command that will update the file should be wsl /mnt/c >> ~/.last_dir
Currently, I do not know how to make scripts for Powershell but surely someone should try that.
As for the IDE's or other embedded tools, we might need to add a script to them that clears ~/.last_dir
file on opening the terminal in there.
You'll need your shell to generate the OSC 9;9
messages, and once that's working, you will get this behaviour for duplicating tabs and splitting panes when that release happens.
This is compatible with ConEmu, so ConEmu's OSC 9;9 "How to set it up" instructions should roughly work, where they use ANSI codes rather than ConEmuC
; the "WSL/cygwin/msys" instructions need to be adjusted as they generate Unix paths, and for Windows Terminal you need Windows paths.
These instructions also do a bunch more, the part you need is the part that generates the 9;9
message, I am unaware of Windows Terminal consuming the 9;12
message, but of course it wouldn't hurt.
e.g. for PowerShell, the given example can be trimmed to this for the minimal change:
function prompt
{
$loc = Get-Location
# Emulate standard PS prompt with location followed by ">"
$out = "PS $loc> "
# Add current working directory (FileSystem)
if ($loc.Provider.Name -eq "FileSystem") {
$out += "$([char]27)]9;9;`"$($loc.Path)`"$([char]7)"
}
return $out
}
Note: I haven't tested this myself, but I wanted to make sure people knew this feature desire wasn't being ignored.
The author of #8330 here. I can confirm it in fact works with the current dev branch. It should be available in 1.6 preview.
I've found a very simple solution to this. What you need to do is execute a function on every cd command and save that somewhere so that it can be read on new instance. To achieve this, you will modify your shell config file. I am using Fish shell on my machine (that uses ruby-like syntax), but you may convert this syntax to make it work for others. (tested on Zsh) Add following to the
/root/.config/fish/config.fish
or your shell's equivalent.function cd builtin cd $argv pwd > ~/.last_dir end if test -f ~/.last_dir cd ( cat ~/.last_dir ) end
⭐As a bonus, if I shutdown/restart my PC and open terminal again I automatically cd into my last project directory. Cool! 😎
Nice, thanks!
The shell script version if this:
cd() { builtin cd $argv pwd > ~/.last_dir } if [ -f ~/.last_dir ]; then cd `cat ~/.last_dir` fi
for bash, $argv should be $1
In a cmd
environment I call start
to open a new console. Can Terminal not capture a call to start
and open a new tab instead?
no that would require #492 run this on cmd to make ctrl+shift+d keep the current dir (will have to restart the current cmd for it to take effect)
setx PROMPT $E]9;9;$P$E\$P$S
Is OSC 9;9 something that can be natively supported by shells? Should I file an issue in PowerShell repo?
Description of the new feature/enhancement
Have the option (or default) of a new terminal tab opening in the current directory of the window of which you hit the hotkey to open a new tab. This is the standard way most linux terminals work and is most handy. I often work in a directory where I need to launch multiple seperate processes, its a pain to CD back into the directory each time.
Proposed technical implementation details (optional)
Hit the new tab hotkey, the new terminal should then be in the same folder as the previouse.
maintainer edit: Before commenting, make sure to check out
Tutorial: Opening a tab or pane in the same directory in Windows Terminal
This is largely something configurable today, this issue is just tracking another way of configuring this