Skip to content

Instantly share code, notes, and snippets.

@twlz0ne
Created April 2, 2019 17:37
Show Gist options
  • Save twlz0ne/a34bee2f5b2b62772ebe42756a1fb469 to your computer and use it in GitHub Desktop.
Save twlz0ne/a34bee2f5b2b62772ebe42756a1fb469 to your computer and use it in GitHub Desktop.
;;; Usage: /path/to/emacs -nw -Q -l /path/to/test-lsp-find-clients.el
;;; Preset:
;;
;; mkdir ~/scratch/c-c++/test-lsp-{clangd,cquery}
;; touch ~/scratch/c-c++/test-lsp-{clangd,cquery}/main.cc
;; touch ~/scratch/c-c++/test-lsp-clangd/CLANGD
;; touch ~/scratch/c-c++/test-lsp-cquery/CQUERY
;;
;;; Date: 2019-04-02_20.20.27
(toggle-debug-on-error)
(global-set-key (kbd "C-h") 'delete-backward-char)
(global-set-key (kbd "M-h") 'backward-kill-word)
(global-set-key (kbd "<f1>") 'help-command)
(define-key isearch-mode-map "\C-h" 'isearch-delete-char)
;; ------------------------------------------------------------------
(setq user-emacs-directory (format "~/.emacs.d/%s/%s/" (file-name-base load-file-name) emacs-version))
(setq package-user-dir (concat user-emacs-directory "elpa/"))
(unless (load "~/.emacs.d/elpa.el" t)
(setq package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/"))))
(package-initialize)
(defun require-packages (&rest packages)
(dolist (pkg packages)
(unless (package-installed-p pkg)
(package-refresh-contents)
(package-install pkg))
(require pkg)))
;; ------------------------------------------------------------------
;; (setq el-get-dir (concat user-emacs-directory "el-get/"))
;; (add-to-list 'load-path (concat el-get-dir "el-get"))
;;
;; (setq el-get-git-shallow-clone t)
;; (setq el-get-byte-compile nil)
;; (setq el-get-bundle-byte-compile nil)
;; (setq el-get-install-skip-emacswiki-recipes t)
;;
;; (unless (require 'el-get nil 'noerror)
;; (with-current-buffer
;; (url-retrieve-synchronously
;; "https://raw.githubusercontent.com/dimitri/el-get/master/el-get-install.el")
;; (goto-char (point-max))
;; (eval-print-last-sexp)))
;;
;; (remove-hook 'el-get-post-install-hooks 'el-get-post-install-notification)
;; ------------------------------------------------------------------
(require-packages
'projectile
'lsp-mode
'company-lsp
'cquery
'ivy)
(require 'lsp-clients)
(require 'cl)
(message "\n---------- start init")
(defmacro lsp-set-activation-fn (server-id fn)
"Store function FN into slot `activation-fn' of client identified by SERVER-ID.
\(fn 'example-ls 'example-activation-func)"
`(let ((cl-x (gethash ,server-id lsp-clients))
(slot (cl-struct-slot-offset 'lsp--client 'activation-fn)))
(assert (and cl-x slot))
(message "==> [lsp-set-activation-fn] server-id: %s, fn: %s" ,server-id ',fn)
(aset cl-x slot ,fn)))
(defun lsp--find-clients@override (buffer-major-mode file-name)
"Fix the misjudgement in original `lsp--find-clients'.
If a client has -activation-fn, it should not continue to check -major-modes."
(let ((remote? (file-remote-p file-name)))
(--when-let (->> lsp-clients
hash-table-values
(-filter (-lambda (client)
(and (or (-some-> client lsp--client-activation-fn (funcall buffer-file-name buffer-major-mode))
(and (not (lsp--client-activation-fn client)) ;; +++
(-contains? (lsp--client-major-modes client) buffer-major-mode)
(eq (---truthy? remote?) (---truthy? (lsp--client-remote? client)))))
(-some-> client lsp--client-new-connection (plist-get :test?) funcall)))))
(lsp-log "Found the following clients for %s: %s"
file-name
(s-join ", "
(-map (lambda (client)
(format "(server-id %s, priority %s)"
(lsp--client-server-id client)
(lsp--client-priority client)))
it)))
(-let* (((add-on-clients main-clients) (-separate 'lsp--client-add-on? it))
(selected-clients (if-let (main-client (and main-clients
(--max-by (> (lsp--client-priority it)
(lsp--client-priority other))
main-clients)))
(cons main-client add-on-clients)
add-on-clients)))
(lsp-log "The following clients were selected based on priority: %s"
(s-join ", "
(-map (lambda (client)
(format "(server-id %s, priority %s)"
(lsp--client-server-id client)
(lsp--client-priority client)))
selected-clients)))
selected-clients))))
(defun lsp-clangd-active-p (filename mode)
(message "==> [lsp-clangd-active-p] file: %s" filename)
(let ((active-p
(and
(eq 'c++-mode mode)
(file-exists-p (concat (lsp-workspace-root filename) "CLANGD")))))
(message "==> [lsp-clangd-active-p] active-p: %s" active-p)
active-p))
(defun lsp-cquery-active-p (filename mode)
(message "==> [lsp-cquery-active-p] file: %s" filename)
(let ((active-p
(and
(eq 'c++-mode mode)
(file-exists-p (concat (lsp-workspace-root filename) "CQUERY")))))
(message "==> [lsp-cquery-active-p] active-p: %s" active-p)
active-p))
(message "clients: %s" (hash-table-keys lsp-clients))
(message "major-modes[clangd]: %s" (lsp--client-major-modes (gethash 'clangd lsp-clients)))
(message "major-modes[cquery]: %s" (lsp--client-major-modes (gethash 'cquery lsp-clients)))
(lsp-set-activation-fn 'clangd 'lsp-clangd-active-p)
(lsp-set-activation-fn 'cquery 'lsp-cquery-active-p)
(add-hook 'c++-mode-hook 'lsp)
;; for mac with homebrew
(add-to-list 'exec-path "/usr/local/opt/llvm/bin/")
(add-hook 'after-init-hook
(lambda ()
(ivy-mode 1)
(message "\n---------- after init")
;; FIX issue that the role of the `client-activation-fn' is offset
(advice-add 'lsp--find-clients :override 'lsp--find-clients@override)
;; expected clangd actived
(find-file "~/scratch/c-c++/test-lsp-clangd/main.cc")
;; expected cquery actived
(find-file-other-window "~/scratch/c-c++/test-lsp-cquery/main.cc")
))
(run-hooks 'after-init-hook)
;;; test-lsp-find-clients.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment