This provides a major mode to edit Racket source files, as well as a major mode for a Racket REPL. The edit/run experience is similar to DrRacket.
-
Focus on Racket.
- Mode line and menu say
Racket. - Omit stuff for various current and historical Schemes that's N/A for Racket.
- Mode line and menu say
-
Use DrRacket concepts where applicable.
- A simple and obvious way to "run" a file: Run F5.
- Allow interaction in the REPL, but the effect is wiped on the next
Run (in contrast to using
enter!). - A simple way to run unit tests (to run the
testsubmodule).
-
More thorough syntax highlighting ("font-lock"):
- All Racket keywords, built-ins, self-evals, and so on.
- All variations of
definefor functions and variables.
-
Correct indentation of Racket forms, including
for/foldandfor*/fold. -
Compatible with Emacs 24.2+. (With earlier versions of Emacs, font-lock will incorrectly highlight portions of things, e.g. the "min" in "aluminum" will be highlighted as the Racket keyword
min.)
-
If you've used other Lisps and Schemes before, you may prefer Geiser, which is very sophisticated.
NOTE: I have an experimental
minor-modebranch that implements a Minor mode to add some features alongside Geiser, as opposed to a stand-alone Major mode. But I'm not using it day-to-day. My gripe is not so much with Geiser -- which is wonderful -- but with the Racketenter!evaluation model that Geiser uses. -
Although I dogfood this -- use it constantly to code Racket -- it is alpha, or at best beta, quality. My total experience writing Emacs modes consists of writing this mode.
-
Someone else proposed adding this to MELPA. Although I didn't object, and I've accepted pull requests to facilitate that, I wasn't seeking to promote it that way.
-
Pull requests from smarter/wiser people are welcome.
-
Please report issues here.
You can install the racket-mode package from MELPA.
Tip: To use MELPA in Emacs 24, add the following to your
.emacsor.emacs.d/init.el:(require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
When a racket-mode window is active, type M-x customize-mode (or choose Customize from the Racket menu).
Set Racket Program to be the pathname of the racket executable.
That is the only required configuration.
If you wish, you can customize the other settings here. For example, in addition to the usual font-lock faces, racket-mode defines a few special ones:
-
racket-keyword-argument-face: Used for Racket#:keywordarguments. -
racket-selfeval-face: Used for numbers, symbols, strings. -
racket-paren-face: Used for( ) [ ] { }. (I like to set these "dim", e.g. light gray, so the parens are less prominent.)
To customize things like key bindings, you can use racket-mode-hook
in your .emacs or .emacs.d/init.el. For example, although
F5 is bound to the racket-run command, let's say you
wanted C-c r to be an additional binding:
(add-hook 'racket-mode-hook
'(lambda ()
(define-key racket-mode-map (kbd "C-c r") 'racket-run)))See the Racket menu. Most of the commands should be
self-explanatory. (If not, report it and I'll improve the
documentation.)
A few notes:
-
Assume you have
foo.rktas your current buffer. racket-run F5 evaluatesfoo.rkt. After which, you can use the*Racket REPL*buffer to inspect or experiment with the result. However when you use F5 again,foo.rktis evaluated from scratch -- the custodian releases resources like threads and the evaluation environment is reset to the contents offoo.rkt. In other words, like DrRacket, this provides the predictability of a "static" baseline, plus some interactive exploration. -
racket-test C-F5 runs the
testsubmodule (consisting of one or more(module+ test ...)forms in the current buffer). -
Output in the
*Racket REPL*buffer that describes a file and position is automatically "linkified". To visit the file at the position, click or use a Compilation mode command such as C-x ` (next error). Examples of such text include:- Racket error messages.
rackunittest failure location messages.prints of#<path>objects.- output from the racket-find-definition command (see below).
-
racket-find-definition C-c C-d tries to find the definition of the symbol at point (or with a prefix, C-u C-c C-d, as prompted). If found, it displays the file/location and function signature in the
*Racket REPL*buffer. You can then use a Compilation mode command such as C-x ` to visit the definition.NOTE: Racket doesn't provide anything like MIT Scheme's
pporpacommands. This is something we hack ourselves -- see defn.rkt -- and it's not perfect.This only finds symbols are defined in...
-
The current namespace. (Use F5 to Run the current buffer, first.)
-
Modules other than Racket
#%kernel.
-
-
racket-help C-c C-h uses
racket/helpfor the symbol at point (or with a prefix, C-u C-c C-h as prompted). -
racket-cycle-paren-shapes C-c C-p cycles the shape of the current s-expression among
(),[], and{}. -
racket-fold-all-tests C-c C-f uses hide/show mode to hide all
testsubmodules. racket-unfold-all-tests C-c C-u shows them all agian. This is handy if you like to interleave function definitions and(module+ test ...)tests, but sometimes want to "hide the clutter". In addition, see the Hide/Show menu for more-selective operations. -
In the
*Racket REPL*bufer you can issue some special commands. Some of them are the foundation for Emacs commands. Others are available only as a command in the REPL.-
,top: Leave the curent file/module and go to the top level. -
,run <file>: Run the file. What racket-run F5 uses. Either"file.rkt"orfile.rktworks. -
,def <symbol>: Find definition of<symbol>. What racket-find-definition C-c C-d uses. -
,doc <symbol-or-string>: Look for<symbol-or-string>in Racket's documentation. What racket-help C-c C-h uses. -
,cd,,pwd: Change and showcurrent-directory. -
,logcontrols the log output level, overall, as well as for specific named loggers created withdefine-logger.-
,log: Show the current levels. -
,log <logger> <level>: Set a logger to show at least levelnone,fatal,error,warning,info, ordebug. -
,log <logger> <level>: Set a logger to use the default level. -
,log <level>: Set the default level for all other loggers not specified indvidually.
-
-
I started this project accidentally, while trying to figure out a font-lock issue with Quack under Emacs 24.2.
Knowing nothing about how to make a mode in Emacs, I tried to isolate the problem by making a simple major mode, then adding things until it broke. It didn't break and I ended up with this.
I took various .emacs.d hacks that I'd previously made to use with
Quack, and rolled them into this mode.
Also, I'd recently spent time adding Racket fontification to the Pygments project, and wanted richer font-lock.
Also, I had experienced issues with enter! not always reloading
modules in recent versions of Racket, and came up with a DrRacket-like
alternative, run!.
Finally, I remembered that when I was new to Racket and Emacs, I got confused by the Scheme menu. It has options that work with various Schemes over the years, but which are N/A for Racket. I would stare it and wonder, "Um, how do I just 'run my program'??". I figured a fresh focus on Racket might be helpful, especially for other folks transitioning from using DrRacket.
Update, Jan 2014: After I had used this for a long time, putting up with its quriks, someone put it on MELPA. That nudged me to take another look, learn more about Elisp and Emacs modes, and improve it. Although I still feel like an amateur, it has probably improved from alpha to beta quality.
-
The existing Emacs Scheme mode and Inferior Scheme mode.
-
The source code for Neil Van Dyke's Quack provided a model for many of the
scheme-indent-functionsettings and smart paren closing.