feat: configure spaces on Tab per language

This commit is contained in:
Valdemar Lorenzen
2026-10-14 12:02:19 +02:00
parent 86718221c4
commit 6a43fb9e0c
10 changed files with 200 additions and 8 deletions
+35 -1
View File
@@ -13,6 +13,7 @@ use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::fmt;
use std::fs::{self, OpenOptions};
use std::io::{self, Read, Write};
use std::num::NonZeroU8;
use std::ops::Range;
#[cfg(unix)]
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
@@ -1778,6 +1779,8 @@ pub struct Editor {
highlight_trailing_whitespace: bool,
whitespace_characters: BTreeMap<char, char>,
whitespace_scope: WhitespaceScope,
tab_spaces: Option<NonZeroU8>,
language_tab_spaces: BTreeMap<String, Option<NonZeroU8>>,
battery_charge: Option<u8>,
battery_label: String,
git_blame: bool,
@@ -1883,6 +1886,8 @@ impl Editor {
highlight_trailing_whitespace: false,
whitespace_characters: BTreeMap::new(),
whitespace_scope: WhitespaceScope::All,
tab_spaces: None,
language_tab_spaces: BTreeMap::new(),
battery_charge: None,
battery_label: String::new(),
git_blame: true,
@@ -2653,6 +2658,15 @@ impl Editor {
self.whitespace_scope = scope;
}
pub(crate) fn set_tab_spaces(
&mut self,
spaces: Option<NonZeroU8>,
languages: BTreeMap<String, Option<NonZeroU8>>,
) {
self.tab_spaces = spaces;
self.language_tab_spaces = languages;
}
pub(crate) fn set_diff_context_options(&mut self, context_lines: usize, expand_lines: usize) {
self.diff_context_options = (context_lines, expand_lines);
if let Some(diff) = &mut self.diff {
@@ -8975,6 +8989,25 @@ impl Editor {
}
fn type_native(&mut self, text: &str) {
const SPACES: [u8; u8::MAX as usize] = [b' '; u8::MAX as usize];
let text = if text == "\t" {
let width = if self.language_tab_spaces.is_empty() {
self.tab_spaces
} else {
crate::syntax::language_name(
self.active.path.as_deref(),
self.active.lines.first().map(String::as_str),
)
.and_then(|language| self.language_tab_spaces.get(language))
.copied()
.unwrap_or(self.tab_spaces)
};
width.map_or(text, |width| {
std::str::from_utf8(&SPACES[..usize::from(width.get())]).expect("spaces are UTF-8")
})
} else {
text
};
if self.edit_snippet(text, None) {
return;
}
@@ -23994,6 +24027,7 @@ mod tests {
fn snippet_arguments_navigation_undo_redo_and_dot_use_resolved_text() {
let directory = Directory::new();
let mut editor = editor();
editor.set_tab_spaces(NonZeroU8::new(2), BTreeMap::new());
type_text(&mut editor, "ica");
editor
.show_completion(vec![snippet_item(
@@ -24026,7 +24060,7 @@ mod tests {
assert_eq!(editor.cursor(), Cursor { row: 0, column: 12 });
type_text(&mut editor, ";\n\ttail");
editor.handle(Input::Escape);
let resolved = "call(foo, 5);\n\ttail";
let resolved = "call(foo, 5);\n tail";
let caret = editor.cursor();
assert_eq!(editor.context().text, resolved);
editor.handle(Input::Char('u'));