|
1 |
| -;;; haskell-doc.el --- show function types in echo area -*- coding: utf-8 -*- |
| 1 | +;;; haskell-doc.el --- show function types in echo area -*- coding: utf-8; lexical-binding: t -*- |
2 | 2 |
|
3 | 3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
|
4 | 4 | ;; Copyright (C) 1997 Hans-Wolfgang Loidl
|
|
343 | 343 | ;;@subsection Emacs portability
|
344 | 344 |
|
345 | 345 | (require 'haskell-mode)
|
| 346 | +(require 'haskell-process) |
| 347 | +(require 'haskell) |
346 | 348 | (require 'inf-haskell)
|
347 | 349 | (require 'imenu)
|
348 | 350 |
|
@@ -1519,7 +1521,14 @@ This function is run by an idle timer to print the type
|
1519 | 1521 | (defun haskell-doc-current-info ()
|
1520 | 1522 | "Return the info about symbol at point.
|
1521 | 1523 | Meant for `eldoc-documentation-function'."
|
1522 |
| - (haskell-doc-sym-doc (haskell-ident-at-point))) |
| 1524 | + ;; There are a number of possible documentation functions. |
| 1525 | + ;; Some of them are asynchronous. |
| 1526 | + (let ((msg (or |
| 1527 | + (when (and (require 'eldoc nil t) ; FIXME eldoc required? |
| 1528 | + (fboundp #'eldoc-print-current-symbol-info)) |
| 1529 | + (haskell-doc-current-info--interaction)) |
| 1530 | + (haskell-doc-sym-doc (haskell-ident-at-point))))) |
| 1531 | + (unless (symbolp msg) msg))) |
1523 | 1532 |
|
1524 | 1533 |
|
1525 | 1534 | ;;@node Mouse interface, Print fctsym, Top level function, top
|
@@ -1583,6 +1592,66 @@ current buffer."
|
1583 | 1592 | (let ((message-log-max nil))
|
1584 | 1593 | (message "%s" doc)))))))
|
1585 | 1594 |
|
| 1595 | +(defvar haskell-doc-current-info--interaction-last nil |
| 1596 | + "If non-nil, a previous eldoc message from an async call, that |
| 1597 | + hasn't been displayed yet.") |
| 1598 | + |
| 1599 | +(defun haskell-doc-current-info--interaction () |
| 1600 | + "Asynchronous call to `haskell-process-get-type', suitable for |
| 1601 | +use in the eldoc function `haskell-doc-current-info'." |
| 1602 | + ;; Return nil if nothing is available, or 'async if something might |
| 1603 | + ;; be available, but asynchronously later. This will call |
| 1604 | + ;; `eldoc-print-current-symbol-info' later. |
| 1605 | + (let (sym prev-message) |
| 1606 | + (cond |
| 1607 | + ((setq prev-message haskell-doc-current-info--interaction-last) |
| 1608 | + (setq haskell-doc-current-info--interaction-last nil) |
| 1609 | + (cdr prev-message)) |
| 1610 | + ((setq sym |
| 1611 | + (if (use-region-p) |
| 1612 | + (buffer-substring-no-properties |
| 1613 | + (region-beginning) (region-end)) |
| 1614 | + (thing-at-point 'symbol 'no-properties))) |
| 1615 | + (haskell-process-get-type |
| 1616 | + sym (lambda (response) |
| 1617 | + (setq haskell-doc-current-info--interaction-last |
| 1618 | + (cons 'async response)) |
| 1619 | + (when (fboundp #'eldoc-print-current-symbol-info) ; FIXME eldoc required? |
| 1620 | + (eldoc-print-current-symbol-info)))) |
| 1621 | + 'async)))) |
| 1622 | + |
| 1623 | +(defun haskell-process-get-type (expr-string &optional callback) |
| 1624 | + "Asynchronously get the type of a given string. |
| 1625 | +
|
| 1626 | +EXPR-STRING should be an expression passed to :type in ghci. |
| 1627 | +
|
| 1628 | +CALLBACK will be called with a formatted type string." |
| 1629 | + (let ((process (haskell-process)) |
| 1630 | + ;; Avoid passing bad strings to ghci |
| 1631 | + (expr-okay (not (string-match-p "\n" expr-string))) |
| 1632 | + (ghci-command (concat ":type " expr-string))) |
| 1633 | + (when (and process expr-okay) |
| 1634 | + (haskell-process-queue-command |
| 1635 | + (haskell-process) |
| 1636 | + (make-haskell-command |
| 1637 | + :go (lambda (_) (haskell-process-send-string process ghci-command)) |
| 1638 | + :complete |
| 1639 | + (lambda (_ response) |
| 1640 | + ;; Responses with empty first line are likely errors |
| 1641 | + (if (string-match-p (rx string-start line-end) response) |
| 1642 | + (setq response nil) |
| 1643 | + ;; Remove a newline at the end |
| 1644 | + (setq response (replace-regexp-in-string "\n\\'" "" response)) |
| 1645 | + ;; Propertize for eldoc |
| 1646 | + (save-match-data |
| 1647 | + (when (string-match " :: " response) |
| 1648 | + ;; Highlight type |
| 1649 | + (let ((name (substring response 0 (match-end 0))) |
| 1650 | + (type (propertize |
| 1651 | + (substring response (match-end 0)) |
| 1652 | + 'face 'eldoc-highlight-function-argument))) |
| 1653 | + (setq response (concat name type)))))) |
| 1654 | + (when callback (funcall callback response)))))))) |
1586 | 1655 |
|
1587 | 1656 | (defun haskell-doc-sym-doc (sym)
|
1588 | 1657 | "Show the type of the function near point.
|
|
0 commit comments