summaryrefslogtreecommitdiffstats
path: root/crates/printer/src/hyperlink_aliases.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/printer/src/hyperlink_aliases.rs')
-rw-r--r--crates/printer/src/hyperlink_aliases.rs88
1 files changed, 76 insertions, 12 deletions
diff --git a/crates/printer/src/hyperlink_aliases.rs b/crates/printer/src/hyperlink_aliases.rs
index 6d429bf8..c98bc0b0 100644
--- a/crates/printer/src/hyperlink_aliases.rs
+++ b/crates/printer/src/hyperlink_aliases.rs
@@ -1,23 +1,87 @@
/// Aliases to well-known hyperlink schemes.
///
/// These need to be sorted by name.
-pub(crate) const HYPERLINK_PATTERN_ALIASES: &[(&str, &str)] = &[
- #[cfg(unix)]
- ("file", "file://{host}/{file}"),
+const HYPERLINK_PATTERN_ALIASES: &[(&str, &str)] = &[
+ #[cfg(not(windows))]
+ ("default", "file://{host}{path}"),
#[cfg(windows)]
- ("file", "file:///{file}"),
+ ("default", "file://{path}"),
+ ("file", "file://{host}{path}"),
// https://github.com/misaki-web/grepp
- ("grep+", "grep+:///{file}:{line}"),
- ("kitty", "file://{host}/{file}#{line}"),
+ ("grep+", "grep+://{path}:{line}"),
+ ("kitty", "file://{host}{path}#{line}"),
// https://macvim.org/docs/gui_mac.txt.html#mvim%3A%2F%2F
- ("macvim", "mvim://open?url=file:///{file}&line={line}&column={column}"),
+ ("macvim", "mvim://open?url=file://{path}&line={line}&column={column}"),
("none", ""),
// https://github.com/inopinatus/sublime_url
- ("subl", "subl://open?url=file:///{file}&line={line}&column={column}"),
+ ("subl", "subl://open?url=file://{path}&line={line}&column={column}"),
// https://macromates.com/blog/2007/the-textmate-url-scheme/
- ("textmate", "txmt://open?url=file:///{file}&line={line}&column={column}"),
+ ("textmate", "txmt://open?url=file://{path}&line={line}&column={column}"),
// https://code.visualstudio.com/docs/editor/command-line#_opening-vs-code-with-urls
- ("vscode", "vscode://file/{file}:{line}:{column}"),
- ("vscode-insiders", "vscode-insiders://file/{file}:{line}:{column}"),
- ("vscodium", "vscodium://file/{file}:{line}:{column}"),
+ ("vscode", "vscode://file{path}:{line}:{column}"),
+ ("vscode-insiders", "vscode-insiders://file{path}:{line}:{column}"),
+ ("vscodium", "vscodium://file{path}:{line}:{column}"),
];
+
+/// Look for the hyperlink format defined by the given alias name.
+///
+/// If one does not exist, `None` is returned.
+pub(crate) fn find(name: &str) -> Option<&str> {
+ HYPERLINK_PATTERN_ALIASES
+ .binary_search_by_key(&name, |&(name, _)| name)
+ .map(|i| HYPERLINK_PATTERN_ALIASES[i].1)
+ .ok()
+}
+
+/// Return an iterator over all available alias names and their definitions.
+pub(crate) fn iter() -> impl Iterator<Item = (&'static str, &'static str)> {
+ HYPERLINK_PATTERN_ALIASES.iter().copied()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::HyperlinkFormat;
+
+ use super::*;
+
+ #[test]
+ fn is_sorted() {
+ let mut prev = HYPERLINK_PATTERN_ALIASES
+ .get(0)
+ .expect("aliases should be non-empty")
+ .0;
+ for &(name, _) in HYPERLINK_PATTERN_ALIASES.iter().skip(1) {
+ assert!(
+ name > prev,
+ "'{prev}' should come before '{name}' in \
+ HYPERLINK_PATTERN_ALIASES",
+ );
+ prev = name;
+ }
+ }
+
+ #[test]
+ fn alias_names_are_reasonable() {
+ for &(name, _) in HYPERLINK_PATTERN_ALIASES.iter() {
+ // There's no hard rule here, but if we want to define an alias
+ // with a name that doesn't pass this assert, then we should
+ // probably flag it as worthy of consideration. For example, we
+ // really do not want to define an alias that contains `{` or `}`,
+ // which might confuse it for a variable.
+ assert!(name.chars().all(|c| c.is_alphanumeric()
+ || c == '+'
+ || c == '-'
+ || c == '.'));
+ }
+ }
+
+ #[test]
+ fn aliases_are_valid_formats() {
+ for (name, definition) in HYPERLINK_PATTERN_ALIASES {
+ assert!(
+ definition.parse::<HyperlinkFormat>().is_ok(),
+ "invalid hyperlink alias '{name}': {definition}",
+ );
+ }
+ }
+}