Code Monkey home page Code Monkey logo

haskell-tools.nvim's Introduction


haskell-tools.nvim


Explore the docs Β»

Report Bug Β· Request Feature Β· Ask Question

Supercharge your Haskell experience in Neovim!

πŸ¦₯

Neovim Lua Haskell Nix

GPL2 License Issues Build Status LuaRocks

All Contributors

Note

πŸ”— Quick Links

❔ Do I need haskell-tools.nvim

If you are starting out with Haskell, nvim-lspconfig.hls is probably enough for you. It provides the lowest common denominator of LSP support. This plugin is for those who would like additional features that are specific to Haskell tooling.

πŸ“ Prerequisites

Required

  • neovim >= 0.10

Optional

πŸ“₯ Installation

This plugin is available on LuaRocks:

:Rocks install haskell-tools.nvim

Example using lazy.nvim:

{
  'mrcjkb/haskell-tools.nvim',
  version = '^4', -- Recommended
  lazy = false, -- This plugin is already lazy
}

Tip

It is suggested to pin to tagged releases if you would like to avoid breaking changes.

To manually generate documentation, use :helptags ALL.

Note

For NixOS users with flakes enabled, this project provides outputs in the form of a package and an overlay; use it as you wish in your NixOS or home-manager configuration. It is also available in nixpkgs.

⚑ Quick Setup

This plugin automatically configures the haskell-language-server builtin LSP client and integrates with other haskell tools. See the Features section for more info.

Warning

Do not call the nvim-lspconfig.hls setup or set up the lsp client for haskell-language-server manually, as doing so may cause conflicts.

This is a filetype plugin that works out of the box, so there is no need to call a setup function or configure anything to get this plugin working.

You will most likely want to add some keymaps. Most keymaps are only useful in haskell and/or cabal files, so I suggest you define them in ~/.config/nvim/after/ftplugin/haskell.lua1 and/or ~/.config/nvim/after/ftplugin/cabal.lua1.

Some suggestions:

-- ~/.config/nvim/after/ftplugin/haskell.lua
local ht = require('haskell-tools')
local bufnr = vim.api.nvim_get_current_buf()
local opts = { noremap = true, silent = true, buffer = bufnr, }
-- haskell-language-server relies heavily on codeLenses,
-- so auto-refresh (see advanced configuration) is enabled by default
vim.keymap.set('n', '<space>cl', vim.lsp.codelens.run, opts)
-- Hoogle search for the type signature of the definition under the cursor
vim.keymap.set('n', '<space>hs', ht.hoogle.hoogle_signature, opts)
-- Evaluate all code snippets
vim.keymap.set('n', '<space>ea', ht.lsp.buf_eval_all, opts)
-- Toggle a GHCi repl for the current package
vim.keymap.set('n', '<leader>rr', ht.repl.toggle, opts)
-- Toggle a GHCi repl for the current buffer
vim.keymap.set('n', '<leader>rf', function()
  ht.repl.toggle(vim.api.nvim_buf_get_name(0))
end, opts)
vim.keymap.set('n', '<leader>rq', ht.repl.quit, opts)

Tip

Important

  • Do not set vim.g.haskell_tools in after/ftplugin/haskell.lua, as the file is sourced after the plugin is initialized.

🌟 Features

codeLens

  • Evaluate all code snippets at once

haskell-language-server can evaluate code snippets using code lenses. haskell-tools.nvim provides a require('haskell-tools').lsp.buf_eval_all() shortcut to evaluate all of them at once.

evalAll

  • Hoogle-search for signature

  • Search for the type signature under the cursor.

  • Falls back to the word under the cursor if the type signature cannot be determined.

  • Telescope keymaps:

    • <CR> to copy the selected entry (<name> :: <signature>) to the clipboard.
    • <C-b> to open the selected entry's Hackage URL in a browser.
    • <C-r> to replace the word under the cursor with the selected entry.
require('haskell-tools').hoogle.hoogle_signature()

hoogleSig

  • Hole-driven development powered by Hoogle

With the <C-r> keymap, the Hoogle search telescope integration can be used to fill holes.

hoogleHole

  • GHCi repl

Start a GHCi repl for the current project / buffer.

  • Automagically detects the appropriate command (cabal repl, stack ghci or ghci) for your project.
  • Choose between a builtin handler or toggleterm.nvim.
  • Dynamically create a repl command for iron.nvim (see advanced configuration).
  • Interact with the repl from within Haskell files using a lua API.

repl

  • Open project/package files for the current buffer

commands

  • Hover actions

Inspired by rust-tools.nvim, this plugin adds the following hover actions (if available):

  • Hoogle search.
  • Open documentation in browser.
  • Open source in browser.
  • Go to definition.
  • Go to type definition.
  • Find references.

Additionally, the default behaviour of stylizing markdown is disabled. And the hover buffer's filetype is set to markdown, so that nvim-treesitter users can benefit from syntax highlighting of code snippets.

hoverActions

  • Automatically generate tags

On attaching, Neovim's LSP client will set up tagfunc to query the language server for locations to jump to. If no location is found, it will fall back to a tags file.

If fast-tags is installed, this plugin will set up autocmds to automatically generate tags:

  • For the whole project, when starting a session.
  • For the current (sub)package, when writing a file.

This feature can be tweaked or disabled in the advanced configuration.

  • Auto-discover haskell-debug-adapter configurations

If the nvim-dap plugin is installed, haskell-tools.nvim will automatically discover haskell-debug-adapter configurations.

dap

Note

haskell-debug-adapter is an experimental design and implementation of a debug adapter for Haskell.

  • Planned

For planned features, refer to the issues.

βš™οΈ Advanced configuration

To modify the default configuration, set vim.g.haskell_tools.

vim.g.haskell_tools = {
  ---@type ToolsOpts
  tools = {
    -- ...
  },
  ---@type HaskellLspClientOpts
  hls = {
    ---@param client number The LSP client ID.
    ---@param bufnr number The buffer number
    ---@param ht HaskellTools = require('haskell-tools')
    on_attach = function(client, bufnr, ht)
      -- Set keybindings, etc. here.
    end,
    -- ...
  },
  ---@type HTDapOpts
  dap = {
    -- ...
  },
}

Tip

vim.g.haskell_tools can also be a function that returns a table.

How to dynamically load different haskell-language-server settings per project

By default, this plugin will look for a hls.json2 file in the project root directory, and attempt to load it. If the file does not exist, or it can't be decoded, the hls.default_settings will be used.

You can change this behaviour with the hls.settings config:

vim.g.haskell_tools = {
  -- ...
  hls = {
    ---@param project_root string Path to the project root
    settings = function(project_root)
      local ht = require('haskell-tools')
      return ht.lsp.load_hls_settings(project_root, {
        settings_file_pattern = 'hls.json'
      })
    end,
  },
}

How to disable individual code lenses

Some code lenses might be more interesting than others. For example, the importLens could be annoying if you prefer to import everything or use a custom prelude. Individual code lenses can be turned off by disabling them in the respective plugin configurations:

hls = {
  settings = {
    haskell = {
      plugin = {
        class = { -- missing class methods
          codeLensOn = false,
        },
        importLens = { -- make import lists fully explicit
          codeLensOn = false,
        },
        refineImports = { -- refine imports
          codeLensOn = false,
        },
        tactics = { -- wingman
          codeLensOn = false,
        },
        moduleName = { -- fix module names
          globalOn = false,
        },
        eval = { -- evaluate code snippets
          globalOn = false,
        },
        ['ghcide-type-lenses'] = { -- show/add missing type signatures
          globalOn = false,
        },
      },
    },
  },
},

Launch haskell-language-server on Cabal files

Since version 1.9.0.0, haskell-language-server can launch on Cabal files, but it does not support all features that it has for Haskell files. You can add cabal-specific keymaps, etc. in ~/.config/nvim/after/ftplugin/cabal.lua.

