@@ -1051,6 +1051,45 @@ fn sort_impl(
10511051 Ok(())
10521052}
10531053
1054+fn reflow(
1055+ cx: &mut compositor::Context,
1056+ args: &[Cow<str>],
1057+ _event: PromptEvent,
1058+) -> anyhow::Result<()> {
1059+ let (view, doc) = current!(cx.editor);
1060+
1061+ const DEFAULT_MAX_LEN: usize = 79;
1062+
1063+ // Find the max line length by checking the following sources in order:
1064+ // - The passed argument in `args`
1065+ // - The configured max_line_len for this language in languages.toml
1066+ // - The const default we set above
1067+ let max_line_len: usize = args
1068+ .get(0)
1069+ .map(|num| num.parse::<usize>())
1070+ .transpose()?
1071+ .or_else(|| {
1072+ doc.language_config()
1073+ .and_then(|config| config.max_line_length)
1074+ })
1075+ .unwrap_or(DEFAULT_MAX_LEN);
1076+
1077+ let rope = doc.text();
1078+
1079+ let selection = doc.selection(view.id);
1080+ let transaction = Transaction::change_by_selection(rope, selection, |range| {
1081+ let fragment = range.fragment(rope.slice(..));
1082+ let reflowed_text = helix_core::wrap::reflow_hard_wrap(&fragment, max_line_len);
1083+
1084+ (range.from(), range.to(), Some(reflowed_text))
1085+ });
1086+
1087+ doc.apply(&transaction, view.id);
1088+ doc.append_changes_to_history(view.id);
1089+
1090+ Ok(())
1091+}
1092+
10541093fn tree_sitter_subtree(
10551094 cx: &mut compositor::Context,
10561095 _args: &[Cow<str>],
@@ -1570,6 +1609,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
15701609 fun: sort_reverse,
15711610 completer: None,
15721611 },
1612+ TypableCommand {
1613+ name: "reflow",
1614+ aliases: &[],
1615+ doc: "Hard-wrap the current selection of lines to a given width.",
1616+ fun: reflow,
1617+ completer: None,
1618+ },
15731619 TypableCommand {
15741620 name: "tree-sitter-subtree",
15751621 aliases: &["ts-subtree"],