unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Emacsy: Context Sensitive Commands Design Question
@ 2013-08-29 20:57 Shane Celis
  2013-08-30  0:26 ` Noah Lavine
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Shane Celis @ 2013-08-29 20:57 UTC (permalink / raw)
  To: Guile Mailing List; +Cc: Ludovic Courtès

Hello guilers,

I'm developing Emacsy[1], and I'm trying to design a good way of grouping and exposing interactive commands.  My interest is specifically related to Emacsy, but for guilers in general the question is, How should one provide exports of a different flavor?  We have only "public" exports.  In my case I want a "command" flavor of export.  But I might want to export "customizable" variables, or "minor-mode"s.  I'm not trying to tackle the general task here.

In Emacs all commands are in the same namespace.  Hit M-x TAB\x04, and you'll probably see thousands of them (I've got ~6k).  A lot of the commands may only be appropriate in certain modes, so I'm playing around with how best we can go about grouping and exposing commands.  My idea is that M-x only shows commands that are in the current COMMAND_PATH, somewhat like a bash PATH.  To show all commands, one can type C-u M-x.

A command in Emacsy is a procedure that requires no arguments.  It's written for the user to invoke on command M-x or from a key binding.  When called interactively, it'll ask the user for information.  When called with all arguments provided, it will run non-interactively.

Suppose I have the following code which creates a command called 'echo':

(define-module (my-great-mode)
  #:use-module (ice-9 optargs)
  #:use-module (emacsy)
  #:export (some-other-proc))

(define (some-other-proc)
  "I am not a command."
  #f)

(define* (echo #:optional (text (read-from-minibuffer "Echo what: ")))
  (message text))

(export-command echo)

This module exports the procedure "some-other-proc" and I want it to _somehow_ export a command called "echo".  The question is how to export this other thing, this command?  I have a couple of ideas, most based off grouping some subset of procedures as commands inside a module, and using modules to group the commands. 

1. Create a command-interface module similar to the public-interface that modules have. So instead of 'resolve-interface' and 'export', I'd have 'resolve-command-interface' and 'export-command'.  

A (resolve-command-interface '(my-great-mode)) would return a module (%module-command-interface) that contained bindings for all that module's commands.  This is the module that COMMAND_PATH would use for commands.

PRO: One could export commands and procedures entirely independently.  Also, one can use the module mechanisms of selecting a subset, algorithmic renaming, etc. on these command modules.
CON: It seems like a lot of magic, but it's using the same mechanisms that public interfaces use.

2. Have (export-command) just keep a list of commands, but just export a custom public interface.  So it might look like this internally:

(define (export-command-proc names)
  (set! %command-set (append! %command-set names)))

(define (resolve-command-interface module-name)
  (resolve-interface module-name #:select %command-set))

PRO: Less magic-y.  
CON: One must export a command to both the public interface and the command; maybe that's ok even preferable that they're not independent.

3. Have (export-command) create a new sub-module (my-great-mode %command).

PRO: Not too tricky.
CON: Pollutes the module namespace a little bit.

4. Still use modules, but make the user segregate their procedures and commands into separate modules manually. So the user would have to define modules (my-great-mode) and (my-great-mode commands).

PRO: No magic. Programmer does everything.
CON: Everything is managed by convention. Separating the commands and procedures might be an awkward boundary.  Consider an internal procedure in (my-great-mode) that a command wants to use in (my-great-mode commands).  Do you expose it as public?  Move it around? Use @@ to get to it?  

5. Don't use modules at all.  Make the user collect and manage <command-set>s the same way they manage keymaps, for instance.  

PRO: Nothing tricky, doesn't use modules at all.  No magic.
CON: It has to work with the command being redefined; we can't just keep the command procedure; we have to keep the variable which points to modules possibly being a better solution.

6. Tag commands as special procedures perhaps by adding something to their procedure properties.  Implement a "command?" procedure.  Export commands and procedures to the same module. Then just pluck the commands out of all the procedures by using command?.

PRO: No new modules. No new exports.
CON: Adding something to the procedure makes wrapping commands in other lambdas awkward.  Might necessitate a define-command, lambda-command, method-command, which I'd prefer to avoid.

* * *

Thanks for indulging my scheme design question.  What's the right thing to do?  What would you do? 

-Shane

[1]: https://github.com/shanecelis/emacsy


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Emacsy: Context Sensitive Commands Design Question
  2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
@ 2013-08-30  0:26 ` Noah Lavine
  2013-08-30  2:02 ` Mark H Weaver
  2013-08-30  7:32 ` Thien-Thi Nguyen
  2 siblings, 0 replies; 5+ messages in thread
