terminal icon indicating copy to clipboard operation
terminal copied to clipboard

Add an action to "Open in File Explorer"

Open zadjii-msft opened this issue 3 years ago • 15 comments

Kinda the opposite of the context menu. Open the CWD in file explorer. Trick here, shell needs to have been configured for path integration.

Maybe there's a way to make the action do nothing if the active Terminal hasn't set one?

Also relevant: #3337, #5916

Other thoughts: What if the user has a path selected? Check if that text is a path, that path exists, and if so, then open that path in explorer maybe?

zadjii-msft avatar Apr 08 '22 16:04 zadjii-msft

It seems like this ought to be a feature of the shell. START . works in CMD, PowerShell, and TCC. In TCC I can assign it to a keystroke.

shell needs to have been configured for path integration

What does that mean? Does it refer to some mechanism that already exists?

vefatica avatar Apr 08 '22 16:04 vefatica

I mean, theoretically, yea. This is super doable in the shell. I'm more tracking this as a sub-task of the right-click context menu, or as a trigger. We need an action internally to hook up the context menu entry.

What does that mean? Does it refer to some mechanism that already exists

Yea I'm talking about the OSC9;9 shell integration, as described in https://docs.microsoft.com/en-us/windows/terminal/tutorials/new-tab-same-directory

zadjii-msft avatar Apr 08 '22 17:04 zadjii-msft

Yea I'm talking about the OSC9;9 shell integration

That's pretty neat and works as advertized (along with Ctrl+Shift+d). It's the sort of thing I don't often want to do. Most likely, by the next time I want to duplicate a tab, I'll have forgotten about the keystroke (and this thread).

Are there other benefits that could come from a shell using OSC9;9 to send a string to WT?

Is OSC9;9 documented anywhere other then the tutorial you mentioned? I didn't find it in https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.

vefatica avatar Apr 09 '22 17:04 vefatica

Are there other benefits that could come from a shell using OSC9;9 to send a string to WT?

At the moment not really, but who knows what we might do with it in the future. Like, maybe #12863.

OSC9;9 was originally authored by ConEmu so they've got slightly better docs https://conemu.github.io/en/ShellWorkDir.html

zadjii-msft avatar Apr 11 '22 14:04 zadjii-msft

Like, maybe https://github.com/microsoft/terminal/issues/12863

That I already have in TCC (popup history and dirhistory). New TCCs use GUI windows for this by default and that doesn't work very well with WT because TCC has no clue where the command line interface window IS. So I use the older option to create the popups in the console screen buffer.

I'm aware of another thread that deals with console apps creating windows. I'm in favor of any improvements on that front, in particular, getting such "popup" windows to have a position which is based on the position of WT's tab. As it is, can WT convey such information to conhost and, if so, can a console app get it?

vefatica avatar Apr 11 '22 14:04 vefatica

in particular, getting such "popup" windows to have a position which is based on the position of WT's tab

I'm interested in this as well. We can get the WT position with GetWindowRect (winuser.h) on TerminalPage::_hostingHwnd, then it's just a question of starting the explorer window in a secure way.

Any suggestions? I'm considering CreateProcess from processthreadsapi.h.

Here's what a potential handler in AppActionHandlers could look like (albeit untested), I used the current implementation of #8330 's code for retrieving the CWD:

void TerminalPage::_HandleOpenInFileExplorer(const IInspectable& /* sender */,
                                             const ActionEventArgs& actionArgs)
{
    const auto focusedTab{ _GetFocusedTabImpl() };
    if (focusedTab)
    {
        const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
        const auto validWorkingDirectory = !workingDirectory.empty();
        if (validWorkingDirectory && _hostingHwnd.has_value())
        {
            LPRECT lpRect;
            GetWindowRect(TerminalPage::_hostingHwnd.value(), lpRect);

            // Spawn Explorer
        }
    }
}

Quick update: spawning Explorer with ShellExecuteW is trivial. However, obtaining the HWND to call MoveWindow is not. I'm open to suggestions on how to proceed, I really don't want to do the established solution of "wait for new process to idle -> enumerate windows -> get window by pid" because that little stutter (which could be a big stutter on weaker systems) followed by an enumeration drops performance shockingly quickly.

