Skip to content

Commit

Permalink
soft-wrap: allow per-language overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
divarvel committed Feb 16, 2023
1 parent 51d9f30 commit e2ce415
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 47 deletions.
28 changes: 28 additions & 0 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub struct LanguageConfiguration {
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
pub comment_token: Option<String>,
pub text_width: Option<usize>,
pub soft_wrap: SoftWrap,

#[serde(default, skip_serializing, deserialize_with = "deserialize_lsp_config")]
pub config: Option<serde_json::Value>,
Expand Down Expand Up @@ -546,6 +547,33 @@ impl LanguageConfiguration {
.ok()
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
pub struct SoftWrap {
/// Soft wrap lines that exceed viewport width. Default to off
pub enable: Option<bool>,
/// Maximum space left free at the end of the line.
/// This space is used to wrap text at word boundaries. If that is not possible within this limit
/// the word is simply split at the end of the line.
///
/// This is automatically hard-limited to a quarter of the viewport to ensure correct display on small views.
///
/// Default to 20
pub max_wrap: Option<u16>,
/// Maximum number of indentation that can be carried over from the previous line when softwrapping.
/// If a line is indented further then this limit it is rendered at the start of the viewport instead.
///
/// This is automatically hard-limited to a quarter of the viewport to ensure correct display on small views.
///
/// Default to 40
pub max_indent_retain: Option<u16>,
/// Indicator placed at the beginning of softwrapped lines
///
/// Defaults to ↪
pub wrap_indicator: Option<String>,
/// Softwrap at `text_width` instead of viewport width if it is shorter
pub wrap_at_text_width: Option<bool>,
}

// Expose loader as Lazy<> global since it's always static?

Expand Down
34 changes: 28 additions & 6 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,12 @@ impl Document {
.language_config()
.and_then(|config| config.text_width)
.unwrap_or(config.text_width);
if config.soft_wrap.wrap_at_text_width {
let soft_wrap_at_text_width = self
.language_config()
.and_then(|config| config.soft_wrap.wrap_at_text_width)
.or(config.soft_wrap.wrap_at_text_width)
.unwrap_or(false);
if soft_wrap_at_text_width {
// We increase max_line_len by 1 because softwrap considers the newline character
// as part of the line length while the "typical" expectation is that this is not the case.
// In particular other commands like :reflow do not count the line terminator.
Expand All @@ -1245,17 +1250,34 @@ impl Document {
viewport_width = viewport_width.min(text_width as u16 + 1)
}
let config = self.config.load();
let soft_wrap = &config.soft_wrap;
let editor_soft_wrap = &config.soft_wrap;
let language_soft_wrap = self.language.as_ref().map(|config| &config.soft_wrap);
let enable_soft_wrap = language_soft_wrap
.and_then(|soft_wrap| soft_wrap.enable)
.or(editor_soft_wrap.enable)
.unwrap_or(false);
let max_wrap = language_soft_wrap
.and_then(|soft_wrap| soft_wrap.max_wrap)
.or(config.soft_wrap.max_wrap)
.unwrap_or(20);
let max_indent_retain = language_soft_wrap
.and_then(|soft_wrap| soft_wrap.max_indent_retain)
.or(editor_soft_wrap.max_indent_retain)
.unwrap_or(40);
let wrap_indicator = language_soft_wrap
.and_then(|soft_wrap| soft_wrap.wrap_indicator.clone())
.or_else(|| config.soft_wrap.wrap_indicator.clone())
.unwrap_or_else(|| "↪ ".into());
let tab_width = self.tab_width() as u16;
TextFormat {
soft_wrap: soft_wrap.enable && viewport_width > 10,
soft_wrap: enable_soft_wrap && viewport_width > 10,
tab_width,
max_wrap: soft_wrap.max_wrap.min(viewport_width / 4),
max_indent_retain: soft_wrap.max_indent_retain.min(viewport_width * 2 / 5),
max_wrap: max_wrap.min(viewport_width / 4),
max_indent_retain: max_indent_retain.min(viewport_width * 2 / 5),
// avoid spinning forever when the window manager
// sets the size to something tiny
viewport_width,
wrap_indicator: soft_wrap.wrap_indicator.clone().into_boxed_str(),
wrap_indicator: wrap_indicator.into_boxed_str(),
wrap_indicator_highlight: theme
.and_then(|theme| theme.find_scope_index("ui.virtual.wrap"))
.map(Highlight),
Expand Down
42 changes: 1 addition & 41 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub use helix_core::register::Registers;
use helix_core::Position;
use helix_core::{
auto_pairs::AutoPairs,
syntax::{self, AutoPairConfig},
syntax::{self, AutoPairConfig, SoftWrap},
Change,
};
use helix_dap as dap;
Expand Down Expand Up @@ -278,46 +278,6 @@ pub struct Config {
pub soft_wrap: SoftWrap,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
pub struct SoftWrap {
/// Soft wrap lines that exceed viewport width. Default to off
pub enable: bool,
/// Maximum space left free at the end of the line.
/// This space is used to wrap text at word boundaries. If that is not possible within this limit
/// the word is simply split at the end of the line.
///
/// This is automatically hard-limited to a quarter of the viewport to ensure correct display on small views.
///
/// Default to 20
pub max_wrap: u16,
/// Maximum number of indentation that can be carried over from the previous line when softwrapping.
/// If a line is indented further then this limit it is rendered at the start of the viewport instead.
///
/// This is automatically hard-limited to a quarter of the viewport to ensure correct display on small views.
///
/// Default to 40
pub max_indent_retain: u16,
/// Indicator placed at the beginning of softwrapped lines
///
/// Defaults to ↪
pub wrap_indicator: String,
/// Softwrap at `text_width` instead of viewport width if it is shorter
pub wrap_at_text_width: bool,
}

impl Default for SoftWrap {
fn default() -> Self {
SoftWrap {
enable: false,
max_wrap: 20,
max_indent_retain: 40,
wrap_indicator: "↪ ".into(),
wrap_at_text_width: true,
}
}
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
pub struct TerminalConfig {
Expand Down

0 comments on commit e2ce415

Please sign in to comment.