Merge pull request #156 from snosov1/fork-dub-imports

Add ac-dcd-add-imports function
This commit is contained in:
Brian Schott 2014-08-12 09:40:58 +00:00
commit ae46655c54
2 changed files with 124 additions and 32 deletions

View File

@ -1,47 +1,59 @@
#Emacs Integration
# Emacs Integration
##Requirements
* You must have the [auto-complete](https://github.com/auto-complete/auto-complete) package.
And, [yasnippet](https://github.com/capitaomorte/yasnippet) and [popwin](https://github.com/m2ym/popwin-el) is recommended.
* Make sure dcd-client and dcd-server is in your exec-path. Otherwise, please set the variable ```dcd-exectutable``` and ```dcd-server-executable``` using ```M-x customize```.
## Requirements
* You must have the
[auto-complete](https://github.com/auto-complete/auto-complete) package. Also,
[yasnippet](https://github.com/capitaomorte/yasnippet) and
[popwin](https://github.com/m2ym/popwin-el) are recommended.
* Make sure `dcd-client` and `dcd-server` are in your exec-path. Otherwise,
please set the variables `dcd-exectutable` and `dcd-server-executable` using
`M-x customize`.
## Setup
* First, follow the Setup section in the root README.
* Second, add the following to your .emacs. With this setting, dcd-server starts automatically when you open file in d-mode. (Of course, you should edit ```path_to_ac-dcd.el``` to suit your enviroment.)
```
;;; ac-dcd
(add-to-list 'load-path "path_to_ac-dcd.el")
(require 'ac-dcd)
* Follow the Setup section in the root README.
* Add the following to your .emacs. With this setting, dcd-server starts
automatically when you open file in d-mode. (Of course, you should edit
`path_to_ac-dcd.el` to suit your environment.)
(add-hook 'd-mode-hook
'(lambda () "set up ac-dcd"
(auto-complete-mode t)
(yas-minor-mode-on)
(ac-dcd-maybe-start-server)
(add-to-list 'ac-sources 'ac-source-dcd)))
;;; ac-dcd
(add-to-list 'load-path "path_to_ac-dcd.el")
(require 'ac-dcd)
(define-key d-mode-map (kbd "C-c ?") 'ac-dcd-show-ddoc-with-buffer)
(define-key d-mode-map (kbd "C-c .") 'ac-dcd-goto-definition)
(define-key d-mode-map (kbd "C-c ,") 'ac-dcd-goto-def-pop-marker)
(add-hook 'd-mode-hook
'(lambda () "set up ac-dcd"
(auto-complete-mode t)
(yas-minor-mode-on)
(ac-dcd-maybe-start-server)
(add-to-list 'ac-sources 'ac-source-dcd)))
(when (featurep 'popwin)
(add-to-list 'popwin:special-display-config
`(,ac-dcd-error-buffer-name :noselect t))
(add-to-list 'popwin:special-display-config
`(,ac-dcd-document-buffer-name :position right :width 80)))
(define-key d-mode-map (kbd "C-c ?") 'ac-dcd-show-ddoc-with-buffer)
(define-key d-mode-map (kbd "C-c .") 'ac-dcd-goto-definition)
(define-key d-mode-map (kbd "C-c ,") 'ac-dcd-goto-def-pop-marker)
```
(when (featurep 'popwin)
(add-to-list 'popwin:special-display-config
`(,ac-dcd-error-buffer-name :noselect t))
(add-to-list 'popwin:special-display-config
`(,ac-dcd-document-buffer-name :position right :width 80)))
* Third, set import path using ```M-x customize-variable RET ac-dcd-flags```.
* When something is wrong, please check variables with ```M-x customize-apropos RET ac-dcd``` and restart server with ```M-x ac-dcd-init-server```.
* You can set import paths using `M-x customize-variable RET ac-dcd-flags`.
* Alternatively, if you're using [DUB](http://code.dlang.org/) to manage your
project, you can use `M-x ac-dcd-add-imports` to add import paths of the
current project automatically.
* When something is wrong, please, check variables with `M-x customize-apropos
RET ac-dcd` and restart server with `M-x ac-dcd-init-server`.
## Features
* Dlang source for auto-complete
* Function calltip expansion with yasnippet
* Show ddoc with ```C-c ?```
* Goto definition with ```C-c .```
* After goto definition, you can pop to previous position with ```C-c ,```
* Show ddoc with `C-c ?`
* Goto definition with `C-c .`
* After goto definition, you can pop to previous position with `C-c ,`
## TODO
* Multi byte character support (Need help!)
* UTF-8 support is in place. However, UTF-16 and UTF-32 may not work correctly.
(Need help!)

View File

@ -527,6 +527,86 @@ output is just like following.\n
(cons nil nil)))
))
(defun ac-dcd-parent-directory (dir)
"Returns parent directory of dir"
(when dir
(file-name-directory (directory-file-name (expand-file-name dir)))))
(defun ac-dcd-search-file-up (name &optional path)
"Searches for file `name' in parent directories recursively"
(let* ((tags-file-name (concat path name))
(parent (ac-dcd-parent-directory path))
(path (or path default-directory))
)
(cond
((file-exists-p tags-file-name) tags-file-name)
((string= parent path) nil)
(t (ac-dcd-search-file-up name parent)))))
(defun ac-dcd-find-imports-dub ()
"Extract import flags from \"dub describe\" output."
(let ((dub-root-dir (ac-dcd-parent-directory
(or (ac-dcd-search-file-up "dub.json" default-directory)
(ac-dcd-search-file-up "package.json" default-directory))))
(dub-executable "dub"))
(when dub-root-dir
(with-temp-buffer
(let ((default-directory dub-root-dir))
(call-process dub-executable nil (current-buffer) nil "describe"))
(require 'json)
(let* ((json-object-type 'hash-table)
(describe-hash (json-read-from-string (buffer-string)))
(packages-array (gethash "packages" describe-hash))
(imports-list '()))
(mapcar
(lambda (package)
(let ((package-path (gethash "path" package))
(import-paths-array (gethash "importPaths" package)))
(mapcar
(lambda (import-path)
(add-to-list 'imports-list
(concat "-I" package-path import-path)))
import-paths-array)))
packages-array)
imports-list)))))
(defun ac-dcd-find-imports-std ()
"Extract import flags from dmd.conf file."
(require 'cl)
(let ((dmd-conf-filename
(find-if 'file-exists-p
(list
;; TODO: the first directory to look into should be dmd's current
;; working dir
(concat (getenv "HOME") "/dmd.conf")
(concat (ac-dcd-parent-directory (executable-find "dmd")) "dmd.conf")
"/etc/dmd.conf"))))
;; TODO: this extracting procedure is pretty rough, it just searches for
;; the first occurrence of the DFLAGS
(save-window-excursion
(with-temp-buffer
(find-file dmd-conf-filename)
(goto-char (point-min))
(search-forward "\nDFLAGS")
(skip-chars-forward " =")
(let ((flags-list (split-string (buffer-substring-no-properties
(point) (line-end-position)))))
(remove-if-not '(lambda (s)
(string-prefix-p "-I" s))
flags-list))))))
(defun ac-dcd-add-imports ()
"Send import flags of the current DUB project to dcd-server.
The root of the project is determined by the \"closest\" dub.json
or package.json file."
(interactive)
(ac-dcd-call-process ""
(append
(ac-dcd-find-imports-std)
(ac-dcd-find-imports-dub))))
(provide 'ac-dcd)
;;; ac-dcd.el ends here