aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock27
-rw-r--r--book/src/generated/typable-cmd.md1
-rw-r--r--helix-core/Cargo.toml1
-rw-r--r--helix-core/src/lib.rs1
-rw-r--r--helix-core/src/syntax.rs1
-rw-r--r--helix-core/src/wrap.rs7
-rw-r--r--helix-term/src/commands/typed.rs46
7 files changed, 84 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 18f50af6..f075249a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -374,6 +374,7 @@ dependencies = [
"slotmap",
"smallvec",
"smartstring",
+ "textwrap",
"toml",
"tree-sitter",
"unicode-general-category",
@@ -1006,6 +1007,12 @@ dependencies = [
]
[[package]]
+name = "smawk"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
+
+[[package]]
name = "socket2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1045,6 +1052,17 @@ dependencies = [
]
[[package]]
+name = "textwrap"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width",
+]
+
+[[package]]
name = "thiserror"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1180,6 +1198,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1218098468b8085b19a2824104c70d976491d247ce194bbd9dc77181150cdfd6"
[[package]]
+name = "unicode-linebreak"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f"
+dependencies = [
+ "regex",
+]
+
+[[package]]
name = "unicode-normalization"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md
index df0841b6..426598e3 100644
--- a/book/src/generated/typable-cmd.md
+++ b/book/src/generated/typable-cmd.md
@@ -59,6 +59,7 @@
| `:get-option`, `:get` | Get the current value of a config option. |
| `:sort` | Sort ranges in selection. |
| `:rsort` | Sort ranges in selection in reverse order. |
+| `:reflow` | Hard-wrap the current selection of lines to a given width. |
| `:tree-sitter-subtree`, `:ts-subtree` | Display tree sitter subtree under cursor, primarily for debugging queries. |
| `:config-reload` | Refreshes helix's config. |
| `:config-open` | Open the helix config.toml file. |
diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index 6e019a42..ab937f0b 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -41,6 +41,7 @@ encoding_rs = "0.8"
chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] }
etcetera = "0.3"
+textwrap = "0.15.0"
[dev-dependencies]
quickcheck = { version = "1", default-features = false }
diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs
index 02341265..a022a42a 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -27,6 +27,7 @@ pub mod syntax;
pub mod test;
pub mod textobject;
mod transaction;
+pub mod wrap;
pub mod unicode {
pub use unicode_general_category as category;
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 3f9e7bcf..eab3ab79 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -67,6 +67,7 @@ pub struct LanguageConfiguration {
pub shebangs: Vec<String>, // interpreter(s) associated with language
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
pub comment_token: Option<String>,
+ pub max_line_length: Option<usize>,
#[serde(default, skip_serializing, deserialize_with = "deserialize_lsp_config")]
pub config: Option<serde_json::Value>,
diff --git a/helix-core/src/wrap.rs b/helix-core/src/wrap.rs
new file mode 100644
index 00000000..eabc47d4
--- /dev/null
+++ b/helix-core/src/wrap.rs
@@ -0,0 +1,7 @@
+use smartstring::{LazyCompact, SmartString};
+
+/// Given a slice of text, return the text re-wrapped to fit it
+/// within the given width.
+pub fn reflow_hard_wrap(text: &str, max_line_len: usize) -> SmartString<LazyCompact> {
+ textwrap::refill(text, max_line_len).into()
+}
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 373c7018..ec86e446 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1051,6 +1051,45 @@ fn sort_impl(
Ok(())
}
+fn reflow(
+ cx: &mut compositor::Context,
+ args: &[Cow<str>],
+ _event: PromptEvent,
+) -> anyhow::Result<()> {
+ let (view, doc) = current!(cx.editor);
+
+ const DEFAULT_MAX_LEN: usize = 79;
+
+ // Find the max line length by checking the following sources in order:
+ // - The passed argument in `args`
+ // - The configured max_line_len for this language in languages.toml
+ // - The const default we set above
+ let max_line_len: usize = args
+ .get(0)
+ .map(|num| num.parse::<usize>())
+ .transpose()?
+ .or_else(|| {
+ doc.language_config()
+ .and_then(|config| config.max_line_length)
+ })
+ .unwrap_or(DEFAULT_MAX_LEN);
+
+ let rope = doc.text();
+
+ let selection = doc.selection(view.id);
+ let transaction = Transaction::change_by_selection(rope, selection, |range| {
+ let fragment = range.fragment(rope.slice(..));
+ let reflowed_text = helix_core::wrap::reflow_hard_wrap(&fragment, max_line_len);
+
+ (range.from(), range.to(), Some(reflowed_text))
+ });
+
+ doc.apply(&transaction, view.id);
+ doc.append_changes_to_history(view.id);
+
+ Ok(())
+}
+
fn tree_sitter_subtree(
cx: &mut compositor::Context,
_args: &[Cow<str>],
@@ -1571,6 +1610,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
completer: None,
},
TypableCommand {
+ name: "reflow",
+ aliases: &[],
+ doc: "Hard-wrap the current selection of lines to a given width.",
+ fun: reflow,
+ completer: None,
+ },
+ TypableCommand {
name: "tree-sitter-subtree",
aliases: &["ts-subtree"],
doc: "Display tree sitter subtree under cursor, primarily for debugging queries.",