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 config for default line ending #5621

Merged
merged 1 commit into from
Jun 16, 2023
Merged
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
1 change: 1 addition & 0 deletions book/src/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Its settings will be merged with the configuration directory `config.toml` and t
| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap-at-text-width` is set | `80` |
| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` |
| `default-line-ending` | The line ending to use for new documents. Can be `native`, `lf`, `crlf`, `ff`, `cr` or `nel`. `native` uses the platform's native line ending (`crlf` on Windows, otherwise `lf`). | `native` |

### `[editor.statusline]` Section

Expand Down
2 changes: 1 addition & 1 deletion helix-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,5 @@ pub use syntax::Syntax;

pub use diagnostic::Diagnostic;

pub use line_ending::{LineEnding, DEFAULT_LINE_ENDING};
pub use line_ending::{LineEnding, NATIVE_LINE_ENDING};
pub use transaction::{Assoc, Change, ChangeSet, Deletion, Operation, Transaction};
4 changes: 2 additions & 2 deletions helix-core/src/line_ending.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{Rope, RopeSlice};

#[cfg(target_os = "windows")]
pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::Crlf;
pub const NATIVE_LINE_ENDING: LineEnding = LineEnding::Crlf;
#[cfg(not(target_os = "windows"))]
pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::LF;
pub const NATIVE_LINE_ENDING: LineEnding = LineEnding::LF;

/// Represents one of the valid Unicode line endings.
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
Expand Down
2 changes: 1 addition & 1 deletion helix-term/tests/test/auto_pairs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use helix_core::{auto_pairs::DEFAULT_PAIRS, hashmap};

use super::*;

const LINE_END: &str = helix_core::DEFAULT_LINE_ENDING.as_str();
const LINE_END: &str = helix_core::NATIVE_LINE_ENDING.as_str();

fn differing_pairs() -> impl Iterator<Item = &'static (char, char)> {
DEFAULT_PAIRS.iter().filter(|(open, close)| open != close)
Expand Down
2 changes: 1 addition & 1 deletion helix-term/tests/test/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ pub fn test_editor_config() -> helix_view::editor::Config {
/// character, and if one doesn't exist already, appends the system's
/// appropriate line ending to the end of a string.
pub fn platform_line(input: &str) -> String {
let line_end = helix_core::DEFAULT_LINE_ENDING.as_str();
let line_end = helix_core::NATIVE_LINE_ENDING.as_str();

// we can assume that the source files in this code base will always
// be LF, so indoc strings will always insert LF
Expand Down
22 changes: 13 additions & 9 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use helix_core::doc_formatter::TextFormat;
use helix_core::encoding::Encoding;
use helix_core::syntax::{Highlight, LanguageServerFeature};
use helix_core::text_annotations::{InlineAnnotation, TextAnnotations};
use helix_core::Range;
use helix_vcs::{DiffHandle, DiffProviderRegistry};

use ::parking_lot::Mutex;
Expand All @@ -31,8 +30,8 @@ use helix_core::{
indent::{auto_detect_indent_style, IndentStyle},
line_ending::auto_detect_line_ending,
syntax::{self, LanguageConfiguration},
ChangeSet, Diagnostic, LineEnding, Rope, RopeBuilder, Selection, Syntax, Transaction,
DEFAULT_LINE_ENDING,
ChangeSet, Diagnostic, LineEnding, Range, Rope, RopeBuilder, Selection, Syntax, Transaction,
NATIVE_LINE_ENDING,
};

use crate::editor::{Config, RedrawHandle};
Expand Down Expand Up @@ -590,6 +589,7 @@ impl Document {
config: Arc<dyn DynAccess<Config>>,
) -> Self {
let (encoding, has_bom) = encoding_with_bom_info.unwrap_or((encoding::UTF_8, false));
let line_ending = config.load().default_line_ending.into();
let changes = ChangeSet::new(&text);
let old_state = None;

Expand All @@ -603,7 +603,7 @@ impl Document {
inlay_hints: HashMap::default(),
inlay_hints_oudated: false,
indent_style: DEFAULT_INDENT,
line_ending: DEFAULT_LINE_ENDING,
line_ending,
restore_cursor: false,
syntax: None,
language: None,
Expand All @@ -623,10 +623,12 @@ impl Document {
focused_at: std::time::Instant::now(),
}
}

pub fn default(config: Arc<dyn DynAccess<Config>>) -> Self {
let text = Rope::from(DEFAULT_LINE_ENDING.as_str());
let text = Rope::from(NATIVE_LINE_ENDING.as_str());
Self::from(text, None, config)
}

// TODO: async fn?
/// Create a new document from `path`. Encoding is auto-detected, but it can be manually
/// overwritten with the `encoding` parameter.
Expand All @@ -643,7 +645,7 @@ impl Document {
from_reader(&mut file, encoding)?
} else {
let encoding = encoding.unwrap_or(encoding::UTF_8);
(Rope::from(DEFAULT_LINE_ENDING.as_str()), encoding, false)
(Rope::from(NATIVE_LINE_ENDING.as_str()), encoding, false)
};

let mut doc = Self::from(rope, Some((encoding, has_bom)), config);
Expand Down Expand Up @@ -887,14 +889,16 @@ impl Document {

/// Detect the indentation used in the file, or otherwise defaults to the language indentation
/// configured in `languages.toml`, with a fallback to tabs if it isn't specified. Line ending
/// is likewise auto-detected, and will fallback to the default OS 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))
});
self.line_ending = auto_detect_line_ending(&self.text).unwrap_or(DEFAULT_LINE_ENDING);
if let Some(line_ending) = auto_detect_line_ending(&self.text) {
self.line_ending = line_ending;
}
}

/// Reload the document from its path.
Expand Down Expand Up @@ -1921,7 +1925,7 @@ mod test {
Document::default(Arc::new(ArcSwap::new(Arc::new(Config::default()))))
.text()
.to_string(),
DEFAULT_LINE_ENDING.as_str()
NATIVE_LINE_ENDING.as_str()
);
}

