ghc-info.el 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;
  3. ;;; ghc-info.el
  4. ;;;
  5. ;; Author: Kazu Yamamoto <Kazu@Mew.org>
  6. ;; Created: Nov 15, 2010
  7. ;;; Code:
  8. (require 'ghc-func)
  9. (defun ghc-show-info (&optional ask)
  10. (interactive "P")
  11. (let* ((modname (or (ghc-find-module-name) "Main"))
  12. (expr0 (ghc-things-at-point))
  13. (expr (if (or ask (not expr0)) (ghc-read-expression expr0) expr0))
  14. (file (buffer-file-name))
  15. (cmds (list "info" file modname expr)))
  16. (ghc-display-information cmds nil)))
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18. ;;;
  19. ;;; type
  20. ;;;
  21. (defvar ghc-type-overlay nil)
  22. (make-variable-buffer-local 'ghc-type-overlay)
  23. (defun ghc-type-set-ix (n)
  24. (overlay-put ghc-type-overlay 'ix n))
  25. (defun ghc-type-get-ix ()
  26. (overlay-get ghc-type-overlay 'ix))
  27. (defun ghc-type-set-point (pos)
  28. (overlay-put ghc-type-overlay 'pos pos))
  29. (defun ghc-type-get-point ()
  30. (overlay-get ghc-type-overlay 'pos))
  31. (defun ghc-type-set-types (types)
  32. (overlay-put ghc-type-overlay 'types types))
  33. (defun ghc-type-get-types ()
  34. (overlay-get ghc-type-overlay 'types))
  35. (ghc-defstruct tinfo beg-line beg-column end-line end-column info)
  36. (defun ghc-type-init ()
  37. (setq ghc-type-overlay (make-overlay 0 0))
  38. (overlay-put ghc-type-overlay 'face 'region)
  39. (ghc-type-clear-overlay)
  40. (setq after-change-functions
  41. (cons 'ghc-type-clear-overlay after-change-functions))
  42. (add-hook 'post-command-hook 'ghc-type-post-command-hook))
  43. (defun ghc-type-clear-overlay (&optional beg end len)
  44. (when (overlayp ghc-type-overlay)
  45. (ghc-type-set-ix 0)
  46. (ghc-type-set-point 0)
  47. (move-overlay ghc-type-overlay 0 0)))
  48. (defun ghc-type-post-command-hook ()
  49. (when (and (eq major-mode 'haskell-mode)
  50. (overlayp ghc-type-overlay)
  51. (/= (ghc-type-get-point) (point)))
  52. (ghc-type-clear-overlay)))
  53. (defun ghc-show-type ()
  54. (interactive)
  55. (if (not (executable-find ghc-module-command))
  56. (message "%s not found" ghc-module-command)
  57. (let ((modname (or (ghc-find-module-name) "Main")))
  58. (ghc-show-type0 modname))))
  59. (defun ghc-show-type0 (modname)
  60. (let* ((buf (current-buffer))
  61. (tinfos (ghc-type-get-tinfos modname)))
  62. (if (null tinfos)
  63. (progn
  64. (ghc-type-clear-overlay)
  65. (message "Cannot guess type"))
  66. (let* ((tinfo (nth (ghc-type-get-ix) tinfos))
  67. (type (ghc-tinfo-get-info tinfo))
  68. (beg-line (ghc-tinfo-get-beg-line tinfo))
  69. (beg-column (ghc-tinfo-get-beg-column tinfo))
  70. (end-line (ghc-tinfo-get-end-line tinfo))
  71. (end-column (ghc-tinfo-get-end-column tinfo))
  72. (left (ghc-get-pos buf beg-line beg-column))
  73. (right (ghc-get-pos buf end-line end-column)))
  74. (move-overlay ghc-type-overlay (- left 1) (- right 1) buf)
  75. (message type)))))
  76. (defun ghc-type-get-tinfos (modname)
  77. (if (= (ghc-type-get-point) (point))
  78. (ghc-type-set-ix
  79. (mod (1+ (ghc-type-get-ix)) (length (ghc-type-get-types))))
  80. (ghc-type-set-types (ghc-type-obtain-tinfos modname))
  81. (ghc-type-set-point (point))
  82. (ghc-type-set-ix 0))
  83. (ghc-type-get-types))
  84. (defun ghc-type-obtain-tinfos (modname)
  85. (let* ((ln (int-to-string (line-number-at-pos)))
  86. (cn (int-to-string (current-column)))
  87. (cdir default-directory)
  88. (file (buffer-file-name)))
  89. (ghc-read-lisp
  90. (lambda ()
  91. (cd cdir)
  92. (apply 'call-process ghc-module-command nil t nil
  93. `(,@(ghc-make-ghc-options) "-l" "type" ,file ,modname ,ln ,cn))
  94. (goto-char (point-min))
  95. (while (search-forward "[Char]" nil t)
  96. (replace-match "String"))))))
  97. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  98. ;;;
  99. ;;; Expanding Template Haskell
  100. ;;;
  101. (defun ghc-expand-th ()
  102. (interactive)
  103. (let* ((file (buffer-file-name))
  104. (cmds (list "expand" file)))
  105. (ghc-display-information cmds t)))
  106. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  107. ;;;
  108. ;;; Display
  109. ;;;
  110. (defun ghc-display-information (cmds fontify)
  111. (interactive)
  112. (if (not (executable-find ghc-module-command))
  113. (message "%s not found" ghc-module-command)
  114. (ghc-display
  115. fontify
  116. (lambda (cdir)
  117. (insert
  118. (with-temp-buffer
  119. (cd cdir)
  120. (apply 'call-process ghc-module-command nil t nil
  121. (append (ghc-make-ghc-options) cmds))
  122. (buffer-substring (point-min) (1- (point-max)))))))))
  123. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  124. ;;;
  125. ;;; Misc
  126. ;;;
  127. (defun ghc-get-pos (buf line col)
  128. (save-excursion
  129. (set-buffer buf)
  130. (goto-line line)
  131. (forward-char col)
  132. (point)))
  133. (defun ghc-read-expression (default)
  134. (if default
  135. (let ((prompt (format "Expression (%s): " default)))
  136. (read-string prompt default nil))
  137. (read-string "Expression: ")))
  138. (defun ghc-find-module-name ()
  139. (save-excursion
  140. (goto-char (point-min))
  141. (if (re-search-forward "^module[ ]+\\([^ \n]+\\)" nil t)
  142. (match-string-no-properties 1))))
  143. (provide 'ghc-info)