Terminal: 在与现有选项卡(OSC 7?)相同的目录中打开新的终端选项卡

创建于 2019-10-11  ·  39评论  ·  资料来源: microsoft/terminal

新功能/增强功能的描述

在您点击热键打开新选项卡的窗口的当前目录中,可以选择(或默认)打开一个新的终端选项卡。 这是大多数 linux 终端工作的标准方式,也是最方便的。 我经常在一个目录中工作,我需要在其中启动多个单独的进程,每次都将 CD 放回到目录中很痛苦。

建议的技术实施细节(可选)

点击新选项卡热键,新终端应该与之前的文件夹位于同一文件夹中。

Area-Settings Area-VT In-PR Issue-Feature Product-Conpty Product-Powershell Product-Terminal

最有用的评论

这是一个关键的缺失功能。

所有39条评论

有一个“标准”转义序列 (OSC 7 ; URI ST) 来设置终端仿真器对当前目录的置信度。 它起源于 macOS Terminal.app,后来被其他一些应用程序采用,包括 GNOME Terminal 和据我所知的 Konsole。

另一种可能的方法是进行一些特定于操作系统的 hack 来检查子进程的内部状态(甚至更深入到后代进程)。

另一种可能性是将两者混合,例如,如果曾经发出过 OSC 7,则转到通过 OSC 7 设置的目录,否则深入研究该过程。

OSC 7 方法的优点是它很聪明地决定了何时跟随子进程以及何时不跟随子进程。 例如,您启动另一个嵌套子shell,它将考虑该子shell 的子目录,因为该子shell 也发出此序列。 但是,启动一个在内部更改目录(例如 make)的应用程序,幸运的是,它不会是 make 使用的内部子目录。

OSC 7 的缺点是它需要 shell 或其他重要应用程序的协作。

只要这个项目是开源的,我就一直拒绝这个功能请求,而且我从来没有了解过 OSC 7。这_非常令人兴奋。_

我不高兴爬过进程树来挖掘最叶进程的 CWD,但我非常高兴支持 OSC 7。

仅供参考,我询问了 Alacritty 的 OSC 7 处理,这最终导致在 gitlab 的“终端工作组”中创建了这个问题: https ://gitlab.freedesktop.org/terminal-wg/specifications/issues/20

那张票上没有多少动静,但您可能有兴趣关注它。 特别是如果你们对 OSC 7 的“正式”规范可能是什么样子有任何意见。

所以作为记录, https://github.com/jwilm/alacritty/pull/2937上的线程有一个很好的讨论。

老实说,我可以很好地使用已经存在的事实标准,即OSC 7 ; <URI> ST机制。 我不确定是否需要比这更正式的东西。


等等,我有一个可怕的想法。 假设bash被配置为发出它,有人在 WSL 中运行bash 。 当有人试图将工作目录设置为/home/zadjii时,我们应该怎么做? 我们如何:

  1. 告诉这是一个 WSL 路径,而不是 Windows 路径
  2. 知道这来自哪个 WSL 发行版吗?

我们是否需要在我们这边添加一些属性来表明“这是一个 WSL 发行版,而不是 Windows exe”? 没有设置它的用户会发生什么,重复选项卡功能是否不起作用(有效地静默)?

然后下一部分变得更难。 当这个命令通过 SSH 输出时会发生什么? 终端不能知道路径不再在这台机器上,对吧? Terminal.app 如何处理这个问题?

也许这确实需要更多的规范😨

(关:要多久才能把你们两个 D Howett 和 D Hewitt 混在一起?:))

这是一个关键的缺失功能。

这应该是不同命令的配置选项。 例如,我希望duplicateTabsplitPane ,但不希望newTab

转义序列记录在 mac os terminal.app 首选项中,如此评论所示alacritty/alacritty#2937(comment)

在 macOS 上,转义序列实际上是在 Terminal.app > Preferences... > Profiles > Tab 中指定的69387948-67d69d00-0c95-11ea-881d-375672873fb4

作为记录,在https://gitlab.freedesktop.org/terminal-wg/specifications/merge_requests/7 中有关于这个特性的规范的激烈争论。 我怀疑我们是否会支持此功能的任何子集,直到那里有一个实际接受的提案 - 在有实际标准之前,我们宁愿不引入另一个不同的实现。

我建议你做相反的事情:)

不少终端都成功实现了OSC 7,互相抄袭,用户满意。

目前有人认为它不够好,他认为需要一个正式的规范; 出一个满是问题的草稿,完全看不懂,只愿意记录两个兄弟中的一个。 (注意:几天前我停止关注该线程。)