I'm also lost on trying to add my handler to the Command Palette. It's registered as an action in the X-macros and I've been testing it through a Command in defaults-universal.json as well as a tab flyout context menu item which looks quite nifty: image However, I do think it needs to be in Command Palette for ease of use. Could someone please point me in the right direction? Thanks!

bfahrenfort avatar Apr 23 '22 12:04 bfahrenfort

However, obtaining the HWND to call MoveWindow is not

Wait hold up why do we need to do that at all? I think it's perfectly fine to just ShellExecute({the path}) and let explorer just do it's thing. At least for a first version of the feature, yea?

a Command in defaults-universal.json

Whoops, we should probably just delete that file - it's not actually used anymore 😅 defaults.json is the file you're looking for, that one should have many, MANY more actions.

zadjii-msft avatar Apr 26 '22 10:04 zadjii-msft

we should probably just delete that file - it's not actually used anymore 😅 defaults.json is the file you're looking for

Hmm. I definitely put it in defaults.json as well. Here's what I used:

{ "command": "openInFileExplorer", "keys": "ctrl+shift+alt+e" },

The keyboard shortcut works, but it still doesn't show up in command palette. Do I have to add it to another place?

Side note, someone should really make a tutorial for registering an action to command palette. I'll open an issue for it when I finish figuring this one out. Thanks!

bfahrenfort avatar Apr 27 '22 13:04 bfahrenfort

Do I have to add it to another place?

Ah, probably. There's a pile of places you need to add this stuff, though, fewer than there used to be. I bet you're missing an entry in ActionAndArgs::GenerateName. That's what generates the names for actions in the command palette.

Side note, someone should really make a tutorial for registering an action to command palette

You know, there actually is a guide, but it's pretty out of date: https://github.com/microsoft/terminal/blob/main/doc/cascadia/AddASetting.md#adding-an-action. We've since added some x-macros to the project that take care of a LOT of the boilerplate, but clearly not all of it.

I might have you also refer to #12097 - looks like that was the most recent merged PR to add an action. That one also needed action args, which I don't think we need in this case, so that should simplify things a bit.

zadjii-msft avatar Apr 27 '22 13:04 zadjii-msft

If I'm understanding the OP correctly, then the following command will open a file manager at the current CLI working directory:

explorer .

that is; launch explorer with the first argument matching (expanded to) the current path (. = current directory, compare .. = parent directory).

Been using this for years (decades?), to great effect.

I'm not sure what the equivalent for PowerShell syntax is.

Lee-Carre avatar Aug 25 '23 22:08 Lee-Carre

There's an actual shortcut which is ii (invoke-item).

i-zanis avatar Oct 22 '23 15:10 i-zanis

What about instead of having a hidden away menu button, we detect file paths and turning them into hyperlinks? image image image

It would then also work with not just the current working directory, but any path from any output. Lets say you run a compiler and it spits out a log containing multiple paths, it would be handy to be able to ctrl+click on them to go right to the URI:

Microsoft Windows [Version 10.0.19045.4717]
(c) Microsoft Corporation. All rights reserved.

C:\Users\Kieran Devlin> compiler.exe run
Compiling 28 source files...
Binary generated in C:\Users\Kieran Devlin\sources\app1\dist\bin\my-bin.exe
Full output log: C:\Users\Kieran Devlin\sources\app1\logs\compiler\2024-08-16 12-01-56.txt

KieranDevvs avatar Aug 16 '24 10:08 KieranDevvs

I made a commit 07ab3d945e4576f8b5c8289eff356298b1a4164b to add this as an action, but I don't see it in the command palette. It works when I attach it to the right click fly out menu though. What am I missing?

michaeljsXu avatar Oct 08 '24 02:10 michaeljsXu

I believe it could be because you're missing an "id" in the defaults.json. DecreaseFontSize for instance doesn't really have anything else on top of your changes.

lhecker avatar Oct 08 '24 09:10 lhecker

Thank you that fixed the problem. I made a PR.

I saw in https://github.com/microsoft/terminal/pull/13526 that the team believes actions related to CWD don't have too much value at the moment since most people don't path integration set up. Is there value in working on an action to open a highlighted directory instead?

michaeljsXu avatar Oct 08 '24 18:10 michaeljsXu