on master help sign in
Merge pull request #663 from obsidiansystems/eac@ghcide

Experimental ghcide support

commitdcd09beba47b23663f6e8f588214356ebd881d5a authorElliot Cameron <3noch@users.noreply.github.com> dateTue 21 Apr 2020, 10:03 (6 years ago) parente19ac204e28db0
4 files changed+103−11
README.md+44−4 all-builds.nix+14−5 default.nix+11−2 haskell-overlays/ghcide.nix+34
README.md+44−4
@@ -10,7 +10,10 @@ Obelisk provides an easy way to develop and deploy your [Reflex](https://github.
1010- [Developing an Obelisk project](#developing-an-obelisk-project)
1111 - [Adding Packages](#adding-packages)
1212 - [Adding Package Overrides](#adding-package-overrides)
13− - [Running over https](#running-over-https)
13+ - [Running over HTTPS](#running-over-https)
14+ - [IDE Support](#ide-support)
15+ - [Terminal-based feedback](#terminal-based-feedback)
16+ - [Experimental `ghcide` support](#experimental-ghcide-support)
1417- [Deploying](#deploying)
1518 - [Locally](#locally)
1619 - [Default EC2 Deployment](#default-ec2-deployment)
@@ -169,9 +172,46 @@ project ./. ({ pkgs, ... }: {
169172
170173### Running over HTTPS
171174
172−To run your app locally over https, update the protocol in `config/common/route` to `https`, and then use `ob run` as normal.
173−
174−Since Obelisk generates a self-signed certificate for running https, the browser will issue a warning about using an invalid certificate. On Chrome, you can go to `chrome://flags/#allow-insecure-localhost` to enable invalid certificates for localhost.
175+To run your app locally over HTTPS, update the protocol in `config/common/route` to `https`, and then use `ob run` as normal.
176+
177+Since Obelisk generates a self-signed certificate for running HTTPS, the browser will issue a warning about using an invalid certificate. On Chrome, you can go to `chrome://flags/#allow-insecure-localhost` to enable invalid certificates for localhost.
178+
179+### IDE Support
180+
181+#### Terminal-based feedback
182+
183+Obelisk officially supports terminal-based feedback (akin to [`ghcid`](https://github.com/ndmitchell/ghcid)) in `ob run` and `ob watch`.
184+
185+#### **Experimental** `ghcide` support
186+
187+> **NOTE:** `ghcide` support is strictly **experimental** and **not officially supported**. There is no guarantee that it will work for you or that this support will be maintained over time.
188+
189+To try out the **experimental** [`ghcide`](https://github.com/digital-asset/ghcide) support:
190+
191+ * Install a `ghcide` plugin for your editor.
192+ * Add `__withGhcide = true;` to your Obelisk project's `default.nix` (inside the call to `project`). With this setting, `ob shell` will provide `ghcide` as well.
193+ * Add `hie-bios.sh` to the root of your project:
194+ ```shell
195+ cat > hie-bios.sh <<'EOF'
196+ #!/usr/bin/env bash
197+ source "$HOME/.bash_profile"; # NOTE: Some editors need help finding 'ob' and this assumes that `ob` is made available on your `$PATH` in `.bash_profile`
198+ ob internal export-ghci-configuration > "$HIE_BIOS_OUTPUT"
199+ EOF
200+ chmod +x hie-bios.sh
201+ ```
202+ * Add `hie.yaml` to the root of your project:
203+ ```shell
204+ echo 'cradle: { bios: { program: hie-bios.sh } }' > hie.yaml
205+ ```
206+ * Test the configuration with `ob shell ghcide`. Assuming your project compiles and works with `ghcide` otherwise, this should succeed.
207+ * Start your editor in a way that it can access the appropriate `ghcide`:
208+ * This can sometimes be achieved with `ob shell 'start my editor'`.
209+ * If you can't easily start your editor in a way that it inherits your shell, you may need to customize how your `ghcide` plugin finds `ghcide` or create a custom `ghcide` replacement script that you install globally. For example, for Visual Studio Code on macOS adding a script called `ghcide` to your `PATH` like the one below will cause `ghcide` from each project's `ob shell` to be used:
210+ ```shell
211+ #!/usr/bin/env bash
212+ source "$HOME/.bash_profile" # NOTE: This assumes that `ob` is made available on your `$PATH` in `.bash_profile`
213+ ob shell "ghcide $@"
214+ ```
175215
176216## Deploying
177217
all-builds.nix+14−5
@@ -53,19 +53,28 @@ let
5353 obelisk.haskellPackageSets.ghcjs
5454 obeliskPackagesCommon;
5555 command = obelisk.command;
56− skeleton = import ./skeleton { inherit obelisk; };
57− serverSkeletonExe = skeleton.exe;
56+
57+ withSkeletonOptions = skel: options: (skel.passthru.__unstable__.self.extend (self: super: {
58+ userSettings = super.userSettings // options;
59+ })).project;
60+ rawSkeleton = import ./skeleton { inherit obelisk; };
61+ skeleton = withSkeletonOptions rawSkeleton {
62+ withHoogle = true; # cache the Hoogle database for the skeleton
63+ __withGhcide = true; # cache the ghcide build for the skeleton
64+ };
65+
66+ serverSkeletonExe = rawSkeleton.exe;
5867 # TODO fix nixpkgs so it doesn't try to run the result of haskell shells as setup hooks.
5968 serverSkeletonShell = local-self.nixpkgs.runCommand "shell-safe-for-dep" {} ''
6069 touch "$out"
6170 echo "return" >> "$out"
6271 cat "${skeleton.shells.ghc}" >> "$out"
6372 '';
64− androidSkeleton = (import ./skeleton { inherit obelisk; }).android.frontend;
65− iosSkeleton = (import ./skeleton { inherit obelisk; }).ios.frontend;
73+ androidSkeleton = skeleton.android.frontend;
74+ iosSkeleton = skeleton.ios.frontend;
6675 nameSuffix = if profiling then "profiled" else "unprofiled";
6776 packages = {
68− skeletonProfiledObRun = skeleton.__unstable__.profiledObRun;
77+ skeletonProfiledObRun = rawSkeleton.__unstable__.profiledObRun;
6978 inherit
7079 command
7180 serverSkeletonShell
default.nix+11−2
@@ -207,13 +207,14 @@ in rec {
207207 , shellToolOverrides ? _: _: {}
208208 , withHoogle ? false # Setting this to `true` makes shell reloading far slower
209209 , __closureCompilerOptimizationLevel ? "ADVANCED" # Set this to `null` to skip the closure-compiler step
210+ , __withGhcide ? false
210211 }:
211212 let
212213 allConfig = nixpkgs.lib.makeExtensible (self: {
213214 base = base';
214215 inherit args;
215216 userSettings = {
216− inherit android ios packages overrides tools shellToolOverrides withHoogle __closureCompilerOptimizationLevel;
217+ inherit android ios packages overrides tools shellToolOverrides withHoogle __closureCompilerOptimizationLevel __withGhcide;
217218 staticFiles = if staticFiles == null then self.base + /static else staticFiles;
218219 };
219220 frontendName = "frontend";
@@ -270,9 +271,17 @@ in rec {
270271 self.frontendName
271272 ];
272273
274+ shellToolOverrides = lib.composeExtensions
275+ self.userSettings.shellToolOverrides
276+ (if self.userSettings.__withGhcide
277+ then (import ./haskell-overlays/ghcide.nix)
278+ else (_: _: {})
279+ );
280+
273281 project = reflexPlatformProject ({...}: self.projectConfig);
274282 projectConfig = {
275− inherit (self.userSettings) shellToolOverrides tools withHoogle;
283+ inherit (self) shellToolOverrides;
284+ inherit (self.userSettings) tools withHoogle;
276285 overrides = self.totalOverrides;
277286 packages = self.combinedPackages;
278287 shells = {
haskell-overlays/ghcide.nixnew file+34
@@ -0,0 +1,34 @@
1+self: super:
2+ let
3+ pkgs = self.callPackage ({ pkgs }: pkgs) {};
4+ inherit (pkgs.haskell.lib) dontCheck;
5+ in {
6+ ghcide = pkgs.haskell.lib.justStaticExecutables (dontCheck ((self.override {
7+ overrides = self: super: {
8+ ghc-check = self.callHackageDirect {
9+ pkg = "ghc-check";
10+ ver = "0.1.0.3";
11+ sha256 = "038llbvryk5y27jbdpbshp0zw5lw1j6m7qk7vx1n96ykqdzkh649";
12+ } {};
13+ lsp-test = dontCheck (self.callHackage "lsp-test" "0.6.1.0" {});
14+ haddock-library = dontCheck (self.callHackage "haddock-library" "1.8.0" {});
15+ haskell-lsp = dontCheck (self.callHackage "haskell-lsp" "0.19.0.0" {});
16+ haskell-lsp-types = dontCheck (self.callHackage "haskell-lsp-types" "0.19.0.0" {});
17+ regex-posix = dontCheck (self.callHackage "regex-posix" "0.96.0.0" {});
18+ test-framework = dontCheck (self.callHackage "test-framework" "0.8.2.0" {});
19+ regex-base = dontCheck (self.callHackage "regex-base" "0.94.0.0" {});
20+ regex-tdfa = dontCheck (self.callHackage "regex-tdfa" "1.3.1.0" {});
21+ shake = dontCheck (self.callHackage "shake" "0.18.4" {});
22+ hie-bios = dontCheck (self.callHackageDirect {
23+ pkg = "hie-bios";
24+ ver = "0.4.0";
25+ sha256 = "19lpg9ymd9656cy17vna8wr1hvzfal94gpm2d3xpnw1d5qr37z7x";
26+ } {});
27+ };
28+ }).callCabal2nix "ghcide" (pkgs.fetchFromGitHub {
29+ owner = "digital-asset";
30+ repo = "ghcide";
31+ rev = "v0.1.0";
32+ sha256 = "1kf71iix46hvyxviimrcv7kvsj67hcnnqlpdsmazmlmybf7wbqbb";
33+ }) {}));
34+}