Terminal-WG 不是正式的权威,它的文件在任何法律上都不是“官方的”,也不是“标准”。 它甚至没有适当的程序、责任人、投票权等等; 没有人知道要在那里“接受”一份文件需要什么,无论这种状态意味着什么。 这只是一群随机的、无组织的人试图想出一些有用的东西。 不要让那些非官方的悬而未决的辩论阻止您实现长期验证的功能。

作为记录,在https://gitlab.freedesktop.org/terminal-wg/specifications/merge_requests/7 中有激烈的争论

我也评论了那个公关中提到的问题😉

对于任何使用 Bash(来自 Windows 的 Git)的人来说,一个临时的解决方法一直在拯救我,是在每次更改目录时存储新路径(别名cd命令),然后在新 shell 时 cd 那里已启动; 这是在我的 _.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
}

我实际上是在测试我是否从 System32(我的终端默认开始位置)开始,以便我仍然可以在资源管理器地址栏中键入wt并从其他地方开始,但该位是可选的,如果您的外壳在不同的文件夹中启动。

我对 PowerShell 或其他 shell 不够流利,但我想您可以做类似的事情。

Ctrl+T 应该打开一个具有相同 shell 和相同目录的新选项卡。

并非所有人都同意这种说法。

并非所有人都同意这种说法。

也许很多人都同意。 这就是终端应用程序在大多数 Linux 桌面上的工作方式。

至少它可以作为一个选项。

嗨,我相信在这个帖子中已经很清楚很多人都同意这是一个有用的功能,Windows 终端团队也意识到了这一点。 而且很明显,这里的问题不是他们不想让这个可配置,而是他们需要首先弄清楚一些阻止该功能成为可能的技术问题

我关注此线程以了解有关此功能和相关讨论的最新信息,但此类消息只会使界面混乱且无济于事。 我想请人们不要发布除了重申已经知道的观点之外没有什么作用的信息。

至少它可以作为一个选项

这是我不明白的固执。 如果你想反对大多数终端的行为方式,那很酷。 甚至不给一个选择? 这其中的逻辑在哪里? 即使代表复制选项卡的 Ctrl+Shit+D 实际上也不会复制它,因为它会将您粘在默认目录中。 就像您有一个甚至不重复的重复功能一样。

阻止此功能实现的“技术内容”是什么? 代码已经存在。 Ctrl+Shift+D 中已经有一个重复的选项卡。 它只需要提供当前工作目录,并且您拥有大多数人习惯的和人们请求的行为。 所以我很困惑这如何有“技术性的东西”阻止它。

我很欣赏这种类型的讨论,因为很明显其中涉及顽固,这意味着这种类型的讨论是必要的。

