Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-view/src/document.rs')
-rw-r--r--helix-view/src/document.rs84
1 files changed, 69 insertions, 15 deletions
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index 1c58eda2..ee5cb468 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -31,6 +31,7 @@ use std::sync::{Arc, Weak};
use std::time::SystemTime;
use helix_core::{
+ editor_config::EditorConfig,
encoding,
history::{History, State, UndoKind},
indent::{auto_detect_indent_style, IndentStyle},
@@ -50,6 +51,7 @@ use crate::{
const BUF_SIZE: usize = 8192;
const DEFAULT_INDENT: IndentStyle = IndentStyle::Tabs;
+const DEFAULT_TAB_WIDTH: usize = 4;
pub const DEFAULT_LANGUAGE_NAME: &str = "text";
@@ -157,6 +159,7 @@ pub struct Document {
/// Current indent style.
pub indent_style: IndentStyle,
+ editor_config: EditorConfig,
/// The document's default line ending.
pub line_ending: LineEnding,
@@ -678,6 +681,7 @@ impl Document {
inlay_hints_oudated: false,
view_data: Default::default(),
indent_style: DEFAULT_INDENT,
+ editor_config: EditorConfig::default(),
line_ending,
restore_cursor: false,
syntax: None,
@@ -712,7 +716,7 @@ impl Document {
/// overwritten with the `encoding` parameter.
pub fn open(
path: &Path,
- encoding: Option<&'static Encoding>,
+ mut encoding: Option<&'static Encoding>,
config_loader: Option<Arc<ArcSwap<syntax::Loader>>>,
config: Arc<dyn DynAccess<Config>>,
) -> Result<Self, DocumentOpenError> {
@@ -721,12 +725,21 @@ impl Document {
return Err(DocumentOpenError::IrregularFile);
}
+ let editor_config = if config.load().editor_config {
+ EditorConfig::find(path)
+ } else {
+ EditorConfig::default()
+ };
+ encoding = encoding.or(editor_config.encoding);
+
// Open the file if it exists, otherwise assume it is a new file (and thus empty).
let (rope, encoding, has_bom) = if path.exists() {
let mut file = std::fs::File::open(path)?;
from_reader(&mut file, encoding)?
} else {
- let line_ending: LineEnding = config.load().default_line_ending.into();
+ let line_ending = editor_config
+ .line_ending
+ .unwrap_or_else(|| config.load().default_line_ending.into());
let encoding = encoding.unwrap_or(encoding::UTF_8);
(Rope::from(line_ending.as_str()), encoding, false)
};
@@ -739,6 +752,7 @@ impl Document {
doc.detect_language(loader);
}
+ doc.editor_config = editor_config;
doc.detect_indent_and_line_ending();
Ok(doc)
@@ -1090,16 +1104,32 @@ impl Document {
/// configured in `languages.toml`, with a fallback to tabs if it isn't specified. Line ending
/// is likewise auto-detected, and will remain unchanged if no line endings were detected.
pub fn detect_indent_and_line_ending(&mut self) {
- self.indent_style = auto_detect_indent_style(&self.text).unwrap_or_else(|| {
- self.language_config()
- .and_then(|config| config.indent.as_ref())
- .map_or(DEFAULT_INDENT, |config| IndentStyle::from_str(&config.unit))
- });
- if let Some(line_ending) = auto_detect_line_ending(&self.text) {
+ self.indent_style = if let Some(indent_style) = self.editor_config.indent_style {
+ indent_style
+ } else {
+ auto_detect_indent_style(&self.text).unwrap_or_else(|| {
+ self.language_config()
+ .and_then(|config| config.indent.as_ref())
+ .map_or(DEFAULT_INDENT, |config| IndentStyle::from_str(&config.unit))
+ })
+ };
+ if let Some(line_ending) = self
+ .editor_config
+ .line_ending
+ .or_else(|| auto_detect_line_ending(&self.text))
+ {
self.line_ending = line_ending;
}
}
+ pub(crate) fn detect_editor_config(&mut self) {
+ if self.config.load().editor_config {
+ if let Some(path) = self.path.as_ref() {
+ self.editor_config = EditorConfig::find(path);
+ }
+ }
+ }
+
pub fn pickup_last_saved_time(&mut self) {
self.last_saved_time = match self.path() {
Some(path) => match path.metadata() {
@@ -1819,9 +1849,14 @@ impl Document {
/// The width that the tab character is rendered at
pub fn tab_width(&self) -> usize {
- self.language_config()
- .and_then(|config| config.indent.as_ref())
- .map_or(4, |config| config.tab_width) // fallback to 4 columns
+ self.editor_config
+ .tab_width
+ .map(|n| n.get() as usize)
+ .unwrap_or_else(|| {
+ self.language_config()
+ .and_then(|config| config.indent.as_ref())
+ .map_or(DEFAULT_TAB_WIDTH, |config| config.tab_width)
+ })
}
// The width (in spaces) of a level of indentation.
@@ -1829,6 +1864,20 @@ impl Document {
self.indent_style.indent_width(self.tab_width())
}
+ /// Whether the document should have a trailing line ending appended on save.
+ pub fn insert_final_newline(&self) -> bool {
+ self.editor_config
+ .insert_final_newline
+ .unwrap_or_else(|| self.config.load().insert_final_newline)
+ }
+
+ /// Whether the document should trim whitespace preceding line endings on save.
+ pub fn trim_trailing_whitespace(&self) -> bool {
+ self.editor_config
+ .trim_trailing_whitespace
+ .unwrap_or_else(|| self.config.load().trim_trailing_whitespace)
+ }
+
pub fn changes(&self) -> &ChangeSet {
&self.changes
}
@@ -2087,12 +2136,17 @@ impl Document {
}
}
+ pub fn text_width(&self) -> usize {
+ self.editor_config
+ .max_line_length
+ .map(|n| n.get() as usize)
+ .or_else(|| self.language_config().and_then(|config| config.text_width))
+ .unwrap_or_else(|| self.config.load().text_width)
+ }
+
pub fn text_format(&self, mut viewport_width: u16, theme: Option<&Theme>) -> TextFormat {
let config = self.config.load();
- let text_width = self
- .language_config()
- .and_then(|config| config.text_width)
- .unwrap_or(config.text_width);
+ let text_width = self.text_width();
let mut soft_wrap_at_text_width = self
.language_config()
.and_then(|config| {