From ab8f059cc19d0a7d9f52a4374636f704a9887f1d Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sat, 6 Nov 2010 14:22:53 +0100 Subject: Manual nits --- doc/parens.texi | 488 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 488 insertions(+) create mode 100644 doc/parens.texi (limited to 'doc/parens.texi') diff --git a/doc/parens.texi b/doc/parens.texi new file mode 100644 index 0000000..7ae5420 --- /dev/null +++ b/doc/parens.texi @@ -0,0 +1,488 @@ +@node Between the parens, Cheat sheet, The REPL, Top +@chapter Between the parens + +A good REPL is a must, but just about half the story of a good Scheme +hacking environment. Well, perhaps a bit more than a half; but, at any +rate, one surely needs also a pleasant way of editing source code. Don't +pay attention to naysayers: Emacs comes with an excellent editor +included for about any language on Earth, and just the best one when +that language is sexpy (specially if you use @ref{paredit,,Paredit}). +Geiser's support for writing Scheme code adds to Emacs' +@code{scheme-mode}, rather than supplanting it; and it does so by means +of a minor mode (unimaginatively dubbed @code{geiser-mode}) that defines +a bunch of new commands to try and, with the help of the same Scheme +process giving you the REPL, make those Scheme buffers come to life. + +@menu +* Activating Geiser:: +* The source and the REPL:: +* Documentation helpers:: +* To eval or not to eval:: +* To err perchance to debug:: +* Jumping around:: +* Geiser writes for you:: +@end menu + +@node Activating Geiser, The source and the REPL, Between the parens, Between the parens +@section Activating Geiser + +@cindex geiser-mode +@img{geiser-mode, right} With Geiser installed following any of the +procedures described in @ref{Setting it up}, Emacs will automatically +activate @i{geiser-mode} when opening a Scheme buffer. Geiser also +instructs Emacs to consider files with the extension @file{rkt} part of +the family, so that, in principle, there's nothing you need to do to +ensure that Geiser's extensions will be available, out of the box, when +you start editing Scheme code. + +Indications that everything is working according to plan include the +'Geiser' minor mode indicator in your mode-line and the appearance of a +new entry for Geiser in the menu bar. If, moreover, the mode-line +indicator is the name of a Scheme implementation, you're indeed in a +perfect world; otherwise, don't despair and keep on reading: i'll tell +you how to fix that in a moment. + +@cindex geiser-mode commands +The menu provides a good synopsis of everthing Geiser brings to the +party, including those keyboard shortcuts we Emacsers love. If you're +seeing the name of your favourite Scheme implementation in the +mode-line, have a running REPL and are comfortable with Emacs, you +can stop reading now and, instead, discover Geiser's joys by yourself. +I've tried to make Geiser as self-documenting as any self-respecting +Emacs package should be. If you follow this route, make sure to take a +look at Geiser's customization buffers (@kbd{M-x customize-group +@key{RET} geiser}): there's lot of fine tunning available there. You +might also want to take a glance at the @ref{Cheat sheet}. + +Since @i{geiser-mode} is a minor mode, you can toggle it with +@kbd{M-x geiser-mode}, and control its activation in hooks with the +functions @code{turn-on-geiser-mode} and @code{turn-off-geiser-mode}. +If, for some reason i cannot fathom, you prefer @i{geiser-mode} not +to be active by default, the following elisp incantation will do the +trick: +@example +(eval-after-load "geiser-mode" + (remove-hook 'scheme-mode-hook 'turn-on-geiser-mode)) +@end example +@cindex scheme file extensions +And if you happen to use a funky extension for your Scheme files that is +not recognised as such by Emacs, just tell her about it with: +@example +(add-to-list 'auto-mode-alist '("\\.funky-extension\\'" . scheme-mode)) +@end example + +@cindex useless wretch +Now, @i{geiser-mode} is just a useless wretch unless there's a running +Scheme process backing it up. Meaning that virtually all the commands it +provides require a REPL up and running, preferably corresponding to +the correct Scheme implementation. In the following section, we'll see +how to make sure that that's actually the case. + +@node The source and the REPL, Documentation helpers, Activating Geiser, Between the parens +@section The source and the REPL + +As i've already mentioned a couple of times, @i{geiser-mode} needs a +running REPL to be operative. Thus, a common usage pattern will be +for you to first call @code{run-geiser} (or one of its variants, see +them described @ref{choosing-impl,,here}), and then open Scheme files; +but there's nothing wrong in first opening a couple Scheme buffers and +then starting the REPL (you can even find it more convenient, since +pressing @kbd{C-c C-z} in a Scheme buffer will start the REPL for +you). Since Geiser supports more than one Scheme implementation, though, +there's the problem of knowing which of them is to be associated with +each Scheme source file. Serviceable as it is, @i{geiser-mode} will try +to guess the correct implementation for you, according to the algorithm +described below. If you find that Geiser is already guessing right the +Scheme implementation, feel free to skip to the +@ref{switching-repl-buff,,next subsection}. + +@subsubheading How Geiser associates a REPL to your Scheme buffer +@cindex scheme implementation, choosing +To determine what Scheme implementation corresponds to a given source +file, Geiser uses the following algorithm: +@enumerate +@item +If the file-local variable @code{geiser-scheme-implementation} is +defined, its value is used. A common way of setting buffer-local +variables is to put them in a comment near the beginning of the file, +surrounded by @code{-*-} marks, as in: +@example +;; -*- geiser-scheme-implementation: guile -*- +@end example +@item +If you've customized @code{geiser-active-implementations} so that it's a +single-element list (as explained @ref{choosing-impl,,here}), that +element is used as the chosen implementation. +@item +The contents of the file is scanned for hints on its associated +implementation. For instance, files that contain a @code{#lang} +directive will be considered Racket source code, while those with a +@code{define-module} form in them will be assigned to a Guile REPL. +@item +The current buffer's file name is checked against the rules given in +@code{geiser-implementations-alist}, and the first match is applied. You +can provide your own rules by customizing this variable, as explained +below. +@item +If we haven't been lucky this far and you have customized +@code{geiser-default-implementation} to the name of a supported +implementation, we'll follow your lead. +@item +See? That's the problem of being a smart alec: one's always outsmarted +by people around. At this point, @i{geiser-mode} will humbly give up and +ask you to explicitly choose the Scheme implementation. +@end enumerate +As you can see in the list above, there are several ways to influence +Geiser's guessing by mean customizable variables. The most direct (and +most impoverishing) is probably limiting the active implementations to a +single one, while customizing @code{geiser-implementations-alist} is the +most flexible (and, unsurprisingly, also the most complex). Here's the +default value for the latter variable: +@example +(((regexp "\\.scm$") guile) + ((regexp "\\.ss$") racket) + ((regexp "\\.rkt$") racket)) +@end example +which describes the simple heuristic that files with @file{.scm} as +extension are by default associated to a Guile REPL while those +ending in @file{.ss} or @file{.rkt} correspond to Racket's +implementation (with the caveat that these rules are applied only if the +previous heuristics have failed to detect the correct implementation, +and that they'll match only if the corresponding implementation is +active). You can add rules to @code{geiser-implementations-alist} (or +replace all of them) by customizing it. Besides regular expressions, you +can also use a directory name; for instance, the following snippet: +@example +(eval-after-load "geiser-impl" + '(add-to-list 'geiser-implementations-alist + '((dir "/home/jao/prj/frob") guile))) +@end example +will add a new rule that says that any file inside my +@file{/home/jao/prj/frob} directory (or, recursively, any of its +children) is to be assigned to Guile. Since rules are first matched, +first served, this new rule will take precedence over the default ones. + +@subsubheading Switching between source files and the REPL +@cindex switching to REPL +@cindex switching to source +@anchor{switching-repl-buff} Once you have a working @i{geiser-mode}, +you can switch from Scheme source buffers to the REPL or @kbd{C-c +C-z}. Those shortcuts map to the interactive command +@code{switch-to-geiser}. + +@cindex switching to module +If you use a numeric prefix, as in @kbd{C-u C-c C-z}, besides being +teleported to the REPL, the latter will switch to the namespace of +the Scheme source file (as if you had used @kbd{C-c C-m} in the REPL, +with the source file's module as argument; cf. @ref{Switching context}). +This command is also bound to @kbd{C-c C-Z}, with a capital zed. + +Once you're in the REPL, the same @kbd{C-c C-z} shortcut will bring +you back to the buffer you jumped from, provided you don't kill the +Scheme process in between. This is why the command is called +@i{switch-to-geiser} instead of @i{switch-to-repl}, and what makes it +really handy, if you ask me. + +@cindex switching schemes +If for some reason you're not happy with the Scheme implementation that +Geiser has assigned to your file, you can change it with @kbd{C-c C-s}, +and probably take a look at @ref{switching-repl-buff,,the previous +subsection} to make sure that Geiser doesn't get confused again. + +@subsubheading A note about context +As explained before (@pxref{Modus operandi}), all Geiser activities take +place in the context of the @i{current namespace}, which, for Scheme +buffers, corresponds to the module that the Scheme implementation +associates to the source file at hand (for instance, in Racket, there's +a one to one correspondence between paths and modules, while Guile +relies on explicit @code{define-module} forms in the source file). + +Now that we have @code{geiser-mode} happily alive in our Scheme buffers +and communicating with the right REPL instance, let us see what it +can do for us, besides jumping to and fro. + +@node Documentation helpers, To eval or not to eval, The source and the REPL, Between the parens +@section Documentation helpers + +@subsubheading Autodoc redux + +@cindex autodoc, in scheme buffers +The first thing you will notice by moving around Scheme source is that, +every now and then, the echo area lightens up with the same autodoc +messages we know and love from our REPL forays. This happens every +time the Scheme process is able to recognise an identifier in the +buffer, and provide information either on its value (for variables) or +on its arity and the name of its formal arguments (for procedures and +macros). That information will only be available if the module the +identifier belongs to has been loaded in the running Scheme image. So it +can be the case that, at first, no autodoc is shown for identifiers +defined in the file you're editing. But as soon as you evaluate them +(either individually or collectively using any of the devices described +in @ref{To eval or not to eval}) their signatures will start appearing +in the echo area. + +@cindex disabling autodoc +Autodoc activation is controlled by a minor mode, @code{geiser-autodoc}, +which you can toggle with @kbd{M-x geiser-autodoc}, or its associated +keyboard shortcut, @kbd{C-c C-d a}. That @t{/A} indicator in the +mode-line is telling you that autodoc is active. If you prefer, for some +obscure reason, that it be inactive by default, just set +@code{geiser-mode-autodoc-p} to @code{nil} in your customization files. + +@cindex autodoc explained +@img{autodoc-req, right} The way autodoc displays information deserves +some explanation. It will first show the name of the module where the +identifier at hand is defined, followed by a colon and the identifier +itself. If the latter corresponds to a procedure or macro, it will be +followed by a list of argument names, starting with the ones that are +required. Then there comes a square-bracketed list of optional argument +names, if any. When an optional argument has a default value (or a form +defining its default value), instead of a plain name, autodoc will +display a list with the name followed by its initialisation form. When +the optional arguments are keywords, their names are prefixed with a +colon. An ellipsis (@dots{}) servers as a marker of an indeterminated +number of parameters, as is the case with @i{rest} arguments or when +autodoc cannot fathom the exact number of arguments (this is often the +case with macros defined using @code{syntax-case}). Another way in which +autodoc displays its ignorance is by using and underscore to display +parameters whose name is beyond its powers. + +@img{autodoc-multi, right} It can also be the case that a function or +macro has more than one signature (e.g., functions defined using +@code{case-lambda}, or some @code{syntax-rules} macros, for which Geiser +has often the black magic necessary to retrieve their actual arities). +In those cases, autodoc shows all known signatures (using the above +rules for each one) separated by a vertical bar (|). As you have already +noticed, the whole thing is enclosed in parenthesis. After all, we're +talking about Scheme here. + +@cindex autodoc for variables +@img{autodoc-var, right} Finally, life is much easier when your cursor +is on a symbol corresponding to a plain variable: you'll see in the echo +area its name, preceded by the module where it's defined, and followed +by its value, with an intervening arrow for greater effect. This time, +there are no enclosing parenthesis (i hope you see the logic in my +madness). + +@cindex autodoc customized +You can change the way Geiser displays the module/identifier combo by +customizing @code{geiser-autodoc-identifier-format}. For example, if you +wanted a tilde surrounded by spaces instead of a colon as a separator, +you would write something like +@example +(setq geiser-autodoc-identifier-format "%s ~ %s") +@end example +in your Emacs initialization files. There's also a face +(@code{geiser-font-lock-autodoc-identifier}) that you can customize (for +instance, with @kbd{M-x customize-face}) to change the appearance of the +text. And another one (@code{geiser-font-lock-autodoc-current-arg}) that +controls how the current argument position is highlighted. + +@subsubheading Other documentation commands + +Sometimes, autodoc won't provide enough information for you to +understand what a function does. In those cases, you can ask Geiser to +ask the running Scheme for further information on a given identifier or +module. + +@cindex documentation for symbol +@cindex docstrings, maybe +For symbols, the incantation is @kbd{M-x geiser-doc-symbol-at-point}, or +@kbd{C-c C-d C-d} for short. If the associated scheme supports +docstrings (as, for instance, Guile does), you'll be teleported to a new +Emacs buffer displaying Geiser's documentation browser, filled with +information about the identifier, including its docstring (if any; +unfortunately, that an implementation supports docstrings doesn't mean +that they're used everywhere). + +@imgc{docstring} + +Pressing @kbd{q} in the documentation buffer will bring you back, +enlightened, to where you were. There's also a handful of other +navigation commands available in that buffer, which you can discover by +means of its menu or via the good old @kbd{C-h m} command. + +For Racket, which does not support docstrings out of the box, this +command will invoke Racket's @code{help} procedure, thereby opening your +configured web browser with the corresponding manual page for you to +peruse. + +You can also ask Geiser to display information about a module, in the +form of a list of its exported identifiers, using @kbd{C-c C-d C-m}, +exactly as you would do @ref{repl-mod,,in the REPL}. This commands works +with all supported Schemes, no strings attached. + +@node To eval or not to eval, To err perchance to debug, Documentation helpers, Between the parens +@section To eval or not to eval + +@cindex philosophy +@cindex incremental development +One of Geiser's main goals is to facilitate incremental development. You +might have noticed that i've made a big fuss of Geiser's ability to +recognize context, by being aware of the namespace where its operations +happen. + +That awareness is specially important when evaluating code in your +scheme buffers, using the commands described below. They allow you to +send code to the running Scheme with a granularity ranging from whole +files to single s-expressions. That code will be evaluated in the module +associated with the file you're editing, allowing you to redefine values +and procedures to your heart's (and other modules') content. + +@cindex incremental development, evil +Macros are, of course, another kettle of fish: one needs to re-evaluate +uses of a macro after redefining it. That's not a limitation imposed by +Geiser, but a consequence of how macros work in Scheme (and other +Lisps). There's also the risk that you lose track of what's actually +defined and what's not during a given session. But, +@uref{http://programming-musings.org/2009/03/29/from-my-cold-prying-hands/,in +my opinion}, those are limitations we lispers are aware of, and they +don't force us to throw the baby with the bathwater and ditch +incremental evaluation. Some people disagree; if you happen to find +@uref{http://blog.racket-lang.org/2009/03/drscheme-repl-isnt-lisp.html, +their arguments} convincing, you don't have to throw away Geiser +together with the baby: @kbd{M-x geiser-restart-repl} will let you +restart the REPL as many times as you see fit. + +@cindex evaluation +@cindex incremental development, not evil +For all of you bearded old lispers still with me, here are some of the +commands performing incremental evaluation in Geiser. + +@code{geiser-eval-last-sexp}, bound to @kbd{C-x C-e}, will eval the +s-expression just before point. + +@code{geiser-eval-definition}, bound to @kbd{C-M-x}, finds the topmost +definition containing point and sends it for evaluation. The variant +@code{geiser-eval-definition-and-go} (@kbd{C-c M-e}) works in the same +way, but it also teleports you to REPL after the evaluation. + +@code{geiser-eval-region}, bound to @kbd{C-c C-r}, evals the current +region. Again, there's an @i{and go} version available, +@code{geiser-eval-region-and-go}, bound to @kbd{C-c M-r}. + +For all the commands above, the result of the evaluation is displayed in +the minibuffer, unless it causes a (scheme-side) error (@pxref{To err +perchance to debug}). + +At the risk of repeating myself, i'll remember you that all these +evaluations will take place in the namespace of the module corresponding +to the Scheme file from which you're sending your code, which, in +general, will be different from the REPL's current module. And, if +all goes according to plan, (re)defined variables and procedures should +be immediately visible inside and, if exported, outside their module. + +Besides evaluating expressions, definitions and regions, you can also +macro-expand them. The corresponding keybindings start with the prefix +@kbd{C-c C-m} and end, respectively, with @kbd{C-e}, @kbd{C-x} and +@kbd{C-r}. The result of the macro expansion always appears in a pop up +buffer. + +@node To err perchance to debug, Jumping around, To eval or not to eval, Between the parens +@section To err: perchance to debug + +@cindex to err is schemey +@cindex backtraces +When an error occurs during evaluation, it will be reported according to +the capabilities of the underlying Scheme REPL. + +@cindex error buffer +In Racket, you'll be presented with a backtrace, in a new buffer where +file paths locating the origin of the error are clickable (you can +navigate them using the @key{TAB} key, and use @key{RET} or the mouse to +jump to the offending spot; or invoke Emacs' stock commands +@code{next-error} and @code{previous-error}, bound to @kbd{M-g n} and +@kbd{M-g p} by default). + +@imgc{eval-error} + +The Racket backtrace also highlights the exception type, making it +clickable. Following the link will open the documentation corresponding +to said exception type. Both the error and exception link faces are +customizable (@code{geiser-font-lock-error-link} and +@code{geiser-font-lock-doc-link}). + +On the other hand, Guile's reaction to evaluation errors is different: +it enters the debugger in its REPL. Accordingly, the REPL buffer will +pop up if your evaluation fails in a Guile file, and the error message +and backtrace will be displayed in there, again clickable and all. But +there you have the debugger at your disposal, with the REPL's current +module set to that of the offender, and a host of special debugging +commands that are described in Guile's fine documentation. + +@imgc{guile-eval-error} + +In addition, Guile will sometimes report warnings for otherwise +successful evaluations. In those cases, it won't enter the debugger, and +Geiser will report the warnings in a debug buffer, as it does for +Racket. You can control how picky Guile is reporting warnings by +customizing the variable @code{geiser-guile-warning-level}, whose +detailed docstring (which see, using, e.g. @kbd{C-h v}) allows me to +offer no further explanation here. The customization group +@i{geiser-guile} is also worth a glance, for a couple of options to fine +tune how Geiser interacts with Guile's debugger (and more). Same thing +for racketeers and @i{geiser-racket}. + +@node Jumping around, Geiser writes for you, To err perchance to debug, Between the parens +@section Jumping around + +@cindex jumping in scheme buffers +This one feature is as sweet as easy to explain: @kbd{M-.} +(@code{geiser-edit-symbol-at-point}) will open the file where the +identifier around point is defined and land your point on its +definition. To return to where you were, press @kbd{M-,} +(@code{geiser-pop-symbol-stack}). This command works also for module +names: Geiser first tries to locate a definition for the identifier at +point and, if that fails, a module with that name; if the latter +succeeds, the file where the module is defined will pop up. + +Sometimes, the underlying Scheme will tell Geiser only the file where +the symbol is defined, but Geiser will use some heuristics (read, +regular expressions) to locate the exact line and bring you there. Thus, +if you find Geiser systematically missing your definitions, send a +message to the mailing list and we'll try to make the algorithm smarter. + +@cindex jumping customized +You can control how the destination buffer pops up by setting +@code{geiser-edit-symbol-method} to either @code{nil} (to open the file +in the current window), @code{'window} (other window in the same frame) +or @code{'frame} (in a new frame). + +@node Geiser writes for you, , Jumping around, Between the parens +@section Geiser writes for you + +@cindex completion in scheme buffers +No self-respecting programming mode would be complete without +completion. In geiser-mode, identifier completion is bound to +@kbd{M-@key{TAB}}, and will offer all visible identifiers starting with +the prefix before point. Visible here means all symbols imported or +defined in the current namespace plus locally bound ones. E.g., if +you're at the end of the following partial expression: + +@example +(let ((default 42)) + (frob def +@end example + +and press @kbd{M-@key{TAB}}, one of the possible completions will be +@code{default}. + +@cindex smart tabs +If you find the @kbd{M} modifier annoying, you always have the option to +activate @code{geiser-smart-tab-mode}, which will make the @key{TAB} key +double duty as the regular Emacs indentation command (when the cursor is +not near a symbol) and Geiser's completion function. If you want this +smarty pants mode always on in Scheme buffers, customize +@code{geiser-mode-smart-tab-p} to @code{t}. + +@cindex completion for module names +Geiser also knows how to complete module names: if no completion for the +prefix at point is found among the currently visible bindings, it will +try to find a module name that matches it. You can also request +explicitly completion only over module names using @kbd{M-`} (that's a +backtick). + +@c Local Variables: +@c mode: texinfo +@c TeX-master: "geiser" +@c End: -- cgit v1.2.3 From f1684f872705bdbb8566f83529cb7707f89cc10b Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sat, 6 Nov 2010 22:56:48 +0100 Subject: Doc fix --- doc/parens.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc/parens.texi') diff --git a/doc/parens.texi b/doc/parens.texi index 7ae5420..9ce0d05 100644 --- a/doc/parens.texi +++ b/doc/parens.texi @@ -61,7 +61,7 @@ If, for some reason i cannot fathom, you prefer @i{geiser-mode} not to be active by default, the following elisp incantation will do the trick: @example -(eval-after-load "geiser-mode" +(eval-after-load "geiser" (remove-hook 'scheme-mode-hook 'turn-on-geiser-mode)) @end example @cindex scheme file extensions -- cgit v1.2.3 From 06ade45ac52d5597dc04655f4668b02f9b3ebdf2 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Mon, 8 Nov 2010 05:44:18 +0100 Subject: geiser-squarify to toggle between () and [] --- README | 1 + doc/cheat.texi | 3 +++ doc/parens.texi | 4 ++++ elisp/geiser-mode.el | 19 +++++++++++++++++++ 4 files changed, 27 insertions(+) (limited to 'doc/parens.texi') diff --git a/README b/README index 8134f97..b10af2a 100644 --- a/README +++ b/README @@ -111,6 +111,7 @@ | M-. | Go to definition of identifier at point | | M-, | Go back to where M-. was last invoked | | C-c C-e m | Ask for a module and open its file | + | C-c C-e [ | Toggle between () and [] for current form | |---------------------+-------------------------------------------------| | C-M-x | Eval definition around point | | C-c M-e | Eval definition around point and switch to REPL | diff --git a/doc/cheat.texi b/doc/cheat.texi index adcc4d8..4e81b92 100644 --- a/doc/cheat.texi +++ b/doc/cheat.texi @@ -31,6 +31,9 @@ @item C-c C-e C-m @tab geiser-edit-module @tab Ask for a module and open its file +@item C-c C-e C-[ +@tab geiser-squarify +@tab Toggle between () and [] for current form @item @tab @tab @item C-M-x @tab geiser-eval-definition diff --git a/doc/parens.texi b/doc/parens.texi index 9ce0d05..9839892 100644 --- a/doc/parens.texi +++ b/doc/parens.texi @@ -482,6 +482,10 @@ try to find a module name that matches it. You can also request explicitly completion only over module names using @kbd{M-`} (that's a backtick). +There's also this little command, @code{geiser-squarify}, which will +toggle the delimiters of the innermost list around point between round +and square brackets. It is bound to @key{C-c C-e [}. + @c Local Variables: @c mode: texinfo @c TeX-master: "geiser" diff --git a/elisp/geiser-mode.el b/elisp/geiser-mode.el index e9e5563..3575474 100644 --- a/elisp/geiser-mode.el +++ b/elisp/geiser-mode.el @@ -176,6 +176,24 @@ With prefix, try to enter the current's buffer module." (goto-char (point-max)) (pop-to-buffer b))) +(defun geiser-squarify () + "Toggle between () and [] for current form." + (interactive) + (let ((pared (and (boundp 'paredit-mode) paredit-mode))) + (when pared (paredit-mode -1)) + (unwind-protect + (save-excursion + (unless (looking-at-p "\\s(") (backward-up-list)) + (let ((p (point)) + (round (looking-at-p "("))) + (forward-sexp) + (backward-delete-char 1) + (insert (if round "]" ")")) + (goto-char p) + (delete-char 1) + (insert (if round "[" "(")))) + (when pared (paredit-mode 1))))) + ;;; Geiser mode: @@ -258,6 +276,7 @@ interacting with the Geiser REPL is at your disposal. ("Complete module name" ((kbd "M-`") (kbd "C-.")) geiser-completion--complete-module) ("Edit module" ("\C-c\C-e\C-m" "\C-c\C-em") geiser-edit-module) + ("Toggle ()/[]" ("\C-c\C-e\C-[" "\C-c\C-e[") geiser-squarify) -- ("Callers" ((kbd "C-c <")) geiser-xref-callers :enable (and (geiser-eval--supported-p 'callers) (symbol-at-point))) -- cgit v1.2.3 From a3743f25313498e96563e3622422bc62d9b80178 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Mon, 8 Nov 2010 06:07:12 +0100 Subject: squarify again, now with numeric prefix --- doc/parens.texi | 4 +++- elisp/geiser-mode.el | 35 +++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'doc/parens.texi') diff --git a/doc/parens.texi b/doc/parens.texi index 9839892..101ece5 100644 --- a/doc/parens.texi +++ b/doc/parens.texi @@ -484,7 +484,9 @@ backtick). There's also this little command, @code{geiser-squarify}, which will toggle the delimiters of the innermost list around point between round -and square brackets. It is bound to @key{C-c C-e [}. +and square brackets. It is bound to @kbd{C-c C-e [}. With numeric a +prefix (as in, say @kbd{M-2 C-c C-e [}), it will perform that many +toggles, forward for positive values and backward for negative ones. @c Local Variables: @c mode: texinfo diff --git a/elisp/geiser-mode.el b/elisp/geiser-mode.el index 3575474..1645ba2 100644 --- a/elisp/geiser-mode.el +++ b/elisp/geiser-mode.el @@ -176,22 +176,33 @@ With prefix, try to enter the current's buffer module." (goto-char (point-max)) (pop-to-buffer b))) -(defun geiser-squarify () - "Toggle between () and [] for current form." - (interactive) - (let ((pared (and (boundp 'paredit-mode) paredit-mode))) +(defun geiser-squarify (n) + "Toggle between () and [] for current form. +With numeric prefix, perform that many toggles, forward for +positive values and backward for negative." + (interactive "p") + (let ((pared (and (boundp 'paredit-mode) paredit-mode)) + (fwd (> n 0)) + (steps (abs n))) (when pared (paredit-mode -1)) (unwind-protect (save-excursion (unless (looking-at-p "\\s(") (backward-up-list)) - (let ((p (point)) - (round (looking-at-p "("))) - (forward-sexp) - (backward-delete-char 1) - (insert (if round "]" ")")) - (goto-char p) - (delete-char 1) - (insert (if round "[" "(")))) + (while (> steps 0) + (let ((p (point)) + (round (looking-at-p "("))) + (forward-sexp) + (backward-delete-char 1) + (insert (if round "]" ")")) + (goto-char p) + (delete-char 1) + (insert (if round "[" "(")) + (setq steps (1- steps)) + (backward-char) + (condition-case nil + (progn (when fwd (forward-sexp 2)) + (backward-sexp)) + (error (setq steps 0)))))) (when pared (paredit-mode 1))))) -- cgit v1.2.3 From 9863645f5fad1974b24b5e6bab0941d3ed9d8cde Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Mon, 8 Nov 2010 06:11:15 +0100 Subject: Documentation typos --- doc/parens.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc/parens.texi') diff --git a/doc/parens.texi b/doc/parens.texi index 101ece5..78149e5 100644 --- a/doc/parens.texi +++ b/doc/parens.texi @@ -484,8 +484,8 @@ backtick). There's also this little command, @code{geiser-squarify}, which will toggle the delimiters of the innermost list around point between round -and square brackets. It is bound to @kbd{C-c C-e [}. With numeric a -prefix (as in, say @kbd{M-2 C-c C-e [}), it will perform that many +and square brackets. It is bound to @kbd{C-c C-e [}. With a numeric +prefix (as in, say, @kbd{M-2 C-c C-e [}), it will perform that many toggles, forward for positive values and backward for negative ones. @c Local Variables: -- cgit v1.2.3