unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Marcin Borkowski <mbork@wmi.amu.edu.pl>
To: help-gnu-emacs@gnu.org
Subject: Re: How to write the "interactive" form for a command acting on a region
Date: Wed, 14 Jan 2015 00:06:27 +0100	[thread overview]
Message-ID: <874mru5li0.fsf@wmi.amu.edu.pl> (raw)
In-Reply-To: <87twzuwbk7.fsf@kuiper.lan.informatimago.com>


On 2015-01-13, at 23:38, Pascal J. Bourguignon <pjb@informatimago.com> wrote:

> Marcin Borkowski <mbork@wmi.amu.edu.pl> writes:
>
>> Hi all,
>>
>> so I want to have a function which should do something on the region.
>> If no region is active, I want it to act on the whole buffer.  If called
>> from Lisp code, I want to be able to supply "begin" and/or "end"
>> parameters, which (if nil) should default to (point-min) and
>> (point-max).  Finally, I want my command to behave differently depending
>> on whether it was called interactively or programmatically.  
>
> If you want a different behavior, then you should have different
> functions:

Why?  In many Emacs functions/commands it works like what I want to
have.  What's wrong with this approach?  And in fact, I /don't/ want
different behavior: I want both the function and the command to
(essentially) do the same, with the (minor) difference that the function
will return a value and the command will print a message.

>     (defun my-FUNCTION (…)
>        …)
>
>     (defun my-COMMAND (…)
>        (interactive …)
>        …
>        (my-function …)
>        …)
>
> (defun my-command (start end)
>    (interactive "r")
>    (message "start=%s end=%s" start end))
>
> A region is always defined, whether transient-mark-mode is on or off,
> and whether the region is active or not.

Yes, of course.  (Incidentally, I didn't notice your snippet above at
first, and just to make sure, I wrote an identical one, differing only
in the names of the parameters and the text of the message;-).)

> Therefore interactive "r" will always give you start and end points.
> You could have a command such as:
>
>     (defun my-command (start end)
>        (interactive "r")
>        (if (use-region-p) ; region is active
>           (my-function start end)
>           (my-function (point-min) (point-max))))

This does not seem very lispy to me, though most probably have much less
experience than you...

> Otherwise, if the behavior of your command and your function was the
> same, you could write a single command, using (require 'cl) to deal with
> the default values.  

I'll have to check cl (I use it anyway for (incf)), but again: what's
wrong with (or start (point-min))?

> But since you want to force the arguments when it's called interactively
> without an active region, you will have to duplicate some code.

This I don't understand.  (Though I /do/ have some duplication, see
below.)

> Separating the function and command is probablyh preferable in your
> situation.
>
>     (require 'cl)
>     (defun* my-command (&optional (start (point-min)) (end (point-max)))
>        (interactive "r")
>        (when (and (called-interactively-p)
>                   (not (use-region-p)))
>           (setf start (point-min)
>                 end   (point-max)))
>        …)

No offence, but this seems plain ugly for me, especially the setf part.

IMHO, using the (interactive) form to define default arguments is more
elegant, though of course I also have some duplicate code (point-min and
point-max appear twice - though for different reasons, so to speak -
which I don't like).  I can't see why your proposal is better - I would
prefer to use defun and not defun*, and the Emacs manual says it's
better to use the interactive form and not called-interactively-p (and
I can see the reason).

Regards,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University



  reply	other threads:[~2015-01-13 23:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.17860.1421186716.1147.help-gnu-emacs@gnu.org>
2015-01-13 22:38 ` How to write the "interactive" form for a command acting on a region Pascal J. Bourguignon
2015-01-13 23:06   ` Marcin Borkowski [this message]
     [not found]   ` <mailman.17861.1421190402.1147.help-gnu-emacs@gnu.org>
2015-01-14  2:04     ` Pascal J. Bourguignon
2015-01-14  3:49       ` Drew Adams
2015-01-13 22:05 Marcin Borkowski
2015-01-13 23:24 ` Nicolas Richard
2015-01-13 23:35   ` Marcin Borkowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=874mru5li0.fsf@wmi.amu.edu.pl \
    --to=mbork@wmi.amu.edu.pl \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).