Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A shortcut to select file/files in the explorer. And copy that path to the terminal. #16966

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
11 changes: 11 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::TerminalConnection;

using namespace ::TerminalApp;

namespace winrt
Expand Down Expand Up @@ -1473,4 +1474,14 @@ namespace winrt::TerminalApp::implementation
_ShowAboutDialog();
args.Handled(true);
}

void TerminalPage::_HandleOpenFileDialog(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
if (const auto& control{ _GetActiveControl() })
{
_OpenFileDialog(control);
}
args.Handled(true);
}
}
99 changes: 99 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Storage::Pickers;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI;
Expand Down Expand Up @@ -2941,6 +2942,104 @@ namespace winrt::TerminalApp::implementation
ShowWindowChanged.raise(*this, args);
}

// Method Description:
// - Open an file dialog and paste the selected filepath(s) in to the current active control
winrt::fire_and_forget TerminalPage::_OpenFileDialog(const IInspectable sender)
{
co_await winrt::resume_background();
try
{
auto weakThis{ get_weak() };
if (const auto& page{ weakThis.get() })
{
FileOpenPicker openPicker;
openPicker.as<::IInitializeWithWindow>()->Initialize((HWND)sender.try_as<TermControl>().OwningHwnd());
openPicker.FileTypeFilter().Append(L"*");
openPicker.ViewMode(PickerViewMode::List);
const auto& files = co_await openPicker.PickMultipleFilesAsync();
const auto count = files.Size();

if (count == 0)
{
co_return;
}

std::vector<std::wstring> fullPaths(count);

for (unsigned int i = 0; i < count; i++)
{
fullPaths.emplace_back(std::wstring{ files.GetAt(i).Path() });
}

// GH#3158
// Have to find an way to access if we should ManglePathsForWsl here.
//const auto isWSL = sender.try_as<TermControl>().ManglePathsForWsl();
std::wstring allPathsString;

for (auto& fullPath : fullPaths)
{
// Join the paths with spaces
if (!allPathsString.empty())
{
allPathsString += L" ";
}

// Fix path for WSL, still has to be implemented
if (false /*IsWsl*/)
{
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');

if (fullPath.size() >= 2 && fullPath.at(1) == L':')
{
// C:/foo/bar -> Cc/foo/bar
fullPath.at(1) = til::tolower_ascii(fullPath.at(0));
// Cc/foo/bar -> /mnt/c/foo/bar
fullPath.replace(0, 1, L"/mnt/");
}
else
{
static constexpr std::wstring_view wslPathPrefixes[] = { L"//wsl.localhost/", L"//wsl$/" };
for (auto prefix : wslPathPrefixes)
{
if (til::starts_with(fullPath, prefix))
{
if (const auto idx = fullPath.find(L'/', prefix.size()); idx != std::wstring::npos)
{
// //wsl.localhost/Ubuntu-18.04/foo/bar -> /foo/bar
fullPath.erase(0, idx);
}
else
{
// //wsl.localhost/Ubuntu-18.04 -> /
fullPath = L"/";
}
break;
}
}
}
}

const auto quotesNeeded = false /*IsWsl*/ || fullPath.find(L' ') != std::wstring::npos;
const auto quotesChar = false /*IsWsl*/ ? L'\'' : L'"';

// Append fullPath and also wrap it in quotes if needed
if (quotesNeeded)
{
allPathsString.push_back(quotesChar);
}
allPathsString.append(fullPath);
if (quotesNeeded)
{
allPathsString.push_back(quotesChar);
}
}
sender.try_as<TermControl>().RawWriteString(allPathsString);
}
}
CATCH_LOG();
co_return;
}

// Method Description:
// - Paste text from the Windows Clipboard to the focused terminal
void TerminalPage::_PasteText()
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ namespace winrt::TerminalApp::implementation
bool _CopyText(const bool dismissSelection, const bool singleLine, const Windows::Foundation::IReference<Microsoft::Terminal::Control::CopyFormat>& formats);

winrt::fire_and_forget _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs);
winrt::fire_and_forget _OpenFileDialog(const IInspectable sender);

void _PasteText();

Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static constexpr std::string_view RestartConnectionKey{ "restartConnection" };
static constexpr std::string_view ToggleBroadcastInputKey{ "toggleBroadcastInput" };
static constexpr std::string_view OpenScratchpadKey{ "experimental.openScratchpad" };
static constexpr std::string_view OpenAboutKey{ "openAbout" };
static constexpr std::string_view OpenFileDialogKey{ "openFileDialog" };

static constexpr std::string_view ActionKey{ "action" };

Expand Down Expand Up @@ -362,6 +363,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{ ShortcutAction::SwapPane, RS_(L"SwapPaneCommandKey") },
{ ShortcutAction::NewTab, RS_(L"NewTabCommandKey") },
{ ShortcutAction::NextTab, RS_(L"NextTabCommandKey") },
{ ShortcutAction::OpenFileDialog, RS_(L"OpenFileDialogCommandKey") },
{ ShortcutAction::OpenNewTabDropdown, RS_(L"OpenNewTabDropdownCommandKey") },
{ ShortcutAction::OpenSettings, RS_(L"OpenSettingsUICommandKey") },
{ ShortcutAction::OpenTabColorPicker, RS_(L"OpenTabColorPickerCommandKey") },
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/AllShortcutActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
ON_ALL_ACTIONS(CloseOtherPanes) \
ON_ALL_ACTIONS(RestartConnection) \
ON_ALL_ACTIONS(ToggleBroadcastInput) \
ON_ALL_ACTIONS(OpenFileDialog) \
ON_ALL_ACTIONS(OpenScratchpad) \
ON_ALL_ACTIONS(OpenAbout)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@
<data name="MoveFocusChildPane" xml:space="preserve">
<value>Move focus to the child pane</value>
</data>
<data name="OpenFileDialogCommandKey" xml:space="preserve">
<value>Open an file select dialog</value>
</data>
<data name="SwapPaneCommandKey" xml:space="preserve">
<value>Swap pane</value>
</data>
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalSettingsModel/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+numpad_minus" },
{ "command": "resetFontSize", "keys": "ctrl+0" },
{ "command": "resetFontSize", "keys": "ctrl+numpad_0" },

{ "command": "openFileDialog", "keys": "ctrl+o" },
// Other commands
{
// Select color scheme...
Expand Down