啊,您说得对,原始讨论丢失了,因为它从未与此线程相关联。 我正在复制另一篇文章(https://github.com/microsoft/terminal/issues/2427#issuecomment-521307534)的内容以供参考:


https://github.com/microsoft/terminal/issues/1756#issuecomment -520048598

只是插嘴;

_(配置文件、工作目录、环境变量等)。_

在一般情况下,关于另一端的_实际过程_的任何事情都是无法复制的。 连接的进程可能是ssh.exe ,其环境变量和工作目录与终端侧的可检测环境和工作目录无关。 奇怪的是,实际上同样适用于 WSL。 它不使用“工作目录”,也不以任何方式将其环境变量暴露给感兴趣的 Windows 进程。

Powershell 甚至不会_设置_当前工作目录,因此也无法检测到它的目录(!)。

https://github.com/microsoft/terminal/issues/2315#issuecomment -519317472

这是在一般情况下不可能但_技术上可行_的事情之一。 这里有很多错综复杂的地方,例如:

powershell
cd d:\users

好吧,powershell 并不是我们启动的第一个进程。 我们会忽略路径d:\users

(in powershell)
cd d:\users

我们会忽略d:\users因为 powershell _doesn 实际上没有设置当前工作目录_ (!!)

如果你的“shell”是ssh [email protected] (我们严格地将 shell 定义为“代表你生成的第一个进程终端”),它的工作目录总是C:\windows\system32不管它是什么远程工作目录是。

我宁愿不提供该功能,也不愿为该功能提供太多警告,以至于它们会填满文档页面。 ☹️ 对不起。

https://github.com/microsoft/terminal/issues/1536#issuecomment -519107586

不,因为这在一般意义上几乎不可能做到。 例如,我们如何复制 vim 的实例? 如果前台进程打开了某种文件以进行独占访问怎么办 - 我们如何复制该进程?

如果有一种方法可以安全地做到这一点,并且通常我对提出的技术解决方案全神贯注,但我认为这是不可能的,所以我不打算调查它。


即使 Powershell _did_ 设置了工作目录,我们仍然不确定在 Windows 上_技术_可能获得另一个进程的 CWD。 所以这就是阻止它工作的“技术”东西。 我很想将其添加为设置。 但肯定还有技术问题需要回答。

该线程中正在讨论的解决方案涉及向终端添加对另一个 VT 序列的支持,_shell_ 将能够发出以提示终端进入它所在的路径。这个 VT 序列没有很好地定义,并且具有仍然需要解决的边缘情况。 即:

  • 当 WSL shell 说“我的 CWD 是/home/foo什么?终端无法知道该路径是 WSL 路径,甚至无法知道它属于哪个发行版,因此复制此选项卡可能最终会出现在C:\home\foo (如果存在)
  • 当您通过 SSH 连接到另一台机器时会发生什么? 终端将无法将这些路径与您自己本地机器上的路径区分开来,因此再次复制该路径将是错误的行为
  • 每个用户都需要_手动_自定义他们对各种 shell 的提示以配合此行为。 这不是一个阻止程序,但这确实意味着它将是一个不能开箱即用的设置。

您正在尝试复制正在运行的进程? 让我们以 Linux 为例。 如果您在终端中运行 SSH 并打开一个新选项卡,则新选项卡不会打开 SSH 连接并浏览到您在 SSH 连接中的位置。 它会在您的机器上打开一个新选项卡。 即使该进程是本地的而不是 SSH,它也不会运行该进程。 所有被复制的是选项卡,而不是正在运行的进程。

听起来这太复杂了。 您不会复制 VIM 或 SSH 或任何其他正在运行的应用程序。 您正在复制终端并回答边缘情况:

  • 对于 WSL,您不是在浏览本地。 如果返回是 /home/foo 那就是位置。 如果位置是 C:\home\foo,它将返回 /mnt/c/home/foo。
  • SSH 是一个过程。 它在 shell 中运行。 您不是在复制流程。 其他终端没有。 您正在复制选项卡。
  • 我不确定用户必须自定义什么,但是从什么时候开始自定义是一个问题?

复制流程并没有错。 我相信有些人会喜欢那个。 这只是复制选项卡选项之上的另一个选项。 应该不是路障。 这是额外的和可选的。

@PandaClone您可能会惊讶地发现_有些人将 ssh.exe 设置为配置文件启动的第一件事,而不是从 shell_ 运行它。

就像不是一样,终端确实没有办法询问wsl.exe ,与 Linux 进程通信的包装应用程序,让它说出其进程中第一个进程的当前工作目录是什么树。
因为它不使用 Windows 工作目录基础结构,它将 WD 存储在进程环境块中,仅使用无聊的旧 Windows API _不足以说明其工作目录是什么。_

这些都是我们必须解决的技术问题。 否则,我们编写的功能仅适用于 25% 的人。

如果事实证明这很容易:我们总是愿意接受社区贡献。

  • 对于 WSL,您不是在浏览本地。 如果返回是 /home/foo 那就是位置。 如果位置是 C:\home\foo,它将返回 /mnt/c/home/foo。

啊,但是看,这个功能按照规范工作的方式,终端不知道谁或什么说“当前工作目录是/home/foo ”。 这可能是cmd.exe - 那么是的,用户想要C:\home\foo 。 这可能是他们的 Ubuntu 发行版,或他们的 Fedora 发行版,或者这可能是 ssh 连接到 centos 或任何其他可能性。 终端得到的只是一个字符串,上面写着“这是现在的工作目录”。

  • 我不确定用户必须自定义什么,但是从什么时候开始自定义是一个问题?

几乎用户运行的每个 shell 都需要手动配置以启用发送此序列。 对于cmd用户,他们需要手动配置他们的 %PROMPT% 以包含序列$e]7;$P$ebash用户需要在他们的PS1 。 PowerShell 肯定会有另一种方法来做到这一点。 但这里的基本问题是默认情况下,shell _不_ 发出此序列。

SSH 不是外壳。 您可以将配置文件设置为首先运行它,但它仍在从外壳运行。 只是您的个人资料被指示立即运行应用程序。 该应用程序可以是任何东西。 它不必通过 SSH。 如果需要,您可以指示您的配置文件运行另一个 shell。

即使在没有终端的情况下,这又是怎么回事? 总有例外。 当没有目录可转到时,默认到主目录是可以的。 这不是一个问题,你只是“哦,这不可能完成”。

此外,这是大多数带有选项卡的终端的标准功能。 运行任何具有自己终端风格的 Linux 发行版,它们都表现出这种打开新选项卡的行为。 对于 Windows 终端来说,这不是一项具有开创性意义的功能。 这是标准功能。

