Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

list output column misalignment #412

Open
1 task done
hsingll opened this issue Sep 9, 2021 · 4 comments
Open
1 task done

list output column misalignment #412

hsingll opened this issue Sep 9, 2021 · 4 comments

Comments

@hsingll
Copy link

hsingll commented Sep 9, 2021

Your Environment

  • mas version:stable 1.8.3
  • macOS version (system_profiler SPSoftwareDataType -detailLevel mini): 10.15.7 (19H1323)

mas Install Method

  • brew install mas (homebrew-core)

Describe the Bug

mas list command output disalignment.

To Reproduce

Steps to reproduce the behavior:

  1. install software above.

Screenshots, Terminal Output

If applicable, add screenshots to help explain your problem.

Snipaste_2021-09-09_10-30-09

$ mas list
...
@hsingll hsingll changed the title 🐛 [BUG] 🐛 [BUG]mas list command output disalignment. Sep 9, 2021
@drewauff
Copy link

drewauff commented Oct 1, 2021

This is much worse when piping through fzf. column -t "fixes" this a little but everything is so spread out.

@rgoldberg rgoldberg changed the title 🐛 [BUG]mas list command output disalignment. list output column misalignment Sep 14, 2024
@rgoldberg rgoldberg self-assigned this Sep 18, 2024
@rgoldberg rgoldberg added this to the 1.8.7 milestone Sep 18, 2024
@rgoldberg
Copy link
Contributor

rgoldberg commented Sep 22, 2024

@mas-cli/contributors

TL;DR: solution:

mas should be a shell script that calls a Swift executable that outputs only JSON (let's call it mas-json for now).

All formatting of output should be done by the mas script.

Users can configure the output via environment variables.

e.g., when mas list is called, it will run something like the following (the real script would use an environment variable with a default if it isn't set, but I'm keeping the example simple):

mas-json list | jq -r '(.[] | [.id, .name, .version]) | @tsv' | column -ts $'\t' -R 1

mas-json list outputs the JSON for the installed apps to stdout.

jq -r '(.[] | [.id, .name, .version]) | @tsv' outputs the id, name & version of each element of the JSON array (i.e. of each installed app) to stdout as a tab separated line.

column -ts $'\t' -R 1 right justifies the first column (id), and creates a properly spaced table from the tab-separated output of jq.

The mas brew formula would depend on jq & util-linux, because jq doesn't come with macOS & column from macOS doesn't support right justification (at least the versions I've seen).

Example except from proposed mas script:

#!/usr/bin/env zsh

case "${1}" in
	list)
		eval "mas-json ${@} ${MAS_LIST_FORMAT-| jq -r '${MAS_LIST_FORMAT_JQ:-(.[] | [.id, .name, .version])} | @tsv' | column -ts $'\t' ${MAS_LIST_FORMAT_COLUMNS--R 1}}"
		;;
	*)
		mas-json "${*}"
		;;
esac

The above uses the following environment variables to reconfigure output:

  • MAS_LIST_FORMAT configures the whole output (needn't be piped to jq or column), which overrides all other formatting environment variables
  • MAS_LIST_FORMAT_JQ configures the tab-separated output of jq with jq's proprietary syntax. Mainly used to select which fields to output, and in which order, but can do other things.
  • MAS_LIST_FORMAT_COLUMNS configures the tabular output of column with column's options. Mainly used to select which columns to right justify.

Reasons why the above solution is advisable:

It is basically impossible to determine the displayed or occupied widths of characters in Swift because:

  • no existing library to do so that I've found (iTerm 2 has some code, but it probably only applies to iTerm 2, and probably isn't always correct)
  • mas Swift code doesn't have access to the terminal itself, it just outputs to stdout, while the column command has access to the terminal, so it can easily space out columns.
  • different terminal apps might have completely different outputs
  • different versions of the same terminal app might have completely different outputs
  • different fonts used by a terminal app might have completely different outputs
  • various combining characters interact with other characters in weird ways
  • carious characters have different displayed & occupied widths (if displayed is wider than occupied, the wide character is superimposed over subsequent characters), so you need to keep track of both values
  • various terminals have bugs in how they handle various characters
  • much more complexity

UNIX principle: Do one thing very well / separate concerns; in this case, i.e. separate data from display. Users could completely change the display however they want. It's much easier to parse JSON than text that was attempted to be formatted into columns. Also, the JSON can include many fields that aren't displayed by default, so users can choose or remove columns easily, apply text colors or other formatting, etc.

@rgoldberg rgoldberg removed this from the 1.8.7 milestone Sep 22, 2024
@phatblat
Copy link
Member

My worry about this project providing a user-editable mas script front-end is how would Homebrew install this script? I don't know if a formula can install a script that isn't overwritten on every update. If the new mas script is customized by users but then overwritten by every update, that would undermine the value of being able to customize the script.

I'm not opposed to the idea of a new front-end script, just calling out a potential snag that needs to be investigated.

Many CLI tools have an optional JSON output by passing a --json flag. Homebrew even has two versions of its JSON output format. This type of dual output formatting (see #190) is what I've figured mas would do eventually, but have never had the time to implement it myself.

@rgoldberg
Copy link
Contributor

rgoldberg commented Oct 26, 2024

I wasn't planning on having users normally edit the script. It was more if they wanted to edit it, then they could, then submit changes to the repo.

But, we should be able to offer enough config options via environment variables or just allowing them to pipe JSON to jq or to some other command to format output however they see fit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants