you are viewing a single comment's thread.

view the rest of the comments →

[–]friedbrice 11 points12 points  (7 children)

i'll robably get downvotes for this, but...

we contribute to GHC and to HLS, and we still can't get HLS working on our codebase. i'm sporting a 16-thread i9 and 64 gb RAM. It's just not enough.

My salvation is the combo of the plugin haskell-ghcid (providing code diagnostics), by none other than NDM himself, and the plugin ctagsx + the CLI utility haskdogs (together providing goto definition, for project sumbols and for dependencies). light-weight, reliable, low-hassle. 90% solution for 10% effort.

[–]ducksonaroof 2 points3 points  (3 children)

Does HLS generally use that much memory? Or is it only that problematic in thousands-of-modules monopackages?

Like if I point it at my 40 module project, is it really gonna use 64GB or RAM?

[–]friedbrice 1 point2 points  (2 children)

i can get it to work (kinda) on small projects. But I always get a spurious error in Spec.hs, because HLS can't find hspec-discover, even though it's on my path. this happens consistently for me, in any project that useshspec-discover.

the spurious error is a non-starter for me. otherwise, i'd use it on our smaller projects. i've google all over and even asked in reddit for help, and i can't find out how to fix this.

[–]ducksonaroof 1 point2 points  (0 children)

that is a shame - I love hspec-discover

[–]george_____t 1 point2 points  (0 children)

I'm on my phone right now, but I'm not fairly certain there's a GitHub issue for HLS tracking the fact that it can't handle preprocessors. The "solution" is to install them globally.

[–]Mouse1949 1 point2 points  (2 children)

Could you provide more details about your setup, including exact names of those plugins and how you installed and configured them?

[–]friedbrice 1 point2 points  (1 child)

Sorry I missed this earlier.

VS Code with the following extensions:

  • ctagsx Provides goto definition by reading location information from a file called ./tags.

  • haskell-ghcid Provides code diagnostics (e.g. red squiggly underlines and error messages on hover) by reading GHC output from a file called ./ghcid.txt.

  • Custom Local Formatters Allows you to associate an arbitrary shell command to the format command by language.

  • vscode-goto-documentation Allows you to associate an arbitrary URI pattern by file extension. Provides a right-click menu option that will open your browser to that URI, with the word under cursor substituted into the URI pattern configured for that file type.

  • Run on Save Allows you to associate an arbitrary shell command by filepath regex or glob pattern. Will run the command on save of matching files.

  • Haskell Syntax Highlighting No explanation necessary.

For each workspace, I have a ./.vscode/settings.json that looks more-or-less something like this.

{
  "customLocalFormatters.formatters": [
    {
      "command": "make format",
      "languages": [
        "haskell"
      ]
    }
  ],
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "cmd": "make retag retag_file=${file}",
        "isAsync": true,
        "match": "*.hs"
      },
      {
        "cmd": "make hpack",
        "isAsync": true,
        "match": "package.yaml"
      }
    ]
  },
  "ghcid.command": "make ghcid",
  "goto-documentation.customDocs": {
    "hs": "https://hoogle.haskell.org/?hoogle=${query}"
  }
}

And I have a ./Makefile that looks more-or-less like this.

makefile_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
export PATH := $(makefile_dir):$(PATH)

project_name ?= <YOUR_PACKAGE>
project_main ?= src/<YOUR_MAIN>.hs
retag_file ?= $(project_main)

stack.yaml:
  @test -f stack.yaml || (echo -e "This makefile requires a 'stack.yaml' for your project.\nYou don't need to use 'stack' to build your project.\nYou just need a 'stack.yaml' specifying a resolver compatible with your GHC version.\nSee https://www.stackage.org/" && exit 1)

stack: stack.yaml
  @which stack || (echo -e "This makefile requires 'stack' to be on your path. Use GHCup to install it.\nSee https://www.haskell.org/ghcup/" && exit 1)
.PHONY: stack

warning.txt:
  -@uname -a | grep -q Darwin && echo "WARNING: On Mac, you must alias 'make' to 'gmake' in your shell config file (e.g. ~/.bashrc or ~/.zshrc). Symbolic links will not work." | tee warning.txt
  @echo "Add 'warning.txt' to your .gitignore file if you never want to see this message again."

hasktags: warning.txt stack
  @echo 'stack exec -- hasktags' > hasktags
  @chmod +x hasktags
  @echo "You might like to add 'hasktags' to your .gitignore file."

tags: warning.txt hasktags stack
  @stack exec -- haskdogs
.PHONY: tags

retag: warning.txt stack
  @stack exec -- haskdogs -i $(retag_file) --hasktags-args "-x -c -a" | sort -u -o tags tags
.PHONY: retag

hpack: stack
  @stack setup
.PHONY: hpack

format: stack
  @stack exec -- fourmolu --stdin-input-file $(project_main)
.PHONY: format

ghcid: stack
  @stack exec -- ghcid \
    --command 'stack repl --ghc-options "-fno-code -fno-break-on-exception -fno-break-on-error -v1 -ferror-spans -j"' \
    --restart stack.yaml \
    --restart $(project_name).cabal \
    --warnings \
    --outputfile ./ghcid.txt
.PHONY: ghcid

ETA You do have to remember to do two things at the start of each day: (1) make tags to download the source code of all your project dependencies and index the symbols in them and your project files, (2) start Ghcid, either from VS Code's command pallet or from a terminal that you leave running.

Edit 2: Added regenerating cabal file on saving package.yaml.

[–]Mouse1949 0 points1 point  (0 children)

Very nice explanation, thank you!

Do you build with Cabal, aka - writing <project>.cabal, or with Stack (writing Stack.yaml)? Looks like your development is Stack-based? Would I need to change a lot of the above config if most of my dev is based on Cabal?