ananthakumaran / tide

Tide - TypeScript Interactive Development Environment for Emacs
GNU General Public License v3.0
1.46k stars 109 forks source link

Make the completion functionality independent of company-mode #62

Open avli opened 8 years ago

avli commented 8 years ago

Not everyone uses company-mode for code completion. Another popular approach, I believe, is using C-M-i combination for getting a list of possible completions in another buffer. This approach works for me pretty good in combination with helm. Could you consider changing the plugin behavior the way to support different completion front-ends?

ananthakumaran commented 7 years ago

I would be happy to accept a PR, as long as it keeps the current async behavior.

marijnh commented 6 years ago

I got this working (more or less, not deeply tested) like this:

(defun tide-completion-at-point ()
  (let ((prefix (progn (looking-back "[a-zA-Z_$]\*" 50 t) (match-string 0))))
    (tide-command:completions prefix
      (lambda (response)
        (completion-in-region (- (point) (length prefix)) (point)
                              (loop for completion in response
                                    if (string-prefix-p prefix completion)
                                    collect completion))))))

;; And then in setup-tide-mode, bind this as a local completion function
(make-local-variable 'completion-at-point-functions)
(push (lambda () 'tide-completion-at-point) completion-at-point-functions)
ananthakumaran commented 6 years ago

I had looked into this issue a bit more since my initial comment. The interface expected by completion-at-point-functions doesn't support async, async here means the UI won't block the user from typing or doing anything else when tide waits for the results from tsserver. Company provides a clean interface to handle the async scenarios. So building company backend on top of completion-at-point function is not possible. That said, I am still open to a PR which adds support for completion-at-point and leaves the company backend implementation as it is.

marijnh commented 6 years ago

completion-at-point-functions doesn't properly support asynchronicity, but it allows you to return a function that will imperatively do the completions by calling completion-in-region, which I do in the snippet I pasted. It's all a bit shaky, but does make the default bindings for completion work.

josteink commented 6 years ago

@marijnh: It seems like you're the ones who are best suited to deliver this. I think the best option is you package this as a PR.

To me it sounds like @avli will be happy to test it and ensure everything works as intended.

When you two are done maybe me and @ananthakumaran can do some code-review too to ensure we're happy about how things are done before merging.

I'm on overall positive to such a change, as long as we can get it working, with reasonably clean & decoupled code.

VitoVan commented 4 years ago

I got this work from @marijnh 's code, with a little modification, since I didn't enable Lexical Binding in my el files:

(defun tide-completion-at-point ()
  (let ((prefix (progn (looking-back "[a-zA-Z_$]\*" 50 t) (match-string 0))))
    (tide-command:completions
     prefix
     `(lambda (response)
        (completion-in-region (- (point) (length ',prefix)) (point)
                              (loop for completion in response
                                    if (string-prefix-p ',prefix completion)
                                    collect completion))))))

and in setup-tide-mode

(defun setup-tide-mode ()
  (interactive)
  ; ... ...
  ; your configurations here
  ; ... ...
  ;; And then in setup-tide-mode, bind this as a local completion function
  (make-local-variable 'completion-at-point-functions)
  (push (lambda () 'tide-completion-at-point) completion-at-point-functions))

I'm interested in bring a PR, but for now I'm wondering how to write a test for this? or do we need a test for this?