neovimhaskell / nvim-hs

Neovim API for Haskell plugins as well as the plugin provider
Other
267 stars 18 forks source link

Provide a non-TH codepath for exporting boring commands #97

Open isovector opened 2 years ago

isovector commented 2 years ago

The current TH-based design makes a lot of usual Haskellisms rather annoying, eg, requiring an explicit binding to get a function into the right shape

doRefine :: CommandArguments -> Neovim CornelisEnv ()
doRefine = const refine

refine :: Neovim CornelisEnv ()
refine = withAgda $ void $ withGoalAtCursor $ \b goal -> do
  agda <- getAgda b
  flip runIOTCM agda $ Cmd_refine_or_intro True (InteractionId $ ip_id goal) noRange ""

just to export it:

$(command "CornelisRefine" 'doRefine) [CmdSync Async]

For simple cases like this, it would be nice to have a function:

exportCommand :: String -> (CommandArguments -> Neovim env ()) -> [CommandOption] -> ExportedFunctionality env

such that the above call could be implemented more simply as

exportCommand "CornelisRefine" (const refine) [CmdSync Async]

which avoids the TH and prevents needing to define the no-op doRefine.

saep commented 2 years ago

The Template Haskell approach has the advantage of giving you compiler errors if the name of the command is invalid or if your command definition cannot be translated to a callable command. The latter is not applicable for this case which will probably cover most use cases, so it doesn't really matter here. I've tried to achieve the former with OverloadedStrings, but the conversion is done at runtime, so I don't know how to achieve a similar user experience if something goes wrong. I think it is very valuable that the error message also tells you the exact position where the error originated from.

/home/saep/git/saepfigs/home/config/nvim/nvim-hs/Neovim/Example/Plugin.hs:27:15: error:
     • Exception when trying to run compile-time code:
         Custom command name must start with a capital letter: "throwExceptionCommand"

I'm not convinced that this is actually worth implementing because it only saves you from writing a type signature. If you are also writing documentation for the command somewhere (vim-help, haddock or something in the Readme) then this additional work is also negligible.

I'm not opposed to an alternative export API that covers functions, commands and autocommands without using Template Haskell as long as it covers the common use cases.