Scheme-complete provides a single function, scheme-smart-complete, which you can use for intelligent, context-sensitive completion for any Scheme implementation.

The intelligent completion comes from the use of simple Type inference. In many cases this can drastically prune the list of possible completions. For example, given the text

(string-ref (n^

where the cursor is represented by ^, typing tab (or whatever you bind the completion function to) would know that in the default R5RS environment the only possible completion of a procedure returning a string and beginning with "n" is number->string and would complete that for you automatically.


(let ((len (string-length str)))
  (string-ref str (- ^

completing would fill in "len" as the only possible completion since a number is required as an argument to - and all the standard R5RS bindings are procedures and syntax.

Relying on this completion for known type procedures is a handy way to avoid type errors, even before the compilation. In more general cases it's just nice to have basic pruning, such as not completing syntax in a non-operator position.

Currently completion inside strings does filename completion, though this may be made for flexible in the future. For Chicken and Gauche, completing after "(use " will complete on all currently installed modules.


To use it just load this file and bind that function to a key in your preferred mode:

(autoload 'scheme-smart-complete "scheme-complete" nil t)
(eval-after-load 'scheme
  '(define-key scheme-mode-map "\e\t" 'scheme-smart-complete))

Alternately, you may want to just bind TAB to the scheme-complete-or-indent function, which indents at the start of a line and otherwise performs the smart completion:

(eval-after-load 'scheme
  '(define-key scheme-mode-map "\t" 'scheme-complete-or-indent))

If you use eldoc-mode (included in Emacs), you can also get live scheme documentation with:

(autoload 'scheme-get-current-symbol-info "scheme-complete" nil t)
(add-hook 'scheme-mode-hook
  (lambda ()
    (make-local-variable 'eldoc-documentation-function)
    (setq eldoc-documentation-function 'scheme-get-current-symbol-info)

You can enable slightly smarter indentation with

(setq lisp-indent-function 'scheme-smart-indent-function)

which basically ignores the scheme-indent-function property for locally overridden symbols (e.g. if you use the (let loop () ...) idiom it won't use the special loop indentation inside).

There's a single custom variable, scheme-default-implementation, which you can use to specify your preferred implementation when we can't infer it from the source code.

That's all there is to it.



  • 0.9.7: 2017/08/24 - improving caching, adding some missing (scheme char) bindings
  • 0.9.6: 2017/04/10 - fix possible inf loop in enclosing-2-sexp-prefixes
  • 0.9.5: 2017/04/02 - completiong for only/except/export, better caching
  • 0.9.4: 2017/04/01 - don't open non-existant files
  • 0.9.3: 2016/06/04 - string-cursors, bugfixes, speedups, introducing unit tests with ert
  • 0.9.2: 2016/05/03 - several bugfixes
  • 0.9.1: 2016/04/08 - fixing bug in cond-expand parsing
  • 0.9.0: 2015/11/25 - R7RS support
  • 0.8.11: 2013/02/20 - formatting for melpa packaging
  • 0.8.10: 2010/01/31 - factoring out a `scheme-get-completions' utility (thanks to Scott Dolim), and not jumping to end of current symbol if there are no completions for it
  • 0.8.9: 2009/10/28 - allowing indented module/library definitions, added various customizations for tab/indent behavior, complete jumps to end of current symbol
  • 0.8.8: 2009/08/18 - fixing bug in scheme-directory-tree-files with funny file names
  • 0.8.7: 2009/07/18 - foof-loop support, don't complete current var, updating chicken 4 module information
  • 0.8.6: 2009/05/03 - fixing support for chicken 4 w/ unbalanced parens
  • 0.8.5: 2009/04/30 - full support for chicken 4, fixed bug in caching
  • 0.8.4: 2008/12/26 - numerous small bugfixes (Merry Christmas!)
  • 0.8.3: 2008/10/06 - smart indent, inferring types from imported modules, optionally caching exports, chicken 4 support
  • 0.8.2: 2008/07/04 - both TAB and M-TAB scroll results (thanks Peter Bex), better MATCH handling, fixed SRFI-55, other bugfixes
  • 0.8.1: 2008/04/17 - great renaming, everthing starts with `scheme-' also, don't scan imported modules multiple times
  • 0.8: 2008/02/08 - several parsing bugfixes on unclosed parenthesis (thanks to Kazushi NODA) filename completion works properly on absolute paths eldoc works properly on dotted lambdas
  • 0.7: 2008/01/18 - handles higher-order types (for apply, map, etc.) smarter string completion (hostname, username, etc.) smarter type inference, various bugfixes
  • 0.6: 2008/01/06 - more bugfixes (merry christmas)
  • 0.5: 2008/01/03 - handling internal defines, records, smarter parsing
  • 0.4: 2007/11/14 - silly bugfix plus better repo env support for searching chicken and gauche modules
  • 0.3: 2007/11/13 - bugfixes, better inference, smart strings
  • 0.2: 2007/10/15 - basic type inference
  • 0.1: 2007/09/11 - initial release