mirror of
https://github.com/wez/wezterm.git
synced 2024-11-26 08:25:50 +03:00
improve default hyperlink_rules. add default_hyperlink_rules()
refs: https://github.com/wez/wezterm/issues/928
This commit is contained in:
parent
c093b8861a
commit
6a9dfc409d
@ -1438,14 +1438,18 @@ fn default_initial_cols() -> u16 {
|
||||
80
|
||||
}
|
||||
|
||||
fn default_hyperlink_rules() -> Vec<hyperlink::Rule> {
|
||||
pub fn default_hyperlink_rules() -> Vec<hyperlink::Rule> {
|
||||
vec![
|
||||
// URL with a protocol
|
||||
hyperlink::Rule::new(r"\b\w+://[\w.-]+\.[a-z]{2,15}\S*\b", "$0").unwrap(),
|
||||
// First handle URLs wrapped with punctuation (i.e. brackets)
|
||||
// e.g. [http://foo] (http://foo) <http://foo>
|
||||
hyperlink::Rule::with_highlight(r"\((\w+://\S+)\)", "$1", 1).unwrap(),
|
||||
hyperlink::Rule::with_highlight(r"\[(\w+://\S+)\]", "$1", 1).unwrap(),
|
||||
hyperlink::Rule::with_highlight(r"<(\w+://\S+)>", "$1", 1).unwrap(),
|
||||
// Then handle URLs not wrapped in brackets
|
||||
// and include terminating ), / or - characters, if any
|
||||
hyperlink::Rule::new(r"\b\w+://\S+[)/a-zA-Z0-9-]+", "$0").unwrap(),
|
||||
// implicit mailto link
|
||||
hyperlink::Rule::new(r"\b\w+@[\w-]+(\.[\w-]+)+\b", "mailto:$0").unwrap(),
|
||||
// file://
|
||||
hyperlink::Rule::new(r"\bfile://\S*\b", "$0").unwrap(),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -353,6 +353,14 @@ end
|
||||
wezterm_mod.set("shell_quote_arg", lua.create_function(shell_quote_arg)?)?;
|
||||
wezterm_mod.set("shell_split", lua.create_function(shell_split)?)?;
|
||||
|
||||
wezterm_mod.set(
|
||||
"default_hyperlink_rules",
|
||||
lua.create_function(move |lua, ()| {
|
||||
let rules = crate::config::default_hyperlink_rules();
|
||||
Ok(to_lua(lua, rules))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
// Define our own os.getenv function that knows how to resolve current
|
||||
// environment values from eg: the registry on Windows, or for
|
||||
// the current SHELL value on unix, even if the user has changed
|
||||
|
@ -79,6 +79,10 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
[#1485](https://github.com/wez/wezterm/issues/1485)
|
||||
* `wezterm sssh` now supports `%l` and `%L` tokens in config files.
|
||||
[#3176](https://github.com/wez/wezterm/issues/3176)
|
||||
* [hyperlink_rules](config/lua/config/hyperlink_rules.md) now support
|
||||
specifying which capture group should be highlighted.
|
||||
* [wezterm.default_hyperlink_rules](config/lua/wezterm/default_hyperlink_rules.md)
|
||||
function makes it easier to extend the default set of hyperlink rules.
|
||||
|
||||
#### Fixed
|
||||
* X11: hanging or killing the IME could hang wezterm
|
||||
@ -131,6 +135,9 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
[#3250](https://github.com/wez/wezterm/issues/3250)
|
||||
* Config was not applied to non-zoomed panes when config was reloaded
|
||||
[#3259](https://github.com/wez/wezterm/issues/3259)
|
||||
* Default [hyperlink_rules](config/lua/config/hyperlink_rules.md) now match
|
||||
URLs with port numbers
|
||||
[#928](https://github.com/wez/wezterm/issues/928)
|
||||
|
||||
#### Changed
|
||||
* `CTRL-SHIFT-P` now activates the new [command
|
||||
|
@ -3,5 +3,109 @@
|
||||
Defines rules to match text from the terminal output and generate
|
||||
clickable links.
|
||||
|
||||
See [Hyperlinks](../../../hyperlinks.md) for more information and
|
||||
examples.
|
||||
The value is a list of rule entries. Each entry has the following fields:
|
||||
|
||||
* `regex` - the regular expression to match
|
||||
* `format` - Controls what will be used to form the link. The string
|
||||
can use placeholders like `$0`, `$1`, `$2` etc. that will be replaced
|
||||
with that numbered capture group. So, `$0` will take the entire
|
||||
region of text matched by the whole regex, while `$1` matches out
|
||||
the first capture group. In the example below, `mailto:$0` is
|
||||
used to prefix a protocol to the text to make it into an URL.
|
||||
* `highlight` - (*Since: nightly builds only*) specifies the range
|
||||
of the matched text that should be highlighted/underlined when
|
||||
the mouse hovers over the link. The default is `0`, highlighting
|
||||
the entire region of text matched by the regex.
|
||||
|
||||
Assigning `hyperlink_rules` overrides the built-in default rules.
|
||||
|
||||
The default value for `hyperlink_rules` can be retrieved using
|
||||
[wezterm.default_hyperlink_rules()](../wezterm/default_hyperlink_rules.md),
|
||||
and is shown below:
|
||||
|
||||
```lua
|
||||
return {
|
||||
hyperlink_rules = {
|
||||
-- Matches: a URL in parens: (URL)
|
||||
{
|
||||
regex = '\\((\\w+://\\S+)\\)',
|
||||
format = '$1',
|
||||
highlight = 1,
|
||||
},
|
||||
-- Matches: a URL in brackets: [URL]
|
||||
{
|
||||
regex = '\\[(\\w+://\\S+)\\]',
|
||||
format = '$1',
|
||||
highlight = 1,
|
||||
},
|
||||
-- Matches: a URL in curly braces: {URL}
|
||||
{
|
||||
regex = '\\{(\\w+://\\S+)\\}',
|
||||
format = '$1',
|
||||
highlight = 1,
|
||||
},
|
||||
-- Matches: a URL in angle brackets: <URL>
|
||||
{
|
||||
regex = '<(\\w+://\\S+)>',
|
||||
format = '$1',
|
||||
highlight = 1,
|
||||
},
|
||||
-- Then handle URLs not wrapped in brackets
|
||||
{
|
||||
regex = '\\b\\w+://\\S+[)/a-zA-Z0-9-]+',
|
||||
format = '$0',
|
||||
},
|
||||
-- implicit mailto link
|
||||
{
|
||||
regex = '\\b\\w+@[\\w-]+(\\.[\\w-]+)+\\b',
|
||||
format = 'mailto:$0',
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
In quoted Lua string literals the backslash character must be
|
||||
quoted even if the following character isn't meaningful to Lua
|
||||
when quoted by a backslash. That means that you'll always want to
|
||||
double it up as `\\` when using it in a regex string.
|
||||
|
||||
Alternatively, you can use the alternative string literal
|
||||
syntax; the following two examples are equivalent:
|
||||
|
||||
```lua
|
||||
regex = [[\b[tT](\d+)\b]]
|
||||
```
|
||||
|
||||
```lua
|
||||
regex = '\\b[tT](\\d+)\\b'
|
||||
```
|
||||
|
||||
Some other examples include:
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
|
||||
-- Use the defaults as a base
|
||||
local hyperlink_rules = wezterm.default_hyperlink_rules()
|
||||
|
||||
-- make task numbers clickable
|
||||
-- the first matched regex group is captured in $1.
|
||||
table.insert(hyperlink_rules, {
|
||||
regex = [[\b[tt](\d+)\b]],
|
||||
format = 'https://example.com/tasks/?t=$1',
|
||||
})
|
||||
|
||||
-- make username/project paths clickable. this implies paths like the following are for github.
|
||||
-- ( "nvim-treesitter/nvim-treesitter" | wbthomason/packer.nvim | wez/wezterm | "wez/wezterm.git" )
|
||||
-- as long as a full url hyperlink regex exists above this it should not match a full url to
|
||||
-- github or gitlab / bitbucket (i.e. https://gitlab.com/user/project.git is still a whole clickable url)
|
||||
table.insert(hyperlink_rules, {
|
||||
regex = [[["]?([\w\d]{1}[-\w\d]+)(/){1}([-\w\d\.]+)["]?]],
|
||||
format = 'https://www.github.com/$1/$3',
|
||||
})
|
||||
|
||||
return {
|
||||
hyperlink_rules = hyperlink_rules,
|
||||
}
|
||||
```
|
||||
|
6
docs/config/lua/wezterm/default_hyperlink_rules.md
Normal file
6
docs/config/lua/wezterm/default_hyperlink_rules.md
Normal file
@ -0,0 +1,6 @@
|
||||
# `wezterm.default_hyperlink_rules()`
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
Returns the compiled-in default values for [hyperlink_rules](../config/hyperlink_rules.md).
|
||||
|
@ -5,66 +5,42 @@ wezterm has support for both implicit and explicit hyperlinks.
|
||||
Implicit hyperlinks are produced by running a series of rules over the output
|
||||
displayed in the terminal to produce a hyperlink. There is a default rule
|
||||
to match URLs and make them clickable, but you can also specify your own rules
|
||||
to make your own links. As an example, at my place of work many of our internal
|
||||
tools use `T123` to indicate task number 123 in our internal task tracking system.
|
||||
It is desirable to make this clickable, and that can be done with the following
|
||||
configuration in your `~/.wezterm.lua`:
|
||||
to make your own links.
|
||||
|
||||
As an example, at my place of work many of our internal tools use `T123` to
|
||||
indicate task number 123 in our internal task tracking system. It is desirable
|
||||
to make this clickable, and that can be done with the following configuration
|
||||
in your `~/.wezterm.lua`:
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
|
||||
-- Use the defaults as a base
|
||||
local hyperlink_rules = wezterm.default_hyperlink_rules()
|
||||
|
||||
-- make task numbers clickable
|
||||
-- the first matched regex group is captured in $1.
|
||||
table.insert(hyperlink_rules, {
|
||||
regex = [[\b[tt](\d+)\b]],
|
||||
format = 'https://example.com/tasks/?t=$1',
|
||||
})
|
||||
|
||||
-- make username/project paths clickable. this implies paths like the following are for github.
|
||||
-- ( "nvim-treesitter/nvim-treesitter" | wbthomason/packer.nvim | wez/wezterm | "wez/wezterm.git" )
|
||||
-- as long as a full url hyperlink regex exists above this it should not match a full url to
|
||||
-- github or gitlab / bitbucket (i.e. https://gitlab.com/user/project.git is still a whole clickable url)
|
||||
table.insert(hyperlink_rules, {
|
||||
regex = [[["]?([\w\d]{1}[-\w\d]+)(/){1}([-\w\d\.]+)["]?]],
|
||||
format = 'https://www.github.com/$1/$3',
|
||||
})
|
||||
|
||||
return {
|
||||
hyperlink_rules = {
|
||||
-- Linkify things that look like URLs and the host has a TLD name.
|
||||
-- Compiled-in default. Used if you don't specify any hyperlink_rules.
|
||||
{
|
||||
regex = '\\b\\w+://[\\w.-]+\\.[a-z]{2,15}\\S*\\b',
|
||||
format = '$0',
|
||||
},
|
||||
|
||||
-- linkify email addresses
|
||||
-- Compiled-in default. Used if you don't specify any hyperlink_rules.
|
||||
{
|
||||
regex = [[\b\w+@[\w-]+(\.[\w-]+)+\b]],
|
||||
format = 'mailto:$0',
|
||||
},
|
||||
|
||||
-- file:// URI
|
||||
-- Compiled-in default. Used if you don't specify any hyperlink_rules.
|
||||
{
|
||||
regex = [[\bfile://\S*\b]],
|
||||
format = '$0',
|
||||
},
|
||||
|
||||
-- Linkify things that look like URLs with numeric addresses as hosts.
|
||||
-- E.g. http://127.0.0.1:8000 for a local development server,
|
||||
-- or http://192.168.1.1 for the web interface of many routers.
|
||||
{
|
||||
regex = [[\b\w+://(?:[\d]{1,3}\.){3}[\d]{1,3}\S*\b]],
|
||||
format = '$0',
|
||||
},
|
||||
|
||||
-- Make task numbers clickable
|
||||
-- The first matched regex group is captured in $1.
|
||||
{
|
||||
regex = [[\b[tT](\d+)\b]],
|
||||
format = 'https://example.com/tasks/?t=$1',
|
||||
},
|
||||
|
||||
-- Make username/project paths clickable. This implies paths like the following are for GitHub.
|
||||
-- ( "nvim-treesitter/nvim-treesitter" | wbthomason/packer.nvim | wez/wezterm | "wez/wezterm.git" )
|
||||
-- As long as a full URL hyperlink regex exists above this it should not match a full URL to
|
||||
-- GitHub or GitLab / BitBucket (i.e. https://gitlab.com/user/project.git is still a whole clickable URL)
|
||||
{
|
||||
regex = [[["]?([\w\d]{1}[-\w\d]+)(/){1}([-\w\d\.]+)["]?]],
|
||||
format = 'https://www.github.com/$1/$3',
|
||||
},
|
||||
},
|
||||
hyperlink_rules = hyperlink_rules,
|
||||
}
|
||||
```
|
||||
|
||||
Note that it is generally convenient to use literal strings (`[[...]]`)
|
||||
when declaring your hyperlink rules, so you won't have to escape
|
||||
backslashes. In the example above, all cases except the first use
|
||||
literal strings for their regular expressions.
|
||||
See also [hyperlink_rules](config/lua/config/hyperlink_rules.md) and
|
||||
[default_hyperlink_rules](config/lua/wezterm/default_hyperlink_rules.md).
|
||||
|
||||
|
||||
### Explicit Hyperlinks
|
||||
|
@ -160,6 +160,10 @@ pub struct Rule {
|
||||
/// with ambiguous replacement of `$11` vs `$1` in the case of
|
||||
/// more complex regexes.
|
||||
pub format: String,
|
||||
|
||||
/// Which capture to highlight
|
||||
#[dynamic(default)]
|
||||
pub highlight: usize,
|
||||
}
|
||||
|
||||
struct RegexWrap(Regex);
|
||||
@ -221,6 +225,7 @@ pub struct RuleMatch {
|
||||
}
|
||||
|
||||
/// An internal intermediate match result
|
||||
#[derive(Debug)]
|
||||
struct Match<'t> {
|
||||
rule: &'t Rule,
|
||||
captures: Captures<'t>,
|
||||
@ -229,16 +234,20 @@ struct Match<'t> {
|
||||
impl<'t> Match<'t> {
|
||||
/// Returns the length of the matched text in bytes (not cells!)
|
||||
fn len(&self) -> usize {
|
||||
let c0 = self.captures.get(0).unwrap();
|
||||
let c0 = self.highlight().unwrap();
|
||||
c0.end() - c0.start()
|
||||
}
|
||||
|
||||
/// Returns the span of the matched text, measured in bytes (not cells!)
|
||||
fn range(&self) -> Range<usize> {
|
||||
let c0 = self.captures.get(0).unwrap();
|
||||
let c0 = self.highlight().unwrap();
|
||||
c0.start()..c0.end()
|
||||
}
|
||||
|
||||
fn highlight(&self) -> Option<regex::Match> {
|
||||
self.captures.get(self.rule.highlight)
|
||||
}
|
||||
|
||||
/// Expand replacements in the format string to yield the URL
|
||||
/// The replacement is as described on Rule::format.
|
||||
fn expand(&self) -> String {
|
||||
@ -260,9 +269,14 @@ impl<'t> Match<'t> {
|
||||
impl Rule {
|
||||
/// Construct a new rule. It may fail if the regex is invalid.
|
||||
pub fn new(regex: &str, format: &str) -> Result<Self> {
|
||||
Self::with_highlight(regex, format, 0)
|
||||
}
|
||||
|
||||
pub fn with_highlight(regex: &str, format: &str, highlight: usize) -> Result<Self> {
|
||||
Ok(Self {
|
||||
regex: Regex::new(regex)?,
|
||||
format: format.to_owned(),
|
||||
highlight,
|
||||
})
|
||||
}
|
||||
|
||||
@ -272,7 +286,10 @@ impl Rule {
|
||||
let mut matches = Vec::new();
|
||||
for rule in rules.iter() {
|
||||
for captures in rule.regex.captures_iter(line) {
|
||||
matches.push(Match { rule, captures });
|
||||
let m = Match { rule, captures };
|
||||
if m.highlight().is_some() {
|
||||
matches.push(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sort the matches by descending match length.
|
||||
|
Loading…
Reference in New Issue
Block a user