Comments (12)
On #10, @xenocons said:
@dungpa I like that preferences section, a lot could be added (especially this parenthesis reduction). I am also wondering:
- With curly braces is it criminal to keep them on the same line as the function name? e.g:
let arec = {
x = 1
y = 2
}
You don't gain or lose a line, but what you do gain is less indentation so you save page width space.
- What are your thoughts on vertical alignment? It costs you page width but can make the code more readable. e.g.
let saturn = {
X = 8.343366718
Y = 4.124798564
Z = -0.4035234171
VX = -0.002767425107 * daysPerYear
VY = 0.004998528012 * daysPerYear
VZ = 2.304172976e-05 * daysPerYear
Mass = 0.0002858859807 * solarMass
}
I couldn't get github to indent my record elements sorry! but hopefully you get the idea.
from fantomas.
Answer:
-
I don't think it is a good idea. A more common style I saw is
let s = seq { for i in 1..4 -> i * i }
where there is an indentation on inner constructs. The argument is if you remove brackets, indentation is still correct.
-
From tool implementer 's point of view, alignment is possible for
=
but not possible for numbers and*
. The reason is that appearance of=
is fixed while you don't know whether you will use numbers or*
in record fields or not.
I'm still not convinced that field alignment should be supported. Hope to hear other voices on this.
from fantomas.
+1 for
let s = seq {
for i in 1..4 -> i * i
}
Space between function/class name and the the open parenthesis:
let f(x: int) = x
type t(x : int) =
class
end
->
let f (x: int) = x
type t (x: int) =
class
end
Space before constructor arguments:
type t (x : int) =
class
end
->
type t (x: int) =
class
end
Do not separate one-liners with an empty line:
let b = a |> Option.map ((*) 3)
let b' = ((*) 3) <!> a
->
let b = a |> Option.map ((*) 3)
let b' = ((*) 3) <!> a
Do not break short list/array/seq declarations:
let files =
["c:\\Test1.txt"
"c:\\Test2.txt"]
->
let files = [ "c:\\Test1.txt"; "c:\\Test2.txt" ]
from fantomas.
@vasily-kirichenko Your 2nd and 3rd examples are achieved by setting SpaceBeforeArgument = true
and SpaceBeforeColon = false
. I will update type constructors' arguments soon to be consistent with function arguments.
Regarding your 4th example, it's not cheap to test for one-liners, so I defer it for now. I will come back to it when I have a chance to implement.
About the last example, it is already working for numbers. It's harder for strings since strings could be multiple lines and there are several kinds of strings (verbatim, triple-quote, multiline ones, etc) so it's not easy to implement it. But of course, I would also like to do so as soon as I can.
from fantomas.
OK, 2 and 3 really work :) Thanks.
Some more suggestions:
- Do not realign one-line type declarations if they fit into
Config.PageWidth
// current
type R =
{ F1: int;
F2: string }
type U =
| C1
| C2
| C3
// desired
type R = { F1: int; F2: string }
type U = C1 | C2 | C3
- Surround with blank lines those type members that are more than one line long
// current
type C () =
let x = 1
let y = 3
let f () =
let x = 1
let y = 2
x + y
let z = 4
// desired
type C () =
let x = 1
let y = 3
let f () =
let x = 1
let y = 2
x + y
let z = 4
- Preserve try...with...finally one-liners
// current
let f () =
try
1 + 1
|> ignore
with
| _ -> ()
// desired
let f () = try 1 + 1 |> ignore with _ -> ()
from fantomas.
-
3rd example:
Again it's the matter of detecting one-liners. I'll keep an eye on this. -
2nd example:
I'll implement it in v0.9.2. Now it's clear to me what the requirement is. -
1st example:
The reason we always give a line break is thattype U = C1 | C2 | C3 member _.Val = ()
fails to compile (you need to add
with
beforemember
) whiletype U = | C1 | C2 | C3 member _.Val = ()
does.
Should I include a line break if type declaration contains members and write them one-liner if not?
The fields could be written in the same line. I just wonder what are qualified for one-liner declaration? In case of DUs, are those the ones that can easily be converted to enums?
from fantomas.
Interesting, I didn't know about differences between "with member..." and just "member". So, I suggest the following:
// UNFORMATTED
type U1 =
| C1
| C2
| C3
member __.Val = ()
type U2 = C1 | C2 | C3
with member __.Val = ()
type U3 =
C1 | C2 | C3
member __.Val = ()
type U4 = C1 | C2 | C3
type U5 = C1 | C2 | C3 // when it exceeds PageWidth
// FORMATTED
// not touch
type U1 =
| C1
| C2
| C3
member __.Val = ()
// add a a line brake and remove "with"
type U2 =
C1 | C2 | C3
member __.Val = ()
// not touch
type U3 =
C1 | C2 | C3 // or | C1 | C2 | C3 - not sure what is better
member __.Val = ()
// not touch
type U4 = C1 | C2 | C3
// add a line break
type U5 =
| C1
| C2
| C3
from fantomas.
The problem is that U1
, U2
and U3
have the same parse tree. It makes sense to choose one format that works for every case.
According to current implementation, when U5
exceeds one line, it will be transform into something like
type U5 = | C1 | C2
| C3
I'm not sure it is a good thing to implement.
If we would like to estimate lengths of all cases and write each in a separate line, a major change is needed.
from fantomas.
Another suggestion. Do not rearrange multi-line expression if it's splitted by operators:
// current
let form =
Formlet.Yield (fun x y -> x + " " + y) <*> Controls.Select 0 ["p1", "1"
"p2", "2"] <*> Controls.Input ""
|> Enhance.WithLegend "Label"
// desired
let form =
Formlet.Yield (fun x y -> x + " " + y)
<*> Controls.Select 0 ["p1", "1"; "p2", "2" ]
<*> Controls.Input ""
|> Enhance.WithLegend "Label"
from fantomas.
Thanks for the suggestion. What is your definition of multi-line expression?
In your example, only Controls.Select
is a multi-line expression. If we treat it differently, we arrive at
let form =
Formlet.Yield (fun x y -> x + " " + y)
<*> Controls.Select 0 ["p1", "1";
"p2", "2" ] <*> Controls.Input ""
|> Enhance.WithLegend "Label"
Your desired example can be achieved by using <*>
as a multi-line operator. The problem is that some time users would like it to be multi-line, sometimes they don't.
At the moment, we have a fixed set of multi-line operators which consists of only piping operators (|>
, ||>
, etc) (see https://github.com/dungpa/fantomas/blob/master/src/Fantomas/FormatConfig.fs#L288).
Should I expose this set as a configuration and let users add new infix operators if they want?
from fantomas.
I think the root of this issue is that Fantomas
does not respect initial format at all (it looses it when transforms the code into AST). I don't think that configurable list of supported infix operators is a good solution.
The proper solution, I think, is taking into account the initial format, i.e., if the user use an operator as multi-line one, Fantomas
should preserve it; if do not, then break long lines to fit into PageWidth
(preferring infix operators as points to break, if possible).
from fantomas.
I understand the limitation. I explained it in my blog post http://lonelypad.blogspot.dk/2013/04/developing-source-code-formatter-for-f.html
I tried to find references for solving formatting problems for whitespace-sensitive languages but I had no luck. As much as I like a full-range solution, it isn't practical yet. In this regard, F# suffers from the same problem as Python does.
The solution would be a clever mixture of lexer-based and parser-based approach. Until we sort out the solution, the goal is to format all F# constructs in a consistent and correct way.
from fantomas.
Related Issues (20)
- Add doc comments in SyntaxNode.fs giving an example of what each node looks like
- Process is reserved keyword
- Unable to format Fable line (cannot determine if Expr Paren Fantomas.Core.SyntaxOak+ExprParenNode is uppercase or lowercase) HOT 2
- Trivia after mutable keyword is missing HOT 1
- Formatting can depend on cursor position HOT 4
- Misplaced comment in "else if" HOT 3
- Fantomas does not support extended interpolated strings HOT 4
- Many Ifdefs seem to cause parse error HOT 1
- Unmatched '{' error when formatting the code HOT 2
- Using `--check` gives error "todo WhileBang" HOT 9
- Breaks shorthand lambda atomicity for lowercase method invocations
- Consider relaxing ASTTransformer treatment of ranges in record fields HOT 1
- Unable to format F# 8 extended interpolated strings with curly braces HOT 3
- Move editor config to library rather than tool HOT 6
- "Incomplete declaration of a static construct" which the F# compiler accepts HOT 2
- Multiline secondary constructor HOT 4
- Equals sign should only be on same line if last tuple is multiline HOT 2
- Return type should go on next line
- Invalid F# code after formatting HOT 1
- Formatting removes necessary additional closing brackets for multiline interpolated strings HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fantomas.