Skip to content

Commit b8f8300

Browse files
committed
fix: indent multiline alias descriptions
1 parent 7954d02 commit b8f8300

2 files changed

Lines changed: 121 additions & 3 deletions

File tree

src/cortex-cli/src/alias_cmd.rs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ use serde::{Deserialize, Serialize};
1212
use std::collections::HashMap;
1313
use std::path::PathBuf;
1414

15+
const DESCRIPTION_PREFIX: &str = " Description: ";
16+
const DESCRIPTION_CONTINUATION_PREFIX: &str = " ";
17+
const ALIAS_LIST_DESCRIPTION_PREFIX: &str = " ";
18+
1519
/// Alias CLI command.
1620
#[derive(Debug, Parser)]
1721
pub struct AliasCli {
@@ -137,6 +141,25 @@ fn save_aliases(config: &AliasConfig) -> Result<()> {
137141
Ok(())
138142
}
139143

144+
fn format_multiline_prefixed_value(
145+
first_prefix: &str,
146+
continuation_prefix: &str,
147+
value: &str,
148+
) -> String {
149+
let mut lines = value.lines();
150+
let Some(first_line) = lines.next() else {
151+
return first_prefix.to_string();
152+
};
153+
154+
let mut formatted = format!("{first_prefix}{first_line}");
155+
for line in lines {
156+
formatted.push('\n');
157+
formatted.push_str(continuation_prefix);
158+
formatted.push_str(line);
159+
}
160+
formatted
161+
}
162+
140163
impl AliasCli {
141164
/// Run the alias command.
142165
pub async fn run(self) -> Result<()> {
@@ -172,7 +195,14 @@ async fn run_set(args: AliasSetArgs) -> Result<()> {
172195

173196
println!("Alias '{}' set to: {}", args.name, args.command);
174197
if let Some(desc) = &args.description {
175-
println!(" Description: {}", desc);
198+
println!(
199+
"{}",
200+
format_multiline_prefixed_value(
201+
DESCRIPTION_PREFIX,
202+
DESCRIPTION_CONTINUATION_PREFIX,
203+
desc
204+
)
205+
);
176206
}
177207

178208
Ok(())
@@ -203,7 +233,14 @@ async fn run_list(args: AliasListArgs) -> Result<()> {
203233
for alias in aliases {
204234
println!(" {} = {}", alias.name, alias.command);
205235
if let Some(desc) = &alias.description {
206-
println!(" {}", desc);
236+
println!(
237+
"{}",
238+
format_multiline_prefixed_value(
239+
ALIAS_LIST_DESCRIPTION_PREFIX,
240+
ALIAS_LIST_DESCRIPTION_PREFIX,
241+
desc
242+
)
243+
);
207244
}
208245
}
209246

@@ -265,7 +302,14 @@ async fn run_show(args: AliasShowArgs) -> Result<()> {
265302
println!("{}", "-".repeat(40));
266303
println!(" Command: {}", alias.command);
267304
if let Some(desc) = &alias.description {
268-
println!(" Description: {}", desc);
305+
println!(
306+
"{}",
307+
format_multiline_prefixed_value(
308+
DESCRIPTION_PREFIX,
309+
DESCRIPTION_CONTINUATION_PREFIX,
310+
desc
311+
)
312+
);
269313
}
270314

271315
Ok(())
@@ -616,4 +660,26 @@ command = "list"
616660
Some("Command with special chars: <>&".to_string())
617661
);
618662
}
663+
664+
#[test]
665+
fn multiline_description_lines_keep_list_indent() {
666+
let formatted =
667+
format_multiline_prefixed_value(" ", " ", "First line\nSecond line");
668+
669+
assert_eq!(formatted, " First line\n Second line");
670+
}
671+
672+
#[test]
673+
fn multiline_description_lines_align_after_description_label() {
674+
let formatted = format_multiline_prefixed_value(
675+
" Description: ",
676+
" ",
677+
"First line\nSecond line",
678+
);
679+
680+
assert_eq!(
681+
formatted,
682+
" Description: First line\n Second line"
683+
);
684+
}
619685
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use std::path::Path;
2+
use std::process::Command;
3+
4+
fn cortex_command(home: &Path) -> Command {
5+
let mut command = Command::new(env!("CARGO_BIN_EXE_Cortex"));
6+
command.env("HOME", home);
7+
command.env("USERPROFILE", home);
8+
command.env("APPDATA", home.join("AppData").join("Roaming"));
9+
command
10+
}
11+
12+
fn run_success(command: &mut Command) -> String {
13+
let output = command.output().expect("run Cortex");
14+
assert!(
15+
output.status.success(),
16+
"command failed\nstatus: {}\nstdout:\n{}\nstderr:\n{}",
17+
output.status,
18+
String::from_utf8_lossy(&output.stdout),
19+
String::from_utf8_lossy(&output.stderr)
20+
);
21+
String::from_utf8_lossy(&output.stdout).to_string()
22+
}
23+
24+
#[test]
25+
fn alias_descriptions_indent_every_multiline_line() {
26+
let temp = tempfile::tempdir().expect("temp dir");
27+
let description = "First line\nSecond line";
28+
29+
let set_output = run_success(
30+
cortex_command(temp.path())
31+
.args(["alias", "set", "bounty_alias_demo", "version", "-d"])
32+
.arg(description)
33+
.arg("-f"),
34+
);
35+
assert!(
36+
set_output.contains(" Description: First line\n Second line"),
37+
"{set_output}"
38+
);
39+
40+
let list_output = run_success(cortex_command(temp.path()).args(["alias", "list"]));
41+
assert!(
42+
list_output.contains(" First line\n Second line"),
43+
"{list_output}"
44+
);
45+
46+
let show_output =
47+
run_success(cortex_command(temp.path()).args(["alias", "show", "bounty_alias_demo"]));
48+
assert!(
49+
show_output.contains(" Description: First line\n Second line"),
50+
"{show_output}"
51+
);
52+
}

0 commit comments

Comments
 (0)