Closed ShadowCreator closed 8 years ago
see also #178
(require 'auto-complete)
(defun my-ac-haskell-mode ()
(setq ac-sources '(ac-source-words-in-same-mode-buffers
ac-source-dictionary
ac-source-etags
)))
(add-hook 'haskell-mode-hook 'my-ac-haskell-mode)
(defun my-haskell-ac-init ()
(when (member (file-name-extension buffer-file-name) '("hs" "lhs"))
(auto-complete-mode t)
(setq ac-sources '(ac-source-words-in-same-mode-buffers
ac-source-dictionary
ac-source-etags
))
))
(add-hook 'find-file-hook 'my-haskell-ac-init)
This issue report was last updated in 2013. Is it still relevant to current code state?
@geraldus: Is this issue describing what you are working on?
Yeah, but I'm very limited in time :( Also, integrate means dependencies, and my current goal is separate packages (backends) for company and AC, built on top of some common functionality from haskell-mode (this is step 1 I'm currently working on).
@geraldus btw, are you by any chance also tackling the issue of asynchronous lookups as you mentioned in #178 ?
@hvr I hope I can tackle this. First of all I need to finish functions which grabs prefix and its context, this information will be used further in completion function (I'm almost done with it, and currently making some final polish).
I'm still need some research, but I suppose the best way to get synchronous completions is to search them in tags, rather than ask REPL (or maybe select tags if REPL is busy or there is no active haskell process). Also I want to use dabbrev--find-all-expansions
function in case it is not possible to get completions from REPL or TAGS, which will also give completions for arbitrary words in string literals and comments.
The benefit of asking the REPL is that it knows what's in scope, and maybe in the future we may be able to ask the REPL (or maybe ide-backend
-- haven't looked at it yet) to give us more context-aware completions for a given location, all stuff that require more meta-information to be known about the symbols you want to offer completions for.
I agree with you (and I've have not looked at ide-backend
too). But, there are some caveats:
let
blocks (this is why we also need dabbrev
stuff).As for ide-backend
if I'm not mistaken FPco IDE is powered by it, and it will be very nice to make Emacs experience a bit closer to FPco IDE. I'm going to play with it, but I want to finish some tasks for plain haskell-mode without extra tools such as GHCi-ng, ghc-mod, and etc.
REPL may also be hanging because currently same repl session is used both for arbitrary user interaction and completion commands. That mean sync completion may hang whole emacs and async completion may not return obvious expected results.
So REPL is the way to go, but needs to be handled more carefully.
@gracjan btw, is there a way to check is REPL currently busy or idling?
There is no reliable way to do that. There are hacks, some more hilarious than others. Standard comint mode decides that a shell-like session is busy if the cursor is in the first column and ready to accept input if cursor is at the end of a non-empty line (presumably prompt).
This is very fragile. That is why we have whole industry of more request-response interactions like ghc-mod, ide-backend, ghci-ng, ghcid and probably others I haven't heard about.
Would be great to split command and interactive channels inside ghci. Would be even better if command channel had a defined command/response separator.
The only one reason we cannot include asynchronous company-backend in haskell-mode
package is company-begin-backend
1 function and this is required by company itself. I'm curious is there a workaround to use this without bringing company dependency?
fboundp
works in such situations.
It's difficult to tell what the overall goal is. Will this have on my current auto-complete sources, if any? Is it specifically to add support for auto completion sources directly from haskell-process
or haskell-interactive-mode
, maybe ide-backend
as well? I'm happy this is being improved, just curious.
One related feature I am interested in helping improve is inlined haddocks in the completion popup. I'm currently populating the auto-complete help buffer with hoogle search --info
commands when possible. I suppose it would be possible to use the current haskell-hoogle-command
.
hey @creichert! so, you're with auto-complete
? If this case can I ask you a questions about auto-complete when/if needed, I'm using company myself and have no much time to play with auto-complete myself.
As for completions popup, company-mode
have slightly different approach and your screenshot shows that's it is quite useful to show such haddock info in case of auto-complete
.
For now I've updated default completion-at-point function, and there is a possibility to provide with completion list special annotation function to get extra information for completions and it's currently unimplemented. Initially I've planned to provide annotations for haskell identifiers using :info
REPL command, but haddock alternative looks nicer. However I don't know how and when Emacs uses this annotation function and how this will affect company and a-c work, need some time to make a research.
As for company it has its own meaning of annotation and meta data, for identifier completions it's better to use module name as annotation and haddock info as meta data, like ghc-mod backend does:
Annotations
Type info in echo area
Haddock info in special company doc-buffer
Sure, I'd be happy to help where I can (feel free to ping me on any issues).
company-mode
and auto-complete
do have a slightly different process but they both support candidates and a doc-buffer. I have to take some time to test and look further at what you've already completed and see how I can help.
The doc buffer shown in my screenshot is hoogle search --info IDENT
, which would be run from the 'document' source below:
;; basic auto-complete source
'((available . (lambda() ...) )
(candidates . (lambda () ... ))
(document . (lambda () ...))
(symbol . "h"))
:info and other commands are definitely suitable as well (so it might need to use haskell-hoogle-command or something similar).
@geraldus, @creichert: Is this issue still needed? What is left to be done here?
@gracjan ahh, I have a plan to have three config files for autocompletions: Emacs native completions, company-mode
and auto-complete
, and update completion code to provide annotations and etc. But I don't know when I will be able to do this. Let's keep this issue for some time, if I decide to leave this idea I will ping you.
Okay, can you describe your idea in a bit more detail here in comments so that we know what you are thinking. Somebody might be coming by and be able to help.
Well… there is a lot of work on auto completion improvements.
Fist of all, we have two cases: non-interactive and interactive.
Let's talk about non-interactive first.
Here the best we can do is to provide dynamic case sensitive completions (dabbrev). We already support hardcoded pragmas, so why not to add hardcoded keywords too (at this moment my company-mode
do not gives me keyword completions)?
Then we already creating completion list for supported GHC options dynamically asking GHC. First of all, I would like to mention one caveat: we have to take in account, that it is possible that GHC is not available in PATH
, but still installed in system if I'm not mistaken (stack
could make possible such situation). We can create hard-coded list of completions for Prelude
identifiers in similar fashion (:browse! Prelude
), but in this case we have to ask GHCi instead, and in some cases this is impossible, e.g. in case of GHCJS (however Luite promised that he will merge GHCJSi branch very soon!).
Here is a quick summary:
stack ghci
)stack
Interactive completions are much nicer and we can grab additional information for completions such as type signature and documentation, but I still do not know how can we get this additional data cheap and easy and also uniformly to support all possible cases: Emacs' native completion machinery, company-mode
, auto-complete
. GHCi itself have some issues in :complete
command, I have fixed operator completion (should become available in GHC 8), but it requires at least one more improvement; also GHCi itself does not provide keyword completions (I'll try to fix this too). When I'll find time to take care about mentioned GHCi issues I will ask people on #ghc about possible improvements for :complete
command, I guess it is possible to make it return not plain list of strings, but also extend this list with additional data (such as completion type, for identifiers: module name, type signature, docstring). But if I understood correctly this will go to 8.0.2 which will be released in one year term. So, due to GHCi is not perfect tool to get completions right now I think the best we can do is to offer to users some existing tools such as ghc-mod
and friends. So, let's delay on interactive part at least for now. One last point: I think we should take in account possible failures when receiving interactive completions and concat to interactive completion list a list of non-interactive completions (dabbrev, keywords).
I would be happy to have fuzzy completion function, let me explain this by example.
Suppose I have few definitions: twice
, toWidget
, takeWhile
, in this case I expect all of them should be listed as candidates of tw
expansion. I haven't though much of such functionality yet, maybe it is possible to achieve this already.
Finally, the best thing I can think of is context aware completion. Likely this is interactive only stuff. What I mean? Simply to sort completions according to given context. For example, if you type function argument then completion function could take in account expected argument type and bump completion candidates with matching type to top of the list. When typing inside string — bump non-identifier candidates. And etc.
We can take care of non-interactive part first.
As an extra piece of information, company-ghc provides auto-completion in non-interactive mode via ghc-mod
(this is the default setting in spacemacs
). It is very good but it might get sluggish with bigger projects (see https://github.com/iquiw/company-ghc/issues/23)
@geraldus Correct me if I am wrong but given that the plan is to do nothing extra in the interactive mode for now, I am under the impression that everything you propose is already achieved by spacemacs
.
In a way I am just saying it is a matter of configuration and it might not be a job for haskell-mode
(at least for now). With HIE along the way are we sure such an integration worths the effort ?
I'd like to have as much non-interactive completions happening without ghc-mod as possible.
Currently PRAGMA and LANGUAGE completions work only when haskell-interactive-mode is enabled, those should work with only pure haskell-mode.
Question: what is the difference between auto-complete and company-mode? Are those significantly different or are they supported by the same implementation mechanism?
@PierreR I haven't used Spacemacs myself, but if I'm not mistaken it have company-mode
integrated, and my major point that we should provide some uniform completion function for all cases: no auto-completion package installed, company-mode
and auto-complete
(and possibly some extended versions depending on if company or AC is available in user config).
everything you propose is already achieved by spacemacs
Surely? Does it provide mentioned fuzzy completions and context aware completions? If this is a case I'd definitely take a look (or are you talking about interactive part only?). And I suppose this is achieved because of some built-in extra packages, I guess this is ghc-mod
.
UPDATE: is it complete keywords too?
@gracjan
Currently PRAGMA and LANGUAGE completions work only when haskell-interactive-mode is enabled
Emmm… Are you sure?
UPDATE: hmm… it looks like I'm missing something, when I load Haskell file I always see Interactive
minor mode, when I wrote "interactive" I meant loading project/file to REPL, that is a haskell session, and non-interactive means coding without REPL interaction. So, do we have a scenario where Interactive
minor mode is not enabled and what is the difference?
what is the difference between auto-complete and company-mode
The former is simpler and synchronous and the latter is more flexible and could work asynchronously (if I'm not mistaken)
@geraldus: I'm pretty sure that pure haskell-mode does not offer completions, see:
$ grep completion-at-point-functions *.el
haskell-interactive-mode.el: (add-hook 'completion-at-point-functions
haskell.el: (add-hook 'completion-at-point-functions
Am I missing something?
@gracjan yes, you're right. But why? I think we definitely can provide non-interactive completion function which completes:
We already had some efforts to make use of dabbrev completions in past. I think we should define a function to collect dabbrev expansions along with customizable haskell-dabbrev-expansion-limit
option with some sensible default value and make use of it in completion-function. This will give us some minimal non-interactive completion function, and finally we can include its results in REPL-completion function when REPL is not available or does not returned results.
Some notes about company-mode
: it is already has dabbrev backends (company-dabbrev
and company-dabbrev-code
), and I suppose we can take two ways:
What do you think?
In the code we should have nothing dabbrev related. On the other hand in the documentation we should have a page saying: 'haskell-mode works great with dabbrev based completion, here is how to enable it'.
I think we should define a function to collect dabbrev expansions along with customizable haskell-dabbrev-expansion-limit option with some sensible default value and make use of it in completion-function.
Isn’t the whole point of dabbrev
that it works without doing anything? It just searches everything in the buffer.
It just searches everything in the buffer.
and other buffers too. I have already mentioned this, but will repeat: dabbrev also have some concept of friendly buffers and search expansion there first, for now we can mark all *.hs
buffers as friendly, in future we can do this based on project files.
dabbrev do not provides a function to get a collection of expansions, it immediately expands thing at point, and if triggered one more time, searches next expansion. It is needed to write some code to get a list of expansions.
Just let company,autocomplete or whatever else deal with that. There is no need to replicate that functionality inside of haskell-mode.
@cocreature in general I agree with you, I just stuck a bit with following case:
no special auto-completion package installed;
non-interactive haskell-mode
if we bind completion-at-point-functions
to yet undefined haskell-completions-at-point-function
(without REPL capabilities) then C-M-i will provide no candidates for identifiers. However, users who aware of dabbrev
could expand it hitting M-/ manually.
no special auto-completion package installed;
Why is that a problem? If people want to have auto completion they’re going to install one of those packages. It’s not like haskell-mode is the only mode requiring you to use one of those.
non-interactive haskell-mode
I agree that something basic completing extensions and the like could be nice in that case.
if we bind completion-at-point-functions to yet undefined haskell-completions-at-point-function (without REPL capabilities) then C-M-i will provide no candidates for identifiers. However, users who aware of dabbrev could expand it hitting M-/ manually.
Again let auto-complete or company take care of mixing completions and falling back on one if the other doesn’t work.
haskell-mode is already pretty big and you are proposing to replicate functionality solved perfectly in other packages making it even bigger. Leaving aside the fact that it will take a ton of work to properly replicate that functionality it’s also just useless. If people care about completion they’re going to install one of those packages so the effort should be spend on documentation for anything specific to haskell there and not on rewriting it just so that it doesn’t need to be installed. For people that don’t care about completion they don’t need some reimplementation of company-mode in haskell-mode.
@geraldus: This is good the way you described. In case of vanilla haskell-mode there should be this:
Note that I personally would never enable dabbrev autocomplete or company because I want C-M-i to be context sensitive and M-/ to be context in-sensitive.
@gracjan ok, it become a bit clear now. Finally let's
haskell-completion-at-point
(language, pragma name, options, extensions, keywords) in haskell-completions.el
completion-at-point-functions
in haskell-mode.el
For interactive part:
haskell-completions-sync-completions-at-point
to haskell-sync-repl-completion-at-point
haskell-completion-at-point
internallyhaskell-completions-at-point-function
in completion-at-point-functions
with haskell-sync-repl-completions-at-point
I'd prefer a bit longer names: haskell-completion-completion-at-point
and haskell-completions-sync-repl-completions-at-point
.
Docs:
If everyone is agree with this I would be happy to implement all this stuff.
And I vote for closing this for now.
Related #1169 #1171
@geraldus: Create an issue and write there exactly the same text that you wrote here. Then we will close this one.
Done.
Sorry for extra noise on this, but I decided to clarify type signature and info aspects a bit.
We do not want to depend on extra tool in haskell-mode itself, and due to GHCi does not provide an ability to get type signatures and info among with completion candidates yet the only way to provide this data (both for auto-complete
and company-mode
) would be send REPL another command after candidates are received. This is doable but I suppose this way possibly very expensive. For now the best option is to provide simple completions by default and mention some third party plugins in documentation. However, even if we'll have a single command to grab all data, simple candidates list method would be faster and it is very likely that we'll need some customization to control this. Since customization will be introduced anyway, we can do this now and provide experimental and possibly slow method to get extra info. Other customizations we likely need:
<f>
, <k>
, I think it's better to create new issue for this topic.
@geraldus: Can you create this new issue for this topic? This one has grown out of manageable state.
Both are auto-completion extensions for Emacs and having decent integration with them would improve productivity
https://github.com/auto-complete/auto-complete
https://github.com/company-mode/company-mode