Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add option to enforce newline at the end of document #5435

Closed
wants to merge 13 commits into from
1 change: 1 addition & 0 deletions book/src/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ on unix operating systems.
| `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file. | `[]` |
| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` |
| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
| `newline-at-eof` | Adds newline at end of file when saving if there is none. | `false` |

### `[editor.statusline]` Section

Expand Down
27 changes: 21 additions & 6 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ use tokio::{
use anyhow::{anyhow, bail, Error};

pub use helix_core::diagnostic::Severity;
pub use helix_core::line_ending::get_line_ending;
pub use helix_core::register::Registers;
use helix_core::Position;
use helix_core::{
auto_pairs::AutoPairs,
syntax::{self, AutoPairConfig},
Change,
Change, Position, Range, Selection, Tendril, Transaction,
};
use helix_dap as dap;
use helix_lsp::lsp;
Expand Down Expand Up @@ -273,6 +273,7 @@ pub struct Config {
pub indent_guides: IndentGuidesConfig,
/// Whether to color modes with different colors. Defaults to `false`.
pub color_modes: bool,
pub newline_at_eof: bool,
pub soft_wrap: SoftWrap,
}

Expand Down Expand Up @@ -771,6 +772,7 @@ impl Default for Config {
bufferline: BufferLine::default(),
indent_guides: IndentGuidesConfig::default(),
color_modes: false,
newline_at_eof: false,
Xalfer marked this conversation as resolved.
Show resolved Hide resolved
soft_wrap: SoftWrap::default(),
}
}
Expand Down Expand Up @@ -1419,7 +1421,22 @@ impl Editor {
// via stream.then() ? then push into main future

let path = path.map(|path| path.into());
let config = self.config();
let doc = doc_mut!(self, &doc_id);

// handle adding newline at the end of the file if there is none
let newline = doc.line_ending.as_str();
let text = doc.text();
let doc_len = text.len_chars();
if config.newline_at_eof && get_line_ending(&text.slice(..)).is_none() {
let view = view_mut!(self);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fetch the currently focused view which may not be the view that's looking at the document. This can cause a panic with this feature enabled: open a split with two different files without newline endings and :wa.

I think it might make sense to solve this in helix-term::commands::typed in write_impl and write_all_impl rather than here in Editor. We probably also do not want to add a trailing newline when documents are being auto-formatted because we may end up fighting with the auto-formatter (language server or external command)

let newline = Tendril::from(newline);
let selection = Selection::point(doc_len);
let transaction = Transaction::insert(text, &selection, newline);
doc.apply(&transaction, view.id);
doc.append_changes_to_history(view);
}

let future = doc.save(path, force)?;

use futures_util::stream;
Expand Down Expand Up @@ -1625,7 +1642,7 @@ impl Editor {

/// Switches the editor into normal mode.
pub fn enter_normal_mode(&mut self) {
use helix_core::{graphemes, Range};
use helix_core::graphemes;

if self.mode == Mode::Normal {
return;
Expand Down Expand Up @@ -1653,9 +1670,7 @@ impl Editor {
}

fn try_restore_indent(doc: &mut Document, view: &mut View) {
use helix_core::{
chars::char_is_whitespace, line_ending::line_end_char_index, Operation, Transaction,
};
use helix_core::{chars::char_is_whitespace, line_ending::line_end_char_index, Operation};

fn inserted_a_new_blank_line(changes: &[Operation], pos: usize, line_end_pos: usize) -> bool {
if let [Operation::Retain(move_pos), Operation::Insert(ref inserted_str), Operation::Retain(_)] =
Expand Down