Set up iron.nvim to use haskell-tools.nvim

Depends on iron.nvim/#300.

local iron = require("iron.core")
iron.setup {
  config = {
    repl_definition = {
      haskell = {
        command = function(meta)
          local file = vim.api.nvim_buf_get_name(meta.current_bufnr)
          -- call `require` in case iron is set up before haskell-tools
          return require('haskell-tools').repl.mk_repl_cmd(file)
        end,
      },
    },
  },
}

Create haskell-debug-adapter launch configurations

There are two ways this plugin will detect haskell-debug-adapter launch configurations:

  1. Automatically, by parsing Cabal or Stack project files.
  2. By loading a launch.json file in the project root.

Available functions and commands

For a complete overview, enter :help haskell-tools in Neovim.

LSP

Command Description
:Hls start Start the LSP client
:Hls stop Stop the LSP client
:Hls restart Restart the LSP client
:Hls evalAll Evaluate all code snippets
local ht = require('haskell-tools')
--- Start or attach the LSP client.
ht.lsp.start()

--- Stop the LSP client.
ht.lsp.stop()

--- Restart the LSP client.
ht.lsp.restart()

--- Callback for dynamically loading haskell-language-server settings
--- Falls back to the `hls.default_settings` if no file is found
--- or one is found, but it cannot be read or decoded.
--- @param project_root string? The project root
ht.lsp.load_hls_settings(project_root)

--- Evaluate all code snippets in comments
ht.lsp.buf_eval_all()

Hoogle

local ht = require('haskell-tools')
--- Run a hoogle signature search for the value under the cursor
ht.hoogle.hoogle_signature()

Repl

Command Description Arguments
:Haskell repl toggle {file?} Toggle a GHCi repl filepath (optional)
:Haskell repl quit Quit the current repl
:Haskell repl load {file?} Load a file into the current repl filepath (optional)
:Haskell repl reload Reload the current repl
:Haskell repl paste_type {register?} Query the repl for the type of {register}
:Haskell repl cword_type Query the repl for the type of the word under the cursor
:Haskell repl paste_info {register?} Query the repl for info on {register}
:Haskell repl cword_info {register?} Query the repl for info on the word under the cursor
local ht = require('haskell-tools')
--- Toggle a GHCi repl for the current project
ht.repl.toggle()

--- Toggle a GHCi repl for `file`
--- @param file string Path to a Haskell file
ht.repl.toggle(file)

--- Quit the repl
ht.repl.quit()

--- Paste a command to the repl from register `reg`.
--- @param reg string? Register to paste from (:h registers), defaults to '"'.
ht.repl.paste(reg)

--- Query the repl for the type of register `reg`, and paste it to the repl.
--- @param reg string? Register to paste from (:h registers), defaults to '"'.
ht.repl.paste_type(reg)

--- Query the repl for the type of word under the cursor
ht.repl.cword_type()

--- Query the repl for info on register `reg`.
--- @param reg string? Register to paste from (:h registers), defaults to '"'.
ht.repl.paste_info(reg)

--- Query the repl for info on the word under the cursor
ht.repl.cword_info()

--- Load a file into the repl
--- @param file string The absolute file path
ht.repl.load_file(file)

--- Reload the repl
ht.repl.reload()

Project

Command Description
:Haskell projectFile Open the project file for the current buffer (cabal.project or stack.yaml)
:Haskell packageYaml Open the package.yaml file for the current buffer
:Haskell packageCabal Open the *.cabal file for the current buffer
local ht = require('haskell-tools')
--- Open the project file for the current buffer (cabal.project or stack.yaml)
ht.project.open_project_file()

--- Open the package.yaml file for the current buffer
ht.project.open_package_yaml()

--- Open the *.cabal file for the current buffer
ht.project.open_package_cabal()

