abingham / emacs-ycmd

Emacs client for ycmd, the code completion system.
MIT License
384 stars 46 forks source link

Sync version of ycmd-goto #465

Closed abo-abo closed 6 years ago

abo-abo commented 6 years ago

I'm trying to adapt ycmd-goto into my workflow; for this I'd like the following:

The point is that if I can detect that ycmd-goto was unsuccessful, I can forward the request to some other mechanism (like TAGS).

The problem currently is that the request is async, so the return result of ycmd-goto doesn't matter, and the failure is simply signaled as a message.

Thinking about it, does it make sense for ycmd-goto to be async at all? Suppose the user called it, and by being async we leave Emacs unblocked for say 0.5s. Can the user do anything useful at that time? Moreover, ycmd-goto will likely change the buffer on completion, so even if the user does a forward-line in that 0.5s time frame, following that the current buffer will change without any further user input. Not a great UX, imo.

abingham commented 6 years ago

ycmd-goto returns a deferred object. I bet you can get what you want like this:

(defun goto-with-fallback ()
  (deferred:$
    (ycmd-goto)
    (deferred:nextc it
      (lambda (response) 
          (if (...response isn't what you want...) (...do the fallback...)))))))

Or whatever. You can learn more at https://github.com/kiwanami/emacs-deferred.

Regarding the greatness or lack thereof of the UX, you'd perhaps be shocked as the whining I get when I make things synchronous. You're the first to complain about too much async behavior. Now that you know about deferred, though, perhaps you can cope.

If this works for you, please close this issue.

abo-abo commented 6 years ago

Thanks for the pointer, this code worked for me in the end:

(and (bound-and-true-p ycmd-mode)
     (let ((inhibit-message t))
       (deferred:sync!
           (ycmd-goto))))