diff options
Diffstat (limited to 'helix-term/src')
-rw-r--r-- | helix-term/src/commands/typed.rs | 70 |
1 files changed, 43 insertions, 27 deletions
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 4237b6f6..abe6dd97 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -6,7 +6,7 @@ use crate::job::Job; use super::*; use helix_core::fuzzy::fuzzy_match; -use helix_core::{encoding, shellwords::Shellwords}; +use helix_core::{encoding, line_ending, shellwords::Shellwords}; use helix_view::document::DEFAULT_LANGUAGE_NAME; use helix_view::editor::{Action, CloseError, ConfigEvent}; use serde_json::Value; @@ -330,12 +330,16 @@ fn write_impl( path: Option<&Cow<str>>, force: bool, ) -> anyhow::Result<()> { - let editor_auto_fmt = cx.editor.config().auto_format; + let config = cx.editor.config(); let jobs = &mut cx.jobs; let (view, doc) = current!(cx.editor); let path = path.map(AsRef::as_ref); - let fmt = if editor_auto_fmt { + if config.insert_final_newline { + insert_final_newline(doc, view); + } + + let fmt = if config.auto_format { doc.auto_format().map(|fmt| { let callback = make_format_callback( doc.id(), @@ -359,6 +363,16 @@ fn write_impl( Ok(()) } +fn insert_final_newline(doc: &mut Document, view: &mut View) { + let text = doc.text(); + if line_ending::get_line_ending(&text.slice(..)).is_none() { + let eof = Selection::point(text.len_chars()); + let insert = Transaction::insert(text, &eof, doc.line_ending.as_str().into()); + doc.apply(&insert, view.id); + doc.append_changes_to_history(view); + } +} + fn write( cx: &mut compositor::Context, args: &[Cow<str>], @@ -658,11 +672,10 @@ pub fn write_all_impl( write_scratch: bool, ) -> anyhow::Result<()> { let mut errors: Vec<&'static str> = Vec::new(); - let auto_format = cx.editor.config().auto_format; + let config = cx.editor.config(); let jobs = &mut cx.jobs; let current_view = view!(cx.editor); - // save all documents let saves: Vec<_> = cx .editor .documents @@ -693,32 +706,35 @@ pub fn write_all_impl( current_view.id }; - let fmt = if auto_format { - doc.auto_format().map(|fmt| { - let callback = make_format_callback( - doc.id(), - doc.version(), - target_view, - fmt, - Some((None, force)), - ); - jobs.add(Job::with_callback(callback).wait_before_exiting()); - }) - } else { - None - }; + Some((doc.id(), target_view)) + }) + .collect(); - if fmt.is_none() { - return Some(doc.id()); - } + for (doc_id, target_view) in saves { + let doc = doc_mut!(cx.editor, &doc_id); + if config.insert_final_newline { + insert_final_newline(doc, view_mut!(cx.editor, target_view)); + } + + let fmt = if config.auto_format { + doc.auto_format().map(|fmt| { + let callback = make_format_callback( + doc_id, + doc.version(), + target_view, + fmt, + Some((None, force)), + ); + jobs.add(Job::with_callback(callback).wait_before_exiting()); + }) + } else { None - }) - .collect(); + }; - // manually call save for the rest of docs that don't have a formatter - for id in saves { - cx.editor.save::<PathBuf>(id, None, force)?; + if fmt.is_none() { + cx.editor.save::<PathBuf>(doc_id, None, force)?; + } } if !errors.is_empty() && !force { |