Skip to content

Commit 7644065

Browse files
committed
Extract formatting logic
1 parent 3e08486 commit 7644065

File tree

6 files changed

+125
-103
lines changed

6 files changed

+125
-103
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363

6464
([Vladislav Shakitskiy](https://github.com/vshakitskiy))
6565

66+
- The format used for `gleam deps list` and the notice of available major
67+
version upgrades has been improved.
68+
([Louis Pilfold](https://github.com/lpil))
69+
6670
### Language server
6771

6872
- The "inline variable" code action can now trigger when used over the let

compiler-cli/src/dependencies.rs

Lines changed: 23 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use crate::{
3939
cli,
4040
fs::{self, ProjectIO},
4141
http::HttpClient,
42+
text_layout::space_table,
4243
};
4344

4445
struct Symbols {
@@ -111,14 +112,17 @@ fn get_manifest_details(paths: &ProjectPaths) -> Result<(PackageConfig, Manifest
111112
}
112113

113114
fn list_manifest_packages<W: std::io::Write>(mut buffer: W, manifest: Manifest) -> Result<()> {
114-
manifest
115+
let packages = manifest
115116
.packages
116117
.into_iter()
117-
.try_for_each(|package| writeln!(buffer, "{}\t{}", package.name, package.version))
118-
.map_err(|e| Error::StandardIo {
119-
action: StandardIoAction::Write,
120-
err: Some(e.kind()),
121-
})
118+
.map(|package| vec![package.name.to_string(), package.version.to_string()])
119+
.collect_vec();
120+
let out = space_table(&["Package", "Version"], packages);
121+
122+
write!(buffer, "{}", out).map_err(|e| Error::StandardIo {
123+
action: StandardIoAction::Write,
124+
err: Some(e.kind()),
125+
})
122126
}
123127

124128
fn list_package_and_dependencies_tree<W: std::io::Write>(
@@ -409,104 +413,26 @@ pub fn resolve_and_download<Telem: Telemetry>(
409413

410414
fn format_versions_and_extract_longest_parts(
411415
versions: dependency::PackageVersionDiffs,
412-
) -> (
413-
impl Iterator<Item = (String, String, String)>,
414-
(usize, usize),
415-
) {
416-
let versions = versions
416+
) -> Vec<Vec<String>> {
417+
versions
417418
.iter()
418-
.map(|(name, (v1, v2))| (name.to_string(), v1.to_string(), v2.to_string()))
419-
.sorted();
420-
421-
let longest_parts =
422-
versions
423-
.clone()
424-
.fold((0, 0), |(max_name, max_current), (name, current, _)| {
425-
(max_name.max(name.len()), max_current.max(current.len()))
426-
});
427-
428-
(versions, longest_parts)
419+
.map(|(name, (v1, v2))| vec![name.to_string(), v1.to_string(), v2.to_string()])
420+
.sorted()
421+
.collect_vec()
429422
}
430423

431424
fn pretty_print_major_versions_available(versions: dependency::PackageVersionDiffs) -> String {
432-
let (versions, (longest_package_name_length, longest_current_version_length)) =
433-
format_versions_and_extract_longest_parts(versions);
434-
435-
let mut output_string = String::new();
436-
437-
output_string.push_str("\nThe following dependencies have new major versions available:\n\n");
438-
for (name, v1, v2) in versions {
439-
let name_padding = " ".repeat(longest_package_name_length - name.len());
440-
let current_version_padding =
441-
" ".repeat(longest_current_version_length - v1.to_string().len());
442-
443-
output_string.push_str(
444-
&[
445-
&name,
446-
&name_padding,
447-
" ",
448-
&v1.to_string(),
449-
&current_version_padding,
450-
" -> ",
451-
&v2.to_string(),
452-
"\n",
453-
]
454-
.concat(),
455-
);
456-
}
425+
let versions = format_versions_and_extract_longest_parts(versions);
457426

458-
output_string
427+
format!(
428+
"\nThe following dependencies have new major versions available:\n\n{}",
429+
space_table(&["Package", "Current", "Latest"], &versions)
430+
)
459431
}
460432

461-
fn pretty_print_version_updates(versions: dependency::PackageVersionDiffs) -> String {
462-
let (versions, (longest_package_name_length, longest_current_version_length)) =
463-
format_versions_and_extract_longest_parts(versions);
464-
465-
let longest_package_name_length = longest_package_name_length.max(7);
466-
let longest_current_version_length = longest_current_version_length.max(8);
467-
468-
let mut output_string = String::new();
469-
470-
let name_padding = " ".repeat(longest_package_name_length - 6);
471-
let current_version_padding = " ".repeat(longest_current_version_length - 7);
472-
473-
output_string.push_str(
474-
&[
475-
"Package",
476-
&name_padding,
477-
" Current",
478-
&current_version_padding,
479-
" Latest\n",
480-
"-------",
481-
&name_padding,
482-
" -------",
483-
&current_version_padding,
484-
" ------\n",
485-
]
486-
.concat(),
487-
);
488-
489-
for (name, v1, v2) in versions {
490-
let name_padding = " ".repeat(longest_package_name_length - name.len());
491-
let current_version_padding =
492-
" ".repeat(longest_current_version_length - v1.to_string().len());
493-
494-
output_string.push_str(
495-
&[
496-
&name,
497-
&name_padding,
498-
" ",
499-
&v1.to_string(),
500-
&current_version_padding,
501-
" ",
502-
&v2.to_string(),
503-
"\n",
504-
]
505-
.concat(),
506-
);
507-
}
508-
509-
output_string
433+
fn pretty_print_version_updates(versions: dependency::PackageVersionDiffs) -> EcoString {
434+
let versions = format_versions_and_extract_longest_parts(versions);
435+
space_table(&["Package", "Current", "Latest"], &versions)
510436
}
511437

512438
async fn add_missing_packages<Telem: Telemetry>(
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
---
22
source: compiler-cli/src/dependencies/tests.rs
3+
assertion_line: 1349
34
expression: output
5+
snapshot_kind: text
46
---
57
The following dependencies have new major versions available:
68

7-
gleam_stdlib 0.45.0 -> 1.0.0
8-
short_name 1.0.0 -> 2.0.0
9-
very_long_package_name 18.382.43 -> 19.0.38
9+
Package Current Latest
10+
------- ------- ------
11+
gleam_stdlib 0.45.0 1.0.0
12+
short_name 1.0.0 2.0.0
13+
very_long_package_name 18.382.43 19.0.38

compiler-cli/src/dependencies/tests.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ fn list_manifest_format() {
5656
list_manifest_packages(&mut buffer, manifest).unwrap();
5757
assert_eq!(
5858
std::str::from_utf8(&buffer).unwrap(),
59-
"root\t1.0.0
60-
aaa\t0.4.2
61-
zzz\t0.4.0
59+
"Package Version
60+
------- -------
61+
root 1.0.0
62+
aaa 0.4.2
63+
zzz 0.4.0
6264
"
6365
)
6466
}

compiler-cli/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ mod publish;
7474
mod remove;
7575
pub mod run;
7676
mod shell;
77+
mod text_layout;
7778

7879
use config::root_config;
7980
use fs::{get_current_directory, get_project_root};

compiler-cli/src/text_layout.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use ecow::EcoString;
2+
3+
/// Generates a string delimeted table with 2 spaces between each column, columns padded with
4+
/// enough spaces to be aligned, and hyphens under the headers (excluding the final column of each
5+
/// row). Rows should have the right number of columns.
6+
///
7+
/// ## Example
8+
///
9+
/// ```txt
10+
/// Package Current Latest
11+
/// ------- ------- ------
12+
/// wibble 1.4.0 1.4.1
13+
/// wobble 1.0.1 2.3.0
14+
/// ```
15+
///
16+
pub fn space_table<Grid, Row, Cell>(headers: &[impl AsRef<str>], data: Grid) -> EcoString
17+
where
18+
Grid: AsRef<[Row]>,
19+
Row: AsRef<[Cell]>,
20+
Cell: AsRef<str>,
21+
{
22+
let mut output = EcoString::new();
23+
24+
let mut column_widths: Vec<usize> =
25+
headers.iter().map(|header| header.as_ref().len()).collect();
26+
27+
for row in data.as_ref() {
28+
for (index, cell) in row.as_ref().iter().enumerate() {
29+
if let Some(width) = column_widths.get_mut(index) {
30+
let cell = cell.as_ref();
31+
*width = (*width).max(cell.len());
32+
}
33+
}
34+
}
35+
36+
for (index, header) in headers.iter().enumerate() {
37+
if index > 0 {
38+
output.push_str(" ");
39+
}
40+
let header = header.as_ref();
41+
output.push_str(header);
42+
// Add padding only if this is NOT the final column
43+
if index < headers.len() - 1 {
44+
let padding = column_widths[index] - header.len();
45+
if padding > 0 {
46+
output.push_str(&" ".repeat(padding));
47+
}
48+
}
49+
}
50+
output.push('\n');
51+
52+
for (index, header) in headers.iter().enumerate() {
53+
if index > 0 {
54+
output.push_str(" ");
55+
}
56+
let header = header.as_ref();
57+
output.push_str(&"-".repeat(header.len()));
58+
if index < headers.len() - 1 {
59+
let padding = column_widths[index] - header.len();
60+
if padding > 0 {
61+
output.push_str(&" ".repeat(padding));
62+
}
63+
}
64+
}
65+
output.push('\n');
66+
67+
for row in data.as_ref() {
68+
for (index, cell) in row.as_ref().iter().enumerate() {
69+
if index > 0 {
70+
output.push_str(" ");
71+
}
72+
let cell = cell.as_ref();
73+
output.push_str(cell);
74+
if index < headers.len() - 1 {
75+
let padding = column_widths[index] - cell.len();
76+
if padding > 0 {
77+
output.push_str(&" ".repeat(padding));
78+
}
79+
}
80+
}
81+
output.push('\n');
82+
}
83+
84+
output
85+
}

0 commit comments

Comments
 (0)