summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README11
-rw-r--r--elisp/Makefile.am1
-rw-r--r--elisp/geiser-autodoc.el6
-rw-r--r--elisp/geiser-company.el111
-rw-r--r--elisp/geiser-completion.el8
-rw-r--r--elisp/geiser-edit.el11
-rw-r--r--elisp/geiser-mode.el7
-rw-r--r--elisp/geiser-reload.el1
-rw-r--r--elisp/geiser-repl.el7
9 files changed, 153 insertions, 10 deletions
diff --git a/README b/README
index 537f291..8870006 100644
--- a/README
+++ b/README
@@ -81,6 +81,17 @@
To start a REPL, M-x geiser.
+*** Completion with company-mode
+ Geiser offers identifier and module name completion, bound to
+ M-TAB and M-` respectively. Only names visible in the current
+ module are offered.
+
+ While that is cool and all, things are even better: if you have
+ [[http://nschum.de/src/emacs/company-mode/][company-mode]] installed, Geiser's completion will use it. Just
+ require company-mode and, from then on, any new scheme buffer or
+ REPL will use it. If you didn't know about Nikolaj Schumacher's
+ awesome mode, check [[http://www.screentoaster.com/watch/stU0lSRERIR1pYRFVdXVlRVFFV/company_mode_for_gnu_emacs][this screencast]].
+
* Quick key reference
*** In Scheme buffers:
diff --git a/elisp/Makefile.am b/elisp/Makefile.am
index a6ff248..9f93e64 100644
--- a/elisp/Makefile.am
+++ b/elisp/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = geiser-install.el.in
dist_lisp_LISP = \
geiser-autodoc.el \
geiser-base.el \
+ geiser-company.el \
geiser-compile.el \
geiser-completion.el \
geiser-connection.el \
diff --git a/elisp/geiser-autodoc.el b/elisp/geiser-autodoc.el
index 26abd8d..5aa6691 100644
--- a/elisp/geiser-autodoc.el
+++ b/elisp/geiser-autodoc.el
@@ -153,9 +153,13 @@ when `geiser-autodoc-display-module-p' is on."
;;; Autodoc function:
+(make-variable-buffer-local
+ (defvar geiser-autodoc--inhibit-flag nil))
+
(defun geiser-autodoc--eldoc-function ()
(condition-case e
- (geiser-autodoc--autodoc (geiser-syntax--scan-sexps))
+ (and (not geiser-autodoc--inhibit-flag)
+ (geiser-autodoc--autodoc (geiser-syntax--scan-sexps)))
(error (format "Autodoc not available (%s)" (error-message-string e)))))
diff --git a/elisp/geiser-company.el b/elisp/geiser-company.el
new file mode 100644
index 0000000..8ae8969
--- /dev/null
+++ b/elisp/geiser-company.el
@@ -0,0 +1,111 @@
+;; geiser-company.el -- integration with company-mode
+
+;; Copyright (C) 2009 Jose Antonio Ortega Ruiz
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Start date: Mon Aug 24, 2009 12:44
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'geiser-autodoc)
+(require 'geiser-completion)
+(require 'geiser-edit)
+(require 'geiser-base)
+
+
+;;; Helpers:
+
+(make-variable-buffer-local
+ (defvar geiser-company--enabled-flag nil))
+
+(defsubst geiser-company--candidates (prefix module)
+ (car (geiser-completion--complete prefix module)))
+
+(defsubst geiser-company--doc (id module)
+ (ignore-errors
+ (if module
+ (format "%s [module]" id)
+ (geiser-autodoc--autodoc (list (list (intern id) 0))))))
+
+(defsubst geiser-company--doc-buffer (id module)
+ nil)
+
+(defun geiser-company--location (id module)
+ (ignore-errors
+ (let ((id (intern id)))
+ (save-current-buffer
+ (if module (geiser-edit-module id) (geiser-edit-symbol id))
+ (cons (current-buffer) (point))))))
+
+(defsubst geiser-company--prefix-at-point (module)
+ (and geiser-company--enabled-flag
+ (looking-at-p "\\_>")
+ (not (nth 8 (syntax-ppss)))
+ (geiser-completion--prefix module)))
+
+
+;;; Activation
+
+(defun geiser-company--setup (enable)
+ (setq geiser-company--enabled-flag enable)
+ (when (fboundp 'company-mode)
+ (company-mode nil)
+ (when enable (company-mode enable)))
+ (when (boundp 'company-lighter)
+ (setq company-lighter "/C")))
+
+(defun geiser-company--inhibit-autodoc (ignored)
+ (setq geiser-autodoc--inhibit-flag t))
+
+(defun geiser-company--restore-autodoc (&optional ignored)
+ (setq geiser-autodoc--inhibit-flag nil))
+
+
+;;; Backends:
+(defmacro geiser-company--make-backend (name mod)
+ `(defun ,name (command &optional arg &rest ignored)
+ "A `company-mode' completion back-end for `geiser-mode'."
+ (interactive (list 'interactive))
+ (case command
+ ('interactive (company-begin-backend ',name))
+ ('prefix (geiser-company--prefix-at-point ,mod))
+ ('candidates (geiser-company--candidates arg ,mod))
+ ('meta (geiser-company--doc arg ,mod))
+ ('doc-buffer (geiser-company--doc-buffer arg ,mod))
+ ('location (geiser-company--location arg ,mod))
+ ('sorted t))))
+
+(defvar geiser-company--backend '(company-geiser-ids company-geiser-modules))
+
+(eval-after-load "company"
+ '(progn
+ (geiser-company--make-backend company-geiser-ids nil)
+ (geiser-company--make-backend company-geiser-modules t)
+ (add-to-list 'company-backends geiser-company--backend)
+ (add-hook 'company-completion-finished-hook 'geiser-company--restore-autodoc)
+ (add-hook 'company-completion-cancelled-hook 'geiser-company--restore-autodoc)
+ (add-hook 'company-completion-started-hook 'geiser-company--inhibit-autodoc)))
+
+
+;;; Reload support:
+
+(defun geiser-company-unload-function ()
+ (when (boundp 'company-backends)
+ (setq company-backends (remove geiser-company--backend company-backends))))
+
+
+(provide 'geiser-company)
+;;; geiser-company.el ends here
diff --git a/elisp/geiser-completion.el b/elisp/geiser-completion.el
index cd03cae..e3bd74b 100644
--- a/elisp/geiser-completion.el
+++ b/elisp/geiser-completion.el
@@ -204,14 +204,16 @@ terminates a current completion."
(funcall geiser-completion--symbol-begin-function module))
(save-excursion (skip-syntax-backward "^-()>") (point))))
+(defsubst geiser-completion--prefix (module)
+ (buffer-substring-no-properties (point)
+ (geiser-completion--symbol-begin module)))
+
(defun geiser-completion--complete-symbol (&optional arg)
"Complete the symbol at point.
Perform completion similar to Emacs' complete-symbol.
With prefix, complete module name."
(interactive "P")
- (let* ((end (point))
- (beg (geiser-completion--symbol-begin arg))
- (prefix (buffer-substring-no-properties beg end))
+ (let* ((prefix (geiser-completion--prefix arg))
(result (geiser-completion--complete prefix arg))
(completions (car result))
(partial (cdr result)))
diff --git a/elisp/geiser-edit.el b/elisp/geiser-edit.el
index ad2c11e..418b6e3 100644
--- a/elisp/geiser-edit.el
+++ b/elisp/geiser-edit.el
@@ -155,13 +155,12 @@ or following links in error buffers.")
(defvar geiser-edit--symbol-history nil)
-(defun geiser-edit-symbol ()
+(defun geiser-edit-symbol (symbol)
"Asks for a symbol to edit, with completion."
- (interactive)
- (let* ((symbol (geiser-completion--read-symbol "Edit symbol: "
- nil
- geiser-edit--symbol-history))
- (cmd `(:eval ((:ge symbol-location) ',symbol))))
+ (interactive (list (geiser-completion--read-symbol "Edit symbol: "
+ nil
+ geiser-edit--symbol-history)))
+ (let ((cmd `(:eval ((:ge symbol-location) ',symbol))))
(geiser-edit--try-edit symbol (geiser-eval--send/wait cmd))))
(defun geiser-edit-symbol-at-point (&optional arg)
diff --git a/elisp/geiser-mode.el b/elisp/geiser-mode.el
index cc5a00f..fa686ec 100644
--- a/elisp/geiser-mode.el
+++ b/elisp/geiser-mode.el
@@ -28,6 +28,7 @@
(require 'geiser-doc)
(require 'geiser-compile)
(require 'geiser-completion)
+(require 'geiser-company)
(require 'geiser-xref)
(require 'geiser-edit)
(require 'geiser-autodoc)
@@ -52,6 +53,11 @@
:group 'geiser-autodoc
:type 'boolean)
+(defcustom geiser-mode-company-p t
+ "Whether to use company-mode for completion, if available."
+ :group 'geiser-mode
+ :type 'boolean)
+
(defcustom geiser-mode-smart-tab-p nil
"Whether `geiser-smart-tab-mode' gets enabled by default in Scheme buffers."
:group 'geiser-mode
@@ -188,6 +194,7 @@ interacting with the Geiser REPL is at your disposal.
(when geiser-mode (geiser-impl--set-buffer-implementation))
(setq geiser-autodoc-mode-string "/A")
(setq geiser-smart-tab-mode-string "/T")
+ (geiser-company--setup (and geiser-mode geiser-mode-company-p))
(when geiser-mode-autodoc-p (geiser-autodoc-mode geiser-mode))
(when geiser-mode-smart-tab-p (geiser-smart-tab-mode geiser-mode)))
diff --git a/elisp/geiser-reload.el b/elisp/geiser-reload.el
index 97b398d..5a30e1f 100644
--- a/elisp/geiser-reload.el
+++ b/elisp/geiser-reload.el
@@ -38,6 +38,7 @@
geiser-doc
geiser-debug
geiser-impl
+ geiser-company
geiser-completion
geiser-autodoc
geiser-compile
diff --git a/elisp/geiser-repl.el b/elisp/geiser-repl.el
index bed653f..4ea1bb7 100644
--- a/elisp/geiser-repl.el
+++ b/elisp/geiser-repl.el
@@ -24,6 +24,7 @@
;;; Code:
+(require 'geiser-company)
(require 'geiser-autodoc)
(require 'geiser-edit)
(require 'geiser-impl)
@@ -70,6 +71,11 @@ implementation name gets appended to it."
:type 'boolean
:group 'geiser-repl)
+(defcustom geiser-repl-company-p t
+ "Whether to use company-mode for completion, if available."
+ :group 'geiser-mode
+ :type 'boolean)
+
(defcustom geiser-repl-read-only-prompt-p t
"Whether the REPL's prompt should be read-only."
:type 'boolean
@@ -293,6 +299,7 @@ If no REPL is running, execute `run-geiser' to start a fresh one."
(set-syntax-table scheme-mode-syntax-table)
(setq geiser-eval--get-module-function 'geiser-repl--module-function)
(when geiser-repl-autodoc-p (geiser-autodoc-mode 1))
+ (geiser-company--setup geiser-repl-company-p)
(compilation-shell-minor-mode 1))
(define-key geiser-repl-mode-map "\C-d" 'delete-char)