--- Search for files within the current (sub)package
--- @param opts table Optional telescope.nvim `find_files` options
ht.project.telescope_package_files(opts)
--- Live grep within the current (sub)package
--- @param opts table Optional telescope.nvim `live_grep` options
ht.project.telescope_package_grep(opts)

Tags

The following functions depend on fast-tags.

local ht = require('haskell-tools')

-- Generate tags for the whole project
---@param path string? An optional file path, defaults to the current buffer
---@param opts table Optional options:
---       opts.refresh boolean
---       - Whether to refresh tags if they have already been generated for a project
ht.tags.generate_project_tags(path, opts)

-- Generate tags for the whole project
---@param path string? An optional file path, defaults to the current buffer
ht.tags.generate_package_tags(path)

Note

By default, haskell-tools will automate generating project and package tags, if fast-tags is detected.

DAP

local ht = require('haskell-tools')

---@param bufnr integer The buffer number
---@param opts table? Optional
---@param opts.autodetect: (boolean)
--- Whether to auto-detect launch configurations
---@param opts.settings_file_pattern: (string)
--- File name or pattern to search for. Defaults to 'launch.json'
ht.dap.discover_configurations(bufnr, opts)

Note

haskell-tools.nvim will discover DAP launch configurations automatically, if nivm-dap is installed and the debug adapter server is executable. There is typically no need to call this function manually.

Telescope extension

If telescope.nvim is installed, haskell-tools.nvim will register the ht extension with the following commands:

Command Description
:Telescope ht package_files Search for files within the current (sub)package
:Telescope ht package_hsfiles Search for Haskell files within the current (sub)package
:Telescope ht package_grep Live grep within the current (sub)package
:Telescope ht package_hsgrep Live grep Haskell files within the current (sub)package
:Telescope ht hoogle_signature Run a Hoogle search for the type signature under the cursor

To load the extension, call

require('telescope').load_extension('ht')

Important

If you lazy-load this plugin, make sure it is loaded before registering the Telescope extension.

🩺 Troubleshooting

For a health check, run :checkhealth haskell-tools

LSP features not working

If hls is unable to show diagnostics, or shows an error diagnostic at the top of your file, you should first check if you can compile your project with cabal or stack. If there are compile errors, open the files that cannot be compiled, and hls should be able to show the error diagnostics for those files.

Check which versions of hls and GHC you are using (e.g. by calling haskell-language-server-wrapper --probe-tools or haskell-language-server --probe-tools). Sometimes, certain features take some time to be implemented for the latest GHC versions. You can see how well a specific GHC version is supported here.

Minimal config

To troubleshoot this plugin with a minimal config in a temporary directory, you can try minimal.lua.

nvim -u minimal.lua

Note

If you use Nix, you can run nix run "github:mrcjkb/haskell-tools.nvim#nvim-minimal-stable". or nix run "github:mrcjkb/haskell-tools.nvim#nvim-minimal-nightly".

If you cannot reproduce your issue with a minimal config, it may be caused by another plugin. In this case, add additional plugins and their configurations to minimal.lua, until you can reproduce it.

Note

This plugin is only tested on Linux. It should work on MacOS, and basic features should also work on Windows (since version 1.9.5), but I have no way to test this myself. Features that rely on external tools, such as hoogle, fast-tags or ghci might break on non-Unix-like operating systems.

Logs

To enable debug logging, set the log level to DEBUG3:

vim.g.haskell_tools = {
  tools = { -- haskell-tools options
    log = {
      level = vim.log.levels.DEBUG,
    },
  },
}

You can also temporarily set the log level by calling

Command Argument
:Haskell log setLevel One of debug error warn info trace off

or

:lua require('haskell-tools').log.set_level(vim.log.levels.DEBUG)

You can find the log files by calling

-- haskell-tools.nvim log
:lua =require('haskell-tools').log.get_logfile()
-- haskell-language-server logs
:lua =require('haskell-tools').log.get_hls_logfile()

or open them by calling

:lua require('haskell-tools').log.nvim_open_logfile() -- or :Haskell log openLog
:lua require('haskell-tools').log.nvim_open_hls_logfile() -- or :Haskell log openHlsLog

