diff --git a/BrowseRouter/BrowserService.cs b/BrowseRouter/BrowserService.cs index 237322f..63a1be8 100644 --- a/BrowseRouter/BrowserService.cs +++ b/BrowseRouter/BrowserService.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Text; namespace BrowseRouter; @@ -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; diff --git a/BrowseRouter/Executable.cs b/BrowseRouter/Executable.cs index ae433cf..c375eef 100644 --- a/BrowseRouter/Executable.cs +++ b/BrowseRouter/Executable.cs @@ -1,4 +1,6 @@ -namespace BrowseRouter; +using System.Text; + +namespace BrowseRouter; public static class Executable { @@ -23,4 +25,83 @@ public static (string, string) GetPathAndArgs(string s) // The single executable without any other arguments. return (s, ""); } + + /// + /// 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. + /// + /// The unformatted arguments + /// The URI to format the arguments with + /// The formatted arguments + 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 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(); + } } \ No newline at end of file diff --git a/README.md b/README.md index d1a39ca..627430e 100644 --- a/README.md +++ b/README.md @@ -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.