feat: pr tab switching btwn body/diff
This commit is contained in:
224
src/util/diff.rs
224
src/util/diff.rs
@@ -44,117 +44,127 @@ pub(crate) fn diff_content(
|
||||
|
||||
for op in diff.ops() {
|
||||
match op {
|
||||
| &similar::DiffOp::Equal {
|
||||
old_index,
|
||||
new_index,
|
||||
len,
|
||||
} => {
|
||||
for i in 0..len {
|
||||
let old_line = old_index + i;
|
||||
let new_line = new_index + i;
|
||||
let old_line_range = &old_line_ranges[old_line];
|
||||
let content = Arc::from(old_content.slice(old_line_range.clone()).as_str()?);
|
||||
diff_lines.push(DiffLine {
|
||||
op: Op::Equal,
|
||||
old_line: Some(old_line),
|
||||
old_content: Some(Arc::clone(&content)),
|
||||
old_byte_range: old_line_range.clone(),
|
||||
new_line: Some(new_line),
|
||||
new_content: Some(content),
|
||||
new_byte_range: new_line_ranges[new_line].clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
| &similar::DiffOp::Insert {
|
||||
new_index, new_len, ..
|
||||
} => {
|
||||
for i in 0..new_len {
|
||||
let new_line_range = &new_line_ranges[new_index + i];
|
||||
let content = Arc::from(new_content.slice(new_line_range.clone()).as_str()?);
|
||||
diff_lines.push(DiffLine {
|
||||
op: Op::Insert,
|
||||
old_line: None,
|
||||
old_content: None,
|
||||
old_byte_range: 0..0,
|
||||
new_line: Some(new_index + i),
|
||||
new_content: Some(content),
|
||||
new_byte_range: new_line_range.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
| &similar::DiffOp::Replace {
|
||||
old_index,
|
||||
old_len,
|
||||
new_index,
|
||||
new_len,
|
||||
} => {
|
||||
for i in 0..new_len.max(old_len) {
|
||||
let old_line = old_index + i;
|
||||
let new_line = new_index + i;
|
||||
|
||||
let diff_line = match (old_line_ranges.get(old_line), new_line_ranges.get(new_line))
|
||||
{
|
||||
| (Some(old_range), Some(new_range)) => DiffLine {
|
||||
op: Op::Replace,
|
||||
old_line: Some(old_line),
|
||||
old_content: Some(Arc::from(old_content.slice(old_range.clone()).as_str()?)),
|
||||
old_byte_range: old_range.clone(),
|
||||
new_line: Some(new_line),
|
||||
new_content: Some(Arc::from(new_content.slice(new_range.clone()).as_str()?)),
|
||||
new_byte_range: new_range.clone(),
|
||||
},
|
||||
|
||||
| (None, Some(new_range)) => DiffLine {
|
||||
op: Op::Replace,
|
||||
old_line: None,
|
||||
old_content: None,
|
||||
old_byte_range: 0..0,
|
||||
new_line: Some(new_index + i),
|
||||
new_content: Some(Arc::from(new_content.slice(new_range.clone()).as_str()?)),
|
||||
new_byte_range: new_range.clone(),
|
||||
},
|
||||
|
||||
| (Some(old_range), None) => DiffLine {
|
||||
op: Op::Replace,
|
||||
old_line: Some(old_index + i),
|
||||
old_content: Some(Arc::from(old_content.slice(old_range.clone()).as_str()?)),
|
||||
old_byte_range: old_range.clone(),
|
||||
new_line: None,
|
||||
new_content: None,
|
||||
new_byte_range: 0..0,
|
||||
},
|
||||
|
||||
| (None, None) => {
|
||||
// unlickly to happen, but if it does, idk
|
||||
panic!(
|
||||
"the unlikely happened: both old & new index of DiffOps::Replace don't point to any line in the parsed line ranges."
|
||||
)
|
||||
| &similar::DiffOp::Equal {
|
||||
old_index,
|
||||
new_index,
|
||||
len,
|
||||
} => {
|
||||
for i in 0..len {
|
||||
let old_line = old_index + i;
|
||||
let new_line = new_index + i;
|
||||
let old_line_range = &old_line_ranges[old_line];
|
||||
let content = Arc::from(old_content.slice(old_line_range.clone()).as_str()?);
|
||||
diff_lines.push(DiffLine {
|
||||
op: Op::Equal,
|
||||
old_line: Some(old_line),
|
||||
old_content: Some(Arc::clone(&content)),
|
||||
old_byte_range: old_line_range.clone(),
|
||||
new_line: Some(new_line),
|
||||
new_content: Some(content),
|
||||
new_byte_range: new_line_ranges[new_line].clone(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
diff_lines.push(diff_line);
|
||||
}
|
||||
}
|
||||
|
||||
| &similar::DiffOp::Delete {
|
||||
old_index, old_len, ..
|
||||
} => {
|
||||
for i in 0..old_len {
|
||||
let old_line_range = &old_line_ranges[old_index];
|
||||
let content = Arc::from(old_content.slice(old_line_range.clone()).as_str()?);
|
||||
diff_lines.push(DiffLine {
|
||||
op: Op::Delete,
|
||||
old_line: Some(old_index + i),
|
||||
old_content: Some(content),
|
||||
old_byte_range: old_line_range.clone(),
|
||||
new_line: None,
|
||||
new_content: None,
|
||||
new_byte_range: 0..0,
|
||||
})
|
||||
| &similar::DiffOp::Insert {
|
||||
new_index, new_len, ..
|
||||
} => {
|
||||
for i in 0..new_len {
|
||||
let new_line_range = &new_line_ranges[new_index + i];
|
||||
let content = Arc::from(new_content.slice(new_line_range.clone()).as_str()?);
|
||||
diff_lines.push(DiffLine {
|
||||
op: Op::Insert,
|
||||
old_line: None,
|
||||
old_content: None,
|
||||
old_byte_range: 0..0,
|
||||
new_line: Some(new_index + i),
|
||||
new_content: Some(content),
|
||||
new_byte_range: new_line_range.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
| &similar::DiffOp::Replace {
|
||||
old_index,
|
||||
old_len,
|
||||
new_index,
|
||||
new_len,
|
||||
} => {
|
||||
for i in 0..new_len.max(old_len) {
|
||||
let old_line = old_index + i;
|
||||
let new_line = new_index + i;
|
||||
|
||||
let diff_line = match (
|
||||
old_line_ranges.get(old_line),
|
||||
new_line_ranges.get(new_line),
|
||||
) {
|
||||
| (Some(old_range), Some(new_range)) => DiffLine {
|
||||
op: Op::Replace,
|
||||
old_line: Some(old_line),
|
||||
old_content: Some(Arc::from(
|
||||
old_content.slice(old_range.clone()).as_str()?,
|
||||
)),
|
||||
old_byte_range: old_range.clone(),
|
||||
new_line: Some(new_line),
|
||||
new_content: Some(Arc::from(
|
||||
new_content.slice(new_range.clone()).as_str()?,
|
||||
)),
|
||||
new_byte_range: new_range.clone(),
|
||||
},
|
||||
|
||||
| (None, Some(new_range)) => DiffLine {
|
||||
op: Op::Replace,
|
||||
old_line: None,
|
||||
old_content: None,
|
||||
old_byte_range: 0..0,
|
||||
new_line: Some(new_index + i),
|
||||
new_content: Some(Arc::from(
|
||||
new_content.slice(new_range.clone()).as_str()?,
|
||||
)),
|
||||
new_byte_range: new_range.clone(),
|
||||
},
|
||||
|
||||
| (Some(old_range), None) => DiffLine {
|
||||
op: Op::Replace,
|
||||
old_line: Some(old_index + i),
|
||||
old_content: Some(Arc::from(
|
||||
old_content.slice(old_range.clone()).as_str()?,
|
||||
)),
|
||||
old_byte_range: old_range.clone(),
|
||||
new_line: None,
|
||||
new_content: None,
|
||||
new_byte_range: 0..0,
|
||||
},
|
||||
|
||||
| (None, None) => {
|
||||
// unlickly to happen, but if it does, idk
|
||||
panic!(
|
||||
"the unlikely happened: both old & new index of DiffOps::Replace don't point to any line in the parsed line ranges."
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
diff_lines.push(diff_line);
|
||||
}
|
||||
}
|
||||
|
||||
| &similar::DiffOp::Delete {
|
||||
old_index, old_len, ..
|
||||
} => {
|
||||
for i in 0..old_len {
|
||||
let old_line_range = &old_line_ranges[old_index];
|
||||
let content = Arc::from(old_content.slice(old_line_range.clone()).as_str()?);
|
||||
diff_lines.push(DiffLine {
|
||||
op: Op::Delete,
|
||||
old_line: Some(old_index + i),
|
||||
old_content: Some(content),
|
||||
old_byte_range: old_line_range.clone(),
|
||||
new_line: None,
|
||||
new_content: None,
|
||||
new_byte_range: 0..0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,17 +27,17 @@ pub(crate) fn classify_content(content: &[u8]) -> ContentType {
|
||||
ContentType::Text
|
||||
} else {
|
||||
match memchr(0, &content[..content.len().min(8192)]) {
|
||||
| None => ContentType::Text,
|
||||
| Some(_) => ContentType::Binary,
|
||||
| None => ContentType::Text,
|
||||
| Some(_) => ContentType::Binary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn file_type_from_path(path: &str) -> FileType {
|
||||
match Path::new(path).extension().map(|it| it.to_str()).flatten() {
|
||||
| Some("rs") => FileType::Rust,
|
||||
| Some("js") | Some("jsx") => FileType::JavaScript,
|
||||
| _ => FileType::Unknown,
|
||||
| Some("rs") => FileType::Rust,
|
||||
| Some("js") | Some("jsx") => FileType::JavaScript,
|
||||
| _ => FileType::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,18 +55,18 @@ pub(crate) fn line_ranges(content: &[u8]) -> Vec<std::ops::Range<usize>> {
|
||||
let c = content[i];
|
||||
|
||||
match (c, content.get(i + 1)) {
|
||||
| (b'\r', Some(b'\n')) => {
|
||||
// if \r found, check if its \r\n or if its a lone \r
|
||||
// if \r\n, then treat as one line break
|
||||
ranges.push(line_start..i + 1);
|
||||
// because we already counted the \n byte, the next iter into it needs to be skipped
|
||||
skip_next = true;
|
||||
line_start = i + 2;
|
||||
}
|
||||
| _ => {
|
||||
ranges.push(line_start..i);
|
||||
line_start = i + 1;
|
||||
}
|
||||
| (b'\r', Some(b'\n')) => {
|
||||
// if \r found, check if its \r\n or if its a lone \r
|
||||
// if \r\n, then treat as one line break
|
||||
ranges.push(line_start..i + 1);
|
||||
// because we already counted the \n byte, the next iter into it needs to be skipped
|
||||
skip_next = true;
|
||||
line_start = i + 2;
|
||||
}
|
||||
| _ => {
|
||||
ranges.push(line_start..i);
|
||||
line_start = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,16 +6,16 @@ fn ts_highlight_configuration_for_file_type(
|
||||
file_type: util::file::FileType,
|
||||
) -> Option<tree_sitter_highlight::HighlightConfiguration> {
|
||||
match file_type {
|
||||
| util::file::FileType::Rust => tree_sitter_highlight::HighlightConfiguration::new(
|
||||
tree_sitter_rust::LANGUAGE.into(),
|
||||
"rust",
|
||||
tree_sitter_rust::HIGHLIGHTS_QUERY,
|
||||
tree_sitter_rust::INJECTIONS_QUERY,
|
||||
"",
|
||||
)
|
||||
.ok(),
|
||||
| util::file::FileType::Rust => tree_sitter_highlight::HighlightConfiguration::new(
|
||||
tree_sitter_rust::LANGUAGE.into(),
|
||||
"rust",
|
||||
tree_sitter_rust::HIGHLIGHTS_QUERY,
|
||||
tree_sitter_rust::INJECTIONS_QUERY,
|
||||
"",
|
||||
)
|
||||
.ok(),
|
||||
|
||||
| _ => None,
|
||||
| _ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,37 +44,37 @@ pub(crate) fn highlight_content(
|
||||
|
||||
for highlight_event in events {
|
||||
match highlight_event.ok()? {
|
||||
| tree_sitter_highlight::HighlightEvent::HighlightStart(h) => {
|
||||
highlight = theme_syntax.as_slice()[h.0];
|
||||
}
|
||||
| tree_sitter_highlight::HighlightEvent::Source { start, end } => {
|
||||
while current_line < line_ranges.len() && start >= line_ranges[current_line].end {
|
||||
highlights.push(Vec::new());
|
||||
current_line += 1;
|
||||
| tree_sitter_highlight::HighlightEvent::HighlightStart(h) => {
|
||||
highlight = theme_syntax.as_slice()[h.0];
|
||||
}
|
||||
let mut line = current_line;
|
||||
while line < line_ranges.len() && end > line_ranges[line].start {
|
||||
if highlights.get(line).is_none() {
|
||||
| tree_sitter_highlight::HighlightEvent::Source { start, end } => {
|
||||
while current_line < line_ranges.len() && start >= line_ranges[current_line].end {
|
||||
highlights.push(Vec::new());
|
||||
current_line += 1;
|
||||
}
|
||||
let mut line = current_line;
|
||||
while line < line_ranges.len() && end > line_ranges[line].start {
|
||||
if highlights.get(line).is_none() {
|
||||
highlights.push(Vec::new());
|
||||
}
|
||||
let line_range = &line_ranges[line];
|
||||
let highlight_start = start.max(line_range.start);
|
||||
let highlight_end = end.min(line_range.end);
|
||||
highlights[line].push((
|
||||
(highlight_start - line_range.start)..(highlight_end - line_range.start),
|
||||
gpui::HighlightStyle {
|
||||
color: Some(highlight.color.into()),
|
||||
font_weight: highlight.font_weight,
|
||||
font_style: Some(highlight.font_style),
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
line += 1;
|
||||
}
|
||||
let line_range = &line_ranges[line];
|
||||
let highlight_start = start.max(line_range.start);
|
||||
let highlight_end = end.min(line_range.end);
|
||||
highlights[line].push((
|
||||
(highlight_start - line_range.start)..(highlight_end - line_range.start),
|
||||
gpui::HighlightStyle {
|
||||
color: Some(highlight.color.into()),
|
||||
font_weight: highlight.font_weight,
|
||||
font_style: Some(highlight.font_style),
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
line += 1;
|
||||
}
|
||||
}
|
||||
| tree_sitter_highlight::HighlightEvent::HighlightEnd => {
|
||||
highlight = default_highlight;
|
||||
}
|
||||
| tree_sitter_highlight::HighlightEvent::HighlightEnd => {
|
||||
highlight = default_highlight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user