WolframResearch / codeformatter

Format Wolfram Language source code
MIT License
47 stars 4 forks source link

$DefaultBreakLinesMethod = None #4

Open hifismith opened 1 year ago

hifismith commented 1 year ago

I would like CodeFormatter to help me with spacing and indentation but not line breaks. I'd like it to

  1. Preserve all line breaks I enter
  2. Prevent the formatter from adding line breaks

So if I write:

a[x_]:=Block[{b},
b=2;x^2+b
]

I would like it to return

a[x_] := Block[{b},
  b = 2; x^2 + b
]

i.e. add spacing and indentation, but do not add or remove line breaks

Is there a way to do this? I tried $DefaultBreakLinesMethod=None, but it appears that symbol has to be set to a string. And I would like to apply these settings in VS Code so I can use "Format Document" or "Format Selection".

hifismith commented 1 year ago

At 25:26 of your 2020 WTC video, you say the formatter tries to preserve line breaks added by the user. It doesn't seem to right now. Being able to set Airiness -> -1 in VS Code's settings.json and preserving user-entered line breaks is pretty close to what I'm looking for.

bostick commented 1 year ago

After that presentation, there have been several updates to CodeFormatter and one was to canonicalize the output by always first stripping out whitespace and newlines.

(specifically https://github.com/WolframResearch/codeformatter/commit/47a3386156d6b6e277070d26dca70d4cc32d2dc1)

This fixes a problem of "history dependence" on input and Airiness settings, i.e., you want to be able to interactively change Airiness and you want to always get the same output for each Airiness setting. If the newlines are preserved, then there is an undesirable "hysteresis" effect.

Now, what you want of not changing newlines at all (not removing existing newlines and not adding new ones) and only modifying whitespace is a good idea and other people have also asked for this sort of thing.

It would not be formatting per se, and I would call this something new like "Fix indentation" or "Fix whitespace" or "Redo whitespace" (suggestions please!)

And could be provided as a different menu item in editors that we support like VSCode and Sublime.

hifismith commented 1 year ago

Makes perfect sense why you would want to get rid of history dependence.

Until "CodeSpacer" comes out (or whatever you call it), is there a way to specify Airiness in VS Code? We have $DefaultLineWidth=Infinity, do we need $DefaultAiriness?

The functionality I describe in my original post is what IntelliJ does when using "Reformat Code"

image
bostick commented 1 year ago

Unfortunately, there is no $DefaultAiriness (I can work to add that) and we will now have to switch to using SetOptions.

I believe specifying:

SetOptions[CodeFormatter`CodeFormatCST, CodeFormatter`Airiness -> Automatic, "BreakLinesMethod" :> $DefaultBreakLinesMethod, "LineWidth" :> $DefaultLineWidth]

in your VSCode command will get you want (with appropriate values specified and making sure to properly escape the strings, and possibly removing spaces because I am paranoid about running commands with spaces in them).

hifismith commented 1 year ago

Nice! Set options on CodeFormatCST. Got it; thanks for that. These settings are close to my preference: Airiness -> -0.5, "LineWidth" -> 90, "BreakLinesMethod" -> "LinkeBreakerV2" (Testing with CodeFormat in a notebook)

It'd be nice if there was an Airiness level that put the commas on the same line as the code. It goes from this at Airness -> -0.84

solanTemperaturePlot[opts : OptionsPattern[]] := Block[{data},
    data = {tsw @ p3TS[kOutT], Thread[{outputs[[ ;; , 1]], outputs[[ ;; , 2, 3]]}]};
    afsPlot[
        data
        ,
        scaleXDate[]
        ,
        Joined -> {True, False}
        ,
        afsPlotFrameQ -> False
        ,
        Flatten[{opts}]
        ,
        PlotStyle -> {{Thickness[0.006], afsColors[[1]]}, {PointSize[0.012], afsColors[[3]]}}
        ,
        AspectRatio -> 1 / 3
        ,
        PlotLabel -> "P3 Wing Valve Temperature Comparison"
        ,
        FrameLabel -> {None, Style["Temperature [°C]", Black]}
        ,
        PlotLegends -> Placed[{"Field Data", "Model Predictions"}, {Scaled[{0.99, 0.31}], {1, 0}}]
    ]
];

to this at -0.85 (notice LineWidth is not respected)

solanTemperaturePlot[opts : OptionsPattern[]] := Block[{data}, data = {tsw @ p3TS[kOutT], Thread[{outputs[[ ;; , 1]], outputs[[ ;; , 2, 3]]}]}; afsPlot[data, scaleXDate[], Joined -> {True, False}, afsPlotFrameQ -> False, Flatten[{opts}], PlotStyle -> {{Thickness[0.006], afsColors[[1]]}, {PointSize[0.012], afsColors[[3]]}}, AspectRatio -> 1 / 3, PlotLabel -> "P3 Wing Valve Temperature Comparison", FrameLabel -> {None, Style["Temperature [°C]", Black]}, PlotLegends -> Placed[{"Field Data", "Model Predictions"}, {Scaled[{0.99, 0.31}], {1, 0}}]]];
hifismith commented 1 year ago

EDIT: I had Wolfram.command edited in the wrong settings file. I copy-pasted into both (.vscode/settings, and user settings). It's working now

ORIGINAL: Is there not a 1-to-1 mapping between CodeFormatCST in VS Code and CodeFormat in a notebook? This is the result of using SetOptions in VS code (Format Selection or Format Document), which looks different from what I pasted in my last post

solanTemperaturePlot[opts : OptionsPattern[]] :=
  Block[{data},
    data = {tsw @ p3TS[kOutT], Thread[{outputs[[ ;; , 1]], outputs[[ ;; , 2, 3]]}]};
    afsPlot[data, scaleXDate[], Joined -> {True, False}, afsPlotFrameQ -> False, Flatten[{opts}], PlotStyle -> {{Thickness[0.006], afsColors[[1]]}, {PointSize[0.012], afsColors[[3]]}}, AspectRatio -> 1 / 3, PlotLabel -> "P3 Wing Valve Temperature Comparison", FrameLabel -> {None, Style["Temperature [\[Degree]C]", Black]}, PlotLegends -> Placed[{"Field Data", "Model Predictions"}, {Scaled[{0.99, 0.31}], {1, 0}}]]
  ];
bostick commented 1 year ago

I'm having trouble reproducing example in your question about going from Airiness -> -0.84 to Airiness -> -0.85.

Can you show all the steps that you used starting with a fresh kernel?

hifismith commented 1 year ago

I can't seem to reproduce either. Was there a new Paclet pushed? Looks like I'm now on 1.7

It's still working the same in VS Code, but I can't reproduce it in a notebook. Here's my VSCode expression:

"Needs[\"LSPServer`\"];SetOptions[CodeFormatter`CodeFormatCST, CodeFormatter`Airiness -> -0.5, \"BreakLinesMethod\" :> \"LineBreakerV2\", \"LineWidth\" :> 120];LSPServer`StartServer[]"

In a notebook (notebook adding line wrapping):

image

Using VS Code (Format Document):

image

Example string: " mOpts = {Splice@Flatten[{opts}], Joined -> {True, False}, afsPlotFrameQ -> False, PlotStyle -> {{Thickness[0.006], afsColors[[1]]}, {PointSize[ 0.012], afsColors[[3]]}} , AspectRatio -> 1 / 3 , PlotLabel -> \"P3 Wing Valve Temperature Comparison\" , FrameLabel -> {None, Style[\"Temperature [°C]\", Black ]} , PlotLegends -> Placed[{\"Field Data\", \"Model Predictions\"}, {Scaled[{0.99, 0.31}], {1, 0}}]};"

bostick commented 1 year ago

Your example above has "LinkeBreakerV2" (typo extra e).

I can also work to warn about unrecognized values for options.

hifismith commented 1 year ago

Thanks! That was it 🤦🏼‍♂️

Are you able to reproduce the same results now?

image
hifismith commented 1 year ago

Here's a notebook if it helps: Google Drive Link

bostick commented 1 year ago

Yes, I see the same thing.

I'm sorry, can you give an example of what you are seeing vs. what you are requesting?

hifismith commented 1 year ago

Maybe at Airness -> -0.75, the commas stay on the previous line like this:

mOpts = {
  Splice @ Flatten[{opts}],
  Joined -> {True, (*True*)False},
  PlotRange -> {165, 185},
  afsPlotFrameQ -> False,
  ImageSize -> 600,
  PlotStyle -> {{Thickness[0.006], afsColors[[1]]}, {PointSize[0.012], afsColors[[3]]}},
  AspectRatio -> 1 / 3,
  PlotLabel -> "P3 ESP Discharge Pressure Comparison",
  FrameLabel -> {None, Style["Pressure [barg]", Black]},
  PlotLegends -> Placed[{"Field Data", "Model Predictions"}, {Scaled[{0.99, 0.71}], {1, 0}}]
};

Reason being, I can then use a plugin to help align the code further to make it more readable and more compact:

image

Here's another example using multi-column alignment:

image

I use "Smart Column Indenter," which doesn't work as well with the comma breaking the pattern between each line. What do you think?

bostick commented 1 year ago

It's a good idea and there is already some cases where commas are kept on the same line if the structure is known.

e.g. LibraryFunction is hard-coded to format like this:

In[7]:= CodeFormat[code]
Out[7]= LibraryFunction["sqlite3_bind_int64"][
    statement,
    Cast[i, "Integer32", "ReinterpretCast"],
    Cast[v, "Integer64"]
]

but it's not a general solution and I have to make some changes to allow it to work in general.