Merge pull request #142 from tsukimizake/master

Update emacs integration, and some bug fix
This commit is contained in:
Brian Schott 2014-06-25 20:07:10 +00:00
commit 6be4bfba95
2 changed files with 102 additions and 13 deletions

View File

@ -1,31 +1,40 @@
#Emacs Integration
##Requirements
* You must have the [auto-complete](https://github.com/auto-complete/auto-complete) package, and [yasnippet](https://github.com/capitaomorte/yasnippet) package is recommended.
* You must have the [auto-complete](https://github.com/auto-complete/auto-complete) package.
And [yasnippet](https://github.com/capitaomorte/yasnippet) package 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```.
## 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.
```
;;; ac-dcd
(add-to-list 'load-path "path_to_ac-dcd.el")
(require 'ac-dcd)
(add-to-list 'ac-modes 'd-mode)
(defun ac-d-mode-setup ()
(ac-dcd-maybe-start-server)
(add-to-list 'ac-sources 'ac-source-dcd)
(auto-complete-mode t))
(add-hook 'd-mode-hook 'ac-d-mode-setup)
(define-key d-mode-map (kbd "C-c C-h") 'ac-dcd-popup-ddoc-at-point) ;of course, you can change this keybind.
(add-hook 'd-mode-hook
'(lambda () "set up ac-dcd"
(ac-dcd-maybe-start-server)
(add-to-list 'ac-sources 'ac-source-dcd)))
(define-key d-mode-map (kbd "C-c ?") 'ac-dcd-popup-ddoc-at-point)
(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)
```
* 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```.
## 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 ,```
## TODO
* goto definition
* Better error handling
* Multi byte character support (Need help!)
* and so on...

View File

@ -274,9 +274,9 @@ When the symbol is not a function, returns nothing"
\\1 is function return type (if exists) and name, and \\2 is args.")
(defsubst ac-dcd-remove-function-return-type (s)
"Remove return type of function."
"Remove return type of the function."
(let ((sl (split-string s)))
(if (string-match "(" (car sl)) ; filter calltip candidate which has no return type. e.g. std.regex.match
(if (string-match "(" (car sl)) ;
s
(mapconcat 'identity (cdr sl) " ")
)))
@ -312,7 +312,7 @@ This function should be called at *dcd-output* buf."
yasstr)
(setq kill-ring (cdr kill-ring)); clean up kill-ring
;remove parenthesis
;;remove parenthesis
(setq str (substring str 1 (- (length str) 1)))
(setq yasstr
@ -342,6 +342,7 @@ This function should be called at *dcd-output* buf."
(defun ac-dcd-get-ddoc (pos)
"Get document with `dcd-client --doc'. `POS' is cursor position.
TODO:reformat it."
(save-buffer)
(let ((args
(append
(ac-dcd-build-complete-args (ac-dcd-cursor-position))
@ -370,9 +371,88 @@ TODO:reformat it."
(when (or(string= doc "")
(string= doc "\n\n\n") ;when symbol has no doc
)
(message "No document for the symbol at point!"))))
(message "No document for the symbol at point!"))
(popup-tip doc)))
;; goto definition
;; thanks to jedi.el by Takafumi Arakaki
(defcustom ac-dcd-goto-definition-marker-ring-length 16
"Length of marker ring to store `ac-dcd-goto-definition' call positions."
:group 'auto-complete)
(defvar ac-dcd-goto-definition-marker-ring
(make-ring ac-dcd-goto-definition-marker-ring-length)
"Ring that stores ac-dcd-goto-symbol-declaration.")
(defsubst ac-dcd-goto-def-push-marker ()
"Push marker at point to goto-def ring."
(ring-insert ac-dcd-goto-definition-marker-ring (point-marker)))
(defun ac-dcd-goto-def-pop-marker ()
"Goto the point where `ac-dcd-goto-definition' was last called."
(interactive)
(if (ring-empty-p ac-dcd-goto-definition-marker-ring)
(error "Marker ring is empty. Can't pop.")
(let ((marker (ring-remove ac-dcd-goto-definition-marker-ring 0)))
(switch-to-buffer (or (marker-buffer marker)
(error "Buffer has been deleted")))
(goto-char (marker-position marker))
;; Cleanup the marker so as to avoid them piling up.
(set-marker marker nil nil))))
(defun ac-dcd-goto-definition ()
"Goto declaration of symbol at point."
(interactive)
(save-buffer)
(ac-dcd-call-process-for-symbol-declaration (point))
(let* ((data (ac-dcd-parse-output-for-get-symbol-declaration))
(file (car data))
(offset (cdr data)))
(if (equal data '(nil . nil))
(message "Not found")
(progn
(ac-dcd-goto-def-push-marker)
(if (string= file "stdin") ; When the declaration is in the current file
(progn
(goto-char (point-min))
(forward-char (string-to-number offset)))
(progn
(find-file file)
(goto-char (point-min))
(forward-char (string-to-number offset))))))))
;; utilities for goto-definition
(defun ac-dcd-call-process-for-symbol-declaration (pos)
"Get location of symbol declaration with `dcd-client --symbolLocation'.
`POS' is cursor position."
(let ((args
(append
(ac-dcd-build-complete-args (ac-dcd-cursor-position))
'("--symbolLocation")
(list (buffer-file-name))))
(buf (get-buffer-create "*dcd-output*")))
(with-current-buffer
buf (erase-buffer)
(apply 'call-process ac-dcd-executable nil buf nil args))
(let ((output (with-current-buffer buf (buffer-string))))
output)))
(defun ac-dcd-parse-output-for-get-symbol-declaration ()
"Parse output of `ac-dcd-get-symbol-declaration'.
output is just like following.\n
`(cons \"PATH_TO_IMPORT/import/std/stdio.d\" \"63946\")'"
(let ((buf (get-buffer-create "*dcd-output*")))
(with-current-buffer buf
(goto-char (point-min))
(if (not (string= "Not found\n" (buffer-string)))
(progn (re-search-forward (rx (submatch (* nonl)) "\t" (submatch (* nonl)) "\n"))
(cons (match-string 1) (match-string 2)))
(cons nil nil)))
))
(provide 'ac-dcd)
;;; ac-dcd.el ends here