From 7e5fb876bb4f5f04ee4827fab21714165bdefc90 Mon Sep 17 00:00:00 2001 From: ricardosantos9521 Date: Thu, 4 Mar 2021 17:15:49 +0000 Subject: [PATCH] [Run][New Plugin] VSCode Workspaces/Remote machines (#9050) * vscode workspaces plugin for Powertoys Run * reduce score * make vscode workspaces dynamic instead of string to prevent exceptions * change icons again * remove unused images and PreserveNewest during build * code refactoring * show vscode ssh remote machines * update score workspaces * vscode workspaces plugin for Powertoys Run * remove unused images and PreserveNewest during build * code refactoring * remove unused packages * get ExecutablePath from AppData and use shell to vscode process * ' instead of \" * try using ((char)34) instead of ' * add comments * translate windows paths * remove unused code * add vscodeworkspace to installer * use the new naming convention for plugins * sign VSCodeWorkspaces.dll * reimplement ssh-config parser * update spell-check * use the new naming convention for community plugins * minor adjustments * add actionKeyword { * prevent copyright * add localization * add github link * bug fix after localization * --new-window --enable-proposed-api ms-vscode-remote.remote-ssh * change order by * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs * Update src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx * Update src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx * Update src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx * Update src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx * Update src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx * fix powertoys run settings not working * update plugin description Co-authored-by: ricar Co-authored-by: Enrico Giordani --- .github/actions/spell-check/expect.txt | 8 + .pipelines/pipeline.user.windows.yml | 1 + PowerToys.sln | 7 + installer/PowerToysSetup/Product.wxs | 24 ++- ...werToys.Run.Plugin.VSCodeWorkspaces.csproj | 90 +++++++++ .../Images/folder.png | Bin 0 -> 1927 bytes .../Images/monitor.png | Bin 0 -> 7349 bytes .../Images/vscode_plugin.png | Bin 0 -> 50731 bytes .../LocProject.json | 14 ++ .../Main.cs | 176 ++++++++++++++++++ .../Properties/Resources.Designer.cs | 126 +++++++++++++ .../Properties/Resources.resx | 145 +++++++++++++++ .../RealPath.cs | 23 +++ .../VSCodeRemoteMachine.cs | 15 ++ .../VSCodeRemoteMachinesApi.cs | 64 +++++++ .../SshConfigParser/Parser.cs | 39 ++++ .../SshConfigParser/SshHost.cs | 53 ++++++ .../VSCodeHelper/VSCodeInstance.cs | 30 +++ .../VSCodeHelper/VSCodeInstances.cs | 133 +++++++++++++ .../WorkspacesHelper/ParseVSCodeUri.cs | 58 ++++++ .../WorkspacesHelper/VSCodeStorageFile.cs | 14 ++ .../WorkspacesHelper/VSCodeWorkspace.cs | 43 +++++ .../WorkspacesHelper/VSCodeWorkspacesApi.cs | 74 ++++++++ .../plugin.json | 14 ++ .../Properties/Resources.Designer.cs | 7 +- 25 files changed, 1153 insertions(+), 5 deletions(-) create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/folder.png create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/monitor.png create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/vscode_plugin.png create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/LocProject.json create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Main.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.Designer.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RealPath.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachine.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachinesApi.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/Parser.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/SshHost.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstance.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstances.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/ParseVSCodeUri.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeStorageFile.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspace.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs create mode 100644 src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/plugin.json diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index ee5ee787a4..66098c9ac2 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -276,6 +276,7 @@ codecvt codeofconduct codeql codereview +Codespaces COINIT colorconv colorhistory @@ -1808,6 +1809,7 @@ rgelt Rgn rgs rhs +ricardosantos Riched Richtext RIGHTSCROLLBAR @@ -2005,6 +2007,7 @@ srre srw srwlock ssf +ssh sstream STACKFRAME stackoverflow @@ -2224,6 +2227,7 @@ uncompilable UNCPRIORITY undef UNDNAME +unescape Ungroup unicode Unindent @@ -2320,8 +2324,10 @@ VOS VREDRAW VSC VSCBD +vscode VSCROLL vse +vsonline vstemplate VSTHRD VSTS @@ -2432,6 +2438,7 @@ wofstream wordpad workaround workflow +workspaces wostream wox wparam @@ -2444,6 +2451,7 @@ WResize wrl wsf wsh +wsl wss wstr wstring diff --git a/.pipelines/pipeline.user.windows.yml b/.pipelines/pipeline.user.windows.yml index 43d33d4a2e..d873aed929 100644 --- a/.pipelines/pipeline.user.windows.yml +++ b/.pipelines/pipeline.user.windows.yml @@ -131,6 +131,7 @@ build: - 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Wox.Infrastructure.dll' - 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Wox.Plugin.dll' - 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Telemetry.dll' + - 'modules\launcher\Plugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll' - 'modules\launcher\Plugins\Service\Microsoft.PowerToys.Run.Plugin.Service.dll' - 'modules\launcher\Plugins\System\Microsoft.PowerToys.Run.Plugin.System.dll' - 'modules\launcher\PowerLauncher.dll' diff --git a/PowerToys.sln b/PowerToys.sln index 0b600fd0b0..c12d4dbf79 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -128,6 +128,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{4AFC EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Calculator", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.csproj", "{59BD9891-3837-438A-958D-ADC7F91F6F7E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.VSCodeWorkspaces", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj", "{4D971245-7A70-41D5-BAA0-DDB5684CAF51}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.WindowWalker", "src\modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Microsoft.Plugin.WindowWalker.csproj", "{74F1B9ED-F59C-4FE7-B473-7B453E30837E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Program", "src\modules\launcher\Plugins\Microsoft.Plugin.Program\Microsoft.Plugin.Program.csproj", "{FDB3555B-58EF-4AE6-B5F1-904719637AB4}" @@ -418,6 +420,10 @@ Global {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.Build.0 = Debug|x64 {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.ActiveCfg = Release|x64 {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.Build.0 = Release|x64 + {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.ActiveCfg = Debug|x64 + {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.Build.0 = Debug|x64 + {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.ActiveCfg = Release|x64 + {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.Build.0 = Release|x64 {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.ActiveCfg = Debug|x64 {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.Build.0 = Debug|x64 {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.ActiveCfg = Release|x64 @@ -665,6 +671,7 @@ Global {FF742965-9A80-41A5-B042-D6C7D3A21708} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} {4AFC9975-2456-4C70-94A4-84073C1CED93} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} {59BD9891-3837-438A-958D-ADC7F91F6F7E} = {4AFC9975-2456-4C70-94A4-84073C1CED93} + {4D971245-7A70-41D5-BAA0-DDB5684CAF51} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {74F1B9ED-F59C-4FE7-B473-7B453E30837E} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {4AFC9975-2456-4C70-94A4-84073C1CED93} diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 6238a4e94c..6130f4c949 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -245,6 +245,10 @@ + + + + @@ -818,7 +822,7 @@ - + @@ -894,6 +898,9 @@ + + + @@ -1006,7 +1013,20 @@ - + + + + + + + + + + + + + + diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj new file mode 100644 index 0000000000..605295bc93 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj @@ -0,0 +1,90 @@ + + + + + netcoreapp3.1 + {4D971245-7A70-41D5-BAA0-DDB5684CAF51} + Properties + Community.PowerToys.Run.Plugin.VSCodeWorkspaces + Community.PowerToys.Run.Plugin.VSCodeWorkspaces + true + false + false + x64 + + + + true + ..\..\..\..\..\x64\Debug\modules\launcher\Plugins\VSCodeWorkspaces\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + 4 + false + + + + ..\..\..\..\..\x64\Release\modules\launcher\Plugins\VSCodeWorkspaces\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + 4 + + + + + PreserveNewest + + + + + + + + + + + + + + + + + C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd + + + + + + Resources.resx + True + True + + + + + + Resources.Designer.cs + ResXFileCodeGenerator + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/folder.png b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd340aff90a9be46059d71421cd8f87d9faab78 GIT binary patch literal 1927 zcmaJ?dsI^C9>pk4M;$304GmZ7nBjvQNevSx6(84R!qQAhywI4XmXAhJl(Zbeh@6}2 z=Jjzk>Ix3yBlDFQO2+7T^BEF4Dw<Nhg<^=Y?7j!< zhI>IPa-pfFLk^tTn!7uyE$v*ZBZ4A*Y#Re_1X8B^#(FGFop(n3qd+l~Qck+!_2?|9 z&jYq+{X_Y?vQl#`wV=Pf<}1U-KZAIIed1;aIQyylAZHU$q}3FKa|NBBVQqy*@w>zL z0vb&|-AS5iVY;Cd>_a>i(Mrm;YTFC)n8h~tbB(H(J1O~HgJJe;rkhXNk6-eHgW(Gi z9)>7;X)VE1JT%Xyt`W+q6K-4($KO$_Y$ed*mXTO>E!Fp}W$XU3*bM8-*QWseAKazv z2)O{^`gAlTH1x=WR|WEDfjJ``rG+HJDPg#qGuHUW%r%*7Bip@UMZBCWSiO7t+Lxxa zrSz=OAY#dJl!d$ee(WW#o1rV$wD^SaWaSjP>mFUH%zi zz*;1vE||I+GUzF@_n-3it*Sf^Gp@8UOi(o#DN1r~(|)3w2>t#u5Qn!DpxW27f=4_Ol3pe|^x#V88(^iy?L=w#%-fM#x;QJdsjnPk zJUP?0pI3DA);xXbH&Th%Z(w6HpXDGRf}h|`tX-CFWrMpD`mGqaBR|-M$oac@I7yGd@IcqM6 z^?BLz(6H(W^0Oiqa`E_U1j>5RvW<`{jWJI{cTxV^Fw(u*NxE&qHK z-o3PK%%{_qMG){$3PvZv`iA)qj-0k>yp|L~Xl3FB(`5sXTl5|FI3NPPn1nn?Plk5d zGS4=DuA7)#k{0~)uoEGr9lC~312=ptIvFqiHePxT?Ea%Fw~%bh(@hxX?r(Za#>GZ$ zcQ3MkDSV9G#|vzT0M@NB6|F?&bb>#+Y)84{ zm@kZT|wE;DayQ+@(-=jqP)L`~LXKT0(GiRT( zfxd>_ld{R%!`M3c*jrPt@ZK1+)%Z`f>6T`@T-3N}z#rXmsK&ON?Rsai>Gz}iZTfkiBv;7} zCkD3yYG`Wem^zFY;}+VaxjuGZg}VgtBdj7;A(_xvU0e!{EP=@R)TnOm7FM9Y{AjR=~LG#-V80^4v5B= z6_NdANLBpaxTCcmBxOgfs1_-IiFm=T$f+$pjCem#+-N_a_Km(Ou4eposizBx_^b;} zuBbT_XOQU2?x`AQ~-g%MwP|ysWci*n7NwF@)Q*nwZc{P q7i=JAtpo{Pu)6JUe@y^DcAO0M%U8oeeFaK04K)yj_O0=bzWN6$QDb@l literal 0 HcmV?d00001 diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/monitor.png b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Images/monitor.png new file mode 100644 index 0000000000000000000000000000000000000000..04a46374f2936804bb7af4d696dd05f0feff25b2 GIT binary patch literal 7349 zcmcIJ=RX_XyNSI*RZ+7otqv8Vh`p;d+p0}eDQYBU%$9`KXuqnh62xrPC}I-?L0f9X z77ejyVpWXN;`;vX{R8fcdq3wn&-3D(&w0*y_BkivzWE&xhcE{K000@?HLy6PTmN=8 zmQ$={wfg>)u(+7qF#w$W+j5%=lK}uxFCzn8%h1gAEVC{c$*waeYk!Kf^2g;fd1<;w zI-(dZs*ZY>!Hf4_=U(1mdlhiof54Wj>@!o@cz@8`0+HiQ`1MuT4a5lY_9f?eQ&#eg z4;D;_fwy%7GZgNrKw{HAxqq2Vqv7{YF5o>jYqNJN`+v65A9-h06HS(mqe(fia z+xQF){pED+L8#>$VV9M)P~t7aTm1&nfummhhm>#L_&3r->WU9C%$FN)JYv`3t!=06 zM#4XW*emK8B!xvg9g@q(Hae|4-SD2~L>?Z!L#e5(J3-;Qf}X=taR0ba+T$cm`8XA+ z=f?B3;iG{b8X_G75;Cn{Rv8f87T}Ph3t@Ac3k*R&iEH@f{V)84`Qmf963i5EL&BFl zBG0+2Hep-m`rYTxCw*yr-cy7__b%DZHgm$F~qmvX7?`yzuk;Nc@Qx9xH#g9c3NVL;ed zw?Jgy3oB+sia3+v0s)3N0)m;bpRgtKdNUir6J^ylC~Ic9Ξ=d3lM_vqhI!xtA`G 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 Ks8qkS3jbeNsk!9< literal 0 HcmV?d00001 diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/LocProject.json b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/LocProject.json new file mode 100644 index 0000000000..e3b4ee8fc9 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/LocProject.json @@ -0,0 +1,14 @@ +{ + "Projects": [ + { + "LanguageSet": "Azure_Languages", + "LocItems": [ + { + "SourceFile": "src\\modules\\launcher\\Plugins\\VSCodeWorkspaces\\Properties\\Resources.resx", + "CopyOption": "LangIDOnName", + "OutputPath": "src\\modules\\launcher\\Plugins\\VSCodeWorkspaces\\Properties" + } + ] + } + ] +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Main.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Main.cs new file mode 100644 index 0000000000..3de8a6e89c --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Main.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Windows.Controls; +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.Properties; +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.RemoteMachinesHelper; +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper; +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper; +using Microsoft.PowerToys.Settings.UI.Library; +using Wox.Plugin; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces +{ + public class Main : IPlugin, IPluginI18n + { + public PluginInitContext _context { get; private set; } + + public string Name => GetTranslatedPluginTitle(); + + public string Description => GetTranslatedPluginDescription(); + + public Main() + { + VSCodeInstances.LoadVSCodeInstances(); + } + + public readonly VSCodeWorkspacesApi _workspacesApi = new VSCodeWorkspacesApi(); + + public readonly VSCodeRemoteMachinesApi _machinesApi = new VSCodeRemoteMachinesApi(); + + public List Query(Query query) + { + var results = new List(); + + if (query != null) + { + // Search opened workspaces + _workspacesApi.Workspaces.ForEach(a => + { + var title = $"{a.FolderName}"; + + var typeWorkspace = a.WorkspaceTypeToString(); + if (a.TypeWorkspace == TypeWorkspace.Codespaces) + { + title += $" - {typeWorkspace}"; + } + else if (a.TypeWorkspace != TypeWorkspace.Local) + { + title += $" - {(a.ExtraInfo != null ? $"{a.ExtraInfo} ({typeWorkspace})" : typeWorkspace)}"; + } + + results.Add(new Result + { + Title = title, + SubTitle = $"{Resources.Workspace}{(a.TypeWorkspace != TypeWorkspace.Local ? $" {Resources.In} {typeWorkspace}" : "")}: {SystemPath.RealPath(a.RelativePath)}", + Icon = a.VSCodeInstance.WorkspaceIcon, + Action = c => + { + bool hide; + try + { + var process = new ProcessStartInfo + { + FileName = a.VSCodeInstance.ExecutablePath, + UseShellExecute = true, + Arguments = $"--folder-uri {a.Path}", + WindowStyle = ProcessWindowStyle.Hidden + }; + Process.Start(process); + + hide = true; + } + catch (Win32Exception) + { + var name = $"Plugin: {_context.CurrentPluginMetadata.Name}"; + var msg = "Can't Open this file"; + _context.API.ShowMsg(name, msg, string.Empty); + hide = false; + } + return hide; + }, + ContextData = a, + }); + }); + + // Search opened remote machines + _machinesApi.Machines.ForEach(a => + { + var title = $"{a.Host}"; + + if (a.User != null && a.User != String.Empty && a.HostName != null && a.HostName != String.Empty) + { + title += $" [{a.User}@{a.HostName}]"; + } + + results.Add(new Result + { + Title = title, + SubTitle = Resources.SSHRemoteMachine, + Icon = a.VSCodeInstance.RemoteIcon, + Action = c => + { + bool hide; + try + { + var process = new ProcessStartInfo() + { + FileName = a.VSCodeInstance.ExecutablePath, + UseShellExecute = true, + Arguments = $"--new-window --enable-proposed-api ms-vscode-remote.remote-ssh --remote ssh-remote+{((char)34) + a.Host + ((char)34)}", + WindowStyle = ProcessWindowStyle.Hidden, + }; + Process.Start(process); + + hide = true; + } + catch (Win32Exception) + { + var name = $"Plugin: {_context.CurrentPluginMetadata.Name}"; + var msg = "Can't Open this file"; + _context.API.ShowMsg(name, msg, string.Empty); + hide = false; + } + return hide; + }, + ContextData = a, + }); + }); + } + + results.ForEach(x => + { + if (x.Score == 0) + { + x.Score = 100; + } + + //if is a remote machine give it 12 extra points + if (x.ContextData is VSCodeRemoteMachine) + { + x.Score = x.Score + (query.Search.Count() * 5); + } + + //intersect the title with the query + var intersection = x.Title.ToLower().Intersect(query.Search.ToLower()).Count(); + x.Score = x.Score - (Convert.ToInt32(((x.Title.Count() - intersection) *2.5))); + }); + + results = results.OrderBy(x => x.Title).ToList(); + + if (query.ActionKeyword == String.Empty || (query.ActionKeyword != String.Empty && query.Search != String.Empty)) + { + results = results.Where(a => a.Title.ToLower().Contains(query.Search.ToLower())).ToList(); + } + + return results; + } + + public void Init(PluginInitContext context) + { + _context = context; + } + + public string GetTranslatedPluginTitle() + { + return Resources.PluginTitle; + } + + public string GetTranslatedPluginDescription() + { + return Resources.PluginDescription; + } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.Designer.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..13ca6c4314 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.Designer.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Community.PowerToys.Run.Plugin.VSCodeWorkspaces.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to in. + /// + internal static string In { + get { + return ResourceManager.GetString("In", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open VSCode previously opened workspaces, remote machines (SSH or Codespaces) and containers.. + /// + internal static string PluginDescription { + get { + return ResourceManager.GetString("PluginDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to VSCode Workspaces. + /// + internal static string PluginTitle { + get { + return ResourceManager.GetString("PluginTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SSH remote machine. + /// + internal static string SSHRemoteMachine { + get { + return ResourceManager.GetString("SSHRemoteMachine", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Container. + /// + internal static string TypeWorkspaceContainer { + get { + return ResourceManager.GetString("TypeWorkspaceContainer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Local. + /// + internal static string TypeWorkspaceLocal { + get { + return ResourceManager.GetString("TypeWorkspaceLocal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Workspace. + /// + internal static string Workspace { + get { + return ResourceManager.GetString("Workspace", resourceCulture); + } + } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx new file mode 100644 index 0000000000..fc639c9cb7 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Properties/Resources.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + VSCode Workspaces + + + in + Used to indicate the location where something is + + + Open VSCode previously opened workspaces, remote machines (SSH or Codespaces) and containers. + + + SSH remote machine + + + Container + As in "Visual Studio Code workspace container type + + + Local + As in "The workspace is on the local machine" + + + Workspace + It refers to the "Visual Studio Code workspace" + + diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RealPath.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RealPath.cs new file mode 100644 index 0000000000..04180331ab --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RealPath.cs @@ -0,0 +1,23 @@ +using System; +using System.Text.RegularExpressions; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces +{ + class SystemPath + { + private static readonly Regex WindowsPath = new Regex(@"^([a-zA-Z]:)", RegexOptions.Compiled); + + public static string RealPath(string path) + { + if (WindowsPath.IsMatch(path)) + { + String windowsPath = path.Replace("/", "\\"); + return $"{windowsPath[0]}".ToUpper() + windowsPath.Remove(0,1); + } + else + { + return path; + } + } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachine.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachine.cs new file mode 100644 index 0000000000..db88fe1419 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachine.cs @@ -0,0 +1,15 @@ +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.RemoteMachinesHelper +{ + public class VSCodeRemoteMachine + { + public string Host { get; set; } + + public string User { get; set; } + + public string HostName { get; set; } + + public VSCodeInstance VSCodeInstance { get; set; } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachinesApi.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachinesApi.cs new file mode 100644 index 0000000000..5571c077d7 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/RemoteMachinesHelper/VSCodeRemoteMachinesApi.cs @@ -0,0 +1,64 @@ +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.SshConfigParser; +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using Wox.Plugin.Logger; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.RemoteMachinesHelper +{ + public class VSCodeRemoteMachinesApi + { + public VSCodeRemoteMachinesApi() { } + + public List Machines + { + get + { + var results = new List(); + + foreach (var vscodeInstance in VSCodeInstances.instances) + { + // settings.json contains path of ssh_config + var vscode_settings = Path.Combine(vscodeInstance.AppData, "User\\settings.json"); + + if (File.Exists(vscode_settings)) + { + var fileContent = File.ReadAllText(vscode_settings); + + try + { + dynamic vscodeSettingsFile = JsonConvert.DeserializeObject(fileContent); + if (vscodeSettingsFile.ContainsKey("remote.SSH.configFile")) + { + var path = vscodeSettingsFile["remote.SSH.configFile"]; + if (File.Exists(path.Value)) + { + foreach (SshHost h in SshConfig.ParseFile(path.Value)) + { + var machine = new VSCodeRemoteMachine(); + machine.Host = h.Host; + machine.VSCodeInstance = vscodeInstance; + machine.HostName = h.HostName != null ? h.HostName : String.Empty; + machine.User = h.User != null ? h.User : String.Empty; + + results.Add(machine); + } + } + } + } + catch (Exception ex) + { + var message = $"Failed to deserialize ${vscode_settings}"; + Log.Exception(message, ex, GetType()); + } + } + } + + return results; + + } + } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/Parser.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/Parser.cs new file mode 100644 index 0000000000..f94b7747c0 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/Parser.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.SshConfigParser +{ + public class SshConfig + { + private static readonly Regex SSH_CONFIG = new Regex(@"^(\w[\s\S]*?\w)$(?=(?:\s+^\w|\z))", RegexOptions.Multiline); + private static readonly Regex KEY_VALUE = new Regex(@"(\w+\s\S+)", RegexOptions.Multiline); + + public static IEnumerable ParseFile(string path) + { + return Parse(File.ReadAllText(path)); + } + + public static IEnumerable Parse(string str) + { + + str = str.Replace("\r", ""); + var list = new List(); + foreach (Match match in SSH_CONFIG.Matches(str)) + { + var sshHost = new SshHost(); + string content = match.Groups.Values.ToList()[0].Value; + foreach (Match match1 in KEY_VALUE.Matches(content)) + { + var split = match1.Value.Split(" "); + var key = split[0]; + var value = split[1]; + sshHost.Properties[key] = value; + } + list.Add(sshHost); + } + return list; + } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/SshHost.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/SshHost.cs new file mode 100644 index 0000000000..f062b3a39d --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/SshHost.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.SshConfigParser +{ + public class SshHost + { + public string IdentityFile + { + get => this[nameof(IdentityFile)]?.ToString(); + set => this[nameof(IdentityFile)] = value; + } + + public string Host + { + get => this[nameof(Host)]?.ToString(); + set => this[nameof(Host)] = value; + } + + public string HostName + { + get => this[nameof(HostName)]?.ToString(); + set => this[nameof(HostName)] = value; + } + + public string User { + get => this[nameof(User)]?.ToString(); + set => this[nameof(User)] = value; + } + + public string ForwardAgent { + get => this[nameof(ForwardAgent)]?.ToString(); + set => this[nameof(ForwardAgent)] = value; + } + + internal Dictionary Properties { get; } = new Dictionary(); + + public object this[string key] + { + get + { + if (Properties.TryGetValue(key, out var value)) + { + return value; + } + + return null; + } + set { Properties[key] = value; } + } + + public IEnumerable Keys => Properties.Keys; + } +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstance.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstance.cs new file mode 100644 index 0000000000..212299dea1 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstance.cs @@ -0,0 +1,30 @@ +using System; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper +{ + public enum VSCodeVersion + { + Stable = 1, + Insiders = 2, + Exploration = 3 + } + + public class VSCodeInstance + { + public VSCodeVersion VSCodeVersion { get; set; } + + public string ExecutablePath { get; set; } = String.Empty; + + public string AppData { get; set; } = String.Empty; + + public ImageSource WorkspaceIcon(){ return WorkspaceIconBitMap; } + + public ImageSource RemoteIcon(){ return RemoteIconBitMap; } + + public BitmapImage WorkspaceIconBitMap { get; set; } + + public BitmapImage RemoteIconBitMap { get; set; } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstances.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstances.cs new file mode 100644 index 0000000000..598089d2cd --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/VSCodeHelper/VSCodeInstances.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper +{ + static class VSCodeInstances + { + private static readonly string PathUserAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + + private static string _systemPath = String.Empty; + + private static string _userAppDataPath = Environment.GetEnvironmentVariable("AppData"); + + public static List instances = new List(); + + private static BitmapImage Bitmap2BitmapImage(Bitmap bitmap) + { + using (var memory = new MemoryStream()) + { + bitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; + + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + bitmapImage.Freeze(); + + return bitmapImage; + } + } + + public static Bitmap bitmapOverlayToCenter(Bitmap bitmap1, Bitmap overlayBitmap) + { + int bitmap1Width = bitmap1.Width; + int bitmap1Height = bitmap1.Height; + + Bitmap overlayBitmapResized = new Bitmap(overlayBitmap, new System.Drawing.Size(bitmap1Width / 2, bitmap1Height / 2)); + + float marginLeft = (float)(bitmap1Width * 0.7 - overlayBitmapResized.Width * 0.5); + float marginTop = (float)(bitmap1Height * 0.7 - overlayBitmapResized.Height * 0.5); + + Bitmap finalBitmap = new Bitmap(bitmap1Width, bitmap1Height); + using (Graphics g = Graphics.FromImage(finalBitmap)) + { + g.DrawImage(bitmap1, System.Drawing.Point.Empty); + g.DrawImage(overlayBitmapResized, marginLeft, marginTop); + } + return finalBitmap; + } + + // Gets the executablePath and AppData foreach instance of VSCode + public static void LoadVSCodeInstances() + { + if (_systemPath != Environment.GetEnvironmentVariable("PATH")) + { + + instances = new List(); + + _systemPath = Environment.GetEnvironmentVariable("PATH"); + var paths = _systemPath.Split(";"); + paths = paths.Where(x => x.Contains("VS Code")).ToArray(); + foreach (var path in paths) + { + if (Directory.Exists(path)) + { + var files = Directory.GetFiles(path); + var iconPath = Path.GetDirectoryName(path); + files = files.Where(x => x.Contains("code") && !x.EndsWith(".cmd")).ToArray(); + + if (files.Length > 0) + { + var file = files[0]; + var version = String.Empty; + + var instance = new VSCodeInstance + { + ExecutablePath = file, + }; + + if (file.EndsWith("code")) + { + version = "Code"; + instance.VSCodeVersion = VSCodeVersion.Stable; + } + else if (file.EndsWith("code-insiders")) + { + version = "Code - Insiders"; + instance.VSCodeVersion = VSCodeVersion.Insiders; + } + else if (file.EndsWith("code-exploration")) + { + version = "Code - Exploration"; + instance.VSCodeVersion = VSCodeVersion.Exploration; + } + + if (version != String.Empty) + { + instance.AppData = Path.Combine(_userAppDataPath, version); + var iconVSCode = Path.Join(iconPath, $"{version}.exe"); + + var bitmapIconVscode = Icon.ExtractAssociatedIcon(iconVSCode).ToBitmap(); + + //workspace + var folderIcon = (Bitmap)System.Drawing.Image.FromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "//Images//folder.png"); + instance.WorkspaceIconBitMap = Bitmap2BitmapImage(bitmapOverlayToCenter(folderIcon, bitmapIconVscode)); + + //remote + var monitorIcon = (Bitmap)System.Drawing.Image.FromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "//Images//monitor.png"); + + instance.RemoteIconBitMap = Bitmap2BitmapImage(bitmapOverlayToCenter(monitorIcon, bitmapIconVscode)); + + instances.Add(instance); + } + } + } + } + } + } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/ParseVSCodeUri.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/ParseVSCodeUri.cs new file mode 100644 index 0000000000..32c54f5a26 --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/ParseVSCodeUri.cs @@ -0,0 +1,58 @@ +using System; +using System.Text.RegularExpressions; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper +{ + public class ParseVSCodeUri + { + private static readonly Regex LocalWorkspace = new Regex("^file:///(.+)$", RegexOptions.Compiled); + + private static readonly Regex RemoteSSHWorkspace = new Regex(@"^vscode-remote://ssh-remote\+(.+?(?=\/))(.+)$", RegexOptions.Compiled); + + private static readonly Regex RemoteWSLWorkspace = new Regex(@"^vscode-remote://wsl\+(.+?(?=\/))(.+)$", RegexOptions.Compiled); + + private static readonly Regex CodespacesWorkspace = new Regex(@"^vscode-remote://vsonline\+(.+?(?=\/))(.+)$", RegexOptions.Compiled); + + public static (TypeWorkspace? TypeWorkspace, String MachineName, String Path) GetTypeWorkspace(string uri) + { + if (LocalWorkspace.IsMatch(uri)) + { + var match = LocalWorkspace.Match(uri); + + if (match.Groups.Count > 1) + { + return (TypeWorkspace.Local, null, match.Groups[1].Value); + } + } + else if (RemoteSSHWorkspace.IsMatch(uri)) + { + var match = RemoteSSHWorkspace.Match(uri); + + if (match.Groups.Count > 1) + { + return (TypeWorkspace.RemoteSSH, match.Groups[1].Value, match.Groups[2].Value); + } + } + else if (RemoteWSLWorkspace.IsMatch(uri)) + { + var match = RemoteWSLWorkspace.Match(uri); + + if (match.Groups.Count > 1) + { + return (TypeWorkspace.RemoteWSL, match.Groups[1].Value, match.Groups[2].Value); + } + } + else if (CodespacesWorkspace.IsMatch(uri)) + { + var match = CodespacesWorkspace.Match(uri); + + if (match.Groups.Count > 1) + { + return (TypeWorkspace.Codespaces, String.Empty, match.Groups[2].Value); + } + } + + return (null, null, null); + } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeStorageFile.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeStorageFile.cs new file mode 100644 index 0000000000..c323dce2db --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeStorageFile.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper +{ + public class VSCodeStorageFile + { + public openedPathsList openedPathsList { get; set; } + } + + public class openedPathsList + { + public List workspaces3 { get; set; } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspace.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspace.cs new file mode 100644 index 0000000000..9690dfd85e --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspace.cs @@ -0,0 +1,43 @@ +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.Properties; +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper +{ + public class VSCodeWorkspace + { + public string Path { get; set; } + + public string RelativePath { get; set; } + + public string FolderName { get; set; } + + public string ExtraInfo { get; set; } + + public TypeWorkspace TypeWorkspace { get; set; } + + public VSCodeInstance VSCodeInstance { get; set; } + + public string WorkspaceTypeToString() + { + switch (TypeWorkspace) + { + case TypeWorkspace.Local: return Resources.TypeWorkspaceLocal; + case TypeWorkspace.Codespaces: return "Codespaces"; + case TypeWorkspace.RemoteContainers: return Resources.TypeWorkspaceContainer; + case TypeWorkspace.RemoteSSH: return "SSH"; + case TypeWorkspace.RemoteWSL: return "WSL"; + } + + return string.Empty; + } + } + + public enum TypeWorkspace + { + Local = 1, + Codespaces = 2, + RemoteWSL = 3, + RemoteSSH = 4, + RemoteContainers = 5 + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs new file mode 100644 index 0000000000..82da3ac43f --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs @@ -0,0 +1,74 @@ +using Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using Wox.Plugin.Logger; + +namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper +{ + public class VSCodeWorkspacesApi + { + public VSCodeWorkspacesApi() { } + + public List Workspaces + { + get + { + + var results = new List(); + + foreach (var vscodeInstance in VSCodeInstances.instances) + { + // storage.json contains opened Workspaces + var vscode_storage = Path.Combine(vscodeInstance.AppData, "storage.json"); + + if (File.Exists(vscode_storage)) + { + var fileContent = File.ReadAllText(vscode_storage); + + try + { + VSCodeStorageFile vscodeStorageFile = JsonConvert.DeserializeObject(fileContent); + + if (vscodeStorageFile != null) + { + foreach (var workspaceUri in vscodeStorageFile.openedPathsList.workspaces3) + { + if (workspaceUri != null && workspaceUri is String) + { + string unescapeUri = Uri.UnescapeDataString(workspaceUri); + var typeWorkspace = ParseVSCodeUri.GetTypeWorkspace(unescapeUri); + if (typeWorkspace.TypeWorkspace.HasValue) + { + var folderName = Path.GetFileName(unescapeUri); + results.Add(new VSCodeWorkspace() + { + Path = workspaceUri, + RelativePath = typeWorkspace.Path, + FolderName = folderName, + ExtraInfo = typeWorkspace.MachineName, + TypeWorkspace = typeWorkspace.TypeWorkspace.Value, + VSCodeInstance = vscodeInstance + }); + } + } + } + } + } + catch (Exception ex) + { + var message = $"Failed to deserialize ${vscode_storage}"; + Log.Exception(message, ex, GetType()); + } + + } + + } + + + return results; + } + } + } +} diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/plugin.json b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/plugin.json new file mode 100644 index 0000000000..bf8ce5323d --- /dev/null +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/plugin.json @@ -0,0 +1,14 @@ +{ + "ID": "525995402BEF4A8CA860D92F6D108092", + "ActionKeyword": "{", + "Name": "VSCode Workspaces", + "Description": "Opened VSCode Workspaces", + "Author": "ricardosantos9521", + "Version": "1.0.0", + "Language": "csharp", + "Website": "https://github.com/ricardosantos9521/PowerToys/", + "ExecuteFileName": "Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll", + "IsGlobal": false, + "IcoPathDark": "Images\\vscode_plugin.png", + "IcoPathLight": "Images\\vscode_plugin.png" +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs index 50464bdb72..3f3267b747 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs @@ -45,7 +45,7 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.Properties { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -68,7 +68,7 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.Properties { return ResourceManager.GetString("wox_plugin_calculator_copy_failed", resourceCulture); } } - + /// /// Looks up a localized string similar to Copy this number to the clipboard. /// @@ -95,6 +95,7 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.Properties { return ResourceManager.GetString("wox_plugin_calculator_not_a_number", resourceCulture); } } + /// /// Looks up a localized string similar to Does mathematical calculations (e.g. 5*3-2).. @@ -104,7 +105,7 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.Properties { return ResourceManager.GetString("wox_plugin_calculator_plugin_description", resourceCulture); } } - + /// /// Looks up a localized string similar to Calculator. ///