Skip to content

Commit d292bfa

Browse files
committed
Add OSC 8 link support to filepath in headers
1 parent b2454ca commit d292bfa

4 files changed

Lines changed: 49 additions & 1 deletion

File tree

src/display/inline.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,18 @@ pub(crate) fn print(
6565
let opposite_to_rhs = opposite_positions(rhs_mps);
6666

6767
for (i, hunk) in hunks.iter().enumerate() {
68+
let first_line = hunk
69+
.novel_lhs
70+
.iter()
71+
.min()
72+
.or_else(|| hunk.novel_rhs.iter().min())
73+
.copied();
74+
6875
println!(
6976
"{}",
7077
style::header(
7178
display_path,
79+
first_line,
7280
extra_info.as_ref(),
7381
i + 1,
7482
hunks.len(),

src/display/side_by_side.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ fn display_single_column(
9090
let mut header_line = String::new();
9191
header_line.push_str(&style::header(
9292
display_path,
93+
Some(0.into()),
9394
old_path,
9495
1,
9596
1,
@@ -598,10 +599,18 @@ pub(crate) fn print(
598599
);
599600

600601
for (i, hunk) in hunks.iter().enumerate() {
602+
let first_line = hunk
603+
.novel_lhs
604+
.iter()
605+
.min()
606+
.or_else(|| hunk.novel_rhs.iter().min())
607+
.copied();
608+
601609
println!(
602610
"{}",
603611
style::header(
604612
display_path,
613+
first_line,
605614
old_path,
606615
i + 1,
607616
hunks.len(),

src/display/style.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Apply colours and styling to strings.
22
33
use std::cmp::{max, min};
4+
use std::path::Path;
45

6+
use crossterm::tty::IsTty;
57
use line_numbers::{LineNumber, SingleLineSpan};
68
use owo_colors::{OwoColorize, Style};
79
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
@@ -13,6 +15,12 @@ use crate::options::DisplayOptions;
1315
use crate::parse::syntax::{AtomKind, MatchKind, MatchedPos, StringKind, TokenKind};
1416
use crate::summary::FileFormat;
1517

18+
// OSC 8 hyperlink escape sequences
19+
// See: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
20+
const OSC_8_START: &str = "\x1b]8;;";
21+
const OSC_8_ST: &str = "\x1b\\";
22+
const OSC_8_END: &str = "\x1b]8;;\x1b\\";
23+
1624
#[derive(Clone, Copy, Debug)]
1725
pub(crate) enum BackgroundColor {
1826
Dark,
@@ -536,8 +544,27 @@ pub(crate) fn apply_line_number_color(
536544
}
537545
}
538546

547+
fn make_path_hyperlink(display_path: &str, line_number: Option<LineNumber>) -> String {
548+
if !std::io::stdout().is_tty() {
549+
return display_path.to_owned();
550+
}
551+
552+
let path = Path::new(display_path);
553+
554+
let Ok(canonical_path) = path.canonicalize() else {
555+
return display_path.to_owned();
556+
};
557+
558+
let mut url = format!("file://{}", canonical_path.display());
559+
if let Some(line_num) = line_number {
560+
url.push_str(&format!(":{}", line_num.0 + 1));
561+
}
562+
format!("{OSC_8_START}{url}{OSC_8_ST}{display_path}{OSC_8_END}")
563+
}
564+
539565
pub(crate) fn header(
540566
display_path: &str,
567+
first_line_number: Option<LineNumber>,
541568
extra_info: Option<&String>,
542569
hunk_num: usize,
543570
hunk_total: usize,
@@ -551,7 +578,7 @@ pub(crate) fn header(
551578
};
552579

553580
let display_path_pretty = apply_header_color(
554-
display_path,
581+
&make_path_hyperlink(display_path, first_line_number),
555582
display_options.use_color,
556583
display_options.background_color,
557584
hunk_num,

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ fn print_diff_result(display_options: &DisplayOptions, summary: &DiffResult) {
884884
"{}",
885885
display::style::header(
886886
&summary.display_path,
887+
None,
887888
summary.extra_info.as_ref(),
888889
1,
889890
1,
@@ -911,6 +912,7 @@ fn print_diff_result(display_options: &DisplayOptions, summary: &DiffResult) {
911912
"{}",
912913
display::style::header(
913914
&summary.display_path,
915+
None,
914916
summary.extra_info.as_ref(),
915917
1,
916918
1,
@@ -966,6 +968,7 @@ fn print_diff_result(display_options: &DisplayOptions, summary: &DiffResult) {
966968
"{}",
967969
display::style::header(
968970
&summary.display_path,
971+
None,
969972
summary.extra_info.as_ref(),
970973
1,
971974
1,
@@ -1014,6 +1017,7 @@ fn print_diff_result(display_options: &DisplayOptions, summary: &DiffResult) {
10141017
"{}",
10151018
display::style::header(
10161019
&summary.display_path,
1020+
None,
10171021
summary.extra_info.as_ref(),
10181022
1,
10191023
1,

0 commit comments

Comments
 (0)