From: Noah Lavine @ 2013-08-30  0:26 UTC (permalink / raw)
  To: Shane Celis; +Cc: Guile Mailing List, Ludovic Courtès

[-- Attachment #1: Type: text/plain, Size: 5203 bytes --]

Hello,

This is a really interesting question.

2 seems like the best combination of elegant and simple to me, but really
it's your preference. I wonder what other Guilers think.

Best,
Noah



On Thu, Aug 29, 2013 at 4:57 PM, Shane Celis <shane.celis@gmail.com> wrote:

> Hello guilers,
>
> I'm developing Emacsy[1], and I'm trying to design a good way of grouping
> and exposing interactive commands.  My interest is specifically related to
> Emacsy, but for guilers in general the question is, How should one provide
> exports of a different flavor?  We have only "public" exports.  In my case
> I want a "command" flavor of export.  But I might want to export
> "customizable" variables, or "minor-mode"s.  I'm not trying to tackle the
> general task here.
>
> In Emacs all commands are in the same namespace.  Hit M-x TAB , and you'll
> probably see thousands of them (I've got ~6k).  A lot of the commands may
> only be appropriate in certain modes, so I'm playing around with how best
> we can go about grouping and exposing commands.  My idea is that M-x only
> shows commands that are in the current COMMAND_PATH, somewhat like a bash
> PATH.  To show all commands, one can type C-u M-x.
>
> A command in Emacsy is a procedure that requires no arguments.  It's
> written for the user to invoke on command M-x or from a key binding.  When
> called interactively, it'll ask the user for information.  When called with
> all arguments provided, it will run non-interactively.
>
> Suppose I have the following code which creates a command called 'echo':
>
> (define-module (my-great-mode)
>   #:use-module (ice-9 optargs)
>   #:use-module (emacsy)
>   #:export (some-other-proc))
>
> (define (some-other-proc)
>   "I am not a command."
>   #f)
>
> (define* (echo #:optional (text (read-from-minibuffer "Echo what: ")))
>   (message text))
>
> (export-command echo)
>
> This module exports the procedure "some-other-proc" and I want it to
> _somehow_ export a command called "echo".  The question is how to export
> this other thing, this command?  I have a couple of ideas, most based off
> grouping some subset of procedures as commands inside a module, and using
> modules to group the commands.
>
> 1. Create a command-interface module similar to the public-interface that
> modules have. So instead of 'resolve-interface' and 'export', I'd have
> 'resolve-command-interface' and 'export-command'.
>
> A (resolve-command-interface '(my-great-mode)) would return a module
> (%module-command-interface) that contained bindings for all that module's
> commands.  This is the module that COMMAND_PATH would use for commands.
>
> PRO: One could export commands and procedures entirely independently.
>  Also, one can use the module mechanisms of selecting a subset, algorithmic
> renaming, etc. on these command modules.
> CON: It seems like a lot of magic, but it's using the same mechanisms that
> public interfaces use.
>
> 2. Have (export-command) just keep a list of commands, but just export a
> custom public interface.  So it might look like this internally:
>
> (define (export-command-proc names)
>   (set! %command-set (append! %command-set names)))
>
> (define (resolve-command-interface module-name)
>   (resolve-interface module-name #:select %command-set))
>
> PRO: Less magic-y.
> CON: One must export a command to both the public interface and the
> command; maybe that's ok even preferable that they're not independent.
>
> 3. Have (export-command) create a new sub-module (my-great-mode %command).
>
> PRO: Not too tricky.
> CON: Pollutes the module namespace a little bit.
>
> 4. Still use modules, but make the user segregate their procedures and
> commands into separate modules manually. So the user would have to define
> modules (my-great-mode) and (my-great-mode commands).
>
> PRO: No magic. Programmer does everything.
> CON: Everything is managed by convention. Separating the commands and
> procedures might be an awkward boundary.  Consider an internal procedure in
> (my-great-mode) that a command wants to use in (my-great-mode commands).
>  Do you expose it as public?  Move it around? Use @@ to get to it?
>
> 5. Don't use modules at all.  Make the user collect and manage
> <command-set>s the same way they manage keymaps, for instance.
>
> PRO: Nothing tricky, doesn't use modules at all.  No magic.
> CON: It has to work with the command being redefined; we can't just keep
> the command procedure; we have to keep the variable which points to modules
> possibly being a better solution.
>
> 6. Tag commands as special procedures perhaps by adding something to their
> procedure properties.  Implement a "command?" procedure.  Export commands
> and procedures to the same module. Then just pluck the commands out of all
> the procedures by using command?.
>
> PRO: No new modules. No new exports.
> CON: Adding something to the procedure makes wrapping commands in other
> lambdas awkward.  Might necessitate a define-command, lambda-command,
> method-command, which I'd prefer to avoid.
>
> * * *
>
> Thanks for indulging my scheme design question.  What's the right thing to
> do?  What would you do?
>
> -Shane
>
> [1]: https://github.com/shanecelis/emacsy
>

[-- Attachment #2: Type: text/html, Size: 6021 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Emacsy: Context Sensitive Commands Design Question
  2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
  2013-08-30  0:26 ` Noah Lavine
@ 2013-08-30  2:02 ` Mark H Weaver
  2013-08-30 11:32   ` Ludovic Courtès
  2013-08-30  7:32 ` Thien-Thi Nguyen
  2 siblings, 1 reply; 5+ messages in thread
From: Mark H Weaver @ 2013-08-30  2:02 UTC (permalink / raw)
  To: Shane Celis; +Cc: Guile Mailing List, Ludovic Courtès

Shane Celis <shane.celis@gmail.com> writes:

> 6. Tag commands as special procedures perhaps by adding something to
> their procedure properties.  Implement a "command?" procedure.  Export
> commands and procedures to the same module. Then just pluck the
> commands out of all the procedures by using command?.

This is closest to what Emacs does, and probably the best solution, IMO.  See
<https://www.gnu.org/software/emacs/manual/html_node/elisp/Interactive-Call.html>
which describes the 'commandp' predicate, whose definition is in eval.c.

    Regards,
      Mark



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Emacsy: Context Sensitive Commands Design Question
  2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
  2013-08-30  0:26 ` Noah Lavine
  2013-08-30  2:02 ` Mark H Weaver
@ 2013-08-30  7:32 ` Thien-Thi Nguyen
  2 siblings, 0 replies; 5+ messages in thread
From: Thien-Thi Nguyen @ 2013-08-30  7:32 UTC (permalink / raw)
  To: Shane Celis; +Cc: Guile Mailing List

[-- Attachment #1: Type: text/plain, Size: 1027 bytes --]

() Shane Celis <shane.celis@gmail.com>
() Thu, 29 Aug 2013 16:57:00 -0400

   6. Tag commands as special procedures [...] Implement "command?"

   CON: Adding something to the procedure makes wrapping commands in
   other lambdas awkward.  Might necessitate a define-command,
   lambda-command, method-command, which I'd prefer to avoid.

Why would you prefer to avoid this?

   What would you do?

I'd explore option 6, starting w/:

 (define command? (make-object-property))

I think object properties are better suited than procedure properties
after observing this in the (Emacs) *scratch* buffer:

 (commandp [42])
 t

It would be cool for Emacsy to have good "keyboard macros" support.
Many a non-programmer fall into consciousness via such, in Emacs.

[cc trimmed]

-- 
Thien-Thi Nguyen
   GPG key: 4C807502
   (if you're human and you know it)
      read my lisp: (responsep (questions 'technical)
                               (not (via 'mailing-list)))
                     => nil

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Emacsy: Context Sensitive Commands Design Question
  2013-08-30  2:02 ` Mark H Weaver
@ 2013-08-30 11:32   ` Ludovic Courtès
  0 siblings, 0 replies; 5+ messages in thread
From: Ludovic Courtès @ 2013-08-30 11:32 UTC (permalink / raw)
  To: Shane Celis; +Cc: Guile Mailing List

Mark H Weaver <mhw@netris.org> skribis:

> Shane Celis <shane.celis@gmail.com> writes:
>
>> 6. Tag commands as special procedures perhaps by adding something to
>> their procedure properties.  Implement a "command?" procedure.  Export
>> commands and procedures to the same module. Then just pluck the
>> commands out of all the procedures by using command?.
>
> This is closest to what Emacs does, and probably the best solution, IMO.  See
> <https://www.gnu.org/software/emacs/manual/html_node/elisp/Interactive-Call.html>
> which describes the 'commandp' predicate, whose definition is in eval.c.

I concur (Thien-Thi’s message shows how this can be achieved.)

So it’s a matter of extending Emacsy’s ‘define-interactive’ to add an
object property.

Then you could have a ‘fold-commands’ procedure that traverses all the
bindings of all the available modules (or a subset thereof), and
iterates on those that match ‘command?’.

Ludo’.



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-08-30 11:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
2013-08-30  0:26 ` Noah Lavine
2013-08-30  2:02 ` Mark H Weaver
2013-08-30 11:32   ` Ludovic Courtès
2013-08-30  7:32 ` Thien-Thi Nguyen

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).