Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to run Fourmolu via the CLI interface of a separate binary, rather than the bundled library #2763

Merged
merged 15 commits into from
Mar 11, 2022

Conversation

georgefst
Copy link
Collaborator

@georgefst georgefst commented Mar 7, 2022

This makes it easier to set up an environment (e.g. a Nix shell) which uses the same version of Fourmolu in HLS as from the command line.

It can also be useful when Fourmolu has updated and we don't want to wait a month for an HLS release, or re-compile. Or when one wants to try out a development version of Fourmolu.

To do

  • Add tests
    • This will require a non-trivial refactor to parameterise runSessionWithServerFormatterCLI and goldenWithHaskellDocFormatterCLI over a Config arg, so I'd like some confirmation that I'm on the right track first.

Future work

  • Add config option to editor plugins e.g. VSCode
    • We need to note that the option currently only affects Fourmolu
    • We should make clear that the binary needs to be on PATH
    • What should we call this option?
  • Implement similar functionality for other formatters?
  • We could add an option to specify the exact path to a binary, rather than requiring it to be in PATH. I'm not sure this would be useful though since we already have the haskell.serverEnvironment option. It would also make it harder to have a single option for all formatters. EDIT: is haskell.serverEnvironment specific to VSCode?

Minor issues

…ary, rather than the bundled library

This makes it easier to set up an environment (e.g. a Nix shell) which uses the same version of Fourmolu in HLS as from the command line.

It can also be useful when Fourmolu has updated and we don't want to wait a month for an HLS release, or re-compile.
@michaelpj
Copy link
Collaborator

I wonder whether we really want this as a generic option. An alternative would be to just provide an additional formatting provider, say, fourmolu-cli which would call out to the CLI. That way we also don't end up with illegal states when people set that option but pick a formatting provider which doesn't support it.

e.g. what happens if you are trying out formatters and you do:

  • Set provider to fourmolu
  • Hmm, maybe I should use the CLI, set that option
  • Hmm, maybe I'll try stylish-haskell (which doesn't support it)
  • It breaks?

This will require a non-trivial refactor to parameterise runSessionWithServerFormatterCLI and goldenWithHaskellDocFormatterCLI over a Config arg, so I'd like some confirmation that I'm on the right track first.

I think my suggestion would also solve that: there would simply be some tests for a different formatting provider.

lspPrinterOpts is unused. I doubt anyone actually cares.

Maybe it doesn't matter that much in this case, but I imagine this sort of thing matters more for e.g. passing the right GHC extensions to tools that need to know that.

That's one advantage of my other proposal to do haskell-language-server format foo: you can be sure to use actually the same options as would be provided by HLS.

We could add an option to specify the exact path to a binary, rather than requiring it to be in PATH. I'm not sure this would be useful though since we already have the haskell.serverEnvironment option.

Not all clients are VSCode. Putting it on the PATH is not onerous, but if having an option to give the path is cheap, I think it's nice. Again, no problem since I'm suggesting not having a single option ;)

@georgefst
Copy link
Collaborator Author

Thanks @michaelpj. Agreed on all points. I'll implement it as a separate plugin.

lspPrinterOpts is unused. I doubt anyone actually cares.

Maybe it doesn't matter that much in this case, but I imagine this sort of thing matters more for e.g. passing the right GHC extensions to tools that need to know that.

It's fine. GHC options etc. come via fileOpts. lspPrinterOpts only deals with tab size set by the editor itself, outside of HLS.

