Conflicts:
	modulecache.d
This commit is contained in:
Hackerpilot 2014-07-07 08:06:58 +00:00
commit 7eb11f936d
14 changed files with 455 additions and 160 deletions

7
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "msgpack-d"] [submodule "msgpack-d"]
path = msgpack-d path = msgpack-d
url = https://github.com/msgpack/msgpack-d.git url = https://github.com/msgpack/msgpack-d.git
[submodule "dscanner"]
path = dscanner
url = https://github.com/Hackerpilot/Dscanner.git
[submodule "editors/ktexteditor"] [submodule "editors/ktexteditor"]
path = editors/ktexteditor path = editors/ktexteditor
url = https://github.com/Dav1dde/lumen.git url = https://github.com/Dav1dde/lumen.git
@ -13,3 +10,7 @@
[submodule "containers"] [submodule "containers"]
path = containers path = containers
url = https://github.com/economicmodeling/containers.git url = https://github.com/economicmodeling/containers.git
[submodule "libdparse"]
path = libdparse
url = https://github.com/Hackerpilot/libdparse.git
branch = master

View File

@ -205,8 +205,7 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
{ {
LexerConfig config; LexerConfig config;
config.fileName = "stdin"; config.fileName = "stdin";
auto tokens = byToken(cast(ubyte[]) sourceCode, config, cache); tokenArray = getTokensForParser(cast(ubyte[]) sourceCode, config, cache);
tokenArray = tokens.array();
auto sortedTokens = assumeSorted(tokenArray); auto sortedTokens = assumeSorted(tokenArray);
return sortedTokens.lowerBound(cast(size_t) cursorPosition); return sortedTokens.lowerBound(cast(size_t) cursorPosition);
} }

View File

@ -1,3 +1,3 @@
dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -O -ofdcd-client dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -O -ofdcd-client -L/EXETYPE:NT -L/SUBSYSTEM:WINDOWS
dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d string_interning.d dscanner/std/d/ast.d dscanner/std/d/entities.d dscanner/std/d/lexer.d dscanner/std/d/parser.d dscanner/std/lexer.d dscanner/std/allocator.d dscanner/formatter.d containers/src/memory/appender.d containers/src/memory/allocators.d containers/src/containers/dynamicarray.d containers/src/containers/ttree.d containers/src/containers/hashset.d containers/src/containers/unrolledlist.d containers/src/containers/internal/hash.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d string_interning.d dscanner/std/d/ast.d dscanner/std/d/entities.d dscanner/std/d/lexer.d dscanner/std/d/parser.d dscanner/std/lexer.d dscanner/std/allocator.d dscanner/formatter.d containers/src/memory/appender.d containers/src/memory/allocators.d containers/src/containers/dynamicarray.d containers/src/containers/ttree.d containers/src/containers/hashset.d containers/src/containers/unrolledlist.d containers/src/containers/internal/hash.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server

View File

@ -23,13 +23,13 @@ dmd\
server.d\ server.d\
stupidlog.d\ stupidlog.d\
string_interning.d\ string_interning.d\
dscanner/std/d/ast.d\ libdparse/src/std/d/ast.d\
dscanner/std/d/entities.d\ libdparse/src/std/d/entities.d\
dscanner/std/d/lexer.d\ libdparse/src/std/d/lexer.d\
dscanner/std/d/parser.d\ libdparse/src/std/d/parser.d\
dscanner/std/lexer.d\ libdparse/src/std/lexer.d\
dscanner/std/allocator.d\ libdparse/src/std/allocator.d\
dscanner/formatter.d\ libdparse/src/std/d/formatter.d\
containers/src/memory/allocators.d\ containers/src/memory/allocators.d\
containers/src/memory/appender.d\ containers/src/memory/appender.d\
containers/src/containers/dynamicarray.d\ containers/src/containers/dynamicarray.d\

@ -1 +1 @@
Subproject commit 36a00d9f109fde9c53db3173fae39439b007c0ce Subproject commit 2a72525f649850f452f21e7f362f70440f487a61

View File

@ -63,6 +63,7 @@ class SimpleParser : Parser
override Unittest parseUnittest() override Unittest parseUnittest()
{ {
expect(tok!"unittest"); expect(tok!"unittest");
if (currentIs(tok!"{"))
skipBraces(); skipBraces();
return null; return null;
} }

View File

