Skip to content

Commit bc80f61

Browse files
committed
feat: add support for printing explicit hyperlinks
1 parent fe7e656 commit bc80f61

5 files changed

Lines changed: 77 additions & 1 deletion

File tree

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,23 @@ from xontrib_term_integrations.utils import set_user_var
3838
set_user_var('my_term_user_var','value_of_my_term_user_var')
3939
```
4040

41-
You can disable registering the alias with a `$XONTRIB_TERM_INTEGRATIONS_SKIP_ALIAS = True`
41+
Print Explicit Hyperlinks[^2] via the helper `print_link` function:
42+
```xsh
43+
# via a xonsh alias
44+
print_link 'https://example.com' 'Example Domain'
45+
46+
# or an explicit Python import
47+
from xontrib_term_integrations.utils import print_link
48+
print_link('https://example.com', 'Example Domain')
49+
```
50+
51+
You can disable registering the aliases with a `$XONTRIB_TERM_INTEGRATIONS_SKIP_ALIAS = True`
52+
53+
(WezTerm) You can disable other features with the following environment variables:
54+
- `$WEZTERM_SHELL_SKIP_ALL = False` to disable all integrations
55+
- `$WEZTERM_SHELL_SKIP_SEMANTIC_ZONES = False` to disable zones
56+
- `$WEZTERM_SHELL_SKIP_CWD = False` to disable OSC 7 cwd setting
57+
- `$WEZTERM_SHELL_SKIP_USER_VARS = False` to disable user vars that capture information about running programs
4258

4359
## Contributing
4460

@@ -70,3 +86,4 @@ pre-commit install-hooks
7086
- WezTerm is _not_ recognized in root shells due to [this issue](https://github.com/wez/wezterm/issues/3114)
7187

7288
[^1]: Variables associated with a given pane rather than a process. [WezTerm](https://wezfurlong.org/wezterm/shell-integration.html#user-vars), [iTerm2](https://iterm2.com/documentation-escape-codes.html)
89+
[^2]: Display a cleaner text instead of a URL that can be clicked to resolve to that URL. [WezTerm](https://wezfurlong.org/wezterm/hyperlinks.html#explicit-hyperlinks), [iTerm2](https://iterm2.com/documentation-escape-codes.html)

xontrib_term_integrations/iterm2.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
from . import utils
44
from .semantic_prompt import ShellIntegrationPrompt
55

6+
env = XSH.env or {}
7+
8+
_skip_alias = env.get("XONTRIB_TERM_INTEGRATIONS_SKIP_ALIAS", False)
9+
610

711
@XSH.builtins.events.on_precommand
812
def iterm_precmd(**_):
@@ -29,3 +33,5 @@ def onpostinit(**__):
2933

3034

3135
XSH.env["PROMPT"] = ShellIntegrationPrompt(XSH.env)
36+
if not _skip_alias:
37+
XSH.aliases["print_link"] = utils.write_osc_hyperlink_alias

xontrib_term_integrations/kitty.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
from . import kitty_completions, utils
55
from .semantic_prompt import ShellIntegrationPrompt
66

7+
env = XSH.env or {}
8+
9+
_skip_alias = env.get("XONTRIB_TERM_INTEGRATIONS_SKIP_ALIAS", False)
10+
711

812
@XSH.builtins.events.on_precommand
913
def iterm_precmd(**_):
@@ -38,4 +42,7 @@ def ps2_multiline_prompt():
3842
XSH.env["PROMPT"] = ShellIntegrationPrompt(XSH.env)
3943
XSH.env["MULTILINE_PROMPT"] = ps2_multiline_prompt
4044

45+
if not _skip_alias:
46+
XSH.aliases["print_link"] = utils.write_osc_hyperlink_alias
47+
4148
add_one_completer("kitty", kitty_completions.xonsh_complete, loc="<import")

xontrib_term_integrations/utils.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ def term_osc7_cmd(code):
4747
return f"{Codes.OSC}7;{code}{Codes.ST}"
4848

4949

50+
def term_osc8_cmd(code):
51+
return f"{Codes.OSC}8;{code}{Codes.ST}"
52+
53+
5054
def term_dcs_cmd(code):
5155
return f"{Codes.DCS}{code}{Codes.ST}"
5256

@@ -86,6 +90,10 @@ def write_osc7_cmd(code):
8690
return write_to_out(term_osc7_cmd(code))
8791

8892

93+
def write_osc8_cmd(code):
94+
return write_to_out(term_osc8_cmd(code))
95+
96+
8997
def write_dcs_cmd(code):
9098
return write_to_out(term_dcs_cmd(code))
9199

@@ -131,6 +139,40 @@ def write_osc_user_host(env):
131139
write_osc_cmd(f"RemoteHost={user}@{host}")
132140

133141

142+
def write_osc_hyperlink(uri, text, params=""):
143+
# wezfurlong.org/wezterm/hyperlinks.html#explicit-hyperlinks
144+
# open : OSC 8 ; params ; [URI] ST
145+
# text : no escape sequences
146+
# close: OSC 8 ; ; ST
147+
write_to_out(term_osc8_cmd(f"{params};{uri}") + f"{text}" + term_osc8_cmd(";"))
148+
149+
150+
def write_osc_hyperlink_fn(
151+
uri: str, text: str, params: Annotated[Optional[str], Arg(nargs="?")] = "" # noqa
152+
):
153+
"""Prints an Explicit Hyperlink `Text` resolving to the given `URL`
154+
(see ``wezfurlong.org/wezterm/hyperlinks.html#explicit-hyperlinks`` for details)
155+
156+
Parameters
157+
----------
158+
uri
159+
Target of the hyperlink, including the scheme, e.g.
160+
`https://` for web addresses
161+
`file://` for local files (followed by a mandatory `hostname`)
162+
`mailto:` for email, etc.
163+
text
164+
Hyperlink text that resolves to the URI on click
165+
params
166+
Additional colon:separated parameters, e.g., `id:1`
167+
"""
168+
169+
write_osc_hyperlink(uri, text, params)
170+
171+
172+
def print_link(uri, text, params=""):
173+
write_osc_hyperlink(uri, text, params)
174+
175+
134176
def set_user_var(
135177
var, val
136178
): # emit an OSC 1337 sequence to set a user var associated with the current
@@ -167,6 +209,9 @@ def set_user_var_fn(
167209
set_user_var(var, val)
168210

169211

212+
write_osc_hyperlink_alias = ArgParserAlias(
213+
func=write_osc_hyperlink_fn, has_args=True, prog="print_link"
214+
)
170215
set_user_var_alias = ArgParserAlias(
171216
func=set_user_var_fn, has_args=True, prog="set_user_var"
172217
)

xontrib_term_integrations/wezterm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ def wezterm_prompt_pre():
127127

128128
if not _skip_alias:
129129
XSH.aliases["set_user_var"] = utils.set_user_var_alias
130+
XSH.aliases["print_link"] = utils.write_osc_hyperlink_alias
130131

131132
prompt_name = ["PROMPT", "RIGHT_PROMPT", "BOTTOM_TOOLBAR", "MULTILINE_PROMPT"]
132133
extend = False if _skip_zone else True

0 commit comments

Comments
 (0)