Skip to content

Commit

Permalink
[PT Run] [Folder Plugin] Environment Variables With Autocomplete (#13811
Browse files Browse the repository at this point in the history
)

* search environment variables folders with autocomplete

* refactoring and tests

* fix
  • Loading branch information
davidegiacometti committed Oct 20, 2021
1 parent 15f3c2f commit 64cc6b7
Show file tree
Hide file tree
Showing 10 changed files with 296 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/actions/spell-check/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@ IEasing
IEnum
IEnumerable
IEnumerator
IEnvironment
IEquality
IEquatable
IEvent
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Plugin.Folder.Sources;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Plugin.Folder.UnitTests
{
[TestClass]
public class EnvironmentHelperTests
{
[DataTestMethod]
[DataRow(@"%", true)]
[DataRow(@"%P", true)]
[DataRow(@"%PROGRAMDATA%", true)]
[DataRow(@"", false)]
[DataRow(@"C:\ProgramData", false)]

public void IsValidEnvironmentVariable(string search, bool expectedSuccess)
{
var helper = new EnvironmentHelper();

var result = helper.IsEnvironmentVariable(search);

Assert.AreEqual(expectedSuccess, result);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using Microsoft.Plugin.Folder.Sources;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Microsoft.Plugin.Folder.UnitTests
{
[TestClass]
public class QueryEnvironmentVariableTests
{
private static IQueryEnvironmentVariable _queryEnvironmentVariable;
private static MockFileSystem _fileSystem;

[TestInitialize]
public void SetupMock()
{
var environmentHelperMock = new Mock<IEnvironmentHelper>();

environmentHelperMock
.Setup(h => h.GetEnvironmentVariables())
.Returns(() => new Dictionary<string, string>
{
{ "OS", "Windows_NT" },
{ "WINDIR", @"C:\Windows" },
{ "PROGRAMDATA", @"C:\ProgramData" },
{ "PROGRAMFILES", @"C:\Program Files" },
});

_fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>()
{
{ @"C:\Windows", new MockDirectoryData() },
{ @"C:\ProgramData", new MockDirectoryData() },
{ @"C:\Program Files", new MockDirectoryData() },
});

_queryEnvironmentVariable = new QueryEnvironmentVariable(_fileSystem.Directory, environmentHelperMock.Object);
}

[DataTestMethod]
[DataRow(@"%OS%")] // Not a directory
[DataRow(@"%CUSTOM%")] // Directory doesn't exist
[DataRow(@"WINDIR")] // Not an environment variable
public void QueryWithEmptyResults(string search)
{
var results = _queryEnvironmentVariable.Query(search);
Assert.AreEqual(results.Count(), 0);
}

[DataTestMethod]
[DataRow(@"", 3)]
[DataRow(@"%", 3)]
[DataRow(@"%WIN", 1)]
[DataRow(@"%WINDIR%", 1)]
[DataRow(@"%PROGRAM", 2)]
public void QueryWithResults(string search, int numberOfResults)
{
var results = _queryEnvironmentVariable.Query(search);
Assert.AreEqual(results.Count(), numberOfResults);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Plugin.Folder.Sources;
using Microsoft.Plugin.Folder.Sources.Result;

namespace Microsoft.Plugin.Folder
{
public class EnvironmentVariableProcessor : IFolderProcessor
{
private readonly IEnvironmentHelper _environmentHelper;
private readonly IQueryEnvironmentVariable _queryEnvironmentVariable;

public EnvironmentVariableProcessor(IEnvironmentHelper environmentHelper, IQueryEnvironmentVariable queryEnvironmentVariable)
{
_environmentHelper = environmentHelper;
_queryEnvironmentVariable = queryEnvironmentVariable;
}

public IEnumerable<IItemResult> Results(string actionKeyword, string search)
{
if (search == null)
{
throw new ArgumentNullException(nameof(search));
}

if (!_environmentHelper.IsEnvironmentVariable(search))
{
return Enumerable.Empty<IItemResult>();
}

return _queryEnvironmentVariable.Query(search);
}
}
}
3 changes: 3 additions & 0 deletions src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ public class Main : IPlugin, IPluginI18n, ISavable, IContextMenu, IDisposable
private static readonly FolderSettings _settings = _storage.Load();
private static readonly IQueryInternalDirectory _internalDirectory = new QueryInternalDirectory(_settings, new QueryFileSystemInfo(_fileSystem.DirectoryInfo), _fileSystem.Directory);
private static readonly FolderHelper _folderHelper = new FolderHelper(new DriveInformation(), new FolderLinksSettings(_settings));
private static readonly IEnvironmentHelper _environmentHelper = new EnvironmentHelper();
private static readonly IQueryEnvironmentVariable _queryEnvironmentVariable = new QueryEnvironmentVariable(_fileSystem.Directory, _environmentHelper);

private static readonly ICollection<IFolderProcessor> _processors = new IFolderProcessor[]
{
new UserFolderProcessor(_folderHelper),
new InternalDirectoryProcessor(_folderHelper, _internalDirectory),
new EnvironmentVariableProcessor(_environmentHelper, _queryEnvironmentVariable),
};

private static PluginInitContext _context;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections;

namespace Microsoft.Plugin.Folder.Sources
{
public class EnvironmentHelper : IEnvironmentHelper
{
public bool IsEnvironmentVariable(string search)
{
if (search == null)
{
throw new ArgumentNullException(paramName: nameof(search));
}

return search.StartsWith('%');
}

public IDictionary GetEnvironmentVariables()
{
return Environment.GetEnvironmentVariables();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections;

namespace Microsoft.Plugin.Folder.Sources
{
public interface IEnvironmentHelper
{
bool IsEnvironmentVariable(string search);

IDictionary GetEnvironmentVariables();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using Microsoft.Plugin.Folder.Sources.Result;

namespace Microsoft.Plugin.Folder.Sources
{
public interface IQueryEnvironmentVariable
{
IEnumerable<IItemResult> Query(string querySearch);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using Microsoft.Plugin.Folder.Sources.Result;

namespace Microsoft.Plugin.Folder.Sources
{
public class QueryEnvironmentVariable : IQueryEnvironmentVariable
{
private readonly IDirectory _directory;
private readonly IEnvironmentHelper _environmentHelper;

public QueryEnvironmentVariable(IDirectory directory, IEnvironmentHelper environmentHelper)
{
_directory = directory;
_environmentHelper = environmentHelper;
}

public IEnumerable<IItemResult> Query(string querySearch)
{
if (querySearch == null)
{
throw new ArgumentNullException(nameof(querySearch));
}

return GetEnvironmentVariables(querySearch)
.OrderBy(v => v.Title)
.Where(v => v.Title.StartsWith(querySearch, StringComparison.InvariantCultureIgnoreCase));
}

public IEnumerable<EnvironmentVariableResult> GetEnvironmentVariables(string querySearch)
{
foreach (DictionaryEntry variable in _environmentHelper.GetEnvironmentVariables())
{
if (variable.Value == null)
{
continue;
}

var name = "%" + (string)variable.Key + "%";
var path = (string)variable.Value;

if (_directory.Exists(path))
{
yield return new EnvironmentVariableResult(querySearch, name, path);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Globalization;
using Wox.Infrastructure;
using Wox.Plugin;

namespace Microsoft.Plugin.Folder.Sources.Result
{
public class EnvironmentVariableResult : IItemResult
{
private readonly IShellAction _shellAction = new ShellAction();

public string Search { get; set; }

public string Title { get; private set; }

public string Subtitle { get; private set; }

public string Path { get; private set; }

public EnvironmentVariableResult(string search, string title, string path)
{
Search = search;
Title = title;
Path = path;
}

public Wox.Plugin.Result Create(IPublicAPI contextApi)
{
return new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Title).MatchData)
{
Title = Title,
IcoPath = Path,

// Using CurrentCulture since this is user facing
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Path),
QueryTextDisplay = Path,
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path },
Action = c => _shellAction.Execute(Path, contextApi),
};
}
}
}

0 comments on commit 64cc6b7

Please sign in to comment.