πŸ”— Recommendations

Here are some other plugins I recommend for Haskell (and nix) development in neovim:

Contributors ✨

Thanks goes to these wonderful people (emoji key):

fabfianda
fabfianda

πŸ“–
Mango The Fourth
Mango The Fourth

πŸš‡
Yen3
Yen3

πŸ’»
Sebastian Selander
Sebastian Selander

πŸ’»
Thomas Li
Thomas Li

πŸ’»
Matthieu Coudron
Matthieu Coudron

πŸš‡ πŸ›
Michael Lan
Michael Lan

πŸ›
Dhruva Srinivas
Dhruva Srinivas

πŸ“–
Andrea Callea (he/him/his)
Andrea Callea (he/him/his)

πŸ› πŸ““
Cyber Oliveira
Cyber Oliveira

πŸ›
Br3akp01nt
Br3akp01nt

πŸ““ πŸ›
Alper Γ‡elik
Alper Γ‡elik

πŸ›
mauke
mauke

πŸ’»
Ravi Dayabhai
Ravi Dayabhai

πŸ› πŸ““
Maciej Jur
Maciej Jur

πŸ›
MaciekFlis
MaciekFlis

πŸ’΅
mbwgh
mbwgh

πŸ“–
AntonVucinic
AntonVucinic

πŸ’»
William Rusnack
William Rusnack

πŸ“–
John Hampton
John Hampton

πŸ’»

This project follows the all-contributors specification. Contributions of any kind welcome!

Footnotes

  1. See :help base-directories ↩ ↩2

  2. haskell-language-server can generate such a file with the generate-default-config CLI argument. ↩

  3. See :help vim.log.levels: ↩

haskell-tools.nvim's People

Contributors

allcontributors[bot] avatar antonvucinic avatar bebesparkelsparkel avatar carrotfarmer avatar dependabot[bot] avatar fabfianda avatar github-actions[bot] avatar mangoiv avatar mauke avatar mrcjkb avatar sebastianselander avatar typesafety avatar yen3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

haskell-tools.nvim's Issues

Make Hoogle independent of LSP

I really like Hoogle integration, but I'd be very nice to use it without having LSP dependency. Perhaps, can you pull of the Hoogle part and make a separate project?

fourmolu as formatting provider doesn't use `fourmolu.yaml` of project

Neovim version (nvim -v)

v0.8.0

Operating system/version

22.11.20221117.3a86856 (Raccoon)

Output of haskell-language-server --version

1.8.0.0 (GHC: 9.2.4)

How to reproduce the issue

use fourmolu as formatting provider

Expected behaviour

fourmolu formats according to the fourmolu.yaml in the repository

Actual behaviour

fourmolu uses default formatting

Log file

No response

Hoogle search: multi-line signatures joined with more than one space

Neovim version (nvim -v)

v0.8.0

Operating system/version

NixOS 22.05

Output of haskell-language-server --version

1.8.0.0 (GHC: 9.0.2)

How to reproduce the issue

  • Find a type with a large type signature
  • Confirm that its type signature is multi-line using hover
  • Run a hoogle search for signature

Expected behaviour

Signature has 1 space between types

Actual behaviour

Signature has multiple spaces between types where hover has line breaks

Log file

No response

feat: open package / project file

  • :OpenPackage -> package.yaml
  • :OpenCabal -> *.cabal
  • :OpenProjectFile -> cabal.project | stack.yaml

... for the file in the current buffer

telescope mandatory ?

Feature description

first and foremost, thanks for the amazing plugin. I knew the code was there but you provide a coherent package that takes advantage of the underlying primitives.

I've been greeted today with a haskell-tools message saying that telescope is mandatory for the plugin to work. Why is that ? is there something missing in vim.select that you need from telescope ?

