Open edemaine opened 8 months ago
Preferred "no implicit return" style: :void vs. trailing comma.
Comma? Not semicolon?
A couple other rules I thought of:
->
vs =>
) for functions that don't use this
. this
checking would need to be recursive for nested =>
but not nested ->
function f()
vs f := ->
){ f() {} }
vs f: ->
)Are you conceiving of the rule list posted here as a list of options that the user of the formatter can go either way on, or are you seeking a One True Civet Format in which the formatter would embody one specific choice on each option (i.e., be "opinionated" in the sense of Prettier)? I ask because in one project I worked on, we all hated one or two of Prettier's choices enough that we invested a fair amount of time in tooling that ran Prettier and then eslint -fix to undo what we saw as a couple bad choices by the creators of Prettier. That was a pain.
Some of these would have to be configurable (maximum line length and :void
vs ;
for example). Ideally, it would be possible to turn all of these off individually, just like with ESLint.
One True Civet Format
Definitely not that. There are so many ways to do things in Civet, and different people have different preferences on what they want to use. The goal is to make these choices fully configurable, to the extent possible (unlike Prettier). We will try to choose reasonable defaults, though. Of course, it's all speculation at the moment. :-)
Civet should either gain a "formatter" mode, or its AST should become rich enough to support a separate formatter tool
Preferably the latter, and with ESLint support (https://github.com/DanielXMoore/Civet/discussions/852) ideally work with eslint --fix
.
See also ESLint Stylistic, and https://antfu.me/posts/why-not-prettier.
I doubt we'd be able to make an AST that's eslint compatible, given how different Civet is from JS. This is the approach taken by CoffeeScript, and in my experience, it's rather fragile (only works on old eslint versions), so I'd hesitate to even try here.
For this reason, I think we need to do formatting ourselves from scratch. We're planning to make it highly configurable, taking best ideas from eslint and Prettier.
On the other hand, we'd like to use existing eslint rules for semantic checks, because that could hopefully be done just on the transformed JS. Hence why this issue is about formatting only. (Of course, it's a blurry line, so maybe one day our formatter does semantic checks too. But this is all hypothetical at the moment.)
Are there any new developments in this discussion. When I try to use Civet in some projects I migrate a lot of code from the original TS. The lack of a formatting tool makes this process extremely difficult. I spend a lot of time tweaking formatting errors to fit Civet.
Civet should either gain a "formatter" mode, or its AST should become rich enough to support a separate formatter tool (probably in the same repo still, because AST changes need to be closely tied). Here are possible specific formatting rules we might aim for:
Statement
AST nodes. (Currently they are arrays[indent, exp, delim]
at specific layers of the AST.)x + 2
→x + 2
. Some of this can be done by processing_
nodes.((x)+y)
→x+y
. This might require us to actually parse binary expressions into proper ASTs, instead of the current flat representation.f(x)
vs.f x
. Obviously can only use the latter when the parens are unnecessary.:void
vs. trailingcommasemicolon.if
conditions: parenthesized vs. not.{ f() {} }
vs.f: ->
)[...]
vs. bullets (once that exists).->
vs.=>
) for functions that don't usethis
.this
checking would need to be recursive for nested=>
but not nested->
function f()
vs.f := ->
)const
/let
vs.:=
/.=
)import
style (import ... from
vs.... from
vs.from ... import
)and
vs.&&
,===
vs.is
,!==
vs.is not
/isnt
?:
vs.if
length
vs.#
<>...</>
when implicit, remove extra{}
s, preferred code block syntax"civet coffeeForLoops"
is fairly challenging but plausibly automatable.Detecting issues should be doable with the AST, possibly once it's fleshed out more. (Ideally we can do this piece by piece.) There are two possible ways to do the emit process:
then
. We've discussed this for other purposes too (#40?). Maybe something parallel totoken
likesource
... The trouble with this is that it requires a lot of work before we can get anything working.f(x)
tof x
, we find the location of(
and replace it with`, and find the location of
)` and remove it. These edits can be applied to the original source code all at once at the end, and then the file can be re-emitted. (Somewhat similar to LSP auto completions.) This is more annoying to work with, and will still require adding some Civet-only tokens that don't normally get emitted, but it's easier to get started with.By contrast, I don't think Civet should gain a full "lint" mode that tests for bugs. See Prettier on formatting vs. code-quality rules. I think ideally the output of Civet would be compatible with most eslint code-quality rules, so we can use eslint directly for those. But formatting is fundamentally tied to the Civet source, not the generated JS/TS.
This post distills Discord discussion with @bbrk24.