终端不只是产生贝壳。 它从字面上调用CreateProcess对您在配置文件配置中提供的内容。 SSH 不是在 shell 中运行,也不是由 shell 产生的。

看,我们正在争论这个功能有多可能。 我们是否可以同意_我们想要这个,每个人都想要它,如果我们有一个合理的前进方式,可以在用户关心的绝大多数用例中工作_我们早就这样做了吗? 我试图通过一些前期的规划和设计工作来减少我们不得不说“不能完成”的次数。

这不是开创性的魔法,它只是被 Windows 和 WSL 进程模型复杂化了,我们认为在某些情况下它会失败。 没有人会说更多。

  • 对于 WSL,您不是在浏览本地。 如果返回是 /home/foo 那就是位置。 如果位置是 C:\home\foo,它将返回 /mnt/c/home/foo。

啊,但是看,这个功能按照规范工作的方式,终端不知道谁或什么说“当前工作目录是/home/foo ”。 这可能是cmd.exe - 那么是的,用户想要C:\home\foo 。 这可能是他们的 Ubuntu 发行版,或他们的 Fedora 发行版,或者这可能是 ssh 连接到 centos 或任何其他可能性。 终端得到的只是一个字符串,上面写着“这是现在的工作目录”。

它怎么不知道当前工作目录是谁或说什么? 你是那个要求它的人。 您知道它是命令提示符、WSL 还是 PowerShell。 您知道它来自哪里,因此您知道如何格式化该位置。

  • 我不确定用户必须自定义什么,但是从什么时候开始自定义是一个问题?

几乎用户运行的每个 shell 都需要手动配置以启用发送此序列。 对于cmd用户,他们需要手动配置他们的 %PROMPT% 以包含序列$e]7;$P$ebash用户需要在他们的PS1 。 PowerShell 肯定会有另一种方法来做到这一点。 但这里的基本问题是默认情况下,shell _不_ 发出此序列。

怎么会有问题? 这不会是第一个需要配置的应用程序,也不会是最后一个。 并非一切都是即插即用的,这是可以理解的。 如果使这项工作起作用的唯一方法是让用户需要进行配置,那么停止点如何?

当 WSL shell 说“我的 CWD 是 /home/foo?终端无法知道该路径是 WSL 路径,甚至它属于哪个发行版时,会发生什么情况,因此复制此选项卡可能会以 C 结尾: \home\foo(如果存在)

我只能为自己说话,但是如果我使用一个配置文件打开了一个选项卡,导航到特定的某个地方,然后在不同的配置文件中打开一个新选项卡,如果工作目录没有,我一点也不感到惊讶或失望结转,并改为使用默认值。

我想您明白大多数要求此功能的人都缺少终端中的行为,例如 GNOME 和 macOS 中包含的终端。 这些终端不必处理与此相同的复杂性,但与此同时,我认为没有人希望您尝试并巧妙地处理它们所使用的软件中根本不存在的边缘情况用作参考点。

即使您稍微缩小范围,这听起来也是一项艰巨的任务。 我希望可以找到一种方法来包含此功能的某个版本,因为它可以节省大量时间。

这个用例可以在短期内由#4472 处理吗? 我个人对cmd.exe /c "wt.exe" new-tab -p "Ubuntu-20.04" -d $(pwd)某些变体(可能绑定到 Bash 宏)感到满意,它会在最近聚焦的窗口中打开一个新选项卡(几乎可以肯定是我在其中键入命令的窗口) )。

我要大胆地说,对根进程的当前目录实施检测比实施命令行远程处理和 IPC 更容易让 WT 在同一窗口中打开选项卡 :smile:

哇,我刚到这里就意识到这似乎需要一段漫长的旅程:)

我们发现在windows终端我们可以通过快捷键alt+shift+D来拆分shell窗口,但是没有设置到同一个目录下

我提出了一个解决方法:更改起始目录。

把这个函数放入$PROFILE (一定要调整$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
}

.. 并且您几乎可以毫不费力地在同一目录中打开新选项卡,只需确保在打开新选项卡之前键入sd

当然,缺点是每次调用函数时都会改变startingDirectory

这将是最好用这个办法一键重新映射,这样当Ctrl+T按下功能自动启动,并在Ctrl+F4startingDirectory正在恢复恢复到原来的价值。

替代方案

里面什么个人资料使用的是例如profile.sh.zshrc创建位于$ HOME目录中的〜/ paths.sh文件。 每当您调用setCWD时,路径都会更新

此解决方案完全覆盖了起始目录。 每当您在生成终端之前生成新的终端调用 setCWD 时,它将始终以您上次调用setCWD的方式直接启动。