NB: I see that you list several required packages: https://github.com/MrcJkb/haskell-tools.nvim#required would you mind adding a rockspec so that nixpkgs can automatically map the plugin dependencies ? I am trying to improve the neovim plugin dependency system via luarocks. See for instance https://github.com/lewis6991/gitsigns.nvim/blob/main/gitsigns.nvim-scm-1.rockspec

lua/haskell-tools/hoogle/web.lua:60: Expected value but found invalid token at character 1

Neovim version (nvim -v)

0.9 (nightly)

Operating system/version

nixos unstable

Output of haskell-language-server --version

1.9

How to reproduce the issue

When I get the tooltip and press K to enter the tooltip, there are several "hoogle search" entries, I press enter than I get

|| E5108: Error executing lua: ...mPackages/start/plenary.nvim/lua/plenary/async/async.lua:18: The coroutine failed with this message: ...tart/haskell-tools.nvim/lua/haskell-tools/hoogle/web.lua:60: Expected value but found invalid token at character 1
|| stack traceback:
|| 	[C]: in function 'error'
|| 	...mPackages/start/plenary.nvim/lua/plenary/async/async.lua:18: in function 'callback_or_next'
|| 	...mPackages/start/plenary.nvim/lua/plenary/async/async.lua:45: in function 'step'
|| 	...mPackages/start/plenary.nvim/lua/plenary/async/async.lua:48: in function 'execute'
|| 	...mPackages/start/plenary.nvim/lua/plenary/async/async.lua:108: in function 'run'
|| 	...tart/haskell-tools.nvim/lua/haskell-tools/hoogle/web.lua:45: in function 'handler'
|| 	...er/start/haskell-tools.nvim/lua/haskell-tools/hoogle.lua:70: in function 'hoogle_signature'
|| 	...start/haskell-tools.nvim/lua/haskell-tools/lsp/hover.lua:53: in function 'action'
|| 	...start/haskell-tools.nvim/lua/haskell-tools/lsp/hover.lua:28: in function 'run_command'
|| 	...start/haskell-tools.nvim/lua/haskell-tools/lsp/hover.lua:176: in function <...start/haskell-tools.nvim/lua/haskell-tools/lsp/hover.lua:175>

local config = deps.require_telescope('telescope.config').values

Expected behaviour

no error

Actual behaviour

errors out

Log files

No response

The minimal config used to reproduce this issue.

I have telescope installed via nixpkgs. Maybe

local config = deps.require_telescope('telescope.config').values
is not always set by telescope. Might investigate later.

REPL toggleterm stopped working

Neovim version (nvim -v)

v0.8.2

Operating system/version

macOS 12.6.2

Output of haskell-language-server --version

haskell-language-server version: 1.9.0.0 (GHC: 9.4.4) (PATH: /Users/gacallea/.ghcup/hls/1.9.0.0/lib/haskell-language-server-1.9.0.0/bin/haskell-language-server-wrapper)

How to reproduce the issue

1 - set the REPL to toggleterm:

    repl = {
      -- 'builtin': Use the simple builtin repl
      -- 'toggleterm': Use akinsho/toggleterm.nvim
      handler = 'toggleterm',
    },

2 - launch the REPL with:

 :lua require('haskell-tools').repl.toggle(vim.api.nvim_buf_get_name(0))

Expected behaviour

  • open the repl with the haskell script loaded in ghci

Actual behaviour

  • the repl won't open anymore

This used to work just fine until a couple of days ago, when I packer synced my extensions. It may be an issue with one of the latest toggleterm update, not sure.

Log file

No response

Enable filtering of codeLenses in config

tools = {
  codeLens = {
    autoRefresh = true,
    typeSignatures = true,
    evaluateCodeSnippets = true,
   -- ...
  }
 -- ...
}

This will probably require a custom textDocument/codeLens handler (or a PR to neovim).

repl: detection of single-package cabal projects

Feature description

Single package cabal projects don't always have a cabal.project file.
The repl module should be able to construct cabal repl commands for such projects.

Currently, it builds a ghci command.

How to specify how a codelens is displayed

Question

