mirror of https://github.com/helix-editor/helix
Merge 893f4c8ece
into 205e7ece70
commit
8ef154f4b3
|
@ -89,3 +89,6 @@
|
||||||
| `:read`, `:r` | Load a file into buffer |
|
| `:read`, `:r` | Load a file into buffer |
|
||||||
| `:echo` | Prints the given arguments to the statusline. |
|
| `:echo` | Prints the given arguments to the statusline. |
|
||||||
| `:noop` | Does nothing. |
|
| `:noop` | Does nothing. |
|
||||||
|
| `:align-text-left`, `:atl` | Align text to the left |
|
||||||
|
| `:align-text-center`, `:atc` | Center-align text, optionally pass a number overriding the current document's text width |
|
||||||
|
| `:align-text-right`, `:atr` | Align text to the right, optionally pass a number overriding the current document's text width |
|
||||||
|
|
|
@ -204,6 +204,84 @@ fn buffer_gather_paths_impl(editor: &mut Editor, args: Args) -> Vec<DocumentId>
|
||||||
document_ids
|
document_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn align_text_impl(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
args: Args,
|
||||||
|
event: PromptEvent,
|
||||||
|
format: fn(usize, &str) -> String,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if event != PromptEvent::Validate {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let editor_text_width = cx.editor.config().text_width;
|
||||||
|
let (view, doc) = current!(cx.editor);
|
||||||
|
let text = doc.text().slice(..);
|
||||||
|
|
||||||
|
let custom_text_width = args.first().map(|arg| {
|
||||||
|
arg.parse::<usize>()
|
||||||
|
.map_err(|_| anyhow!("Could not parse argument as a number: {arg}"))
|
||||||
|
});
|
||||||
|
|
||||||
|
let text_width = custom_text_width.unwrap_or(Ok(doc
|
||||||
|
.language_config()
|
||||||
|
.and_then(|c| c.text_width)
|
||||||
|
.unwrap_or(editor_text_width)))?;
|
||||||
|
|
||||||
|
let lines = get_lines(doc, view.id);
|
||||||
|
let mut changes = Vec::with_capacity(lines.len());
|
||||||
|
|
||||||
|
for line_idx in lines {
|
||||||
|
let line = doc.text().line(line_idx);
|
||||||
|
let old_line = line.to_string();
|
||||||
|
|
||||||
|
let aligned_line = format(text_width, old_line.trim());
|
||||||
|
let aligned_line = aligned_line.trim_end();
|
||||||
|
let tendril = Tendril::from(aligned_line);
|
||||||
|
|
||||||
|
changes.push((
|
||||||
|
text.line_to_char(line_idx),
|
||||||
|
text.line_to_char(line_idx + 1) - doc.line_ending.len_chars(),
|
||||||
|
Some(tendril),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
let transaction = Transaction::change(doc.text(), changes.into_iter());
|
||||||
|
|
||||||
|
doc.apply(&transaction, view.id);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align_text_left(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
args: Args,
|
||||||
|
event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
align_text_impl(cx, args, event, |text_width, text| {
|
||||||
|
format!("{:<text_width$}", text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align_text_center(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
args: Args,
|
||||||
|
event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
align_text_impl(cx, args, event, |text_width, text| {
|
||||||
|
format!("{:^text_width$}", text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align_text_right(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
args: Args,
|
||||||
|
event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
align_text_impl(cx, args, event, |text_width, text| {
|
||||||
|
format!("{:>text_width$}", text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn buffer_close(
|
fn buffer_close(
|
||||||
cx: &mut compositor::Context,
|
cx: &mut compositor::Context,
|
||||||
args: Args,
|
args: Args,
|
||||||
|
@ -3567,6 +3645,39 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
|
||||||
..Signature::DEFAULT
|
..Signature::DEFAULT
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "align-text-left",
|
||||||
|
aliases: &["atl"],
|
||||||
|
doc: "Align text to the left",
|
||||||
|
fun: align_text_left,
|
||||||
|
completer: CommandCompleter::none(),
|
||||||
|
signature: Signature {
|
||||||
|
positionals: (0, Some(0)),
|
||||||
|
..Signature::DEFAULT
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "align-text-center",
|
||||||
|
aliases: &["atc"],
|
||||||
|
doc: "Center-align text, optionally pass a number overriding the current document's text width",
|
||||||
|
fun: align_text_center,
|
||||||
|
completer: CommandCompleter::none(),
|
||||||
|
signature: Signature {
|
||||||
|
positionals: (0, Some(1)),
|
||||||
|
..Signature::DEFAULT
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "align-text-right",
|
||||||
|
aliases: &["atr"],
|
||||||
|
doc: "Align text to the right, optionally pass a number overriding the current document's text width",
|
||||||
|
fun: align_text_right,
|
||||||
|
completer: CommandCompleter::none(),
|
||||||
|
signature: Signature {
|
||||||
|
positionals: (0, Some(1)),
|
||||||
|
..Signature::DEFAULT
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableCommand>> =
|
pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableCommand>> =
|
||||||
|
|
|
@ -2,6 +2,7 @@ use helix_term::application::Application;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
mod align_text;
|
||||||
mod insert;
|
mod insert;
|
||||||
mod movement;
|
mod movement;
|
||||||
mod write;
|
mod write;
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const IN: &str = indoc! {"
|
||||||
|
#[pub fn docgen() -> Result<(), DynError> {
|
||||||
|
use crate::docgen::*;
|
||||||
|
write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?);
|
||||||
|
write(STATIC_COMMANDS_MD_OUTPUT, &static_commands()?);
|
||||||
|
write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?);
|
||||||
|
Ok(())
|
||||||
|
}\n|]#"};
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn left() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
IN,
|
||||||
|
":align-text-left<ret>",
|
||||||
|
indoc! {"\
|
||||||
|
#[pub fn docgen() -> Result<(), DynError> {
|
||||||
|
use crate::docgen::*;
|
||||||
|
write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?);
|
||||||
|
write(STATIC_COMMANDS_MD_OUTPUT, &static_commands()?);
|
||||||
|
write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?);
|
||||||
|
Ok(())
|
||||||
|
}\n|]#"},
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn center() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
IN,
|
||||||
|
":align-text-center<ret>",
|
||||||
|
indoc! {"\
|
||||||
|
#[ pub fn docgen() -> Result<(), DynError> {
|
||||||
|
use crate::docgen::*;
|
||||||
|
write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?);
|
||||||
|
write(STATIC_COMMANDS_MD_OUTPUT, &static_commands()?);
|
||||||
|
write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?);
|
||||||
|
Ok(())
|
||||||
|
}\n|]#"},
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn right() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
IN,
|
||||||
|
":align-text-right<ret>",
|
||||||
|
indoc! {"\
|
||||||
|
#[ pub fn docgen() -> Result<(), DynError> {
|
||||||
|
use crate::docgen::*;
|
||||||
|
write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?);
|
||||||
|
write(STATIC_COMMANDS_MD_OUTPUT, &static_commands()?);
|
||||||
|
write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?);
|
||||||
|
Ok(())
|
||||||
|
}\n|]#"},
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue