Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions BrowseRouter/BrowserService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Text;

namespace BrowseRouter;

Expand Down Expand Up @@ -35,13 +36,15 @@ public async Task LaunchAsync(string url, string windowTitle)

(string path, string args) = Executable.GetPathAndArgs(pref.Browser.Location);

Log.Write($"Launching {path} with args \"{args} {uri.OriginalString}\"");
args = Executable.FormatArguments(args, uri);

Log.Write($"Launching {path} with args \"{args}\"");

string name = GetAppName(path);

path = Environment.ExpandEnvironmentVariables(path);

if (!Actions.TryRun(() => Process.Start(path, $"{args} \"{uri.OriginalString}\"")))
if (!Actions.TryRun(() => Process.Start(path, args)))
{
await notifier.NotifyAsync($"Error", $"Could not open {name}. Please check the log for more details.");
return;
Expand Down
83 changes: 82 additions & 1 deletion BrowseRouter/Executable.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace BrowseRouter;
using System.Text;

namespace BrowseRouter;

public static class Executable
{
Expand All @@ -23,4 +25,83 @@ public static (string, string) GetPathAndArgs(string s)
// The single executable without any other arguments.
return (s, "");
}

/// <summary>
/// Complete the arguments to call the browser with, with the uri requested and according to the recognized tags in them.
/// If no tags is recognized the uri is simply added to the end of the arguments.
/// </summary>
/// <param name="originalArgs">The unformatted arguments</param>
/// <param name="uri">The URI to format the arguments with</param>
/// <returns>The formatted arguments</returns>
public static string FormatArguments(string originalArgs, Uri uri)
{
int tagReplacedCount = 0;
StringBuilder args = new();

int nextIndexToAdd = 0;
int tagStartIndex = originalArgs.IndexOf('{');

while (tagStartIndex >= 0)
{
args.Append(originalArgs.AsSpan(nextIndexToAdd, tagStartIndex - nextIndexToAdd));
nextIndexToAdd = tagStartIndex;

int tagEndIndex = originalArgs.IndexOf('}', tagStartIndex);
if (tagEndIndex < 0) // if there's no more '}' in the rest of the args string
break;

bool successfullyReplacedTag = true;

ReadOnlySpan<char> tagContent = originalArgs.AsSpan(tagStartIndex + 1, tagEndIndex - 1 - tagStartIndex);
switch (tagContent)
{
case "url":
args.Append(uri.OriginalString);
break;
case "userinfo":
args.Append(uri.UserInfo);
break;
case "host":
args.Append(uri.Host);
break;
case "port":
args.Append(uri.Port);
break;
case "authority":
args.Append(uri.Authority);
break;
case "path":
args.Append(uri.AbsolutePath);
break;
case "query":
args.Append(uri.Query);
break;
case "fragment":
args.Append(uri.Fragment);
break;

default:
successfullyReplacedTag = false;
break;
}

if (successfullyReplacedTag)
{
tagReplacedCount++;

nextIndexToAdd = tagEndIndex + 1;
tagStartIndex = originalArgs.IndexOf('{', tagEndIndex);
}
else
tagStartIndex = originalArgs.IndexOf('{', tagStartIndex + 1);
}

if (nextIndexToAdd < originalArgs.Length)
args.Append(originalArgs.AsSpan(nextIndexToAdd));

if (tagReplacedCount == 0)
args.Append($" \"{uri.OriginalString}\"");

return args.ToString();
}
}
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ Slack | Test = chrome
- Arguments are optional. However, if you provide arguments the path _must_ be enclosed in quotes. For example, `"chrome.exe" --new-window`
- If there are no arguments, then the paths do not need to be quoted. For example, `chrome.exe` will work.

By default the URL to open is added as the last argument after the call to the executable.
But if you want it to be called differently, or only partially, you can use specific tags in the arguments you provide.
These tag will be replaced by their corresponding value in the URL :
- `{url}` the full, untruncated URL
- `{userinfo}` the userinfo part of the URL, might be blank if not present in the URL
- `{host}` the host of the URL, most often this will be a domain name (subdomain included)
- `{port}` the specific port of the URL, might be blank if not present in the URL
- `{authority}` the combination of userinfo, host and port separated by their respective delimiters if needed
- `{path}` the path of the URL, might be only `/` if the link targets the root of the domain
- `{query}` the query of the URL with the leading `?`, might be blank if not present in the URL
- `{fragment}` the fragment of the URL with the leading `#`, might be blank if not present in the URL

For example if you want a browser which strip the query from the opened links, you can add this line:
`noQueryFF = "firefox.exe" "{authority}{path}{fragment}"`

[More details and example about URI composition is available here!](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Example_URIs)

### Sources

- You can optionally specify a "source preference" which matches the window title of the application used to open the link.
Expand Down
Loading