请注意,我在.zshrc内完成了此操作

代码:

source ~/paths.sh

if [[ $SAVED_PWD != $PWD  ]]
then
  cd $SAVED_PWD
fi

function setCWD(){
  echo export SAVED_PWD=$(pwd) > ~/paths.sh
}

您可能需要创建一个初始文件,因此只需调用setCWD

顺便说一句,如果您使用的是自动热键,这里有一个很好且快速的脚本来使事情正常进行

创建一个名为windows-terminal.ahk ,然后将此代码粘贴到下面。 运行该文件,一切就绪。 (我建议将此文件移动到启动部分,以便在您重新启动时重新应用此功能。

#IfWinActive, ahk_exe WindowsTerminal.exe
  ^t::
    Send, setCWD {enter}
    Send, ^t

伙计们,这对生产力非常重要,几乎就像它高于一切一样。 请解决这个问题,我和我的朋友会很乐意放弃所有其他劣质终端模拟器。

看起来在终端工作组“标准化”OSC 7 的尝试已经停滞

是否仍然有兴趣实现 OSC 7 基本上就像它在Terminal.app 中一样

鉴于此,我们将为给定的终端提供“当前主机和 CWD”,这只是对“进程黑客”的讨论; 然后可以决定/实施用户行为以利用该信息,例如:

  • “当前目录中的新选项卡”命令;
  • 默认情况下使“拆分”执行此操作;
  • 将 WSL 会话与 Windows 会话区分开来的魔法(如果它们甚至报告相同的主机名?我没看过...);
  • 在您_知道_的配置文件中,“抑制 OSC 7”的配置选项将发送您不想使用的看起来有效的 OSC 7,例如 sshing 到声称与您的 Windows 主机具有相同主机名的远程机器;
  • 将值公开为您可以粘贴在命令行上的内容,因此您的 ssh 或 wsl 会话 _can_ 出现在与您刚刚复制的工作目录相同的工作目录中。

这个讨论非常集中在第一部分(获取当前的 CWD),但我怀疑第二部分是需要更多考虑的部分,基于以上现有的评论。 即使对于那份想法清单,我也确信对_每一个_都存在合理的反对意见。

对于那些仍然对这个话题感兴趣的人,我在#7668 中做了一个早期的 PR。 这是一个友好的ping。 我真的很想听听大家的意见。

如果多个选项卡不继承当前目录,那么它们的意义何在,尤其是快速复制? 这是一个如此重要的特征。 为什么不现在添加一个“hacky”解决方法? 如果从 Windows 上的进程中提取 CWD 可以提高所有用户的生产力,我真的不认为有问题,考虑到 Windows 本身已经包含多个这样的解决方案超过 20 年。

我不明白为什么这个功能不是默认的。 我真的很困惑为什么甚至没有办法启用这个功能。 这是我对终端的最大用户体验批评:从方便的角度来看,我最好不使用终端,而是使用资源管理器并右键单击我想打开 shell 的目录并选择“在此处打开 PowerShell 窗口”,因为它是比击中alt+shift+d然后必须cd到正确的位置要快。

终端为 Windows 开发人员增加了很多生活质量。 这个功能对我来说是一个巨大的进步(我怀疑其他人)。 我将加入我的声音,主张将此功能作为重中之重。

我不明白为什么这个功能不是默认的。

我不明白为什么人们不费心去阅读在这个线程中所做的所有调查,在 #7668、#8214、#8166 和其他链接线程中,以理解为什么这实际上是一个很难解决的问题解决。 事实证明,您不能只让客户端应用程序发出它的路径 - 因为终端不会_必然_知道这是 Windows 还是 WSL 或 cygwin 路径。

好在我们有一群才华横溢的贡献者,他们正在努力寻找实现此功能支持的正确方法,同时又不破坏其他应用程序的向后兼容性。 我们_就在本周_提出了一个我们满意的解决方案,不久就会实施。

谢谢@zadjii-msft !

在重读我的评论时,我意识到它带有强烈的指责性,这不是我的意图。 我来这里是为了说:

终端为 Windows 开发人员增加了很多生活质量。 这个功能对我来说是一个巨大的进步(我怀疑其他人)。 我将加入我的声音,主张将此功能作为重中之重。

到目前为止,我的用户体验是这样的:

我不明白为什么这个功能不是默认的。 我真的很困惑为什么甚至没有办法启用这个功能。 这是最大的用户体验...等

我可能应该在我的第一段开头加上“作为用户”。

我为我所冒犯的任何罪行道歉。

此页面是否有帮助?
0 / 5 - 0 等级