Codelenses are displayed directly after some code with no space and in the same color that the code is written in. I would like them to be displayed in a different colour and perhaps with a separator, similarly to how I can style diagnostics.

Thanks in advance.

Where should binaries be installed with Nix?

Question

I'm trying to figure out where the best place is to include haskell-language-server when it comes to scope in NixOS. Should I couple hls in my flake based project directory and include haskell-tools in my global configuration? Or should I try and keep haskell-tools with my project?

My current neovim configuration is here:
https://github.com/collinarnett/brew/blob/main/modules/home-manager/neovim/neovim.nix

For scala, I keep my lsp server embedded in my project where my configuration for said lsp server stays in my global neovim configuration.

I'm sorta new to haskell and I don't have complex project with cabal and stack configurations but I would like to leverage auto-completion and error detection so I'm just a bit confused on where I should put things.

Option to enrich documentation on hover with information from Hackage

The hls provided documentation on hover is quite meager, compared to that on Hackage (unless the project is compiled with haddock, which can significantly impair performance).

haskell-language-server without haddock...

head :: forall a. [a] -> a
─────────────────────────────────────────
*Defined in β€˜GHC.List’* *(base-4.15.1.0)*

* * *

_ :: [Int] -> Int

vs Hackage...

head :: HasCallStack => [a] -> a

O(1)

. Extract the first element of a list, which must be non-empty.

>>> head [1, 2, 3]
1
>>> head [1..]
1
>>> head []
*** Exception: Prelude.head: empty list

WARNING: This function is partial. You can use case-matching, uncons or listToMaybe instead.

It might be useful to have an option to enrich the documentation with information fetched from Hackage.

cabal-hoogle support

cabal-hoogle is a tool for generating hoogle database for local packages and dependecies, like stack hoogle command, but for cabal projects.

A question about type signature color

First, thank you for the great plugin. It contains lots of useful functions. I feel joy to write haskell programs with it.

I have a question. Is there any way to change the highlight of type signature? I try to find it but no idea.

Screen Shot 2022-11-02 at 9 26 04 PM

Thank you for the help!

Module for interacting with ghci

  • Detect file type
  • Detect build tool (cabal | stack | fallback to ghci)
  • Send files, lines, selection, text objects, ... to repl

Possible alternative: iron.nvim
Does not seem flexible enough as a standalone, but it may be feasible to interface with it by setting repl_definition.haskell.command (?)

haskell-tools mappings don't seem to be picked up

Neovim version (nvim -v)

NVIM v0.9.0-dev+1009-gf1816f9ee

Operating system/version

Fedora 37

Output of haskell-language-server-wrapper --version

haskell-language-server version: 1.9.1.0 (GHC: 9.4.4)