Expand Down
52 changes: 50 additions & 2 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub use helix_core::register::Registers;
use helix_core::{
auto_pairs::AutoPairs,
syntax::{self, AutoPairConfig, SoftWrap},
Change,
Change, LineEnding, NATIVE_LINE_ENDING,
};
use helix_core::{Position, Selection};
use helix_dap as dap;
Expand Down Expand Up @@ -271,7 +271,7 @@ pub struct Config {
pub search: SearchConfig,
pub lsp: LspConfig,
pub terminal: Option<TerminalConfig>,
/// Column numbers at which to draw the rulers. Default to `[]`, meaning no rulers.
/// Column numbers at which to draw the rulers. Defaults to `[]`, meaning no rulers.
pub rulers: Vec<u16>,
#[serde(default)]
pub whitespace: WhitespaceConfig,
Expand All @@ -284,6 +284,8 @@ pub struct Config {
pub soft_wrap: SoftWrap,
/// Workspace specific lsp ceiling dirs
pub workspace_lsp_roots: Vec<PathBuf>,
/// Which line ending to choose for new documents. Defaults to `native`. i.e. `crlf` on Windows, otherwise `lf`.
pub default_line_ending: LineEndingConfig,
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -716,6 +718,51 @@ impl Default for IndentGuidesConfig {
}
}

/// Line ending configuration.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LineEndingConfig {
/// The platform's native line ending.
///
/// `crlf` on Windows, otherwise `lf`.
Native,
CptPotato marked this conversation as resolved.
Show resolved Hide resolved
/// Line feed.
LF,
/// Carriage return followed by line feed.
Crlf,
/// Form feed.
#[cfg(feature = "unicode-lines")]
FF,
/// Carriage return.
#[cfg(feature = "unicode-lines")]
CR,
/// Next line.
#[cfg(feature = "unicode-lines")]
Nel,
CptPotato marked this conversation as resolved.
Show resolved Hide resolved
}

impl Default for LineEndingConfig {
fn default() -> Self {
LineEndingConfig::Native
}
}

impl From<LineEndingConfig> for LineEnding {
fn from(line_ending: LineEndingConfig) -> Self {
match line_ending {
LineEndingConfig::Native => NATIVE_LINE_ENDING,
LineEndingConfig::LF => LineEnding::LF,
LineEndingConfig::Crlf => LineEnding::Crlf,
#[cfg(feature = "unicode-lines")]
LineEndingConfig::FF => LineEnding::FF,
#[cfg(feature = "unicode-lines")]
LineEndingConfig::CR => LineEnding::CR,
#[cfg(feature = "unicode-lines")]
LineEndingConfig::Nel => LineEnding::Nel,
}
}
}

impl Default for Config {
fn default() -> Self {
Self {
Expand Down Expand Up @@ -759,6 +806,7 @@ impl Default for Config {
text_width: 80,
completion_replace: false,
workspace_lsp_roots: Vec::new(),
default_line_ending: LineEndingConfig::default(),
}
}
}
Expand Down