@ -19,7 +19,7 @@
module conversion.first; module conversion.first;
import actypes; import actypes;
import formatter; import std.d.formatter;
import std.allocator; import std.allocator;
import memory.allocators; import memory.allocators;
import memory.appender; import memory.appender;

View File

@ -190,7 +190,7 @@ private:
ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix) ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix)
{ {
import formatter; import std.d.formatter;
if (suffix.star) if (suffix.star)
return symbol; return symbol;
if (suffix.array || suffix.type) if (suffix.array || suffix.type)

@ -1 +0,0 @@
Subproject commit f54f7823dc62c14b7afb6b7db6e7693e79be34fa

View File

@ -1,16 +1,44 @@
#EMACS Integration #Emacs Integration
This is a first cut at emacs support. It is far from complete.
##Requirements ##Requirements
* You must have the [auto-complete](https://github.com/auto-complete/auto-complete) package * You must have the [auto-complete](https://github.com/auto-complete/auto-complete) package.
* This integration will not automatically start dcd-server, so you'll have to do that yourself. [yasnippet](https://github.com/capitaomorte/yasnippet) and [popwin](https://github.com/m2ym/popwin-el) is recommended.
* Make sure dcd-client is in your path * 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```.
* Add the following to your .emacs
## 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) (require 'ac-dcd)
(add-to-list 'ac-modes 'd-mode) (add-to-list 'ac-modes 'd-mode)
(defun ac-d-mode-setup ()
(setq ac-sources (append '(ac-source-dcd) ac-sources)) (add-hook 'd-mode-hook
(global-auto-complete-mode t)) '(lambda () "set up ac-dcd"
(add-hook 'd-mode-hook 'ac-d-mode-setup) (ac-dcd-maybe-start-server)
(add-to-list 'ac-sources 'ac-source-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)
(when (featurep 'popwin)
(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```.
## 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
* Better error handling
* Multi byte character support (Need help!)

View File

@ -21,54 +21,110 @@
;;; Code: ;;; Code:
(provide 'ac-dcd)
(require 'auto-complete) (require 'auto-complete)
(require 'rx)
(require 'yasnippet)
(require 'eshell)
(defcustom ac-dcd-executable (defcustom ac-dcd-executable
(executable-find "dcd-client") "dcd-client"
"*Location of dcd-client executable" "Location of dcd-client executable."
:group 'auto-complete :group 'auto-complete
:type 'file) :type 'file)
;;; Extra compilation flags to pass to dcd.
(defcustom ac-dcd-flags nil (defcustom ac-dcd-flags nil
"Extra flags to pass to the Dcd executable. "Extra flags to pass to the dcd-server.
This variable will typically contain include paths, e.g., ( \"-I~/MyProject\", \"-I.\" )." This variable will typically contain include paths,
e.g., (\"-I~/MyProject\", \"-I.\").
You can't put port number flag here. Set `ac-dcd-server-port' instead."
:group 'auto-complete :group 'auto-complete
:type '(repeat (string :tag "Argument" ""))) :type '(repeat (string :tag "Argument" "")))
(defconst ac-dcd-completion-pattern (defconst ac-dcd-completion-pattern
"^\\(%s[^\s\n]*\\)[ \t]+[cisuvmkfgepM]") "^\\(%s[^\s\n]*\\)[ \t]+\\([cisuvmkfgepM]\\)"
"Regex to parse dcd output.
\\1 is candidate itself, \\2 is kind of candidate.")
(defconst ac-dcd-error-buffer-name "*dcd error*") (defconst ac-dcd-error-buffer-name "*dcd-error*")
(defconst ac-dcd-output-buffer-name "*dcd-output*")
(defconst ac-dcd-document-buffer-name "*dcd-document*")
(defcustom ac-dcd-server-executable
"dcd-server"
"Location of dcd-server executable."
:group 'auto-complete
:type 'file)
(defcustom ac-dcd-server-port 9166
"Port number of dcd-server. default is 9166."
:group 'auto-complete)
(defvar ac-dcd-delay-after-kill-process 200
"Duration after killing server process in milli second.
If `ac-dcd-init-server' doesn't work correctly, please set bigger number for this variable.")
;;server handle functions
(defun ac-dcd-stop-server ()
"Stop dcd-server manually. Ordinary, you don't have to call it.
If you want to restart server, use `ac-dcd-init-server' instead."
(interactive)
(interrupt-process "dcd-server"))
(defsubst ac-dcd-start-server ()
"Start dcd-server."
(let ((buf (get-buffer-create "*dcd-server*")))
(with-current-buffer buf (start-process "dcd-server" (current-buffer)
ac-dcd-server-executable
(mapconcat 'identity ac-dcd-flags " ")
"-p"
(format "%s" ac-dcd-server-port)
))))
(defun ac-dcd-maybe-start-server ()
"Start dcd-server. When the server process is already running, do nothing."
(unless (get-process "dcd-server")
(ac-dcd-start-server)))
(defun ac-dcd-init-server ()
"Start dcd-server. When the server process is already running, restart it."
(interactive)
(when (get-process "dcd-server")
(ac-dcd-stop-server)
(sleep-for 0 ac-dcd-delay-after-kill-process))
(ac-dcd-start-server))
;; output parser functions
(defun ac-dcd-parse-output (prefix) (defun ac-dcd-parse-output (prefix)
"Parse dcd output."
(goto-char (point-min)) (goto-char (point-min))
(let ((pattern (format ac-dcd-completion-pattern (let ((pattern (format ac-dcd-completion-pattern
(regexp-quote prefix))) (regexp-quote prefix)))
lines match detailed_info lines match detailed-info
(prev-match "")) (prev-match ""))
(while (re-search-forward pattern nil t) (while (re-search-forward pattern nil t)
(setq match (match-string-no-properties 1)) (setq match (match-string-no-properties 1))
(unless (string= "Pattern" match) (unless (string= "Pattern" match)
(setq detailed_info (match-string-no-properties 2)) (setq detailed-info (match-string-no-properties 2))
(if (string= match prev-match) (if (string= match prev-match)
(progn (progn
(when detailed_info (when detailed-info
(setq match (propertize match (setq match (propertize match
'ac-dcd-help 'ac-dcd-help
(concat (concat
(get-text-property 0 'ac-dcd-help (car lines)) (get-text-property 0 'ac-dcd-help (car lines))
"\n" "\n"
detailed_info))) detailed-info)))
(setf (car lines) match))) (setf (car lines) match)))
(setq prev-match match) (setq prev-match match)
(when detailed_info (when detailed-info
(setq match (propertize match 'ac-dcd-help detailed_info))) (setq match (propertize match 'ac-dcd-help detailed-info)))
(push match lines)))) (push match lines))))
lines)) lines))
(defun ac-dcd-handle-error (res args) (defun ac-dcd-handle-error (res args)
"Notify error on parse failure."
(goto-char (point-min)) (goto-char (point-min))
(let* ((buf (get-buffer-create ac-dcd-error-buffer-name)) (let* ((buf (get-buffer-create ac-dcd-error-buffer-name))
(cmd (concat ac-dcd-executable " " (mapconcat 'identity args " "))) (cmd (concat ac-dcd-executable " " (mapconcat 'identity args " ")))
@ -89,72 +145,51 @@ This variable will typically contain include paths, e.g., ( \"-I~/MyProject\", \
(setq buffer-read-only t) (setq buffer-read-only t)
(goto-char (point-min)))))) (goto-char (point-min))))))
(defun ac-dcd-call-process (prefix &rest args)
(let ((buf (get-buffer-create "*dcd-output*")) ;; utility functions to call process
(defun ac-dcd-call-process (prefix args)
(let ((buf (get-buffer-create ac-dcd-output-buffer-name))
res) res)
(with-current-buffer buf (erase-buffer)) (with-current-buffer buf (erase-buffer))
(setq res (apply 'call-process-region (point-min) (point-max) (setq res (apply 'call-process-region (point-min) (point-max)
ac-dcd-executable nil buf nil args)) ac-dcd-executable nil buf nil
args
))
(with-current-buffer buf (with-current-buffer buf
(unless (eq 0 res) (unless (eq 0 res)
(ac-dcd-handle-error res args)) (ac-dcd-handle-error res args))
;; Still try to get any useful input. ;; Still try to get any useful input.
(ac-dcd-parse-output prefix)))) (ac-dcd-parse-output prefix))))
(defsubst ac-dcd-cursor-position ()
"Get cursor position to pass to dcd-client.
TODO: multi byte character support"
(point))
(defsubst ac-dcd-build-complete-args (pos) (defsubst ac-dcd-build-complete-args (pos)
(append '() (list
'("-c") "-c"
(list (format "%s" pos)) (format "%s" pos)
ac-dcd-flags)) "-p"
(format "%s" ac-dcd-server-port)
))
(defsubst ac-dcd-clean-document (s)
(when s
(setq s (replace-regexp-in-string "<#\\|#>\\|\\[#" "" s))
(setq s (replace-regexp-in-string "#\\]" " " s)))
s)
(defun ac-dcd-document (item)
(if (stringp item)
(let (s)
(setq s (get-text-property 0 'ac-dcd-help item))
(ac-dcd-clean-document s))))
(defsubst ac-in-string/comment () (defsubst ac-in-string/comment ()
"Return non-nil if point is in a literal (a comment or string)." "Return non-nil if point is in a literal (a comment or string)."
(nth 8 (syntax-ppss))) (nth 8 (syntax-ppss)))
;; interface to communicate with auto-complete.el
(defun ac-dcd-candidate () (defun ac-dcd-candidate ()
(unless (ac-in-string/comment) (unless (ac-in-string/comment)
(save-restriction (save-restriction
(widen) (widen)
(apply 'ac-dcd-call-process (ac-dcd-call-process
ac-prefix ac-prefix
(ac-dcd-build-complete-args (point)))))) (ac-dcd-build-complete-args (ac-dcd-cursor-position))))))
(defvar ac-template-start-point nil)
(defvar ac-template-candidates (list "ok" "no" "yes:)"))
(defun ac-dcd-action ()
(interactive)
(let ((help (ac-dcd-clean-document (get-text-property 0 'ac-dcd-help (cdr ac-last-completion))))
(raw-help (get-text-property 0 'ac-dcd-help (cdr ac-last-completion)))
(candidates (list)) ss fn args (ret-t "") ret-f)
(setq ss (split-string raw-help "\n"))
(dolist (s ss)
(when (string-match "\\[#\\(.*\\)#\\]" s)
(setq ret-t (match-string 1 s)))
(setq s (replace-regexp-in-string "\\[#.*?#\\]" "" s)))
(cond (candidates
(setq candidates (delete-dups candidates))
(setq candidates (nreverse candidates))
(setq ac-template-candidates candidates)
(setq ac-template-start-point (point))
(ac-complete-template)
(unless (cdr candidates) ;; unless length > 1
(message (replace-regexp-in-string "\n" " ; " help))))
(t
(message (replace-regexp-in-string "\n" " ; " help))))))
(defun ac-dcd-prefix () (defun ac-dcd-prefix ()
(or (ac-prefix-symbol) (or (ac-prefix-symbol)
@ -166,64 +201,299 @@ This variable will typically contain include paths, e.g., ( \"-I~/MyProject\", \
(eq ?: (char-before (1- (point)))))) (eq ?: (char-before (1- (point))))))
(point))))) (point)))))
(defun ac-dcd-document (item)
"Return popup document of `ITEM'."
(if (stringp item)
(let (s)
(setq s (get-text-property 0 'ac-dcd-help item))
(cond
((equal s "c") "class")
((equal s "i") "interface")
((equal s "s") "struct")
((equal s "u") "union")
((equal s "v") "variable")
((equal s "m") "member variable")
((equal s "k") "keyword")
((equal s "f") "function")
((equal s "g") "enum")
((equal s "e") "enum member")
((equal s "P") "package")
((equal s "M") "module")
((equal s "a") "array")
((equal s "A") "associative array")
((equal s "l") "alias")
((equal s "t") "template")
((equal s "T") "mixin template")
(t (format "candidate kind undetected: %s" s))
))))
(defun ac-dcd-action ()
"Try function calltip expansion."
(when (featurep 'yasnippet)
(let ((lastcompl (cdr ac-last-completion)))
(cond
((equal "f" (get-text-property 0 'ac-dcd-help lastcompl)) ; when it was a function
(progn
(ac-complete-dcd-calltips)))
(t nil)
))))
(ac-define-source dcd (ac-define-source dcd
'((candidates . ac-dcd-candidate) '((candidates . ac-dcd-candidate)
(prefix . ac-dcd-prefix) (prefix . ac-dcd-prefix)
(requires . 0) (requires . 0)
(document . ac-dcd-document) (document . ac-dcd-document)
(action . ac-dcd-action) (action . ac-dcd-action)
(cache)))
(defun ac-dcd-same-count-in-string (c1 c2 s)
(let ((count 0) (cur 0) (end (length s)) c)
(while (< cur end)
(setq c (aref s cur))
(cond ((eq c1 c)
(setq count (1+ count)))
((eq c2 c)
(setq count (1- count))))
(setq cur (1+ cur)))
(= count 0)))
(defun ac-dcd-split-args (s)
(let ((sl (split-string s ", *")))
(cond ((string-match "<\\|(" s)
(let ((res (list)) (pre "") subs)
(while sl
(setq subs (pop sl))
(unless (string= pre "")
(setq subs (concat pre ", " subs))
(setq pre ""))
(cond ((and (ac-dcd-same-count-in-string ?\< ?\> subs)
(ac-dcd-same-count-in-string ?\( ?\) subs))
(push subs res))
(t
(setq pre subs))))
(nreverse res)))
(t
sl))))
(defun ac-template-candidate ()
ac-template-candidates)
(defun ac-template-action ()
(interactive)
(unless (null ac-template-start-point)
(let ((pos (point)) sl (snp "")
(s (get-text-property 0 'raw-args (cdr ac-last-completion)))))))
(defun ac-template-prefix ()
ac-template-start-point)
;; this source shall only be used internally.
(ac-define-source template
'((candidates . ac-template-candidate)
(prefix . ac-template-prefix)
(requires . 0)
(action . ac-template-action)
(document . ac-dcd-document)
(cache) (cache)
(symbol . "t"))) (symbol . "D")
))
;;; auto-complete-dcd.el ends here
;; function calltip expansion with yasnippet
(defun ac-dcd-calltip-candidate ()
"Do calltip completion of the D symbol at point.
The cursor must be at the end of a D symbol.
When the symbol is not a function, returns nothing"
(let ((buf (get-buffer-create ac-dcd-output-buffer-name)))
(ac-dcd-call-process-for-calltips)
(with-current-buffer buf (ac-dcd-parse-calltips))
))
(defun ac-dcd-call-process-for-calltips ()
"Call process to get calltips of the function at point."
(insert "( ;")
(backward-char 2)
(ac-dcd-call-process
(concat (cdr ac-last-completion) "(")
(ac-dcd-build-complete-args (ac-dcd-cursor-position)))
(forward-char 2)
(delete-char -3)
)
(defconst ac-dcd-calltip-pattern
(rx bol (submatch (* nonl)) (submatch "(" (* nonl) ")") eol)
"Regexp to parse calltip completion output.
\\1 is function return type (if exists) and name, and \\2 is args.")
(defsubst ac-dcd-cleanup-function-candidate (s)
"Remove return type of the head of the function.
`S' is candidate string."
(let (res)
(with-temp-buffer
(insert s)
;;goto beggining of function name
(progn
(end-of-line)
(backward-sexp)
(re-search-backward (rx (or bol " "))))
(setq res (buffer-substring
(point)
(progn
(end-of-line)
(point))))
(when (equal " " (substring res 0 1))
(setq res (substring res 1)))
res
)))
(defun ac-dcd-parse-calltips ()
"Parse dcd output for calltip completion.
It returns a list of calltip candidates."
(goto-char (point-min))
(let ((pattern ac-dcd-calltip-pattern)
lines
match
(prev-match ""))
(while (re-search-forward pattern nil t)
(setq match
(ac-dcd-cleanup-function-candidate
(concat (match-string-no-properties 1) (match-string-no-properties 2))
))
(push match lines))
lines
))
(defun ac-dcd-calltip-action ()
"Format the calltip to yasnippet style.
This function should be called at *dcd-output* buf."
(let (beg end)
(save-excursion
(setq end (point))
(setq beg (progn
(backward-sexp)
(point)
))
(kill-region beg end))
(let ((str (car kill-ring))
yasstr)
(setq kill-ring (cdr kill-ring)); clean up kill-ring
;;remove parenthesis
(setq str (substring str 1 (- (length str) 1)))
(setq yasstr
(mapconcat
(lambda (s) "format each args to yasnippet style" (concat "${" s "}"))
(split-string str ", ")
", "))
(setq yasstr (concat "(" yasstr ")"))
;; ;;debug
;; (message (format "str: %s" str))
;; (message (format "yasstr: %s" yasstr))
(yas-expand-snippet yasstr)
)))
(defun ac-dcd-calltip-prefix ()
(car ac-last-completion))
(ac-define-source dcd-calltips
'((candidates . ac-dcd-calltip-candidate)
(prefix . ac-dcd-calltip-prefix)
(action . ac-dcd-calltip-action)
(cache)
))
;;show document
(defun ac-dcd-reformat-document ()
"Currently, it just decodes \n and \\n."
(with-current-buffer (get-buffer ac-dcd-document-buffer-name)
;;doit twice to catch '\n\n'
(goto-char (point-min))
(while (re-search-forward (rx (and (not (any "\\")) (submatch "\\n"))) nil t)
(replace-match "\n" nil nil nil 1))
(goto-char (point-min))
(while (re-search-forward (rx (and (not (any "\\")) (submatch "\\n"))) nil t)
(replace-match "\n" nil nil nil 1))
;; replace '\\n' in D src to '\n'
(while (re-search-forward (rx "\\\\n") nil t)
(replace-match "\\\\n"))
))
(defun ac-dcd-get-ddoc (pos)
"Get document with `dcd-client --doc'. `POS' is cursor position."
(save-buffer)
(let ((args
(append
(ac-dcd-build-complete-args (ac-dcd-cursor-position))
'("-d")
(list (buffer-file-name))))
(buf (get-buffer-create ac-dcd-document-buffer-name)))
;; If I use `call-process', dcd-client errors out when to get long doc(e.g. doc of writef).
;; I have no idea why.
(with-current-buffer buf
(erase-buffer)
(eshell-command
(mapconcat 'identity `(,(executable-find ac-dcd-executable) ,@args) " ")
t)
(when (or
(string= (buffer-string) "")
(string= (buffer-string) "\n\n\n") ;when symbol has no doc
)
(error "No document for the symbol at point!"))
(buffer-string)
)))
(defun ac-dcd-show-ddoc-with-buffer ()
"Display Ddoc at point using `display-buffer'."
(interactive)
(ac-dcd-get-ddoc (ac-dcd-cursor-position))
(ac-dcd-reformat-document)
(display-buffer (get-buffer-create ac-dcd-document-buffer-name)))
;; 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))
'("-l")
(list (buffer-file-name))))
(buf (get-buffer-create ac-dcd-output-buffer-name)))
(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 ac-dcd-output-buffer-name)))
(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

View File

@ -20,7 +20,7 @@ local function autocomplete()
dcd.registerImages() dcd.registerImages()
dcd.autocomplete() dcd.autocomplete()
if not buffer:auto_c_active() then if not buffer:auto_c_active() then
textadept.editing.autocomplete_word(keywords) textadept.editing.autocomplete("word")
end end
end end

1
libdparse Submodule

@ -0,0 +1 @@
Subproject commit d9387eb3b275295cd0263bdc273c4b0b63f29f98

View File

@ -135,9 +135,8 @@ struct ModuleCache
ACSymbol*[] symbols; ACSymbol*[] symbols;
try // try
{ // {
import core.memory;
import std.stdio; import std.stdio;
import std.typecons; import std.typecons;
File f = File(cachedLocation); File f = File(cachedLocation);
@ -150,12 +149,9 @@ struct ModuleCache
config.fileName = cachedLocation; config.fileName = cachedLocation;
auto parseStringCache = StringCache(StringCache.defaultBucketCount); auto parseStringCache = StringCache(StringCache.defaultBucketCount);
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64))); auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64)));
DynamicArray!(Token, false) tokens; const(Token)[] tokens = getTokensForParser(
auto tokenRange = byToken(
(source.length >= 3 && source[0 .. 3] == "\xef\xbb\xbf"c) ? source[3 .. $] : source, (source.length >= 3 && source[0 .. 3] == "\xef\xbb\xbf"c) ? source[3 .. $] : source,
config, &parseStringCache); config, &parseStringCache);
foreach (t; tokenRange)
tokens.insert(t);
Mallocator.it.deallocate(source); Mallocator.it.deallocate(source);
Module m = parseModuleSimple(tokens[], cachedLocation, semanticAllocator); Module m = parseModuleSimple(tokens[], cachedLocation, semanticAllocator);
@ -180,12 +176,12 @@ struct ModuleCache
typeid(Scope).destroy(third.moduleScope); typeid(Scope).destroy(third.moduleScope);
typeid(SemanticSymbol).destroy(third.rootSymbol); typeid(SemanticSymbol).destroy(third.rootSymbol);
symbolsAllocated += first.symbolsAllocated; symbolsAllocated += first.symbolsAllocated;
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
Log.error("Couln't parse ", location, " due to exception: ", ex.msg); // Log.error("Couln't parse ", location, " due to exception: ", ex.msg);
return []; // return [];
} // }
SysTime access; SysTime access;
SysTime modification; SysTime modification;
getTimes(cachedLocation, access, modification); getTimes(cachedLocation, access, modification);