Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions company-phpactor.el
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@
(require 'company)
(require 'phpactor)

(defgroup company-phpactor nil
"Company backend for Phpactor."
:prefix "company-phpactor-"
:group 'company
:group 'phpactor)

(defcustom company-phpactor-request-async t
"When non-NIL, asynchronous recuest to Phpactor."
:type 'boolean
:group 'company-phpactor)

(defun company-phpactor--grab-symbol ()
"If point is at the end of a symbol, return it.
Otherwise, if point is not inside a symbol, return an empty string.
Expand All @@ -51,9 +62,9 @@ Here we create a temporary syntax table in order to add $ to symbols."
(let ((response (phpactor--rpc "complete" (phpactor--command-argments :source :offset))))
(plist-get (plist-get (plist-get response :parameters) :value) :suggestions)))

(defun company-phpactor--get-candidates ()
"Build a list of candidates with text-properties extracted from phpactor's output."
(let ((suggestions (company-phpactor--get-suggestions)) candidate)
(defun company-phpactor--get-candidates (suggestions)
"Build a list of candidates with text-properties extracted from phpactor's output `SUGGESTIONS'."
(let (candidate)
(mapcar
(lambda (suggestion)
(setq candidate (plist-get suggestion :name))
Expand All @@ -75,6 +86,17 @@ Here we create a temporary syntax table in order to add $ to symbols."
"Show additional info (ARG) from phpactor as lateral annotation."
(message (concat " " (get-text-property 0 'annotation arg))))

(defun company-phpactor--get-candidates-async (callback)
"Get completion candidates asynchronously calling `CALLBACK' by Phpactor."
(if (not company-phpactor-request-async)
(funcall callback (company-phpactor--get-candidates (company-phpactor--get-suggestions)))
(phpactor--rpc-async "complete" (phpactor--command-argments :source :offset)
(lambda (proc)
(let* ((response (phpactor--parse-json (process-buffer proc)))
(suggestions
(plist-get (plist-get (plist-get response :parameters) :value) :suggestions)))
(funcall callback (company-phpactor--get-candidates suggestions)))))))

;;;###autoload
(defun company-phpactor (command &optional arg &rest ignored)
"`company-mode' completion backend for Phpactor."
Expand All @@ -87,7 +109,7 @@ Here we create a temporary syntax table in order to add $ to symbols."
(`annotation (company-phpactor--annotation arg))
(`interactive (company-begin-backend 'company-phpactor))
(`prefix (company-phpactor--grab-symbol))
(`candidates (company-phpactor--get-candidates))))))
(`candidates (cons :async #'company-phpactor--get-candidates-async))))))

(provide 'company-phpactor)
;;; company-phpactor.el ends here
18 changes: 17 additions & 1 deletion phpactor.el
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
;; Created: 8 Apr 2018
;; Version: 0.1.0
;; Keywords: tools, php
;; Package-Requires: ((emacs "24.4") (cl-lib "0.5") (f "0.17") (php-runtime "0.2") (composer "0.1"))
;; Package-Requires: ((emacs "24.4") (cl-lib "0.5") (f "0.17") (php-runtime "0.2") (composer "0.1") (async "1.9.3"))
;; URL: https://github.com/emacs-php/phpactor.el
;; License: GPL-3.0-or-later

Expand Down Expand Up @@ -52,6 +52,7 @@
(require 'ring)
(require 'subr-x)
(require 'composer)
(require 'async)

;; Custom variables
;;;###autoload
Expand Down Expand Up @@ -223,6 +224,21 @@ have to ensure a compatible version of phpactor is used."
(call-process-region (point-min) (point-max) phpactor-executable nil output nil "rpc" (format "--working-dir=%s" default-directory))
(phpactor--parse-json output))))

(defun phpactor--rpc-async (action arguments callback)
"Async execute Phpactor `ACTION' subcommand with `ARGUMENTS' and calling `CALLBACK' after process."
(declare (indent 2))
(phpactor--add-history 'phpactor--rpc-async (list action arguments))
(let* ((json (phpactor--serialize-json (list :action action
:parameters arguments)))
(coding-system-for-write 'utf-8)
(default-directory (phpactor-get-working-dir))
(executable phpactor-executable)
(proc (async-start-process
"phpactor-async" executable callback
"rpc" (format "--working-dir=%s" default-directory))))
(process-send-string proc json)
(process-send-eof proc)))

(defun phpactor--parse-json (buffer)
"Read JSON string from BUFFER."
(with-current-buffer buffer
Expand Down