diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..91f3a33 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,47 @@ +name: build + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + strategy: + matrix: + platform: [x64, ARM64] + + runs-on: windows-latest + + steps: + + - uses: actions/checkout@v4 + + - name: Setup dotnet + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore /p:Platform=${{ matrix.platform }} + + - name: Test + if: ${{matrix.platform == 'x64'}} + run: dotnet test --no-build --verbosity normal /p:Platform=${{ matrix.platform }} + + - name: Get short commit sha + run: echo "SHORT_SHA=$($env:GITHUB_SHA.Substring(0, 7))" >> $env:GITHUB_ENV + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts-${{ matrix.platform }}-${{ env.SHORT_SHA }} + path: | + Community.PowerToys.Run.Plugin.RiderProjects/bin + if-no-files-found: error + overwrite: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3512292 --- /dev/null +++ b/.gitignore @@ -0,0 +1,353 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +!*/Libs/x64 +!*/Libs/ARM64 diff --git a/.idea/.idea.RiderProjects/.idea/.gitignore b/.idea/.idea.RiderProjects/.idea/.gitignore new file mode 100644 index 0000000..f35f950 --- /dev/null +++ b/.idea/.idea.RiderProjects/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/.idea.RiderProjects.iml +/modules.xml +/projectSettingsUpdater.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.RiderProjects/.idea/.name b/.idea/.idea.RiderProjects/.idea/.name new file mode 100644 index 0000000..7c93a79 --- /dev/null +++ b/.idea/.idea.RiderProjects/.idea/.name @@ -0,0 +1 @@ +RiderProjects \ No newline at end of file diff --git a/.idea/.idea.RiderProjects/.idea/encodings.xml b/.idea/.idea.RiderProjects/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.RiderProjects/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.RiderProjects/.idea/indexLayout.xml b/.idea/.idea.RiderProjects/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.RiderProjects/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.RiderProjects/.idea/riderPublish.xml b/.idea/.idea.RiderProjects/.idea/riderPublish.xml new file mode 100644 index 0000000..c494241 --- /dev/null +++ b/.idea/.idea.RiderProjects/.idea/riderPublish.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.RiderProjects/.idea/vcs.xml b/.idea/.idea.RiderProjects/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.RiderProjects/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests.csproj b/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests.csproj new file mode 100644 index 0000000..cda614d --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests.csproj @@ -0,0 +1,26 @@ + + + + net8.0-windows + x64;ARM64 + $(Platform) + true + $(OutputPath)$(AssemblyName).xml + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests/MainTests.cs b/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests/MainTests.cs new file mode 100644 index 0000000..38dc37a --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects.UnitTests/MainTests.cs @@ -0,0 +1,40 @@ +// Copyright (c) Mpho Jele. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +// using Wox.Plugin; + +namespace Community.PowerToys.Run.Plugin.RiderProjects.UnitTests +{ + [TestClass] + public class MainTests + { + private Main _main; + + [TestInitialize] + public void TestInitialize() + { + _main = new Main(); + } + + [TestMethod] + public void Query_should_return_results() + { + // TODO: Implement a way to mock the RiderProjectsService + // var results = _main.Query(new("search")); + + // Assert.IsNotNull(results.First()); + } + + [TestMethod] + public void LoadContextMenus_should_return_results() + { + // var results = _main.LoadContextMenus(new Result { ContextData = "search" }); + + // Assert.IsNotNull(results.First()); + } + } +} diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/Community.PowerToys.Run.Plugin.RiderProjects.csproj b/Community.PowerToys.Run.Plugin.RiderProjects/Community.PowerToys.Run.Plugin.RiderProjects.csproj new file mode 100644 index 0000000..def90e7 --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects/Community.PowerToys.Run.Plugin.RiderProjects.csproj @@ -0,0 +1,31 @@ + + + + net8.0-windows + true + x64;ARM64 + $(Platform) + true + $(OutputPath)$(AssemblyName).xml + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/Helpers/RiderLocatorEnvironment.cs b/Community.PowerToys.Run.Plugin.RiderProjects/Helpers/RiderLocatorEnvironment.cs new file mode 100644 index 0000000..3d84d00 --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects/Helpers/RiderLocatorEnvironment.cs @@ -0,0 +1,70 @@ +// Copyright (c) Mpho Jele. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Runtime.InteropServices; + +// using System.Text.Json; +// using System.Text.Json.Serialization; +using JetBrains.Rider.PathLocator; +using Newtonsoft.Json; +using Wox.Plugin.Logger; + +namespace Community.PowerToys.Run.Plugin.RiderProjects.Helpers; + +public class RiderLocatorEnvironment : IRiderLocatorEnvironment +{ + // private readonly JsonSerializerOptions _jsonSerializerOptions = new(JsonSerializerDefaults.Web) + // { + // UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, + // PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + // }; + public OS CurrentOS + { + get + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OS.Windows; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return OS.Linux; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return OS.MacOSX; + } + + return OS.Other; + } + } + + public T FromJson(string json) + { + // return JsonSerializer.Deserialize(json, _jsonSerializerOptions); + return JsonConvert.DeserializeObject(json); + } + + public void Info(string message, Exception e = null) + { + Log.Info(message, GetType()); + } + + public void Warn(string message, Exception e = null) + { + Log.Warn(message, GetType()); + } + + public void Error(string message, Exception e = null) + { + Log.Error(message, GetType()); + } + + public void Verbose(string message, Exception e = null) + { + Log.Info(message, GetType()); + } +} diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/Helpers/RiderProjectsService.cs b/Community.PowerToys.Run.Plugin.RiderProjects/Helpers/RiderProjectsService.cs new file mode 100644 index 0000000..2931bbb --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects/Helpers/RiderProjectsService.cs @@ -0,0 +1,31 @@ +// Copyright (c) Mpho Jele. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.ObjectModel; +using JetBrains.Rider.PathLocator; + +namespace Community.PowerToys.Run.Plugin.RiderProjects.Helpers; + +public class RiderProjectsService +{ + private RiderPathLocator.RiderInfo[] _instances; + private IRiderLocatorEnvironment _locatorEnvironment; + private RiderPathLocator _riderPathLocator; + + public void InitInstances() + { + _locatorEnvironment = new RiderLocatorEnvironment(); + _riderPathLocator = new RiderPathLocator(_locatorEnvironment); + _instances = _riderPathLocator.GetAllRiderPaths(); + } + + public ReadOnlyCollection GetInstances() + { + if (_instances == null) + { + InitInstances(); + } + + return new(_instances!); + } +} diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/Images/riderprojects.dark.png b/Community.PowerToys.Run.Plugin.RiderProjects/Images/riderprojects.dark.png new file mode 100644 index 0000000..413611e Binary files /dev/null and b/Community.PowerToys.Run.Plugin.RiderProjects/Images/riderprojects.dark.png differ diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/Images/riderprojects.light.png b/Community.PowerToys.Run.Plugin.RiderProjects/Images/riderprojects.light.png new file mode 100644 index 0000000..7f94b8d Binary files /dev/null and b/Community.PowerToys.Run.Plugin.RiderProjects/Images/riderprojects.light.png differ diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/Main.cs b/Community.PowerToys.Run.Plugin.RiderProjects/Main.cs new file mode 100644 index 0000000..5260685 --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects/Main.cs @@ -0,0 +1,232 @@ +// Copyright (c) Mpho Jele. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Windows.Input; +using System.Xml.Linq; +using Community.PowerToys.Run.Plugin.RiderProjects.Helpers; +using Newtonsoft.Json.Linq; +using Wox.Infrastructure; +using Wox.Plugin; +using Wox.Plugin.Logger; + +namespace Community.PowerToys.Run.Plugin.RiderProjects +{ + /// + /// Main class of this plugin that implement all used interfaces. + /// + public class Main : IPlugin, IContextMenu, IDisposable + { + private readonly RiderProjectsService _riderProjectsService = new(); + + /// + /// Gets the ID of the plugin. + /// + // ReSharper disable once InconsistentNaming + public static string PluginID => "62D86F0E2E9D45BFA0E067CD14694EC2"; + + /// + /// Gets the name of the plugin. + /// + public string Name => "RiderProjects"; + + /// + /// Gets the description of the plugin. + /// + public string Description => "Opens projects previously opened in JetBrains Rider"; + + private bool Disposed { get; set; } + + /// + /// Return a filtered list, based on the given query. + /// + /// The query to filter the list. + /// A filtered list, can be empty when nothing was found. + public List Query(Query query) + { + var instances = _riderProjectsService.GetInstances(); + var search = query.Search; + + var results = new List(); + var instanceType = GetType(); + + foreach (var instance in instances) + { + // TODO: Check if the config directory hasn't been set to something else in idea.properties + var productInfoPath = Path.Combine(instance.Path, "../../product-info.json"); + if (!File.Exists(productInfoPath)) + { + continue; + } + + var productInfo = JObject.Parse(File.ReadAllText(productInfoPath)); + var dataDirectoryName = productInfo["dataDirectoryName"]?.ToString(); + if (string.IsNullOrEmpty(dataDirectoryName)) + { + continue; + } + + var appDataRoaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + var recentOpenedProjectsFile = appDataRoaming + + $"/JetBrains/{dataDirectoryName}/options/recentSolutions.xml"; + if (!File.Exists(recentOpenedProjectsFile)) + { + continue; + } + + var recentProjects = XDocument.Load(recentOpenedProjectsFile); + foreach (var project in recentProjects.Descendants("entry")) + { + var projectPath = (string)project.Attribute("key"); + + projectPath = projectPath?.Replace( + "$USER_HOME$", Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)); + Log.Info("project path: " + projectPath, instanceType); + var lastOpened = DateTimeOffset.UtcNow.UtcDateTime.ToLocalTime(); + + var metaInfo = project.Descendants("RecentProjectMetaInfo").First(); + var title = + (string)metaInfo.Attribute("frameTitle") ?? + (string)metaInfo.Attribute("displayName") ?? + projectPath ?? + "Unknown"; + Log.Info("title: " + title, instanceType); + + var matchResult = StringMatcher.FuzzySearch(search, title); + if (!string.IsNullOrWhiteSpace(search) && matchResult.Score <= 0) + { + continue; + } + + foreach (var option in project.Descendants("option")) + { + if ((string)option.Attribute("name") != "projectOpenTimestamp") + { + continue; + } + + if (long.TryParse((string)option.Attribute("value"), out var lastOpenedTimestamp)) + { + lastOpened = DateTimeOffset.FromUnixTimeMilliseconds(lastOpenedTimestamp) + .UtcDateTime.ToLocalTime(); + } + } + + var subtitle = + $"{instance.Presentation}: {projectPath}, Last Opened: {lastOpened:yyyy-MM-dd HH:mm}"; + results.Add(new Result + { + QueryTextDisplay = search, + IcoPath = instance.Path, + Title = title, + SubTitle = $"{instance.Presentation}: {projectPath}, Last Opened: {lastOpened:yyyy-MM-dd HH:mm}", + ToolTipData = new ToolTipData(title, subtitle), + ContextData = new CodeContainer(projectPath, instance.Path, lastOpened), + Action = _ => + { + Helper.OpenInShell(instance.Path, $"\"{projectPath}\""); + return true; + }, + }); + } + } + + Log.Info($"results count: {results.Count}", instanceType); + + return results.OrderByDescending(x => ((CodeContainer)x.ContextData).LastOpened).ToList(); + } + + /// + /// Initialize the plugin with the given . + /// + /// The for this plugin. + public void Init(PluginInitContext context) + { + _riderProjectsService.InitInstances(); + } + + /// + /// Return a list context menu entries for a given (shown on the right side of the result). + /// + /// The for the list with context menu entries. + /// A list context menu entries. + public List LoadContextMenus(Result selectedResult) + { + if (selectedResult.ContextData is not CodeContainer container) + { + return []; + } + + return + [ + new() + { + Title = "Run as administrator (Ctrl+Shift+Enter)", + Glyph = "\xE7EF", + FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", + AcceleratorKey = Key.Enter, + AcceleratorModifiers = ModifierKeys.Control | ModifierKeys.Shift, + PluginName = Name, + Action = _ => + { + Helper.OpenInShell( + container.InstancePath, + $"\"{container.FullPath}\"", + runAs: Helper.ShellRunAsType.Administrator); + return true; + }, + }, + + new() + { + Title = "Open containing folder (Ctrl+Shift+E)", + Glyph = "\xE838", + FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", + AcceleratorKey = Key.E, + AcceleratorModifiers = ModifierKeys.Control | ModifierKeys.Shift, + PluginName = Name, + Action = _ => + { + Helper.OpenInShell(Path.GetDirectoryName(container.FullPath)); + return true; + }, + } + + ]; + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Wrapper method for that dispose additional objects and events form the plugin itself. + /// + /// Indicate that the plugin is disposed. + private void Dispose(bool disposing) + { + if (Disposed || !disposing) + { + return; + } + + Disposed = true; + } + + // TODO: Move this class to a separate file + private class CodeContainer(string fullPath, string instancePath, DateTime lastOpened) + { + public string FullPath { get; } = fullPath; + + public string InstancePath { get; } = instancePath; + + public DateTime LastOpened { get; } = lastOpened; + } + } +} diff --git a/Community.PowerToys.Run.Plugin.RiderProjects/plugin.json b/Community.PowerToys.Run.Plugin.RiderProjects/plugin.json new file mode 100644 index 0000000..95ca857 --- /dev/null +++ b/Community.PowerToys.Run.Plugin.RiderProjects/plugin.json @@ -0,0 +1,14 @@ +{ + "ID": "62D86F0E2E9D45BFA0E067CD14694EC2", + "ActionKeyword": "^", + "IsGlobal": false, + "Name": "RiderProjects", + "Author": "mphojele", + "Version": "0.1.0", + "Language": "csharp", + "Website": "https://github.com/mphojele/Powertoys-Run-RiderProjects", + "ExecuteFileName": "Community.PowerToys.Run.Plugin.RiderProjects.dll", + "IcoPathDark": "Images\\riderprojects.dark.png", + "IcoPathLight": "Images\\riderprojects.light.png", + "DynamicLoading": true +} diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..9aaa859 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,10 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + \ No newline at end of file diff --git a/GlobalSuppressions.cs b/GlobalSuppressions.cs new file mode 100644 index 0000000..c2e2109 --- /dev/null +++ b/GlobalSuppressions.cs @@ -0,0 +1,13 @@ +// Copyright (c) Mpho Jele. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. +// Most of these rules are coming from PowerToys own GlobalSuppressions.cs +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:FieldNamesMustNotBeginWithUnderscore", Justification = "We follow the C# Core Coding Style which uses underscores as prefixes rather than using `this.`.")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:PrefixLocalCallsWithThis", Justification = "We follow the C# Core Coding Style which avoids using `this` unless absolutely necessary.")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1652:Enable XML documentation output", Justification = "We do not want to enable XML documentation output ;-)")] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..25a97d6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) Mpho Jele. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7376af9 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +
+ +# PowerToys Run - Rider Projects Plugin + +[![Maintainability](https://api.codeclimate.com/v1/badges/4a9107e36ba549e8691e/maintainability)](https://codeclimate.com/github/khensunny/PowerToys-Run-RiderProjects/maintainability) +[![GitHub repo size](https://img.shields.io/github/repo-size/khensunny/PowerToys-Run-RiderProjects)](#) +
+[![Build](https://github.com/khensunny/PowerToys-Run-RiderProjects/actions/workflows/build.yml/badge.svg)](https://github.com/khensunny/PowerToys-Run-RiderProjects/actions/workflows/build.yml) +[![GitHub release (release name instead of tag name)](https://img.shields.io/github/v/release/khensunny/PowerToys-Run-RiderProjects)](https://github.com/khensunny/PowerToys-Run-RiderProjects/releases/latest) + +
+ +This plugin adds Jetbrains Rider projects results to PowerToys Run.
+It has been developed and tested with Rider `2024.2.4` and PowerToys `v0.84.1`. + +#### Prerequisites +1) [Install PowerToys](https://docs.microsoft.com/en-us/windows/powertoys/install) + +#### Install instructions +1) Manual Installation (ZIP) : [Download from release page](https://github.com/khensunny/PowerToys-Run-RiderProjects/releases/latest) + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/khensunny) +
+ +https://github.com/khensunny/PowerToys-Run-RiderProjects/blob/main/docs/ptr-riderprojects-demo.mp4 \ No newline at end of file diff --git a/RiderProjects.sln b/RiderProjects.sln new file mode 100644 index 0000000..d1b5865 --- /dev/null +++ b/RiderProjects.sln @@ -0,0 +1,40 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35027.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Community.PowerToys.Run.Plugin.RiderProjects", "Community.PowerToys.Run.Plugin.RiderProjects\Community.PowerToys.Run.Plugin.RiderProjects.csproj", "{C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Community.PowerToys.Run.Plugin.RiderProjects.UnitTests", "Community.PowerToys.Run.Plugin.RiderProjects.UnitTests\Community.PowerToys.Run.Plugin.RiderProjects.UnitTests.csproj", "{E3D9EA13-3B1E-487D-9219-18DEB9C87220}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Debug|ARM64.Build.0 = Debug|ARM64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Debug|x64.ActiveCfg = Debug|x64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Debug|x64.Build.0 = Debug|x64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Release|ARM64.ActiveCfg = Release|ARM64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Release|ARM64.Build.0 = Release|ARM64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Release|x64.ActiveCfg = Release|x64 + {C32F81B1-BE7A-42B1-9731-1046F0A6B0AD}.Release|x64.Build.0 = Release|x64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Debug|ARM64.Build.0 = Debug|ARM64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Debug|x64.ActiveCfg = Debug|x64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Debug|x64.Build.0 = Debug|x64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Release|ARM64.ActiveCfg = Release|ARM64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Release|ARM64.Build.0 = Release|ARM64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Release|x64.ActiveCfg = Release|x64 + {E3D9EA13-3B1E-487D-9219-18DEB9C87220}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FF666520-8AC9-4276-9762-0EA94991801B} + EndGlobalSection +EndGlobal diff --git a/StyleCop.json b/StyleCop.json new file mode 100644 index 0000000..ce8fb9f --- /dev/null +++ b/StyleCop.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "xmlHeader": false, + "companyName": "Mpho Jele", + "copyrightText": "Copyright (c) {companyName}. All rights reserved.\nLicensed under the MIT license. See LICENSE file in the project root for full license information.", + "documentExposedElements": false, + "documentInterfaces": false, + "documentInternalElements": false + }, + "layoutRules": { + "newlineAtEndOfFile": "require" + }, + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace", + "systemUsingDirectivesFirst": true + } + } +}