added goto_[first|next|prev|last]_error

pull/8717/head
Constantin Gahr 1 year ago
parent 101a74bf6e
commit bde7d52490

@ -18,6 +18,7 @@ use helix_core::{
char_idx_at_visual_offset,
chars::char_is_word,
comment,
diagnostic::Severity,
doc_formatter::TextFormat,
encoding, find_workspace,
graphemes::{self, next_grapheme_boundary, RevRopeGraphemes},
@ -35,8 +36,8 @@ use helix_core::{
text_annotations::{Overlay, TextAnnotations},
textobject,
unicode::width::UnicodeWidthChar,
visual_offset_from_block, Deletion, LineEnding, Position, Range, Rope, RopeGraphemes,
RopeReader, RopeSlice, Selection, SmallVec, Syntax, Tendril, Transaction,
visual_offset_from_block, Deletion, Diagnostic, LineEnding, Position, Range, Rope,
RopeGraphemes, RopeReader, RopeSlice, Selection, SmallVec, Syntax, Tendril, Transaction,
};
use helix_view::{
document::{FormatterError, Mode, SCRATCH_BUFFER_NAME},
@ -416,6 +417,10 @@ impl MappableCommand {
goto_last_diag, "Goto last diagnostic",
goto_next_diag, "Goto next diagnostic",
goto_prev_diag, "Goto previous diagnostic",
goto_first_error, "Goto first error",
goto_last_error, "Goto last error",
goto_next_error, "Goto next error",
goto_prev_error, "Goto previous error",
goto_next_change, "Goto next change",
goto_prev_change, "Goto previous change",
goto_first_change, "Goto first change",
@ -3656,82 +3661,91 @@ fn exit_select_mode(cx: &mut Context) {
}
}
fn goto_first_diag(cx: &mut Context) {
fn goto_first_or_last_diag_impl(cx: &mut Context, direction: Direction, min_severity: Severity) {
let (view, doc) = current!(cx.editor);
let selection = match doc.diagnostics().first() {
Some(diag) => Selection::single(diag.range.start, diag.range.end),
None => return,
let is_severe = |diag: &&Diagnostic| diag.severity.unwrap_or(Severity::Hint) >= min_severity;
let diagnostic = match direction {
Direction::Forward => doc.diagnostics().iter().find(is_severe),
Direction::Backward => doc.diagnostics().iter().rfind(is_severe),
};
let Some(diagnostic) = diagnostic else {
return;
};
let selection = match direction {
Direction::Forward => Selection::single(diagnostic.range.start, diagnostic.range.end),
Direction::Backward => Selection::single(diagnostic.range.end, diagnostic.range.start),
};
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
}
fn goto_first_diag(cx: &mut Context) {
goto_first_or_last_diag_impl(cx, Direction::Forward, Severity::Hint)
}
fn goto_last_diag(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let selection = match doc.diagnostics().last() {
Some(diag) => Selection::single(diag.range.start, diag.range.end),
None => return,
};
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
goto_first_or_last_diag_impl(cx, Direction::Backward, Severity::Hint)
}
fn goto_first_error(cx: &mut Context) {
goto_first_or_last_diag_impl(cx, Direction::Forward, Severity::Error)
}
fn goto_last_error(cx: &mut Context) {
goto_first_or_last_diag_impl(cx, Direction::Backward, Severity::Error)
}
fn goto_next_diag(cx: &mut Context) {
let motion = move |editor: &mut Editor| {
let (view, doc) = current!(editor);
fn goto_next_or_prev_diag_impl(cx: &mut Context, direction: Direction, min_severity: Severity) {
let (view, doc) = current!(cx.editor);
let is_severe = |diag: &&Diagnostic| diag.severity.unwrap_or(Severity::Hint) >= min_severity;
let cursor_pos = doc
.selection(view.id)
.primary()
.cursor(doc.text().slice(..));
let diag = doc
let diagnostic = match direction {
Direction::Forward => doc
.diagnostics()
.iter()
.find(|diag| is_severe(diag) && (cursor_pos < diag.range.end - 1)),
Direction::Backward => doc
.diagnostics()
.iter()
.find(|diag| diag.range.start > cursor_pos)
.or_else(|| doc.diagnostics().first());
.rfind(|diag| is_severe(diag) && (cursor_pos > diag.range.start)),
};
let selection = match diag {
Some(diag) => Selection::single(diag.range.start, diag.range.end),
None => return,
let Some(diagnostic) = diagnostic else {
return goto_first_or_last_diag_impl(cx, direction, min_severity);
};
let selection = match direction {
Direction::Forward => Selection::single(diagnostic.range.start, diagnostic.range.end),
Direction::Backward => Selection::single(diagnostic.range.end, diagnostic.range.start),
};
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
};
}
cx.editor.apply_motion(motion);
fn goto_next_diag(cx: &mut Context) {
goto_next_or_prev_diag_impl(cx, Direction::Forward, Severity::Hint)
}
fn goto_prev_diag(cx: &mut Context) {
let motion = move |editor: &mut Editor| {
let (view, doc) = current!(editor);
let cursor_pos = doc
.selection(view.id)
.primary()
.cursor(doc.text().slice(..));
goto_next_or_prev_diag_impl(cx, Direction::Backward, Severity::Hint)
}
let diag = doc
.diagnostics()
.iter()
.rev()
.find(|diag| diag.range.start < cursor_pos)
.or_else(|| doc.diagnostics().last());
fn goto_next_error(cx: &mut Context) {
goto_next_or_prev_diag_impl(cx, Direction::Forward, Severity::Error)
}
let selection = match diag {
// NOTE: the selection is reversed because we're jumping to the
// previous diagnostic.
Some(diag) => Selection::single(diag.range.end, diag.range.start),
None => return,
};
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
};
cx.editor.apply_motion(motion)
fn goto_prev_error(cx: &mut Context) {
goto_next_or_prev_diag_impl(cx, Direction::Backward, Severity::Error)
}
fn goto_first_change(cx: &mut Context) {

@ -110,6 +110,8 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"[" => { "Left bracket"
"d" => goto_prev_diag,
"D" => goto_first_diag,
"q" => goto_prev_error,
"Q" => goto_first_error,
"g" => goto_prev_change,
"G" => goto_first_change,
"f" => goto_prev_function,
@ -124,6 +126,8 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"]" => { "Right bracket"
"d" => goto_next_diag,
"D" => goto_last_diag,
"q" => goto_next_error,
"Q" => goto_last_error,
"g" => goto_next_change,
"G" => goto_last_change,
"f" => goto_next_function,

Loading…
Cancel
Save