irony-mode
irony-mode copied to clipboard
How to check and install irony server from .emacs
I naively tried this:
(use-package irony
:ensure t
:config
(unless (irony--locate-server-executable)
(irony-install-server))
)
but that fails with:
Error (use-package): irony :config: Wrong number of arguments: (lambda (command) "Install or reinstall the Irony server.
The installation requires CMake and the libclang developpement package." (interactive (list (let ((command (format (concat "%s %s %s && %s --build . " "--use-stderr --config Release --target install") (shell-quote-argument irony-cmake-executable) (shell-quote-argument (concat "-DCMAKE_INSTALL_PREFIX=" (expand-file-name irony-server-install-prefix))) (shell-quote-argument irony-server-source-dir) (shell-quote-argument irony-cmake-executable)))) (irony--install-server-read-command command)))) (let ((build-dir (or irony-server-build-dir (concat (file-name-as-directory temporary-file-directory) (file-name-as-directory (format "build-irony-server-%s" (irony-version))))))) (make-directory build-dir t) (let ((default-directory build-dir)) (irony-server-kill) (save-current-buffer (set-buffer (compilation-start command nil (function (lambda (maj-mode) "*irony-server build*")))) (set (make-local-variable (quote compilation-finish-functions)) (quote (irony--server-install-finish-function))))))), 0
Is there a more appropriate way to check to see if the server is installed, and if not install it?
The signature of the function is (irony-install-server COMMAND):
You can try to specify the default command line manually.
Is the default command line defined in the code anywhere, so that it can be used?
You can look at the code with M-x find-function RET irony-install-server RET.
This is not a simple string, it depends on some other variables but it should work for a given .emacs.
I see that command is built here: https://github.com/Sarcasm/irony-mode/blob/ebc373b0b4f2b3f491c91d3a7f6dc9ce565a2960/irony.el#L490 But that is private to the irony-install-server function. Could it be hoisted out of the function, so that can the be reused?
Just as an FYI, this started as part of this discussion: https://www.reddit.com/r/emacs/comments/5p475u/is_there_a_way_to_invoke_a_command_only_when_the/dewrg9c/
Ok, thanks for the link. I guess it's slightly similar to a recent on Emacs-devel regarding the installation of modules: https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00653.html
Anyway, for irony-mode I think the best is to simply make the command argument optional (unless this does not play well with interactive but I doubt it).
You could try to change the signature locally to something like this:
(defun irony-install-server (&optional command)
;; detect command == nil, and use the default command in this situation
...
You can try that locally and propose a pull request, I would gladly accept it. :+1:
I should really give use-package a try.
How about just:
(use-package irony
:ensure t
:config
(unless (irony--locate-server-executable)
(call-interactively #'irony-install-server)))
And if you want it to be fully automatic (so no need to hit enter to accept the default compile command for irony) - from http://emacs.stackexchange.com/a/10416/144:
;; -*- lexical-binding: t -*-
(defmacro with-minibuffer-input (form &rest inputs)
(declare (indent 1))
`(minibuffer-with-setup-hook
(lambda ()
(minibuffer-input-provider ',inputs))
,form))
(defun minibuffer-input-provider (inputs)
(let ((hook (make-symbol "hook")))
(fset hook (lambda ()
(remove-hook 'post-command-hook hook)
(when inputs
(when (= 0 (minibuffer-depth))
(error "Too many inputs"))
(when (cdr inputs)
(add-hook 'post-command-hook hook))
(insert (pop inputs))
(exit-minibuffer))))
(add-hook 'post-command-hook hook)))
(use-package irony
:ensure t
:config
(unless (irony--locate-server-executable)
(with-minibuffer-input
(call-interactively #'irony-install-server) "")))
@alexmurray Thanks for that. While that seems to work, it definitely strikes me as hack around irony-install-server. I think @Sarcasm suggestion of making the argument passed to irony-install-server optional is the correct approach, as it simplifies using this function programmatically. Hopefully I'll get some time to look at implementing the suggestion, though my elisp skills are weak.
@alexmurray I found the macro with-minibuffer-input can't work because some wrong in minibuffer-input-provider.
Maybe can change it like this.
(defun minibuffer-input-provider (inputs)
(fset 'hook (lambda (hook_inputs)
(eval `(remove-hook 'post-command-hook
(lambda () (hook ',hook_inputs))) )
(when hook_inputs
(when (= 0 (minibuffer-depth))
(error "Too many inputs"))
(if (cdr hook_inputs)
(eval `(add-hook 'post-command-hook
(lambda () (hook ',(cdr hook_inputs)))))
(unintern "hook" nil))
(insert (pop hook_inputs))
(exit-minibuffer))))
(eval `(add-hook 'post-command-hook
(lambda () (hook ',inputs)))))