Skip to content

Support simple completions in non-interactive context. Support keyword completions #1172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 23, 2016
Merged

Support simple completions in non-interactive context. Support keyword completions #1172

merged 7 commits into from
Feb 23, 2016

Conversation

geraldus
Copy link
Contributor

Related #1171

@geraldus
Copy link
Contributor Author

I'm modifying REPL completion function right now and can push few commits here.

@gracjan
Copy link
Contributor

gracjan commented Feb 21, 2016

Good stuff. Can you remove these things from haskell-interactive-mode?

@geraldus
Copy link
Contributor Author

Ok it looks like it works properly. One thing I haven't checked is that REPL completion function should take precedence to simple completion function in completion-at-point-functions hook, former is added in interactive minor mode and the latter is in haskell major mode.

@gracjan didn't catch your point about interactive mode, what should I remove? (: This one

(defun haskell-interactive-mode-completion-at-point-function ()
"Offer completions for partial expression between prompt and point"
(when (haskell-interactive-at-prompt)
(let* ((process (haskell-interactive-process))
(inp (haskell-interactive-mode-input-partial))
(resp2 (haskell-process-get-repl-completions process inp))
(rlen (- (length inp) (length (car resp2))))
(coll (append (if (string-prefix-p inp "import") '("import"))
(if (string-prefix-p inp "let") '("let"))
(cdr resp2))))
(list (- (point) rlen) (point) coll))))
?

haskell-completions-ghc-option-prefix
haskell-completions-language-extension-prefix))
;; provide simple completions
(haskell-completions--simple-completions prefix-data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand there will be two completions hooks installed at the same time, one by haskell-mode other by interactive-haskell-mode. The non-interactive one will return completions for PRAGMA, GHC_OPTION and LANGUAGE, so there is no need to return those completions here again.

Unless I'm mistaken how the mechanism works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gracjan I tested this, and if first function in hook returns nil there will no completions. I tested this creating two dummy completion functions and added both of them to completion-at-point-functions hook in elisp mode. All time only first function was used to return completion candidates. I don't know why it works this way though.

(defun complete-ab ()
  (let ((end (point)))
    (save-excursion
      (backward-word)
      (when (looking-at "ab")
        (let ((start (point)))
          (list start end '("abcde" "abcdf" "abcdef")))))))

(defun complete-other ()
  (let ((end (point)))
    (save-excursion
      (backward-word)
      (let* ((start (point))
             (word (buffer-substring start end)))
        (list start end '(concat word "123"))))))

(add-hook 'completion-at-point-functions #'complete-other nil t)
(add-hook 'completion-at-point-functions #'complete-ab nil t)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've repeated this experiment and it works like described in Emacs docs (and unlike you say). That means I'm able to complete "1" to "123" and "ab" to any of the options listed. Emacs seems to work correctly.

@geraldus
Copy link
Contributor Author

As for haskell-interactive-mode-completion-at-point-function, to remove it we have to support REPL command completions. haskell-completions-sync-repl-completions can give right candidates if we take care of : when grabbing prefix in REPL buffer.

UPDATE: I have already implemented such support and indeed substituting haskell-interactive-mode-completion-at-point-function with haskell-completions-sync-repl-completions for REPL buffer works fine in general (though I've already found something to improve :D), but I stuck with circular dependency interactive-mode/completions. I need to think a bit.

UPDATE: finally, I think we can leave haskell-interactive-mode-completion-at-point-function untouched (except maybe some better name). This function is simpler because it does not use haskell-ident-pos-at-point and passes all input string to REPL's :complete command; GHCi handles whole input itself and correctly completes module names for import …, :m [+-]…, :module [+-]…, :bro … and etc. while all these cases will require extra checks in haskell-completions-grab-prefix-function. Also, GHCi can complete filename, which is not a case for functions from haskell-completions.el.

@fice-t
Copy link
Contributor

fice-t commented Feb 22, 2016

Should the hardcoded completions have extra information for support for eldoc-mode? That is, in haskell-doc-mode, there are a few huge hardcoded alists that are currently outdated.

I was thinking that you could make new giant alists so that eldoc could use its keys and values, and the completion would just use the keys.

@geraldus
Copy link
Contributor Author

@fice-t hmm, I didn't catch your idea, if we do have such list already why we need another one? Can you clarify?

@gracjan
Copy link
Contributor

gracjan commented Feb 22, 2016

I wonder how useful the hints by haskell-doc-mode are. Old timers know basic language constructs by heart, can newbies sort out keyword usage from the very short descriptions provided by haskell-doc-mode?

@geraldus
Copy link
Contributor Author

I like doc messages for top-level forms, but keyword doc strings seem for me quite confusing :D

@geraldus
Copy link
Contributor Author

By the way, @gracjan in Emacs 25 I have colored message in mini-buffer from eldoc, should we follow this (I remember in past you suggested not to fontify haskell-doc messages)?

@fice-t
Copy link
Contributor

fice-t commented Feb 22, 2016

The lists are old as they're for Haskell-98. According to git they haven't been updated in over a decade.

@geraldus
Copy link
Contributor Author

@fice-t I agree, I saw that before, I just do not understand what benefits of extra information in hard-coded lists?

@fice-t
Copy link
Contributor

fice-t commented Feb 22, 2016

The extra information would be used in eldoc hints. For example:

("filter" . "(a -> Bool) -> [a] -> [a]")
The completion could just use filter, but eldoc could use both to create filter :: (a-> Bool) -> [a] -> [a]. The same for the keywords (though that might not be as useful).

So it's just using the same list for different purposes.

@geraldus
Copy link
Contributor Author

@fice-t, pal, I'm still confused. Look, haskell-completions--pragma-names and haskell-completions--keywords lists are used only to provide completion candidates, that is either when complete-symbol function is invoked, or completion functions from haskell-completions.el. They have no relation to haskell-doc.el, it have separate hard-coded lists, and I see doc-strings in mini-buffer for keywords and top-level form when haskell session is present (and in my configuration haskell-doc mode is not enabled, Global-Eldoc somehow magically gets information from haskell-doc itself). Are you facing some issues with haskell-doc?

Make use of implemented simple completion funciton.  Complete keywords.
@gracjan
Copy link
Contributor

gracjan commented Feb 22, 2016

I still think the static and the interactive completion functions should be completely separate.

For the interactive case there should be only haskell-completions-grab-identifier-prefix called, this should return nil if inside of a comment.

For the static case there should be only haskell-completions-grab-pragma-prefix called, this should return nil if outside of a pragma comment.

Emacs will call the hooks one by one, stopping with the one that returns non-nil value. This seems perfectly reasonable to me.

Am I missing something?

@geraldus
Copy link
Contributor Author

@gracjan sounds reasonable, but you forgot about keywords in static case

Emacs will call the hooks one by one

Can you please test this (as I mentioned before in my tests second completion function was not triggered when first one returned nil, I updated my comment previous comment with code I've used to tests).

@fice-t
Copy link
Contributor

fice-t commented Feb 22, 2016

Look, haskell-completions--pragma-names and haskell-completions--keywords lists are used only to provide completion candidates, that is either when complete-symbol function is invoked, or completion functions from haskell-completions.el.

That's why I'm saying this. I'm saying (I believe) there could be a single list which both completion and hints could use in some cases, such as keywords and basic/Prelude functions. That might be beneficial as one could maintain just a single list (and periodically generate a separate completion list if one was to speed completion up).

Global-Eldoc somehow magically gets information from haskell-doc itself)

Yeah, eldoc-documentation-function is bound to a function that calls another function that checks the hardcoded haskell-doc lists.

@geraldus
Copy link
Contributor Author

@fice-t ok, now I got it :D
First of all, both lists are incomplete according to the wiki page, they do not include operator-like things such as <-, -> and friends. While it feels sensible to add this stuff to haskell-doc.el, this is not a case for completions. Secondly, I added to completion list special entities such as data family, import qualified. Why? For example type im, in case of company-mode this will give you both import and import qualified candidates in list, in case of vanilla Emacs hitting TAB or C-M-i first expand it to import, consequential command invocation will pop-up a Completion List buffer where both candidates are listed. In we'll use keywords from haskell-doc we'll loose this feature, though it's possible to have a tiny list with such improved candidates and append it to haskell-doc list.

@geraldus
Copy link
Contributor Author

@gracjan this is my thought about your proposal.

  1. I suppose that keywords should be completed in both cases
  2. there is :exclusive property allowing Emacs to run next completion function in case when it can't find matching candidate in list returned by current function. Initially I though this could solve our puzzle, however, if static function will return keywords list with :exclusive no property user won't get other interactive completions if thing to be expanded matches some keyword, that is
    ca with give sole completion case, but it is possible that interactive function could return much more candidates; only when user will type car Emacs will call interactive completions.
  3. if we'll follow your proposal we have to be sure that interactive completion function should be preceded by static, this will require removal static function from hook and then re-addition both in desired order. Current implementation requires reversed order, e.g. interactive function should go first, then static one and this is done out-of-box.

@gracjan
Copy link
Contributor

gracjan commented Feb 23, 2016

@geraldus: I think you convinced me that Emacs default handling of competion-at-point-functions is not appropriate and haskell-mode should handle completions on its own.

In this case you should implement it as you have done. Ping me when the PR is ready to merge.

gracjan added a commit that referenced this pull request Feb 23, 2016
Support simple completions in non-interactive context.  Support keyword completions
@gracjan gracjan merged commit bcfe134 into haskell:master Feb 23, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants