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

Support automatic installation #92

Open
michaelpj opened this issue Nov 19, 2020 · 10 comments · May be fixed by #97
Open

Support automatic installation #92

michaelpj opened this issue Nov 19, 2020 · 10 comments · May be fixed by #97

Comments

@michaelpj
Copy link
Collaborator

lsp-mode now lets clients specify download-server-fun which can be used to automatically install the server. We have static binaries so we should be able to do this. We can probably do the same thing as the vscode extension.

@michaelpj
Copy link
Collaborator Author

It looks like they may be trying to abstract out the whole provision of binaries with this lsp-dependency thing, but I'm not really sure yet.

@lukel97
Copy link

lukel97 commented Dec 5, 2020

I'm taking a quick stab at this. Will report back

@michaelpj
Copy link
Collaborator Author

Quick notes on where I got to:

@lukel97
Copy link

lukel97 commented Dec 5, 2020

@michaelpj I was looking at the exact same files as you commented this 😃 We could do either the fancy thing that vscode-haskell does where it first downloads the wrapper, checks the version, and then downloads the corresponding GHC version binary. Or we can just download all of them including the wrapper at once. The latter will be simpler to do, but the former is nicer on disk space

@michaelpj
Copy link
Collaborator Author

I'd probably just do the latter. I think it's fine to download a reasonably chunky "distribution", especially since then it's all set up for various GHC versions. We can always be pickier later if people complain!

@lukel97
Copy link

lukel97 commented Dec 11, 2020

The first scenario was not too difficult actually: The way lsp-mode.el handles finding executables and dependencies means it only really downloads what it needs. Our binaries are compressed with gzip though, so I've had to make a PR upstream to allow us to decompress them emacs-lsp/lsp-mode#2400

@lukel97
Copy link

lukel97 commented Dec 11, 2020

diff --git a/lsp-haskell.el b/lsp-haskell.el
index c85b430..9ae750d 100644
--- a/lsp-haskell.el
+++ b/lsp-haskell.el
@@ -1,4 +1,4 @@
-;;; lsp-haskell.el --- Haskell support for lsp-mode
+;;; lsp-haskell.el --- Haskell support for lsp-mode -*- lexical-binding: t; -*-
 
 ;; Version: 1.0
 ;; Package-Requires: ((lsp-mode "3.0") (haskell-mode "1.0"))
@@ -246,15 +246,53 @@ and `lsp-haskell-server-args' and `lsp-haskell-server-wrapper-function'."
 ;; https://microsoft.github.io/language-server-protocol/specification#textDocumentItem
 (add-to-list 'lsp-language-id-configuration '(haskell-literate-mode . "haskell"))
 
+(defun lsp-haskell--github-system-type-suffix ()
+  (pcase system-type
+    ('gnu/linux "Linux")
+    ('windows-nt "Windows")
+    ('darwin "macOS")))
+
+(defcustom lsp-haskell-language-server-github-releases-url
+  "https://github.com/haskell/haskell-language-server/releases/latest/download/"
+  "GitHub releases url for haskell-language-server and its binaries. Make sure to include the trailing directory slash."
+  :type 'string
+  :group 'lsp-haskell
+  :package-version '(lsp-mode . "7.1"))
+
+(lsp-dependency
+ 'haskell-language-server-wrapper
+ '(:system "haskell-language-server-wrapper")
+ `(:download :url ,(concat lsp-haskell-language-server-github-releases-url
+			  (format "haskell-language-server-wrapper-%s.gz"
+				  (lsp-haskell--github-system-type-suffix)))
+	     :store-path ,(f-join lsp-server-install-dir "haskell" "haskell-language-server-wrapper")
+	     :gzip? t
+	     :set-executable? t))
+
+(defun lsp-haskell--project-ghc-version ()
+  (s-trim
+   (shell-command-to-string
+    (format "%s --project-ghc-version 2>/dev/null"
+	    (lsp-package-path 'haskell-language-server-wrapper)))))
+
 ;; Register the client itself
 (lsp-register-client
   (make-lsp--client
-    :new-connection (lsp-stdio-connection (lambda () (lsp-haskell--server-command)))
+   :new-connection (lsp-stdio-connection
+		    (lambda ()
+		      (let* ((proj-ghc-ver (lsp-haskell--project-ghc-version))
+			     (store-path (f-join lsp-server-install-dir "haskell" (format "haskell-language-server-%s" proj-ghc-ver))))
+			(message (format "proj-ghc-ver is %s\n path %s " proj-ghc-ver store-path))
+			(list
+			 (lsp-download-path
+			  :store-path store-path
+			  :set-executable? t)
+			 "--lsp"))))
     ;; Should run under haskell-mode and haskell-literate-mode. We need to list the
     ;; latter even though it's a derived mode of the former
     :major-modes '(haskell-mode haskell-literate-mode)
     ;; This is arbitrary.
-    :server-id 'lsp-haskell
+    :server-id 'haskell-language-server
     ;; We need to manually pull out the configuration section and set it. Possibly in
     ;; the future lsp-mode will asssociate servers with configuration sections more directly.
     :initialized-fn (lambda (workspace)
@@ -263,6 +301,26 @@ and `lsp-haskell-server-args' and `lsp-haskell-server-wrapper-function'."
     ;; This is somewhat irrelevant, but it is listed in lsp-language-id-configuration, so
     ;; we should set something consistent here.
     :language-id "haskell"
+    :download-server-fn (lambda (_client callback error-callback _update?)
+			  (lsp-package-ensure
+			   'haskell-language-server-wrapper
+			   (lambda ()
+			     (let*
+				 ((proj-ghc-ver (lsp-haskell--project-ghc-version))
+				  (binary-store-path
+				   (f-join lsp-server-install-dir "haskell" (format "haskell-language-server-%s" proj-ghc-ver))))
+			       (lsp-download-install
+				callback
+				error-callback
+				:url (concat
+				      lsp-haskell-language-server-github-releases-url
+				      (format
+				       "haskell-language-server-%s-%s.gz"
+				       (lsp-haskell--github-system-type-suffix)
+				       proj-ghc-ver))
+				:store-path binary-store-path
+				:gzip? t)))
+			   error-callback))
     ))
 
 ;; ---------------------------------------------------------------------

Here's my POC though with this upstream patch: https://streamable.com/d7se3g

@alanz
Copy link
Contributor

alanz commented Dec 11, 2020

@bubba looks great

@lukel97 lukel97 linked a pull request Dec 12, 2020 that will close this issue
@jcs090218
Copy link
Member

Any progress on this?

@michaelpj
Copy link
Collaborator Author

Nope. If someone wants to pick this up now, I'd highly recommend delegating to ghcup for installation, that's what the vscode extension does.

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

Successfully merging a pull request may close this issue.

4 participants