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

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

Loading…
Cancel
Save