Repository: TypeScript
Issue: [CLI DX] Improve positioning of compiler error messaging info
Labels: Help Wanted,Discussion,Good First Issue,Experience Enhancement,Effort: Casual

_Note_: This is still up for debate, but we think this is a pretty strong contender to ship. We may still change our minds on details. So, if you give it a shot, expect some of us to come in and maybe make changes at the end of the PR's lifecycle.

# Suggestion

As of 4.4, a run of `tsc` looks like:

```sh
$ /Users/ortatherox/dev/typescript/repros/compilerSamples/node_modules/.bin/tsc
index.ts:2:1 - error TS2588: Cannot assign to 'a' because it is a constant.

2 a = "123"
  ~

index.ts:4:1 - error TS2588: Cannot assign to 'a' because it is a constant.

4 a = 543
  ~
```

I propose instead we make the output terminal length aware, and by using that information we change the whitespace and positioning of the different pieces of information. 

#### Example

```
$ /Users/ortatherox/dev/typescript/repros/compilerSamples/node_modules/.bin/tsc
● index.ts:2:1                                                                       TS2720
  | a = "123"                                                                              
    ▔                                                      
  Cannot assign to 'a' because it is a constant.                                           
                                                                                           
● index.ts:4:1                                                                       TS2720
  | a = 543                                                                                
    ▔                                                                                        
  Cannot assign to 'a' because it is a constant.                                           
``` 

This change _does not_ add any new lines to the output. There's a reasonable argument that we might want an extra new-line between the location and source code though, might have to get a feel for this in prod. We also switch from `~` to `▔` to "fake" a full linebreak. 

#### Details

We take into account the knowledge about the width of the current terminal in order to provide more space between the key elements of the TS output. 

- ● is a sigil per-compiler message, and lives on its own column. This means you can easily see when compiler messages start/end

- The `TS1234` error message is de-empathized and moved to the right, these messages are useful for searching the internet for similar problems but are less valuable for understanding the errors. I dropped 'error' from that message because aside from #45714 we always show errors here.

- Code is moved above the error message. There's two ideas in play here:
  1. We don't need to repeat the location information by placing the location and source code next to each other. That also means that the code samples are in a consistent location because the length of the line number does not affect how far right we show the source code.
  2. The line of code is one of the best ways to get context before you read the error message, so IMO having it first makes a bit more sense than after. I have a sense of the cases when it does not, and I have ideas to address that in another issue later.

## Notes

We had a lot of design experiments ranging from [rust-y](https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html), eslint-y, [errata-y](https://twitter.com/firstdrafthell/status/1427364851593224197), [miette-y](https://lib.rs/crates/miette) but we've got quite a lot of backwards compatibility guarantees to keep and this proposal is about the wrapping to the error messaging - and it leaves individual error messages to be able to do a better job of giving context.

We want these to be safe to copy & paste (it should be better now the message is on its own lines) and parsable via [regexes](https://github.com/actions/toolkit/blob/main/docs/problem-matchers.md#multiline-matching) for things like problem matchers (though they now need to be multi-line to grab the message)

## Exceptions

If we do not know the width of the terminal _or it is too thin_ ( < 60 cols) then we drop all fancy re-ordering and leave it to your terminal to handle. This means: 

- The TS#### is moved to be a space after the location
- We don't indent the code/message

```
$ /Users/ortatherox/dev/typescript/repros/compil
erSamples/node_modules/.bin/tsc
● index.ts:2:1 TS2720
| a = "123"                                                                              
  ▔                                                      
Cannot assign to 'a' because it is a constant.                                           
                                                                                           
● index.ts:4:1 TS2720
| a = 543                                                                                
  ▔                                                                                        
Cannot assign to 'a' because it is a constant.                                           
```