I may have to think about factoring out convertDynFlags somewhere (where?), rather than duplicating it in a third place (it originally came from the Ormolu plugin.

@georgefst
Copy link
Collaborator Author

Actually, I think we'd get most of the benefits, along with easier maintenance, by just making it a plugin-specific option. I'd completely missed that we now have #691.

@georgefst
Copy link
Collaborator Author

Putting it on the PATH is not onerous, but if having an option to give the path is cheap, I think it's nice.

It's not immediately obvious to me how to achieve this, and I'm keen to get this PR in to the impending release if possible. So I'll save it for future work.

@georgefst
Copy link
Collaborator Author

Right. I think I'm using Properties correctly, but I can't seem to affect any change via editor settings. i.e. adding "haskell.plugin.fourmolu.cli": true in VSCode has no effect. Is there another step needed, or is that just not the right string?

Ensures expected config files are found.
@georgefst
Copy link
Collaborator Author

georgefst commented Mar 9, 2022

I also can't find a nice way to set this new plugin-specific option in the tests. I could refactor Fourmolu.hs to expose a Bool argument to descriptor instead (or something along those lines), but it's non-trivial...

EDIT: Actually it is pretty straightforward. It's just kind of ugly, and doesn't scale nicely to adding more plugin-specific options.

@georgefst
Copy link
Collaborator Author

Somehow 3d9f964 has broken the functionality completely. Odd.

@michaelpj
Copy link
Collaborator

Actually, I think we'd get most of the benefits, along with easier maintenance, by just making it a plugin-specific option.

Yes, I think you're right. The only issue would be that you might end up with illegal combinations of plugin options? e.g. if you have some other fourmolu option that can't actually take effect when you're using the CLI version. Just a hypothetical worry, though.

adding "haskell.plugin.fourmolu.cli": true in VSCode has no effect.

I think the VSCode extension also needs to be extended so it knows about the new setting, while the config is "generic" on the HLS side, I don't think is on the VSCode side. I don't really know how it works, though.

I'd probably just test it in a grimy way by setting it to true by default 😆

@michaelpj
Copy link
Collaborator

It's not immediately obvious to me how to achieve this, and I'm keen to get this PR in to the impending release if possible. So I'll save it for future work.

Isn't it just a matter of adding another plugin-specific option? "Path to fourmolu binary (only used if cli option is set)"

@georgefst
Copy link
Collaborator Author

It's not immediately obvious to me how to achieve this, and I'm keen to get this PR in to the impending release if possible. So I'll save it for future work.

Isn't it just a matter of adding another plugin-specific option? "Path to fourmolu binary (only used if cli option is set)"

Yes, I'm sure you're right. I started writing that before I'd implemented the first option.

The only issue would be that you might end up with illegal combinations of plugin options?

I don't anticipate that being an issue any time soon.

I'd probably just test it in a grimy way by setting it to true by default 😆

Yeah, don't worry, I've already done that, and it works nicely. Well, it did before the CWD change, which I haven't been able to investigate yet.

I should be able to get this finished up later today.

@georgefst georgefst marked this pull request as ready for review March 10, 2022 01:28
Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks fine.

<> map ("-o" <>) fileOpts
){cwd = Just $ takeDirectory fp'}
contents
T.hPutStrLn stderr err
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should get logged properly

Copy link
Collaborator Author

@georgefst georgefst Mar 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's no worse than with the non-CLI version. I'll open a new issue to track better logging for both.

@@ -152,11 +154,14 @@ goldenWithHaskellDocFormatter plugin formatter title testDataDir path desc ext a
runSessionWithServer :: PluginDescriptor IdeState -> FilePath -> Session a -> IO a
runSessionWithServer plugin = runSessionWithServer' [plugin] def def fullCaps

runSessionWithServerFormatter :: PluginDescriptor IdeState -> String -> FilePath -> Session a -> IO a
runSessionWithServerFormatter plugin formatter =
runSessionWithServerFormatter :: PluginDescriptor IdeState -> String -> PluginConfig -> FilePath -> Session a -> IO a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe document this function while you're here

plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs Outdated Show resolved Hide resolved
(printerOpts <> lspPrinterOpts)
defaultPrinterOpts
}
properties :: Properties '[ 'PropertyKey "cli" 'TBoolean]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bikeshedding: "external"? "shell"? I think "cli" seems fine though.

Copy link
Collaborator Author

@georgefst georgefst Mar 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, surpisingly no word I could think of here seems perfect.

Copy link
Collaborator Author

@georgefst georgefst Mar 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided I do prefer "external": 558a3bc. Not going to bother changing the variable names though.

@georgefst georgefst merged commit fd34887 into master Mar 11, 2022
@georgefst
Copy link
Collaborator Author

As for:

Add config option to editor plugins e.g. VSCode

Is there anything I need to do? I see from #1576 that we have some auto-generation script. Is this part of the release process? Is any of this (i.e. the process of adding an option) documented anywhere?

@michaelpj
Copy link
Collaborator

I have no idea. I suspect it isn't documented: I had a look at the CONTRIBUTING for vscode-haskell and it didn't say. Maybe you can write it down when you find out. @berberman might know?

@burkettd
Copy link

burkettd commented May 2, 2022

This looks like this PR adds support for using a locally installed binary of fourmolu instead of the version bundled with hls.

I'm using hls 1.7.0.0, and installed fourmolu 0.6.0.0 on my path. I tried setting "haskell.plugin.fourmolu.cli": true in my coc config for neovim, but it doesn't seem to work because it doesn't seem to apply my import-export-comma-style setting which I think was added in 0.6.0.0.

What settings do I need to set to tell HLS to use a locally installed version of fourmolu?

@georgefst
Copy link
Collaborator Author

What settings do I need to set to tell HLS to use a locally installed version of fourmolu?

I genuinely don't know. My personal use case for this disappeared shortly after it was merged. I can only suggest subscribing to #2827.

@cydparser
Copy link
Contributor

cydparser commented Mar 3, 2023

The setting was later renamed to "external":

{
  "haskell.formattingProvider": "fourmolu",
  "haskell.plugin.fourmolu.config.external": true
}

@tablitza
Copy link

Using GHC 9.4.8 HLS 2.5.0.0 with lsp-mode on emacs, the bundled fourmolu does not apply indentation from the yaml file, and using the external binary triggers the error fourmolu: Internal Error: fourmolu: createProcess: posix_spawnp: does not exist (No such file or directory)

@michaelpj
Copy link
Collaborator

Is fourmolu on your editor's path?

@tablitza
Copy link

Yes, ~/.cabal/bin is on my emacs exec-path variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants