From d42a1565b1b7c532e3dbeaaa4ec0f0cb5ba79f69 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Mon, 20 Jul 2020 10:56:02 +0200 Subject: [PATCH] Add documentation for v4 (#971) * WIP document settings * Some more settings documented * Finished writing documentation. * Add documentation for fsharp_align_function_signature_to_indentation and fsharp_alternative_long_member_definitions. * Add release notes for v4 beta 1. * Add last fix before beta --- RELEASE_NOTES.md | 122 ++- docs/Documentation.md | 968 ++++++++++++++---- .../Fantomas.CoreGlobalTool.Tests.fsproj | 2 +- .../Fantomas.CoreGlobalTool.fsproj | 2 +- src/Fantomas.Tests/Fantomas.Tests.fsproj | 2 +- ...ormatConfigEditorConfigurationFileTests.fs | 6 + src/Fantomas/Fantomas.fsproj | 2 +- 7 files changed, 873 insertions(+), 231 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d3b04c15d4..64ce38bf9e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,121 @@ -### 4.0.0-alpha-014 - 07/2020 -* WIP for [#705](https://github.com/fsprojects/fantomas/issues/705) -* FCS 36.0.3 -* Replaced json configuration with .editorconfig +### 4.0.0-beta-001 - 07/2020 + +* Update FCS to 36. [#899](https://github.com/fsprojects/fantomas/pull/899), [#961](https://github.com/fsprojects/fantomas/pull/961) +* Replaced json configuration with .editorconfig. [#650](https://github.com/fsprojects/fantomas/issues/650) +* Sunset setting ReorderOpenDeclaration. [#645](https://github.com/fsprojects/fantomas/issues/645) +* Sunset setting KeepNewlineAfter. [#737](https://github.com/fsprojects/fantomas/issues/737) +* Renamed setting IndentSpaceNum to IndentSize. [#940](https://github.com/fsprojects/fantomas/pull/940) +* Renamed setting PageWidth to MaxLineLength. [#940](https://github.com/fsprojects/fantomas/pull/940) +* Removed all style configuration options from CLI tool. [#704](https://github.com/fsprojects/fantomas/issues/704) +* Added [Benchmarks](https://fsprojects.github.io/fantomas/). [#867](https://github.com/fsprojects/fantomas/issues/867) +* Split up setting SpaceBeforeArgument to multiple settings. [#649](https://github.com/fsprojects/fantomas/pull/649) + - SpaceBeforeParameter + - SpaceBeforeLowercaseInvocation + - SpaceBeforeUppercaseInvocation + - SpaceBeforeClassConstructor + - SpaceBeforeMember +* Increase control over length of certain code constructs. [#697](https://github.com/fsprojects/fantomas/issues/697) + - MaxRecordWidth + - MaxArrayOrListWidth + - MaxValueBindingWidth + - MaxFunctionBindingWidth + - MaxElmishWidth +* Better support for Elmish inspired code. [#922](https://github.com/fsprojects/fantomas/pull/922) +* Feature SingleArgumentWebMode. [#927](https://github.com/fsprojects/fantomas/issues/927) +* Feature AlignFunctionSignatureToIndentation. [#946](https://github.com/fsprojects/fantomas/issues/946) +* Feature AlternativeLongMemberDefinitions. [#913](https://github.com/fsprojects/fantomas/issues/913) +* Feature MultilineBlockBracketsOnSameColumn. [#453](https://github.com/fsprojects/fantomas/issues/453) +* Feature NewlineBetweenTypeDefinitionAndMembers. [#752](https://github.com/fsprojects/fantomas/issues/752) +* Feature KeepIfThenInSameLine. [#825](https://github.com/fsprojects/fantomas/issues/825) +* Fix List expression can get combined to a single line with different semantics. [#931](https://github.com/fsprojects/fantomas/issues/931) +* Fix Additional new line inserted around attributes. [#949](https://github.com/fsprojects/fantomas/issues/949) +* Fix `with get` removal in FSI invalid. [#945](https://github.com/fsprojects/fantomas/issues/945) +* Fix FSI file has "abstract" stripped. [#944](https://github.com/fsprojects/fantomas/issues/944) +* Fix Insertion of space before function application can break dot-chaining. [#943](https://github.com/fsprojects/fantomas/issues/943) +* Fix Concatenation of lines can break operator precedence. [#942](https://github.com/fsprojects/fantomas/issues/942) +* Fix Extra spaces inserted in record definition. [#941](https://github.com/fsprojects/fantomas/issues/941) +* Fix Comments at the end of async blocks are deleted automatically. [#936](https://github.com/fsprojects/fantomas/issues/936) +* Fix Newline between comments should lead to individual comments. [#920](https://github.com/fsprojects/fantomas/issues/920) +* Fix VS Code | Extra white space added to record definition. [#910](https://github.com/fsprojects/fantomas/issues/910) +* Fix When cutting off function invocations, should place each param in its own line (or align them to the 1st param). [#907](https://github.com/fsprojects/fantomas/issues/907) +* Fix Try online link points to old location. [#890](https://github.com/fsprojects/fantomas/issues/890) +* Fix Leading `|` in single-case union type with access modifier. [#889](https://github.com/fsprojects/fantomas/issues/889) +* Fix Type constraint on a type definition causes a loss of the type definition. [#887](https://github.com/fsprojects/fantomas/issues/887) +* Fix Fantomas removes the 'and' if there are multiple member constraints on a function declaration. [#886](https://github.com/fsprojects/fantomas/issues/886) +* Fix Comments inside a type definition can cause issues. [#885](https://github.com/fsprojects/fantomas/issues/885) +* Fix Long function signature should align with equal sign. [#883](https://github.com/fsprojects/fantomas/issues/883) +* Fix Newline not preserved between let and let bang. [#879](https://github.com/fsprojects/fantomas/issues/879) +* Fix Stackoverflow problem with let bang in match. [#876](https://github.com/fsprojects/fantomas/issues/876) +* Fix Incorrect formatting for chained class members using Websharper. [#871](https://github.com/fsprojects/fantomas/issues/871) +* Fix Pipe before and inside lambda leads to wrong indent of following lambda. [#870](https://github.com/fsprojects/fantomas/issues/870) +* Fix Formatting Program.fs with `--check` fails. [#869](https://github.com/fsprojects/fantomas/issues/869) +* Fix Possible wrong indentation for functions with parameters over multiple lines. [#868](https://github.com/fsprojects/fantomas/issues/868) +* Fix Invalid unit test ``different attributes according to defines``. [#864](https://github.com/fsprojects/fantomas/issues/864) +* Fix Invalid unit test ``record instance with inherit keyword``. [#861](https://github.com/fsprojects/fantomas/issues/861) +* Fix Invalid unit test ``should add space before type provider params``. [#859](https://github.com/fsprojects/fantomas/issues/859) +* Fix Incorrect end of line added after "(" which makes the code not to compile. [#856](https://github.com/fsprojects/fantomas/issues/856) +* Fix Incorrect end of line added after "(". [#855](https://github.com/fsprojects/fantomas/issues/855) +* Fix SpaceBeforeUppercaseInvocation applied in the middle of a invocation chain. [#853](https://github.com/fsprojects/fantomas/issues/853) +* Fix MultilineBlockBracketsOnSameColumn not working properly when calling base constructors. [#852](https://github.com/fsprojects/fantomas/issues/852) +* Fix PageWidth not respected for member with one long parameter. [#850](https://github.com/fsprojects/fantomas/issues/850) +* Fix Wrong indentation in member definition. [#844](https://github.com/fsprojects/fantomas/issues/844) +* Fix Class type with long variable names results in invalid formatted F# code. [#841](https://github.com/fsprojects/fantomas/issues/841) +* Fix Multiline let bang should have newline before. [#838](https://github.com/fsprojects/fantomas/issues/838) +* Fix complex computation expression identifier looks off. [#835](https://github.com/fsprojects/fantomas/issues/835) +* Fix keyword before type declaration leads to invalid F# code. [#830](https://github.com/fsprojects/fantomas/issues/830) +* Fix Inconsistent if-then-else cut. [#825](https://github.com/fsprojects/fantomas/issues/825) +* Fix MultilineBlockBracketsOnSameColumn=true not working on records with short names. [#823](https://github.com/fsprojects/fantomas/issues/823) +* Fix --config fantomas-config.json gives error. [#821](https://github.com/fsprojects/fantomas/issues/821) +* Fix multiline let bang should have a newline. [#819](https://github.com/fsprojects/fantomas/issues/819) +* Fix Updated value not indented correctly. [#817](https://github.com/fsprojects/fantomas/issues/817) +* Fix Comment removed in multi-case pattern matching. [#813](https://github.com/fsprojects/fantomas/issues/813) +* Fix Wrong handling multi lines comment at the end of file after function application. [#810](https://github.com/fsprojects/fantomas/issues/810) +* Fix Opening brace for test missing. [#806](https://github.com/fsprojects/fantomas/issues/806) +* Fix Return attribute deleted on reformatting. [#800](https://github.com/fsprojects/fantomas/issues/800) +* Fix Fantomas crash with evaluation of array member. [#798](https://github.com/fsprojects/fantomas/issues/798) +* Fix Type restrictions in FSI files. [#797](https://github.com/fsprojects/fantomas/issues/797) +* Fix AssemblyInfo.fs attributes get squashed together. [#796](https://github.com/fsprojects/fantomas/issues/796) +* Fix Byte-order mark is stripped. [#795](https://github.com/fsprojects/fantomas/issues/795) +* Fix Fantomas replaces "abstract" in fsi, leading to compile errors. [#794](https://github.com/fsprojects/fantomas/issues/794) +* Fix Broken links in Readme.md. [#791](https://github.com/fsprojects/fantomas/issues/791) +* Fix Multiline first member should not introduce initial newline. [#789](https://github.com/fsprojects/fantomas/issues/789) +* Fix Newline added before let binding with attribute in class. [#786](https://github.com/fsprojects/fantomas/issues/786) +* Fix Some floating-point numbers are changed. [#785](https://github.com/fsprojects/fantomas/issues/785) +* Fix Adding newline before first comment in module. [#784](https://github.com/fsprojects/fantomas/issues/784) +* Fix Parameter after multiline string parameter. [#783](https://github.com/fsprojects/fantomas/issues/783) +* Fix Modulo operator misplaced. [#780](https://github.com/fsprojects/fantomas/issues/780) +* Fix double-backtick identifier is formatted wrong when starts with non-alphanum character. [#776](https://github.com/fsprojects/fantomas/issues/776) +* Fix Line comment after record not printed. [#774](https://github.com/fsprojects/fantomas/issues/774) +* Fix Additional blank lines inserted after formatting. [#772](https://github.com/fsprojects/fantomas/issues/772) +* Fix Error while formatting Fantomas unit test with compiler define. [#761](https://github.com/fsprojects/fantomas/issues/761) +* Fix AbstractSlot with line comment is consider multi line. [#757](https://github.com/fsprojects/fantomas/issues/757) +* Fix Missing space after multiline string. [#754](https://github.com/fsprojects/fantomas/issues/754) +* Fix Cannot determine upper or lowercase. [#753](https://github.com/fsprojects/fantomas/issues/753) +* Fix Feature: Add blank line between type definition and members. [#752](https://github.com/fsprojects/fantomas/issues/752) +* Fix Default member implementation changed to member during formatting. [#742](https://github.com/fsprojects/fantomas/issues/742) +* Fix Long function definition should put equals and body on a newline. [#740](https://github.com/fsprojects/fantomas/issues/740) +* Fix Add extra space between prefix operator and string. [#736](https://github.com/fsprojects/fantomas/issues/736) +* Fix MaxIfThenElseShortWidth is not respected. [#734](https://github.com/fsprojects/fantomas/issues/734) +* Fix Shouldn't remove getters. [#733](https://github.com/fsprojects/fantomas/issues/733) +* Fix Comment after `then` keyword gets removed. [#730](https://github.com/fsprojects/fantomas/issues/730) +* Fix Determine if DotGet expression is upper- or lowercase. [#729](https://github.com/fsprojects/fantomas/issues/729) +* Fix Check for Trivia content before the equals sign in let bindings. [#728](https://github.com/fsprojects/fantomas/issues/728) +* Fix When advising user to file a bug, should mention the file it was trying to format. [#726](https://github.com/fsprojects/fantomas/issues/726) +* Fix space removed from parameters passed to inherited class. [#720](https://github.com/fsprojects/fantomas/issues/720) +* Fix Place parameters on a new line for very long member definitions. [#719](https://github.com/fsprojects/fantomas/issues/719) +* Fix Exception: Unexpected scenario when formatting else if / elif. [#713](https://github.com/fsprojects/fantomas/issues/713) +* Fix Fantomas keeps adding newlines every time you format. [#709](https://github.com/fsprojects/fantomas/issues/709) +* Fix Duplicate spaces and lost of linecomment. [#687](https://github.com/fsprojects/fantomas/issues/687) +* Fix Formatting of array literals of BigInteger. [#682](https://github.com/fsprojects/fantomas/issues/682) +* Fix Hash directive not between namespace and module. [#681](https://github.com/fsprojects/fantomas/issues/681) +* Fix Comment above static member is wrongly placed. [#680](https://github.com/fsprojects/fantomas/issues/680) +* Fix Do not remove property setters. [#664](https://github.com/fsprojects/fantomas/issues/664) +* Fix StringConstant printed twice. [#646](https://github.com/fsprojects/fantomas/issues/646) +* Fix Newline after "bang" keywords in computation expressions. [#615](https://github.com/fsprojects/fantomas/issues/615) +* Fix Incorrect indentation when folding a record update expression. [#536](https://github.com/fsprojects/fantomas/issues/536) +* Fix Preserve comments after record. [#516](https://github.com/fsprojects/fantomas/issues/516) +* Fix Long function signature broken into two lines. [#492](https://github.com/fsprojects/fantomas/issues/492) +* Fix "Better" support for nesting complex expressions in async { } blocks. [#386](https://github.com/fsprojects/fantomas/issues/386) ### 3.3.0 - 02/2020 diff --git a/docs/Documentation.md b/docs/Documentation.md index 694673f541..a0e03ccfd0 100644 --- a/docs/Documentation.md +++ b/docs/Documentation.md @@ -1,282 +1,804 @@ -## Fantomas: How to use +# Fantomas: How to use -### Using the command line tool +## Using the command line tool --- +Create a [.NET tool manifest](https://docs.microsoft.com/en-us/dotnet/core/tools/local-tools-how-to-use) to install tools locally +> dotnet new tool-manifest + +Install the command line tool with: +> dotnet tool install fantomas-tool + +or install the tool globally with +> dotnet tool install -g fantomas-tool + For the overview how to use the tool, you can type the command - Fantomas --help + dotnet fantomas --help + +``` +USAGE: dotnet fantomas [--help] [--recurse] [--force] [--profile] [--fsi ] [--stdin] [--stdout] [--out ] [--check] [--version] [] + +INPUT: + + Input path: can be a folder or file with *.fs,*.fsi,*.fsx,*.ml,*.mli extension. + +OPTIONS: + + --recurse, -r Process the input folder recursively. + --force Print the source unchanged if it cannot be parsed correctly. + --profile Print performance profiling information. + --fsi Read F# source from stdin as F# signatures. + --stdin Read F# source from standard input. + --stdout Write the formatted source code to standard output. + --out Give a valid path for files/folders. Files should have .fs, .fsx, .fsi, .ml or .mli extension only. + --check Don't format files, just check if they have changed. Exits with 0 if it's formatted correctly, with 1 if some files need formatting and 99 if there was an internal error + was an internal error + --version, -v Displays the version of Fantomas + --help display this list of options. + +``` You have to specify an input path and optionally an output path. The output path is prompted by `--out` e.g. - Fantomas ../../../../tests/stackexchange/array.fs --out ../../../../tests/stackexchange_output/array.fs + dotnet fantomas ../../../../tests/stackexchange/array.fs --out ../../../../tests/stackexchange_output/array.fs Both paths have to be files or folders at the same time. If they are folders, the structure of input folder will be reflected in the output one. The tool will explore the input folder recursively if you set `--recurse` option (see [Options section](#options)). If you omit the output path, Fantomas will overwrite the input files. -#### Options +## Configuration + +Fantomas ships with a series of format options. +These can be stored in an [.editorconfig](https://editorconfig.org/) file and will be picked up automatically by the commandline tool. + +A default .editorconfig file would look like +```ini +[*.fs] +indent_size=4 +max_line_length=120 +fsharp_semicolon_at_end_of_line=false +fsharp_space_before_parameter=true +fsharp_space_before_lowercase_invocation=true +fsharp_space_before_uppercase_invocation=false +fsharp_space_before_class_constructor=false +fsharp_space_before_member=false +fsharp_space_before_colon=false +fsharp_space_after_comma=true +fsharp_space_before_semicolon=false +fsharp_space_after_semicolon=true +fsharp_indent_on_try_with=false +fsharp_space_around_delimiter=true +fsharp_max_if_then_else_short_width=40 +fsharp_max_infix_operator_expression=50 +fsharp_max_record_width=40 +fsharp_max_array_or_list_width=40 +fsharp_max_value_binding_width=40 +fsharp_max_function_binding_width=40 +fsharp_multiline_block_brackets_on_same_column=false +fsharp_newline_between_type_definition_and_members=false +fsharp_keep_if_then_in_same_line=false +fsharp_max_elmish_width=40 +fsharp_single_argument_web_mode=false +fsharp_align_function_signature_to_indentation=false +fsharp_alternative_long_member_definitions=false +fsharp_strict_mode=false +``` + +### indent_size -##### `--recurse` +` indent_size` has to be between 1 and 10. -traverse the input folder recursively (if it is really a folder) to get all F# source files. +This preference sets the indentation +The common values are 2 and 4. +The same indentation is ensured to be consistent in a source file. +Default = 4. -##### `--force` +`defaultConfig` -force writing original contents to output files. -This is helpful if the tool fails on some unknown F# constructs. +```fsharp +let inline selectRandom (f: _ []) = + let r = random 1.0 -##### `--stdin` + let rec find = + function + | 0 -> fst f.[0] + | n when r < snd f.[n] -> fst f.[n] + | n -> find (n - 1) -read input from standard input. This option is convenient to use with piping + find <| f.Length - 1 +``` - echo 'open System;; let () = printfn "Hello World"' | Fantomas --stdin --out output.fs +`{ defaultConfig with IdentSize = 2 }` -or +```fsharp +let inline selectRandom (f: _ []) = + let r = random 1.0 - cat input.fs | Fantomas --stdin --out output.fs + let rec find = + function + | 0 -> fst f.[0] + | n when r < snd f.[n] -> fst f.[n] + | n -> find (n - 1) -##### `--stdout` + find <| f.Length - 1 +``` -write formatted source code to standard output e.g. - - Fantomas input.fs --stdout +### max_line_length -##### `--fsi` +`max_line_length` has to be an integer greater or equal to 60. +This preference sets the column where we break F# constructs into new lines. +Default = 120. -this option to be used with `--stdin` to specify that we are formatting F# signatures e.g. +`defaultConfig` - type input.fsi | Fantomas --fsi --stdin --stdout +```fsharp +match myValue with +| Some foo -> someLongFunctionNameThatWillTakeFooAndReturnsUnit foo +| None -> printfn "nothing" +``` -##### `--check` +`{ defaultConfig with MaxLineLength = 60 }` -Checks if the files provided require formatting and: +```fsharp +match myValue with +| Some foo -> + someLongFunctionNameThatWillTakeFooAndReturnsUnit foo +| None -> printfn "nothing" +``` -* Exits with `0` if no files require formatting -* Exits with `1` if some files require formatting. It also outputs the path of the files that require formatting. -* Exits with `99` if some files contain errors (e.g. parsing errors, etc.) +### fsharp_semicolon_at_end_of_line -For example: +Add semicolons at the end of lines. +Default = false. - # given an example project - ls src/MyProject - File1.fs # correctly formatted - File2.fs # needs formatting - File3.fs # has compilation errors +`defaultConfig` - # running a check - Fantomas --check src/MyProject - src/MyProject/File2.fs requires formatting - error: Failed to format src/MyProject/File3.fs: +```fsharp +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 } +``` - # if you check the exit code - echo $? - 99 +`{ defaultConfig with SemicolonAtEndOfLine = true }` + +```fsharp +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 } +``` -#### Preferences +### fsharp_space_before_parameter -##### `--indent ` +Add a space after the name of a function and before the opening parenthesis of the first parameter. +This setting influences function definitions. +Default = true. -`number` has to be between 1 and 10. +`defaultConfig` -This preference sets the indentation (default = 4). -The common values are 2 and 4. -The same indentation is ensured to be consistent in a source file. -To illustrate, here is a code fragment with `--indent 2`: - - ```fsharp - let inline selectRandom(f : _[]) = - let r = random 1.0 - let rec find = - function - | 0 -> fst f.[0] - | n when r < snd f.[n] -> fst f.[n] - | n -> find(n - 1) - find <| f.Length - 1 - ``` - -##### `--pageWidth ` - -`number` has to be an integer greater or equal to 60. -This preference sets the column where we break F# constructs into new lines. -The default value is 120. To see its effects, please take a look at some [output files](tests/stackexchange_output) with `--pageWidth 90` preference. - -##### `--semicolonEOL` - -add semicolons at the end of lines e.g. - - ```fsharp - 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 } - ``` - - vs. - - ```fsharp - 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 } - ``` - -##### `--spaceBeforeColon` - -if being set, there is a space before `:` e.g. - - ```fsharp - type Planet = - { mutable X: float - mutable Y: float - mutable Z: float - mutable VX: float - mutable VY: float - mutable VZ: float - Mass: float } - ``` - - vs. - - ```fsharp - type Planet = - { mutable X : float - mutable Y : float - mutable Z : float - mutable VX : float - mutable VY : float - mutable VZ : float - Mass : float } - ``` - -##### `--noSpaceAfterComma` - -is useful if you would like to save spaces in tuples, arguments, etc. -To illustrate, `(1, 2, 3)` is rewritten to `(1,2,3)`. - -##### `--noSpaceAfterSemiColon` - -saves spaces on records, arrays, lists, etc. Now - - ```fsharp - let planets = [|sun; jupiter; saturn; uranus; neptune|] - ``` - - becomes - - ```fsharp - let planets = [|sun;jupiter;saturn;uranus;neptune|] - ``` - -Note: there is also the possibility to add a space before the semicolon.
-This can be set by adding `"SpaceBeforeSemicolon": true` in a Fantomas configuration file (see below). - - ##### `--indentOnTryWith` - -if being set, `with` blocks will be indented like in the following example: - - ```fsharp - try - if System.DateTime.Now.Second % 3 = 0 - then raise(new System.Exception()) - else raise(new System.ApplicationException()) - with - | :? System.ApplicationException -> - printfn "A second that was not a multiple of 3" - | _ -> - printfn "A second that was a multiple of 3" - ``` - -##### `--noSpaceAroundDelimiter` - -saves spaces around delimiters of records, arrays, lists e.g. - - ```fsharp - let planets = [| sun; jupiter; saturn; uranus; neptune |] - ``` - - becomes - - ```fsharp - let planets = [|sun; jupiter; saturn; uranus; neptune|] - ``` - -##### `--strictMode` - -if being set, pretty printing is only done via ASTs. Compiler directives, inline comments and block comments will be ignored. - -##### `--maxIfThenElseShortWidth ` +```fsharp +let value (a:int) = x +let DumpTrace () = () +``` -`number` if being set, controls when if/then/else expressions will be formatted as single line or as multiple lines. +`{ defaultConfig with SpaceBeforeParameter = false }` -Fantomas tries to follow [the F# style guide](https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting#formatting-if-expressions) as close as possible when formatting if expressions. +```fsharp +let value(a: int) = x +let DumpTrace() = () +``` + +### fsharp_space_before_lowercase_invocation + +Add a space after the name of a lowercased function and before the opening parenthesis of the first argument. +This setting influences function invocation. +Default = true. + +`defaultConfig` + +```fsharp +value (a, b) +startTimer () +``` + +`{ defaultConfig with SpaceBeforeLowercaseInvocation = false }` + +```fsharp +value(a, b) +startTimer() +``` + +### fsharp_space_before_uppercase_invocation + +Add a space after the name of a uppercased function and before the opening parenthesis of the first argument. +This setting influences function invocation. +Default = false. + +`defaultConfig` + +```fsharp +Value(a, b) +person.ToString() +``` + +`{ defaultConfig with SpaceBeforeUppercaseInvocation = true }` + +```fsharp +Value (a, b) +person.ToString () +``` + +### fsharp_space_before_class_constructor + +Add a space after a type name and before the class constructor. +Default = false. + +`defaultConfig` + +```fsharp +type Person() = + class + end +``` + +`{ defaultConfig with SpaceBeforeClassConstructor = true } + +```fsharp +type Person () = + class + end +``` + +### fsharp_space_before_member + +Add a space after a member name and before the opening parenthesis of the first parameter. +Default = false. + +`defaultConfig` + +```fsharp +type Person() = + member this.Walk(distance: int) = () + member this.Sleep() = ignore + member __.singAlong() = () + member __.swim(duration: TimeSpan) = () +``` + +`{ defaultConfig with SpaceBeforeMember = true }` + +```fsharp +type Person() = + member this.Walk (distance: int) = () + member this.Sleep () = ignore + member __.singAlong () = () + member __.swim (duration: TimeSpan) = () +``` + +### fsharp_space_before_colon + +Add a space before `:`. +Default = false. + +`defaultConfig` + +```fsharp +type Point = { x: int; y: int } + +let update (msg: Msg) (model: Model): Model = model +``` + +`{ defaultConfig with SpaceBeforeColon = true }` + +```fsharp +type Point = { x : int; y : int } + +let update (msg : Msg) (model : Model) : Model = model +``` + +### fsharp_space_after_comma + +Adds a space after `,` in tuples. +Default = true. + +`defaultConfig` + +```fsharp +myValue.SomeFunction(foo, bar, somethingElse) +(a, b, c) +``` + +`{ defaultConfig with SpaceAfterComma = false }` + +```fsharp +myValue.SomeFunction(foo,bar,somethingElse) +(a,b,c) +``` + +### fsharp_space_before_semicolon + +Adds a space before `;` in records, arrays, lists, etc. +Default = false. + +`defaultConfig` + +```fsharp +let a = [ 1; 2; 3 ] +let b = [| foo; bar |] +type C = { X: int; Y: int } +``` + +`{ defaultConfig with SpaceBeforeSemicolon = true }` + +```fsharp +let a = [ 1 ; 2 ; 3 ] +let b = [| foo ; bar |] +type C = { X: int ; Y: int } +``` + +### fsharp_space_after_semicolon + +Adds a space after `;` in records, arrays, lists, etc. +Default = true. + +`defaultConfig` + +```fsharp +let a = [ 1; 2; 3 ] +let b = [| foo; bar |] +type C = { X: int; Y: int } +``` + +`{ defaultConfig with SpaceAfterSemicolon = false }` + +```fsharp +let a = [ 1;2;3 ] +let b = [| foo;bar |] +type C = { X: int;Y: int } +``` + +### fsharp_indent_on_try_with + +Adds an extra indent to the `with` block of a try/with expression. +Default = false. + +`defaultConfig` + +```fsharp +try + if System.DateTime.Now.Second % 3 = 0 + then raise (new System.Exception()) + else raise (new System.ApplicationException()) +with +| :? System.ApplicationException -> printfn "A second that was not a multiple of 3" +| _ -> printfn "A second that was a multiple of 3" +``` + +`{ defaultConfig with IndentOnTryWith = true }` + +```fsharp +try + if System.DateTime.Now.Second % 3 = 0 + then raise (new System.Exception()) + else raise (new System.ApplicationException()) +with + | :? System.ApplicationException -> printfn "A second that was not a multiple of 3" + | _ -> printfn "A second that was a multiple of 3" +``` + +### fsharp_space_around_delimiter + +Adds a space around delimiters like `[`,`[|`,`{`. +Default = true. + +`defaultConfig` + +```fsharp +let a = [ 1;2;3 ] +let b = [| 4;5;6 |] +``` + +`{ defaultConfig with SpaceAroundDelimiter = false }` + +```fsharp +let a = [1;2;3] +let b = [|4;5;6|] +``` -The style guide says: +### fsharp_max_if_then_else_short_width + +Fantomas by default follows the if/then/else conventions listed in the [Microsoft F# style guide](https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting#formatting-if-expressions). +There is stated: > If either cond, e1 or e2 are longer, but not multi-line: +> if cond +> then e1 +> else e2 + +This setting controls what exactly short means in terms of character count. +Default = 40. + +`defaultConfig` ```fsharp -if cond -then e1 -else e2 +if System.Char.IsUpper(c) then sprintf "_%s" (c.ToString().ToLower()) else c.ToString() ``` -But what exactly is longer right? By default Fantomas will use 40 width to determine if the expression needs to be formatted to the example above or remain as a oneliner (`if cond then e1 else e2`). +Neither of the expression is longer than the default 40 here. +`{ defaultConfig with MaxIfThenElseShortWidth = 30 }` -So if either `cond`, `e1` or `e2` is longer than `maxIfThenElseShortWidth` but not multiline, it will format on three lines. -See [unit tests](https://github.com/fsprojects/fantomas/blob/9d4b499c09a1f06f5485835817844657cc51215b/src/Fantomas.Tests/IfThenElseTests.fs#L734) for more examples. +```fsharp +if System.Char.IsUpper(c) +then sprintf "_%s" (c.ToString().ToLower()) +else c.ToString() +``` -That said, most of the preferences are very simple. -But they demonstrate the flexibility of Fantomas on a set of configurations. -More preferences will be added depending on use cases. +### fsharp_max_infix_operator_expression -##### Settings configuration +Control the maximum length for which infix expression can be on one line. +Default = 50. -Use an .editorconfig configuration file to set the formatting options. +`defaultConfig` -A default .editorconfig file would look like -```ini -[*.fs] -indent_size=4 -max_line_length=120 -fsharp_semicolon_at_end_of_line=false -fsharp_space_before_parameter=true -fsharp_space_before_lowercase_invocation=true -fsharp_space_before_uppercase_invocation=false -fsharp_space_before_class_constructor=false -fsharp_space_before_member=false -fsharp_space_before_colon=false -fsharp_space_after_comma=true -fsharp_space_before_semicolon=false -fsharp_space_after_semicolon=true -fsharp_indent_on_try_with=false -fsharp_space_around_delimiter=true -fsharp_max_if_then_else_short_width=40 -fsharp_max_infix_operator_expression=50 -fsharp_max_record_width=40 -fsharp_max_array_or_list_width=40 -fsharp_max_value_binding_width=40 -fsharp_max_function_binding_width=40 -fsharp_multiline_block_brackets_on_same_column=false -fsharp_newline_between_type_definition_and_members=false -fsharp_keep_if_then_in_same_line=false -fsharp_max_elmish_width=40 -fsharp_single_argument_web_mode=false -fsharp_strict_mode=false +```fsharp +let WebApp = + route "/ping" >=> authorized >=> text "pong" +``` + +`{ defaultConfig with MaxInfixOperatorExpression = 20 }` + +```fsharp +let WebApp = + route "/ping" + >=> authorized + >=> text "pong" +``` + +### fsharp_max_record_width + +Control the maximum width for which records should be in one line. +Default = 40. + +`defaultConfig` + +```fsharp +type MyRecord = { X: int; Y: int; Length: int } +let myInstance = { X = 10; Y = 20; Length = 90 } +``` + +`{ defaultConfig with MaxRecordWidth = 20 }` + +```fsharp +type MyRecord = + { X: int + Y: int + Length: int } + +let myInstance = + { X = 10 + Y = 20 + Length = 90 } +``` + +### fsharp_max_array_or_list_width + +Control the maximum width for which lists and arrays should be in one line. +Default = 40. + +`defaultConfig` + +```fsharp +let myArray = [| one; two; three |] +``` + +`{ defaultConfig with MaxArrayOrListWidth = 20 }` + +```fsharp +let myArray = + [| one + two + three |] +``` + +### fsharp_max_value_binding_width + +Control the maximum width for which let and member value bindings should be in one line. +Default = 40. + +`defaultConfig` + +```fsharp +let title = "Great title of project" + +type MyType() = + member this.HelpText = "Some help text" +``` + +`{ defaultConfig with MaxValueBindingWidth = 10 }` + +```fsharp +let title = + "Great title of project" + +type MyType() = + member this.HelpText = + "Some help text" +``` + +### fsharp_max_function_binding_width + +Control the maximum width for which let and member function bindings should be in one line. +Default = 40. + +`defaultConfig` + +```fsharp +let printScore score total = printfn "%i / %i" score total + +type Triangle() = + member this.CalculateSurface(width: int, height: int) = width * height / 2 +``` + +`{ defaultConfig with MaxFunctionBindingWidth = 10 }` + +```fsharp +let printScore score total = + printfn "%i / %i" score total + +type Triangle() = + member this.CalculateSurface(width: int, height: int) = + width * height / 2 ``` -### Using the API +### fsharp_multiline_block_brackets_on_same_column + +Alternative way of formatting records, arrays and lists. This will align the braces at the same column level. +Default = false. + +`defaultConfig` + +```fsharp +let myRecord = + { Level = 1 + Progress = "foo" + Bar = "bar" + Street = "Bakerstreet" + Number = 42 } + +type Range = + { From: float + To: float } + +let a = + [| (1, 2, 3) + (4, 5, 6) + (7, 8, 9) |] +``` + +`{ defaultConfig with MultilineBlockBracketsOnSameColumn = true }` + +```fsharp +let myRecord = + { + Level = 1 + Progress = "foo" + Bar = "bar" + Street = "Bakerstreet" + Number = 42 + } + +type Range = + { + From: float + To: float + } + +let a = + [| + (1, 2, 3) + (4, 5, 6) + (7, 8, 9) + |] +``` + +### fsharp_newline_between_type_definition_and_members + +Adds a new line between a type definition and its first member. +Default = false. + +`defaultConfig` + +```fsharp +type Range = + { From: float + To: float } + member this.Length = this.To - this.From +``` + +`{ defaultConfig with NewlineBetweenTypeDefinitionAndMembers = true }` + +```fsharp +type Range = + { From: float + To: float } + + member this.Length = this.To - this.From +``` + +### fsharp_keep_if_then_in_same_line + +Bypasses the situation where `if`,`then` and `else` are placed underneath each other. +This will ensure `if` and `then` are kept in the same line. +Default = false. + +`defaultConfig` + +```fsharp +if System.Char.IsUpper(c) +then sprintf "________%s" (c.ToString().ToLower()) +else c.ToString() +``` + +`{ defaultConfig with KeepIfThenInSameLine = true }` + +```fsharp +if System.Char.IsUpper(c) then + sprintf "________%s" (c.ToString().ToLower()) +else + c.ToString() +``` + +### fsharp_max_elmish_width + +Control the maximum width for which an elmish expression should be in one line. +See [Formatting Elmish style guide](./Formatting-Elmish-code.md) for more information. +Default = 40. + +`defaultConfig` + +```fsharp +let d = div [] [ p [] [ str "meh" ] ] +``` + +`{ defaultConfig with MaxElmishWidth = 10 }` + +```fsharp +let d = + div [] [ + p [] [ + str "meh" + ] + ] +``` + +### fsharp_single_argument_web_mode + +Applies similar behavior when the elmish expression only contains a single argument. +Default = false. + +`defaultConfig` + +```fsharp +let a = + Html.button [ prop.style [ style.marginLeft 5 ] + prop.onClick (fun _ -> setCount (count - 1)) + prop.text "Decrement" ] +``` + +`{ defaultConfig with SingleArgumentWebMode = true} ` + +```fsharp +let a = + Html.button [ + prop.style [ style.marginLeft 5 ] + prop.onClick (fun _ -> setCount (count - 1)) + prop.text "Decrement" + ] +``` + +### fsharp_align_function_signature_to_indentation + +When a function signature exceeds the `max_line_length`, Fantomas will put the all but first parameters and the return type on new lines. +These will align with the start column of the first parameter. +This setting will place all parameters on the next line and align with one indent instead. +Default = false. + +`defaultConfig` + +```fsharp +[] +let run ([] req: HttpRequest) + (log: ILogger) + : HttpResponse = + Http.main CodeFormatter.GetVersion format FormatConfig.FormatConfig.Default log req +``` + +`{ defaultConfig with AlignFunctionSignatureToIndentation = true }` + +```fsharp +[] +let run + ([] req: HttpRequest) + (log: ILogger) + : HttpResponse + = + Http.main CodeFormatter.GetVersion format FormatConfig.FormatConfig.Default log req +``` + +### fsharp_alternative_long_member_definitions + +Provides an alternative way of formatting long member and constructor definitions. +Default = false. + +`defaultConfig` + +```fsharp +type C(aVeryLongType: AVeryLongTypeThatYouNeedToUse, + aSecondVeryLongType: AVeryLongTypeThatYouNeedToUse, + aThirdVeryLongType: AVeryLongTypeThatYouNeedToUse) = + class + end +``` + +`{ defaultConfig with AlternativeLongMemberDefinitions = true }` + +```fsharp +type C + ( + aVeryLongType: AVeryLongTypeThatYouNeedToUse, + aSecondVeryLongType: AVeryLongTypeThatYouNeedToUse, + aThirdVeryLongType: AVeryLongTypeThatYouNeedToUse + ) + = + class + end +``` + +### fsharp_strict_mode + +If being set, pretty printing is only done via ASTs. Compiler directives, inline comments and block comments will be ignored. +There are numerous situations when the information in the AST alone cannot restored the original code. +**Please do not use this setting for formatting hand written code!** +Valid us-case of this settings is code generation in projects like [FsAst](https://github.com/ionide/FsAst) and [Myriad](https://github.com/MoiraeSoftware/myriad). +Default = false. + +`hand written code` + +```fsharp +// some great comment +let add a b = +#if INTERACTIVE + 42 +#else + a + b +#endif +``` + +`{ defaultConfig with StriceMode = true }` + +```fsharp +let add a b = a + b +``` + +## Using the API + +See [CodeFormatter.fsi](../src/Fantomas/CodeFormatter.fsi) to view the public API of Fantomas. + +## FAKE Helpers -See [CodeFormatter.fsi](../src/Fantomas/CodeFormatter.fsi) to view the API of Fantomas. +Fantomas also exposes some less official helper functions when formatting code in FAKE scripts. +Checkout the [FAKE sample](../fake-sample/README.md) for more details. +These functions are not consider to be part of the public API, so they could be improved without the need to bump the major version. \ No newline at end of file diff --git a/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj b/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj index 0ff34191e3..4d6f00747d 100644 --- a/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj +++ b/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj @@ -4,7 +4,7 @@ netcoreapp3.1 false false - 4.0.0-alpha-014 + 4.0.0-beta-001 FS0988 diff --git a/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj b/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj index 31efe85be2..e4c504df72 100644 --- a/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj +++ b/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj @@ -4,7 +4,7 @@ netcoreapp3.1 fantomas True - 4.0.0-alpha-014 + 4.0.0-beta-001 fantomas-tool diff --git a/src/Fantomas.Tests/Fantomas.Tests.fsproj b/src/Fantomas.Tests/Fantomas.Tests.fsproj index 7776060e91..31896fe5bc 100644 --- a/src/Fantomas.Tests/Fantomas.Tests.fsproj +++ b/src/Fantomas.Tests/Fantomas.Tests.fsproj @@ -1,7 +1,7 @@ - 4.0.0-alpha-014 + 4.0.0-beta-001 FS0988 netcoreapp3.1 diff --git a/src/Fantomas.Tests/FormatConfigEditorConfigurationFileTests.fs b/src/Fantomas.Tests/FormatConfigEditorConfigurationFileTests.fs index 9c1e0cb49c..2e58fe09b3 100644 --- a/src/Fantomas.Tests/FormatConfigEditorConfigurationFileTests.fs +++ b/src/Fantomas.Tests/FormatConfigEditorConfigurationFileTests.fs @@ -188,3 +188,9 @@ fsharp_indent_on_try_with=true CodeFormatter.ReadConfiguration fsharpFile.FSharpFile config.IndentSize == 5 + +[] +let ``print default editorconfig settings`` () = + FormatConfig.Default + |> EditorConfig.configToEditorConfig + |> printfn "%s" diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index a3bba55ed9..a8a68d4ff7 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -4,7 +4,7 @@ netstandard2.0 true - 4.0.0-alpha-014 + 4.0.0-beta-001 Source code formatter for F#