Skip to content
Open
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
72 changes: 69 additions & 3 deletions src/cortex-cli/src/alias_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;

const DESCRIPTION_PREFIX: &str = " Description: ";
const DESCRIPTION_CONTINUATION_PREFIX: &str = " ";
const ALIAS_LIST_DESCRIPTION_PREFIX: &str = " ";

/// Alias CLI command.
#[derive(Debug, Parser)]
pub struct AliasCli {
Expand Down Expand Up @@ -137,6 +141,25 @@ fn save_aliases(config: &AliasConfig) -> Result<()> {
Ok(())
}

fn format_multiline_prefixed_value(
first_prefix: &str,
continuation_prefix: &str,
value: &str,
) -> String {
let mut lines = value.lines();
let Some(first_line) = lines.next() else {
return first_prefix.to_string();
};

let mut formatted = format!("{first_prefix}{first_line}");
for line in lines {
formatted.push('\n');
formatted.push_str(continuation_prefix);
formatted.push_str(line);
}
formatted
}

impl AliasCli {
/// Run the alias command.
pub async fn run(self) -> Result<()> {
Expand Down Expand Up @@ -172,7 +195,14 @@ async fn run_set(args: AliasSetArgs) -> Result<()> {

println!("Alias '{}' set to: {}", args.name, args.command);
if let Some(desc) = &args.description {
println!(" Description: {}", desc);
println!(
"{}",
format_multiline_prefixed_value(
DESCRIPTION_PREFIX,
DESCRIPTION_CONTINUATION_PREFIX,
desc
)
);
}

Ok(())
Expand Down Expand Up @@ -203,7 +233,14 @@ async fn run_list(args: AliasListArgs) -> Result<()> {
for alias in aliases {
println!(" {} = {}", alias.name, alias.command);
if let Some(desc) = &alias.description {
println!(" {}", desc);
println!(
"{}",
format_multiline_prefixed_value(
ALIAS_LIST_DESCRIPTION_PREFIX,
ALIAS_LIST_DESCRIPTION_PREFIX,
desc
)
);
}
}

Expand Down Expand Up @@ -265,7 +302,14 @@ async fn run_show(args: AliasShowArgs) -> Result<()> {
println!("{}", "-".repeat(40));
println!(" Command: {}", alias.command);
if let Some(desc) = &alias.description {
println!(" Description: {}", desc);
println!(
"{}",
format_multiline_prefixed_value(
DESCRIPTION_PREFIX,
DESCRIPTION_CONTINUATION_PREFIX,
desc
)
);
}

Ok(())
Expand Down Expand Up @@ -616,4 +660,26 @@ command = "list"
Some("Command with special chars: <>&".to_string())
);
}

#[test]
fn multiline_description_lines_keep_list_indent() {
let formatted =
format_multiline_prefixed_value(" ", " ", "First line\nSecond line");

assert_eq!(formatted, " First line\n Second line");
}

#[test]
fn multiline_description_lines_align_after_description_label() {
let formatted = format_multiline_prefixed_value(
" Description: ",
" ",
"First line\nSecond line",
);

assert_eq!(
formatted,
" Description: First line\n Second line"
);
}
}
52 changes: 52 additions & 0 deletions src/cortex-cli/tests/alias_multiline_description.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::path::Path;
use std::process::Command;

fn cortex_command(home: &Path) -> Command {
let mut command = Command::new(env!("CARGO_BIN_EXE_Cortex"));
command.env("HOME", home);
command.env("USERPROFILE", home);
command.env("APPDATA", home.join("AppData").join("Roaming"));
command
}

fn run_success(command: &mut Command) -> String {
let output = command.output().expect("run Cortex");
assert!(
output.status.success(),
"command failed\nstatus: {}\nstdout:\n{}\nstderr:\n{}",
output.status,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8_lossy(&output.stdout).to_string()
}

#[test]
fn alias_descriptions_indent_every_multiline_line() {
let temp = tempfile::tempdir().expect("temp dir");
let description = "First line\nSecond line";

let set_output = run_success(
cortex_command(temp.path())
.args(["alias", "set", "bounty_alias_demo", "version", "-d"])
.arg(description)
.arg("-f"),
);
assert!(
set_output.contains(" Description: First line\n Second line"),
"{set_output}"
);

let list_output = run_success(cortex_command(temp.path()).args(["alias", "list"]));
assert!(
list_output.contains(" First line\n Second line"),
"{list_output}"
);

let show_output =
run_success(cortex_command(temp.path()).args(["alias", "show", "bounty_alias_demo"]));
assert!(
show_output.contains(" Description: First line\n Second line"),
"{show_output}"
);
}