ghc-mod/elisp/ghc-comp.el

279 lines
7.6 KiB
EmacsLisp
Raw Normal View History

2010-01-06 05:38:06 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ghc-comp.el
;;;
;; Author: Kazu Yamamoto <Kazu@Mew.org>
;; Created: Sep 25, 2009
;;; Code:
(require 'ghc-func)
(require 'ghc-rewrite)
2010-01-06 05:38:06 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Customize Variables
;;;
2010-06-14 03:03:14 +00:00
(defvar ghc-idle-timer-interval 30
2014-04-21 08:35:10 +00:00
"*Period of idle timer in second. When timeout, the names of
2010-06-14 03:03:14 +00:00
unloaded modules are loaded")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Constants
;;;
2010-01-06 05:38:06 +00:00
;; must be sorted
2010-06-14 03:03:14 +00:00
(defconst ghc-reserved-keyword-for-bol '("class" "data" "default" "import" "infix" "infixl" "infixr" "instance" "main" "module" "newtype" "type"))
2010-01-06 05:38:06 +00:00
;; must be sorted
2010-06-14 03:03:14 +00:00
(defconst ghc-reserved-keyword '("case" "deriving" "do" "else" "if" "in" "let" "module" "of" "then" "where"))
2010-01-06 05:38:06 +00:00
2014-04-21 11:36:16 +00:00
(defconst ghc-extra-keywords '("ByteString" "Text"))
2010-03-10 06:33:18 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Local Variables
;;;
(defvar ghc-window-configuration nil)
(mapc 'make-variable-buffer-local
'(ghc-window-configuration))
2010-01-06 05:38:06 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Initializer
;;;
(defvar ghc-module-names nil) ;; completion for "import"
(defvar ghc-merged-keyword nil) ;; completion for type/func/...
2010-04-02 06:37:04 +00:00
(defvar ghc-language-extensions nil)
(defvar ghc-option-flags nil)
2014-03-26 06:01:11 +00:00
(defvar ghc-pragma-names '("LANGUAGE" "OPTIONS_GHC" "INCLUDE" "WARNING" "DEPRECATED" "INLINE" "NOINLINE" "ANN" "LINE" "RULES" "SPECIALIZE" "UNPACK" "SOURCE"))
2010-01-06 05:38:06 +00:00
2010-06-14 03:03:14 +00:00
(defconst ghc-keyword-prefix "ghc-keyword-")
2010-01-06 05:38:06 +00:00
(defvar ghc-keyword-Prelude nil)
2012-01-23 09:30:07 +00:00
(defvar ghc-keyword-Control.Applicative nil)
(defvar ghc-keyword-Control.Exception nil)
(defvar ghc-keyword-Control.Monad nil)
2012-01-23 09:30:07 +00:00
(defvar ghc-keyword-Data.Char nil)
(defvar ghc-keyword-Data.List nil)
(defvar ghc-keyword-Data.Maybe nil)
(defvar ghc-keyword-System.IO nil)
2010-01-06 05:38:06 +00:00
(defvar ghc-loaded-module nil)
(defun ghc-comp-init ()
2010-05-04 03:49:22 +00:00
(let* ((syms '(ghc-module-names
2012-01-23 09:37:50 +00:00
ghc-language-extensions
ghc-option-flags
2014-03-27 03:44:09 +00:00
;; hard coded in GHCMod.hs
2012-01-23 09:37:50 +00:00
ghc-keyword-Prelude
ghc-keyword-Control.Applicative
ghc-keyword-Control.Exception
ghc-keyword-Control.Monad
2012-01-23 09:37:50 +00:00
ghc-keyword-Data.Char
ghc-keyword-Data.List
ghc-keyword-Data.Maybe
ghc-keyword-System.IO))
2010-05-04 08:52:16 +00:00
(vals (ghc-boot (length syms))))
2010-05-04 03:49:22 +00:00
(ghc-set syms vals))
2010-05-04 07:35:40 +00:00
(ghc-add ghc-module-names "qualified")
(ghc-add ghc-module-names "hiding")
2014-03-27 03:44:09 +00:00
;; hard coded in GHCMod.hs
2012-01-23 09:30:07 +00:00
(ghc-merge-keywords '("Prelude"
"Control.Applicative"
"Control.Exception"
"Control.Monad"
2012-01-23 09:30:07 +00:00
"Data.Char"
"Data.List"
"Data.Maybe"
"System.IO")))
2010-01-06 05:38:06 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Executing command
;;;
2010-05-04 08:52:16 +00:00
(defun ghc-boot (n)
(prog2
(message "Initializing...")
(ghc-sync-process "boot\n" n)
(message "Initializing...done")))
2010-05-04 08:52:16 +00:00
(defun ghc-load-modules (mods)
(if mods
2014-04-26 12:00:28 +00:00
(mapcar 'ghc-load-module mods)
(message "No new modules")
nil))
(defun ghc-load-module (mod)
2014-04-26 12:00:28 +00:00
(prog2
(message "Loading symbols for %s..." mod)
(ghc-sync-process (format "browse %s\n" mod))
(message "Loading symbols for %s...done" mod)))
2010-01-06 05:38:06 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Completion
;;;
(defvar ghc-completion-buffer-name "*Completions*")
(defun ghc-complete ()
(interactive)
(if (ghc-should-scroll)
(ghc-scroll-completion-buffer)
2015-08-12 03:58:47 +00:00
(ghc-try-complete)))
2010-01-06 05:38:06 +00:00
(defun ghc-should-scroll ()
(let ((window (ghc-completion-window)))
(and (eq last-command this-command)
window (window-live-p window) (window-buffer window)
(buffer-name (window-buffer window)))))
(defun ghc-scroll-completion-buffer ()
(let ((window (ghc-completion-window)))
(with-current-buffer (window-buffer window)
(if (pos-visible-in-window-p (point-max) window)
(set-window-start window (point-min))
(save-selected-window
(select-window window)
(scroll-up))))))
(defun ghc-completion-window ()
(get-buffer-window ghc-completion-buffer-name 0))
(defun ghc-try-complete ()
(let* ((end (point))
(symbols (ghc-select-completion-symbol))
(beg (ghc-completion-start-point))
(pattern (buffer-substring-no-properties beg end))
(completion (try-completion pattern symbols)))
(cond
((eq completion t) ;; completed
) ;; do nothing
((null completion) ;; no completions
(ding))
((not (string= pattern completion)) ;; ???
(delete-region beg end)
(insert completion)
2010-03-10 06:33:18 +00:00
(ghc-reset-window-configuration))
2010-01-06 05:38:06 +00:00
(t ;; multiple completions
(let* ((list0 (all-completions pattern symbols))
(list (sort list0 'string<)))
2010-03-10 06:33:18 +00:00
(if (= (length list) 1)
(ghc-reset-window-configuration)
(ghc-save-window-configuration)
(with-output-to-temp-buffer ghc-completion-buffer-name
2014-06-30 03:26:30 +00:00
(display-completion-list list))))))))
2010-03-10 06:33:18 +00:00
(defun ghc-save-window-configuration ()
(unless (get-buffer-window ghc-completion-buffer-name)
(setq ghc-window-configuration (current-window-configuration))))
(defun ghc-reset-window-configuration ()
(when ghc-window-configuration
(set-window-configuration ghc-window-configuration)
(setq ghc-window-configuration nil)))
2010-01-06 05:38:06 +00:00
(defun ghc-module-completion-p ()
(or (minibufferp)
2010-08-03 03:26:25 +00:00
(let ((end (point)))
(save-excursion
(beginning-of-line)
(and (looking-at "import ")
(not (search-forward "(" end t)))))
(save-excursion
(beginning-of-line)
2010-08-03 03:26:25 +00:00
(looking-at " +module "))))
2010-01-06 05:38:06 +00:00
(defun ghc-select-completion-symbol ()
(cond
((ghc-module-completion-p)
2010-01-06 05:38:06 +00:00
ghc-module-names)
2010-04-02 06:37:04 +00:00
((save-excursion
(beginning-of-line)
(looking-at "{-# LANGUAGE "))
2010-04-02 06:37:04 +00:00
ghc-language-extensions)
((save-excursion
(beginning-of-line)
(looking-at "{-# OPTIONS_GHC "))
ghc-option-flags)
((save-excursion
(beginning-of-line)
(looking-at "{-# "))
ghc-pragma-names)
2010-01-06 05:38:06 +00:00
((or (bolp)
(let ((end (point)))
(save-excursion
(beginning-of-line)
(not (search-forward " " end t)))))
ghc-reserved-keyword-for-bol)
(t ghc-merged-keyword)))
(defun ghc-completion-start-point ()
(save-excursion
(let ((beg (save-excursion (beginning-of-line) (point)))
(regex (if (ghc-module-completion-p) "[ (,`]" "[\[ (,`.]")))
(if (re-search-backward regex beg t)
2010-01-06 05:38:06 +00:00
(1+ (point))
beg))))
2010-01-06 05:39:30 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Loading keywords
;;;
2010-05-04 08:52:16 +00:00
(defun ghc-import-module ()
(interactive)
(ghc-load-module-buffer))
2010-05-04 08:52:16 +00:00
(defun ghc-unloaded-modules (mods)
(ghc-filter (lambda (mod)
(and (member mod ghc-module-names)
(not (member mod ghc-loaded-module))))
mods))
(defun ghc-load-module-buffer ()
(ghc-load-merge-modules (ghc-gather-import-modules-buffer)))
(defun ghc-load-merge-modules (mods)
(let* ((umods (ghc-unloaded-modules mods))
(syms (mapcar 'ghc-module-symbol umods))
(names (ghc-load-modules umods)))
(ghc-set syms names)
(ghc-merge-keywords umods)))
(defun ghc-merge-keywords (mods)
(setq ghc-loaded-module (append mods ghc-loaded-module))
2010-01-06 05:39:30 +00:00
(let* ((modkeys (mapcar 'ghc-module-keyword ghc-loaded-module))
(keywords (cons ghc-extra-keywords (cons ghc-reserved-keyword modkeys)))
2010-01-06 05:39:30 +00:00
(uniq-sorted (sort (ghc-uniq-lol keywords) 'string<)))
(setq ghc-merged-keyword uniq-sorted)))
2010-05-04 08:52:16 +00:00
(defun ghc-module-symbol (mod)
(intern (concat ghc-keyword-prefix mod)))
(defun ghc-module-keyword (mod)
(symbol-value (ghc-module-symbol mod)))
2010-01-06 05:38:06 +00:00
(defun ghc-gather-import-modules-buffer ()
(let (ret)
(save-excursion
(goto-char (point-min))
2015-08-27 01:42:28 +00:00
(while (re-search-forward "^import +\\(qualified\\)? *\\([^\n ]+\\)" nil t)
2010-05-04 08:52:16 +00:00
(ghc-add ret (match-string-no-properties 2))
2010-01-06 05:38:06 +00:00
(forward-line)))
ret))
2010-05-04 08:52:16 +00:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Background Idle Timer
;;;
2010-01-06 05:38:06 +00:00
(provide 'ghc-comp)