Skip to content

Commit 1ba5a25

Browse files
authored
CmdPal: Add custom search engine option to Web Search extension (#43941)
## Summary of the Pull Request This PR allows user to customize a search query in Command Palette's Web Search built-in extension. This will also solve a problem with some browser that doesn't handle argument in form "? <query>" as it will allow user to specify the complete URI. - Introduces a new text box in Web Search extension settings for specifying a custom search engine URI - If the text box is non-empty, the provided URI is used for queries - If left empty, the extension defaults to previous behavior, sending queries in the format "? query" ## Pictures? Pictures! <img width="825" height="566" alt="image" src="https://github.com/user-attachments/assets/fbf3d3a5-ebfe-4c16-a5f1-0d044b6f9047" /> <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43940 - [x] Closes: #42867 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
1 parent 8aea589 commit 1ba5a25

File tree

6 files changed

+68
-1
lines changed

6 files changed

+68
-1
lines changed

src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.WebSearch.UnitTests/MockSettingsInterface.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public class MockSettingsInterface : ISettingsInterface
1818

1919
public int HistoryItemCount { get; set; }
2020

21+
public string CustomSearchUri { get; }
22+
2123
public IReadOnlyList<HistoryItem> HistoryItems => _historyItems;
2224

2325
public MockSettingsInterface(int historyItemCount = 0, bool globalIfUri = true, List<HistoryItem> mockHistory = null)

src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Commands/SearchWebCommand.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,44 @@ internal SearchWebCommand(string arguments, ISettingsInterface settingsManager,
2828

2929
public override CommandResult Invoke()
3030
{
31-
if (!_browserInfoService.Open($"? {Arguments}"))
31+
var uri = BuildUri();
32+
33+
if (!_browserInfoService.Open(uri))
3234
{
3335
// TODO GH# 138 --> actually display feedback from the extension somewhere.
3436
return CommandResult.KeepOpen();
3537
}
3638

39+
// remember only the query, not the full URI
3740
if (_settingsManager.HistoryItemCount != 0)
3841
{
3942
_settingsManager.AddHistoryItem(new HistoryItem(Arguments, DateTime.Now));
4043
}
4144

4245
return CommandResult.Dismiss();
4346
}
47+
48+
private string BuildUri()
49+
{
50+
if (string.IsNullOrWhiteSpace(_settingsManager.CustomSearchUri))
51+
{
52+
return $"? " + Arguments;
53+
}
54+
55+
// if the custom search URI contains query placeholder, replace it with the actual query
56+
// otherwise append the query to the end of the URI
57+
// support {query}, %query% or %s as placeholder
58+
var placeholderVariants = new[] { "{query}", "%query%", "%s" };
59+
foreach (var placeholder in placeholderVariants)
60+
{
61+
if (_settingsManager.CustomSearchUri.Contains(placeholder, StringComparison.OrdinalIgnoreCase))
62+
{
63+
return _settingsManager.CustomSearchUri.Replace(placeholder, Uri.EscapeDataString(Arguments), StringComparison.OrdinalIgnoreCase);
64+
}
65+
}
66+
67+
// is this too smart?
68+
var separator = _settingsManager.CustomSearchUri.Contains('?') ? '&' : '?';
69+
return $"{_settingsManager.CustomSearchUri}{separator}q={Uri.EscapeDataString(Arguments)}";
70+
}
4471
}

src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/ISettingsInterface.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@ public interface ISettingsInterface
1818

1919
public IReadOnlyList<HistoryItem> HistoryItems { get; }
2020

21+
string CustomSearchUri { get; }
22+
2123
public void AddHistoryItem(HistoryItem historyItem);
2224
}

src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ public event EventHandler? HistoryChanged
4141
Resources.plugin_global_if_uri,
4242
false);
4343

44+
private readonly TextSetting _customSearchUri = new(
45+
Namespaced(nameof(CustomSearchUri)),
46+
Resources.plugin_custom_search_uri,
47+
Resources.plugin_custom_search_uri,
48+
string.Empty)
49+
{
50+
Placeholder = Resources.plugin_custom_search_uri_placeholder,
51+
};
52+
4453
private readonly ChoiceSetSetting _historyItemCount = new(
4554
Namespaced(HistoryItemCountLegacySettingsKey),
4655
Resources.plugin_history_item_count,
@@ -51,6 +60,8 @@ public event EventHandler? HistoryChanged
5160

5261
public int HistoryItemCount => int.TryParse(_historyItemCount.Value, out var value) && value >= 0 ? value : 0;
5362

63+
public string CustomSearchUri => _customSearchUri.Value ?? string.Empty;
64+
5465
public IReadOnlyList<HistoryItem> HistoryItems => _history.HistoryItems;
5566

5667
public SettingsManager()
@@ -59,6 +70,7 @@ public SettingsManager()
5970

6071
Settings.Add(_globalIfURI);
6172
Settings.Add(_historyItemCount);
73+
Settings.Add(_customSearchUri);
6274

6375
LoadSettings();
6476

src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,10 @@
187187
<data name="default_browser" xml:space="preserve">
188188
<value>default browser</value>
189189
</data>
190+
<data name="plugin_custom_search_uri" xml:space="preserve">
191+
<value>Custom search engine URL</value>
192+
</data>
193+
<data name="plugin_custom_search_uri_placeholder" xml:space="preserve">
194+
<value>Use {query} or %s as the search query placeholder; e.g. https://www.bing.com/search?q={query}</value>
195+
</data>
190196
</root>

0 commit comments

Comments
 (0)