bat icon indicating copy to clipboard operation
bat copied to clipboard

FR: use different style when showing multiple files, one file, (maybe) piped input

Open ilyagr opened this issue 5 months ago • 1 comments

Request

Currently, there is a --style=auto option for using the "full" style when showing files and the "plain" style when showing piped input.

Instead, I would like to use my preferred style (--style header,grid) when showing multiple files, and to use the plain style when showing piped input or one file from the command line.

Possible design

The most obvious (to me) approach would be to have three new options: --style-single-file, --style-stdin, and --style-multiple-files, which would each override --style in the relevant situation.

A corner case is what to do for

echo qq | bat -

I'd use --style-stdin here, it's more consistent with bat and bat - behaving the same. OTOH, --style-single-file would also be OK and slightly more consistent with the next corner case I describe below.

Another corner case is

echo qq | bat - filename

My preference would be to use --style-multiple-files for both STDIN and the filename. Using different styles on different files printed together would look weird.

Alternative possibilities

We could also implement slightly less (for now) and have just two options, --style-multiple-files and --style-single-file, where the latter is applied to piped input as well (except for the echo qq | bat - filename case). I think I'd personally be just as happy with this as I'd be with implementing three options. This would not allow expressing --style=auto with the new options.

My original idea was to ask merely for using my preferred style on files and using the plain style when showing piped input. That would also be an improvement, though I then realized what I really care about is whether multiple files are shown.

ilyagr avatar Oct 05 '25 18:10 ilyagr

I think maybe it'd help to suggest the actual values that we would put in those as an example of use

To give an example myself, I could achieve behaviour more like head/tail with these settings:

  • --style-single-file: plain
  • --style-stdin: plain
  • --style-multi-file: header
louis 🚶 ~/dev/bat $ bat --style=plain a.py
1
louis 🚶 ~/dev/bat $ bat --style header a.py b.py 
File: a.py
1

File: b.py
2
louis 🚶 ~/dev/bat $ head a.py
1
louis 🚶 ~/dev/bat $ head a.py b.py
==> a.py <==
1

==> b.py <==
2

As opposed to the current typical settings which are all the same (all auto, which looks like default)

louis 🚶 ~/dev/bat $ bat a.py 
─────┬──────────────────────────────────────────────────────────────────────────────────────────
     │ File: a.py
─────┼──────────────────────────────────────────────────────────────────────────────────────────
   1 │ 1
─────┴──────────────────────────────────────────────────────────────────────────────────────────
louis 🚶 ~/dev/bat $ bat a.py b.py 
─────┬──────────────────────────────────────────────────────────────────────────────────────────
     │ File: a.py
─────┼──────────────────────────────────────────────────────────────────────────────────────────
   1 │ 1
─────┴──────────────────────────────────────────────────────────────────────────────────────────
─────┬──────────────────────────────────────────────────────────────────────────────────────────
     │ File: b.py
─────┼──────────────────────────────────────────────────────────────────────────────────────────
   1 │ 2
─────┴──────────────────────────────────────────────────────────────────────────────────────────
louis 🚶 ~/dev/bat $ cat a.py | bat -
─────┬──────────────────────────────────────────────────────────────────────────────────────────
     │ STDIN
─────┼──────────────────────────────────────────────────────────────────────────────────────────
   1 │ 1
─────┴──────────────────────────────────────────────────────────────────────────────────────────

i.e. you would pass them as

bat --style-single-file=plain --style-stdin=plain --style-multifile=auto

in which case you would only actually need to pass two

bat --style-single-file=plain --style-stdin=plain

So that suggests to me that another way to do this would be a sort of notion of 'profiles', which would be a hashmap (key:value) arg type, maybe instead named --style-contexts or --style-ctx and with colon-separated key:values and comma separating both the keys and the values (i.e. allow specifying duplicate keys from the same multi-styled value)

You'd have to allow it to be passed multiple times (I think adding a further level of conjoined string would be a step too far) but if you were re-applying a style to multiple contexts (as would be typical) it'd be simplified by the comma-separated context names.

Currently, there is a --style=auto option for using the "full" style when showing files and the "plain" style when showing piped input.

I would like to use my preferred style (--style header,grid) when showing multiple files, and to use the plain style when showing piped input or one file from the command line.

So it'd be

bat --style-ctx=single,stdin:plain --style-ctx=multi:header,grid

I think for a context name a smaller name would be preferable

  • --style-ctx
    • instead of --style-contexts
  • single
    • instead of single-file
  • multi
    • instead of multiple-file
  • pipe
    • instead of stdin (more legible, as well as fewer chars? or no need since filename is displayed as "STDIN"?)

Other comments

  • I agree this should be opt-in (new flag/s) rather than change auto behaviour. Let users who want this explicitly configure it.
  • Also add BAT_STYLE_CTXS env var
  • Yes to both those corner cases piping to bat - (stdin/pipe) and bat - filename (multi) 👍
  • I would prefer to add this as a single flag named either --style-ctx or --style-context as 3 flags seems to be adding a relatively large amount of 'surface area' to the CLI for one feature (hence 3 env vars, etc)
  • Setting the style this way should be seen as equivalent to setting via CLI flag (so if the style in context is not auto then the auto behaviour should not be expected, the only thing that comes to mind RE: this is piping behaviour, as is already documented)

lmmx avatar Oct 19 '25 23:10 lmmx