How to reproduce the issue

  1. Open a Haskell project (like https://github.com/haskell-text/text-display for instance)
  2. Try and use a mapping like 'K' (hover)
  3. No result

Expected behaviour

Any kind of output or message.

Actual behaviour

nvim has a little spike of CPU consumption (from 0.0% to 0.7%) but nothing happens on the UI.

Log files

No response

The minimal config used to reproduce this issue.

-- Minimal nvim config with packer
-- Assumes a directory in $NVIM_DATA_MINIMAL
-- Start with $NVIM_DATA_MINIMAL=$(mktemp -d) nvim -u minimal.lua
-- Then exit out of neovim and start again.

-- Ignore default config
local buffer = vim.api.nvim_get_current_buf()
local fn = vim.fn
local config_path = fn.stdpath('config')
local def_opts = { noremap = true, silent = true, }
local keymap = vim.keymap


vim.opt.runtimepath:remove(config_path)

-- Ignore default plugins
local data_path = fn.stdpath('data')
local pack_path = data_path .. '/site'
vim.opt.packpath:remove(pack_path)

--append temporary config and pack dir
data_path = os.getenv('NVIM_DATA_MINIMAL')
if not data_path then
  error('$NVIM_DATA_MINIMAL environment variable not set!')
end
vim.opt.runtimepath:append('.')
vim.opt.runtimepath:append(data_path)
vim.opt.runtimepath:append(data_path .. '/site/pack/packer/start/plenary.nvim')
vim.opt.packpath:append(data_path .. '/site')

-- bootstrap packer
local packer_install_path = data_path .. '/site/pack/packer/start/packer.nvim'
local install_plugins = false

if vim.fn.empty(vim.fn.glob(packer_install_path)) > 0 then
  vim.cmd('!git clone [email protected]:wbthomason/packer.nvim ' .. packer_install_path)
  vim.cmd('packadd packer.nvim')
  install_plugins = true
else
  vim.cmd('packadd packer.nvim')
end

local packer = require('packer')

packer.init {
  package_root = data_path .. '/site/pack',
  compile_path = data_path .. '/plugin/packer_compiled.lua',
}

vim.cmd('runtime! plugin/plenary.vim')

packer.startup(function(use)
  use('wbthomason/packer.nvim')
  use {
    'MrcJkb/haskell-tools.nvim',
    requires = {
      'nvim-lua/plenary.nvim',
    },
    config = function()
      hls = {
        default_settings = {
          haskell = {
            checkProject = true,
          }
        },
        -- See nvim-lspconfig's  suggested configuration for keymaps, etc.
        on_attach = function(client, bufnr)
          local opts = vim.tbl_extend('keep', def_opts, { buffer = bufnr, })
          keymap.set('n', '<F2>', vim.lsp.buf.rename, opts)
          keymap.set('n', '<F3>', '<cmd>TroubleToggle<CR>', opts)
          keymap.set('n', '<F4>', vim.lsp.buf.code_action, opts)
          keymap.set('n', '<F5>', vim.lsp.codelens.run, opts)
          keymap.set('n', '<space>D', vim.lsp.buf.type_definition, opts)
          keymap.set('n', '<space>ca', vim.lsp.codelens.run, opts)
          keymap.set('n', '<space>e', vim.lsp.diagnostic.show_line_diagnostics, opts)
          keymap.set('n', '<space>ea', ht.lsp.buf_eval_all, opts)
          keymap.set('n', '<space>hs', ht.hoogle.hoogle_signature, opts)
          keymap.set('n', '<space>q', vim.lsp.diagnostic.set_loclist, opts)
          keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, opts)
          keymap.set('n', '<space>wl', print(vim.inspect(vim.lsp.buf.list_workspace_folders())), opts)
          keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, opts)
          keymap.set('n', 'K', vim.lsp.buf.hover, opts)
          keymap.set('n', '[d', vim.lsp.diagnostic.goto_prev, opts)
          keymap.set('n', ']d', vim.lsp.diagnostic.goto_next, opts)
          keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
          keymap.set('n', 'gh', ht.hoogle.hoogle_signature, opts)
          keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
          keymap.set('n', 'gr', vim.lsp.buf.references, opts)

        end,
      }

  if install_plugins then
    packer.sync()
  end
  end}
end)

Set up autocmds for tag generation

Feature description

Neovim's vim.lsp.tagfunc falls back to tags if textDocument/definition yields no results.

fast-tags is designed for use with autocmds.

Neovim could generate tags on { 'BufEnter', 'BufWritePost', 'FileType' }, by calling:

fast-tags -R <project-path> <package-path>

add health checks

Feature description

# autoload/health/haskell-tools.vim

function! health#haskell-tools#check()
  lua require 'haskell-tools.health'.check()
endfunction

Idea: Diagnostic actions

Feature description

Similar to hover actions, but for diagnostics.

In monorepos with multiple projects, hls will fail to start if there is an error in a subpackage the package depends on. It will show a single diagnostic containing the ghc error, including the file where the error occurred.
In this case, a diagnostic action could parse the error location and add an action for going to the error location (This might be something to improve in hls).

Additionally, hls sometimes provides code actions that can fix diagnostic issues. These could be identified and presented as diagnostic actions, too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.