|
32 | 32 | :link '(url-link "https://github.com/eclipse-che4z/che-che4z-lsp-for-cobol")
|
33 | 33 | :package-version `(lsp-mode . "8.0.1"))
|
34 | 34 |
|
| 35 | +(defcustom lsp-cobol-server-path nil |
| 36 | + "Path points for COBOL language service. |
| 37 | +
|
| 38 | +This is only for development use." |
| 39 | + :type 'string |
| 40 | + :group 'lsp-cobol) |
| 41 | + |
35 | 42 | (defcustom lsp-cobol-port 1044
|
36 | 43 | "Port to connect server to."
|
37 | 44 | :type 'integer
|
38 | 45 | :group 'lsp-cobol)
|
39 | 46 |
|
| 47 | +;; |
| 48 | +;;; Util |
| 49 | + |
| 50 | +(defmacro lsp-cobol--mute-apply (&rest body) |
| 51 | + "Execute BODY without message." |
| 52 | + (declare (indent 0) (debug t)) |
| 53 | + `(let (message-log-max) |
| 54 | + (with-temp-message (or (current-message) nil) |
| 55 | + (let ((inhibit-message t)) ,@body)))) |
| 56 | + |
| 57 | +(defun lsp-cobol--execute (cmd &rest args) |
| 58 | + "Return non-nil if CMD executed succesfully with ARGS." |
| 59 | + (save-window-excursion |
| 60 | + (lsp-cobol--mute-apply |
| 61 | + (= 0 (shell-command (concat cmd " " |
| 62 | + (mapconcat #'shell-quote-argument |
| 63 | + (cl-remove-if #'null args) |
| 64 | + " "))))))) |
| 65 | + |
| 66 | +;; |
| 67 | +;;; Installation |
| 68 | + |
| 69 | +(defcustom lsp-cobol-server-store-path |
| 70 | + (expand-file-name "cobol/" lsp-server-install-dir) |
| 71 | + "The path to the file in which COBOL language service will be stored." |
| 72 | + :type 'file |
| 73 | + :group 'lsp-cobol) |
| 74 | + |
| 75 | +(defcustom lsp-cobol-server-version "2.1.1" |
| 76 | + "The COBOL language service version to install." |
| 77 | + :type 'file |
| 78 | + :group 'lsp-cobol) |
| 79 | + |
| 80 | +(defconst lsp-cobol-download-url-format |
| 81 | + "https://github.com/eclipse-che4z/che-che4z-lsp-for-cobol/releases/download/%s/cobol-language-support-%s-%s-%s%s.vsix" |
| 82 | + "Format to the download url link.") |
| 83 | + |
| 84 | +(defun lsp-cobol--server-url () |
| 85 | + "Return Url points to the cobol language service's zip/tar file." |
| 86 | + (let* ((x86 (string-prefix-p "x86_64" system-configuration)) |
| 87 | + (arch (if x86 "x64" "arm64")) |
| 88 | + (version lsp-cobol-server-version)) |
| 89 | + (cl-case system-type |
| 90 | + ((cygwin windows-nt ms-dos) |
| 91 | + (format lsp-cobol-download-url-format |
| 92 | + version "win32" arch version "-signed")) |
| 93 | + (darwin |
| 94 | + (format lsp-cobol-download-url-format |
| 95 | + version "darwin" arch version "")) |
| 96 | + (gnu/linux |
| 97 | + (format lsp-cobol-download-url-format |
| 98 | + version "linux" arch version ""))))) |
| 99 | + |
| 100 | +(defvar lsp-cobol--server-download-url (lsp-cobol--server-url) |
| 101 | + "The actual url used to download language server.") |
| 102 | + |
| 103 | +(defvar lsp-cobol--downloaded-file (f-join lsp-cobol-server-store-path "temp.tar") |
| 104 | + "The full file path after downloading the server zipped file.") |
| 105 | + |
| 106 | +(defun lsp-cobol--extract-compressed-file (callback) |
| 107 | + "Install COBOL language service." |
| 108 | + (cond ((file-exists-p lsp-cobol--downloaded-file) |
| 109 | + ;; Suprisingly, you can just use `tar' to unzip a zip file on Windows. |
| 110 | + ;; Therefore, just use the same command. |
| 111 | + (lsp-cobol--execute "tar" "-xvzf" lsp-cobol--downloaded-file "-C" lsp-cobol-server-store-path) |
| 112 | + ;; Delete the zip file. |
| 113 | + (ignore-errors (delete-file lsp-cobol--downloaded-file))) |
| 114 | + (t |
| 115 | + (error "Can't extract the downloaded file: %s" lsp-cobol--downloaded-file))) |
| 116 | + (funcall callback)) |
| 117 | + |
| 118 | +(defun lsp-cobol--stored-executable () |
| 119 | + "Return the stored COBOL language service executable." |
| 120 | + (executable-find |
| 121 | + (f-join lsp-cobol-server-store-path |
| 122 | + (concat "extension/server/native/" |
| 123 | + (cl-case system-type |
| 124 | + ((cygwin windows-nt ms-dos) "engine.exe") |
| 125 | + (darwin "server-mac") |
| 126 | + (gnu/linux "server-linux")))))) |
| 127 | + |
| 128 | +(lsp-dependency |
| 129 | + 'cobol-ls |
| 130 | + '(:system "cobol-ls") |
| 131 | + `(:download :url ,lsp-cobol--server-download-url |
| 132 | + :store-path ,lsp-cobol--downloaded-file)) |
| 133 | + |
| 134 | +;; |
| 135 | +;;; Server |
| 136 | + |
| 137 | +;;;###autoload |
| 138 | +(add-hook 'cobol-mode-hook #'lsp-cobol-start-ls) |
| 139 | + |
| 140 | +;;;###autoload |
| 141 | +(defun lsp-cobol-start-ls () |
| 142 | + "Start the COBOL language service." |
| 143 | + (interactive) |
| 144 | + (when-let ((exe (lsp-cobol--executable)) |
| 145 | + ((lsp--port-available "localhost" lsp-cobol-port))) |
| 146 | + (lsp-async-start-process #'ignore #'ignore exe))) |
| 147 | + |
| 148 | +;; |
| 149 | +;;; Core |
| 150 | + |
| 151 | +(defun lsp-cobol--executable () |
| 152 | + "Return the COBOL language service executable." |
| 153 | + (or lsp-cobol-server-path |
| 154 | + (lsp-cobol--stored-executable))) |
| 155 | + |
| 156 | +(defun lsp-cobol-server-start-fn (&rest _) |
| 157 | + "Define COOBL language service start function." |
| 158 | + `(,(lsp-cobol--executable))) |
| 159 | + |
40 | 160 | (defun lsp-cobol--tcp-connect-to-port ()
|
41 | 161 | "Define a TCP connection to language server."
|
42 | 162 | (list
|
43 |
| - :connect (lambda (filter sentinel name _environment-fn _workspace) |
44 |
| - (let* ((host "localhost") |
45 |
| - (port lsp-cobol-port) |
46 |
| - (tcp-proc (lsp--open-network-stream host port (concat name "::tcp")))) |
| 163 | + :connect |
| 164 | + (lambda (filter sentinel name _environment-fn _workspace) |
| 165 | + (let* ((host "localhost") |
| 166 | + (port lsp-cobol-port) |
| 167 | + (tcp-proc (lsp--open-network-stream host port (concat name "::tcp")))) |
47 | 168 |
|
48 |
| - (set-process-query-on-exit-flag tcp-proc nil) |
49 |
| - (set-process-filter tcp-proc filter) |
50 |
| - (set-process-sentinel tcp-proc sentinel) |
51 |
| - (cons tcp-proc tcp-proc))) |
52 |
| - :test? (lambda () t))) |
| 169 | + ;; TODO: Same :noquery issue (see above) |
| 170 | + (set-process-query-on-exit-flag tcp-proc nil) |
| 171 | + (set-process-filter tcp-proc filter) |
| 172 | + (set-process-sentinel tcp-proc sentinel) |
| 173 | + (cons tcp-proc tcp-proc))) |
| 174 | + :test? (lambda () (file-executable-p (lsp-cobol--executable))))) |
53 | 175 |
|
54 | 176 | (lsp-register-client
|
55 |
| - (make-lsp-client :new-connection (lsp-cobol--tcp-connect-to-port) |
56 |
| - :activation-fn (lsp-activate-on "cobol") |
57 |
| - :server-id 'cobol)) |
| 177 | + (make-lsp-client |
| 178 | + :new-connection (lsp-cobol--tcp-connect-to-port) |
| 179 | + :activation-fn (lsp-activate-on "cobol") |
| 180 | + :priority -1 |
| 181 | + :server-id 'cobol-ls |
| 182 | + :download-server-fn |
| 183 | + (lambda (_client callback error-callback _update?) |
| 184 | + (lsp-package-ensure 'cobol-ls |
| 185 | + (lambda () (lsp-cobol--extract-compressed-file callback)) |
| 186 | + error-callback)))) |
58 | 187 |
|
59 | 188 | (lsp-consistency-check lsp-cobol)
|
60 | 189 |
|
|
0 commit comments