Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
resolver = "2"
resolver = "3"
members = [
"helix-core",
"helix-view",
Expand Down Expand Up @@ -65,7 +65,7 @@ quickcheck = { version = "1", default-features = false }

[workspace.package]
version = "25.7.1"
edition = "2021"
edition = "2024"
authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
categories = ["editor"]
repository = "https://github.com/helix-editor/helix"
Expand Down
9 changes: 5 additions & 4 deletions helix-core/src/auto_pairs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,11 @@ pub fn hook_delete(doc: &Rope, range: &Range, pairs: &AutoPairs) -> Option<(Dele
let second_next = doc.get_char(graphemes::next_grapheme_boundary(text, cursor))?;
log::debug!("second_prev: {}, second_next: {}", second_prev, second_next);

if let Some(pair) = pairs.get(second_prev) {
if pair.open == second_prev && pair.close == second_next {
return handle_delete(doc, range);
}
if let Some(pair) = pairs.get(second_prev)
&& pair.open == second_prev
&& pair.close == second_next
{
return handle_delete(doc, range);
}
}

Expand Down
5 changes: 2 additions & 3 deletions helix-core/src/doc_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,9 @@ impl<'t> DocumentFormatter<'t> {
loop {
if let Some(&mut (ref mut annotation, highlight)) =
self.inline_annotation_graphemes.as_mut()
&& let Some(grapheme) = annotation.next()
{
if let Some(grapheme) = annotation.next() {
return Some((grapheme, highlight));
}
return Some((grapheme, highlight));
}

if let Some((annotation, highlight)) =
Expand Down
149 changes: 74 additions & 75 deletions helix-core/src/indent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,18 +869,18 @@ fn init_indent_query<'a, 'b>(
.is_some();

// Check for extend captures, potentially changing the node that the indent calculation starts with
if let Some(deepest_preceding) = deepest_preceding {
if !descended {
extend_nodes(
&mut node,
deepest_preceding,
&extend_captures,
text,
line,
tab_width,
indent_width,
);
}
if let Some(deepest_preceding) = deepest_preceding
&& !descended
{
extend_nodes(
&mut node,
deepest_preceding,
&extend_captures,
text,
line,
tab_width,
indent_width,
);
}
Some((node, query_result.indent_captures, opaque_ranges))
}
Expand Down Expand Up @@ -1160,10 +1160,11 @@ fn containment_accounting<'a>(
}
}
// Innermost containing alignment wins (first seen on the upward walk).
if let Some(a) = node_align {
if contains && align.is_none() {
align = Some(a);
}
if let Some(a) = node_align
&& contains
&& align.is_none()
{
align = Some(a);
}
}
match node.parent() {
Expand Down Expand Up @@ -1294,69 +1295,67 @@ pub fn indent_for_newline(
indent_heuristic,
syntax.and_then(|syntax| loader.indent_query(syntax.root_language())),
syntax,
) && let Some(indent) = treesitter_indent_for_pos(
query,
syntax,
loader,
tab_width,
indent_width,
text,
line_before,
line_before_end_pos,
true,
) {
if let Some(indent) = treesitter_indent_for_pos(
query,
syntax,
loader,
tab_width,
indent_width,
text,
line_before,
line_before_end_pos,
true,
) {
if *indent_heuristic == IndentationHeuristic::Hybrid {
// We want to compute the indentation not only based on the
// syntax tree but also on the actual indentation of a previous
// line. This makes indentation computation more resilient to
// incomplete queries, incomplete source code & differing indentation
// styles for the same language.
// However, using the indent of a previous line as a baseline may not
// make sense, e.g. if it has a different alignment than the new line.
// In order to prevent edge cases with long running times, we only try
// a constant number of (non-empty) lines.
const MAX_ATTEMPTS: usize = 4;
let mut num_attempts = 0;
for line_idx in (0..=line_before).rev() {
let line = text.line(line_idx);
let first_non_whitespace_char = match line.first_non_whitespace_char() {
Some(i) => i,
None => {
continue;
}
};
if let Some(indent) = (|| {
let computed_indent = treesitter_indent_for_pos(
query,
syntax,
loader,
tab_width,
indent_width,
text,
line_idx,
text.line_to_char(line_idx) + first_non_whitespace_char,
false,
)?;
let leading_whitespace = line.slice(0..first_non_whitespace_char);
indent.relative_indent(
&computed_indent,
leading_whitespace,
indent_style,
tab_width,
)
})() {
return indent;
}
num_attempts += 1;
if num_attempts == MAX_ATTEMPTS {
break;
if *indent_heuristic == IndentationHeuristic::Hybrid {
// We want to compute the indentation not only based on the
// syntax tree but also on the actual indentation of a previous
// line. This makes indentation computation more resilient to
// incomplete queries, incomplete source code & differing indentation
// styles for the same language.
// However, using the indent of a previous line as a baseline may not
// make sense, e.g. if it has a different alignment than the new line.
// In order to prevent edge cases with long running times, we only try
// a constant number of (non-empty) lines.
const MAX_ATTEMPTS: usize = 4;
let mut num_attempts = 0;
for line_idx in (0..=line_before).rev() {
let line = text.line(line_idx);
let first_non_whitespace_char = match line.first_non_whitespace_char() {
Some(i) => i,
None => {
continue;
}
};
if let Some(indent) = (|| {
let computed_indent = treesitter_indent_for_pos(
query,
syntax,
loader,
tab_width,
indent_width,
text,
line_idx,
text.line_to_char(line_idx) + first_non_whitespace_char,
false,
)?;
let leading_whitespace = line.slice(0..first_non_whitespace_char);
indent.relative_indent(
&computed_indent,
leading_whitespace,
indent_style,
tab_width,
)
})() {
return indent;
}
num_attempts += 1;
if num_attempts == MAX_ATTEMPTS {
break;
}
}
return indent.to_string(indent_style, tab_width);
};
}
}
return indent.to_string(indent_style, tab_width);
};
// Fallback in case we either don't have indent queries or they failed for some reason
let indent_level = indent_level_for_line(text.line(current_line), tab_width, indent_width);
indent_style.as_str().repeat(indent_level)
Expand Down
39 changes: 19 additions & 20 deletions helix-core/src/match_brackets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,35 +92,34 @@ fn find_pair(

if let (Some((start_pos, open)), Some((end_pos, close))) =
(as_char(doc, &open), as_char(doc, &close))
&& PAIRS.contains(&(open, close))
&& start_pos <= pos_
&& pos_ <= end_pos
{
if PAIRS.contains(&(open, close)) && start_pos <= pos_ && pos_ <= end_pos {
if end_pos == pos_ {
return Some(start_pos);
}

// We return the end char if the cursor is either on the start char
// or at some arbitrary position between start and end char.
if traverse_parents || start_pos == pos_ {
return Some(end_pos);
}
if end_pos == pos_ {
return Some(start_pos);
}

// We return the end char if the cursor is either on the start char
// or at some arbitrary position between start and end char.
if traverse_parents || start_pos == pos_ {
return Some(end_pos);
}
}
}
// this node itselt wasn't a pair but maybe its siblings are

if let Some((start_char, end_char)) = as_close_pair(doc, &node) {
if let Some(pair_start) =
if let Some((start_char, end_char)) = as_close_pair(doc, &node)
&& let Some(pair_start) =
find_pair_end(doc, node.prev_sibling(), start_char, end_char, Backward)
{
return Some(pair_start);
}
{
return Some(pair_start);
}
if let Some((start_char, end_char)) = as_open_pair(doc, &node) {
if let Some(pair_end) =
if let Some((start_char, end_char)) = as_open_pair(doc, &node)
&& let Some(pair_end) =
find_pair_end(doc, node.next_sibling(), start_char, end_char, Forward)
{
return Some(pair_end);
}
{
return Some(pair_end);
}

if traverse_parents {
Expand Down
8 changes: 4 additions & 4 deletions helix-core/src/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,10 @@ pub fn goto_treesitter_object(

let cap_name = |t: TextObject| format!("{}.{}", object_name, t);
let nodes = textobject_query?.capture_nodes_any(
&[
&cap_name(TextObject::Movement),
&cap_name(TextObject::Around),
&cap_name(TextObject::Inside),
[
cap_name(TextObject::Movement),
cap_name(TextObject::Around),
cap_name(TextObject::Inside),
],
&slice_tree,
slice,
Expand Down
8 changes: 4 additions & 4 deletions helix-core/src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,10 @@ pub fn visual_offset_from_anchor(
}
}

if let Some(anchor_line) = anchor_line {
if grapheme.visual_pos.row >= anchor_line + max_rows {
return Err(VisualOffsetError::PosAfterMaxRow);
}
if let Some(anchor_line) = anchor_line
&& grapheme.visual_pos.row >= anchor_line + max_rows
{
return Err(VisualOffsetError::PosAfterMaxRow);
}
}

Expand Down
12 changes: 6 additions & 6 deletions helix-core/src/snippets/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ fn text<'a>(
while let Some((i, c)) = chars.next() {
match c {
'\\' => {
if let Some(&(_, c)) = chars.peek() {
if escape_chars.contains(&c) {
chars.next();
res.push(c);
continue;
}
if let Some(&(_, c)) = chars.peek()
&& escape_chars.contains(&c)
{
chars.next();
res.push(c);
continue;
}
res.push('\\');
}
Expand Down
Loading
Loading