unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Defining  functions on the fly
@ 2015-06-15  9:24 Andreas Röhler
  2015-06-15  9:32 ` Dmitry Gutov
                   ` (3 more replies)
  0 siblings, 4 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-15  9:24 UTC (permalink / raw)
  To: help-gnu-emacs

Hi,

have a bunch of subroutines which are useful in several modes - 
beginning/end of expressions, string positions, comments etc.

Now every mode should get its own prefix.
Can't write

(defun (concat "current-prefix-" foo) ())

as defun expects a symbol.

Exists "fset" - is there a recommended way to go?

Thanks,

Andreas





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

* Re: Defining functions on the fly
  2015-06-15  9:24 Defining functions on the fly Andreas Röhler
@ 2015-06-15  9:32 ` Dmitry Gutov
  2015-06-15  9:47 ` Alexis
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 43+ messages in thread
From: Dmitry Gutov @ 2015-06-15  9:32 UTC (permalink / raw)
  To: Andreas Röhler, help-gnu-emacs

On 06/15/2015 12:24 PM, Andreas Röhler wrote:

> Exists "fset" - is there a recommended way to go?

Probably not.

You might want to look at `cl-labels'.



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

* Re: Defining  functions on the fly
  2015-06-15  9:24 Defining functions on the fly Andreas Röhler
  2015-06-15  9:32 ` Dmitry Gutov
@ 2015-06-15  9:47 ` Alexis
  2015-06-15 10:20   ` Andreas Röhler
  2015-06-15 10:00 ` Tassilo Horn
       [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org>
  3 siblings, 1 reply; 43+ messages in thread
From: Alexis @ 2015-06-15  9:47 UTC (permalink / raw)
  To: help-gnu-emacs


Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

> Now every mode should get its own prefix.  Can't write
>
> (defun (concat "current-prefix-" foo) ())
>
> as defun expects a symbol.

i'm probably misunderstanding you, but does:

    (defun (intern (concat "current-prefix-" foo) ...

do what you need?


Alexis.



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

* Re: Defining  functions on the fly
       [not found] <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org>
@ 2015-06-15  9:57 ` Pascal J. Bourguignon
  2015-06-15 11:21   ` Andreas Röhler
  2015-06-15 23:51 ` Gene
  1 sibling, 1 reply; 43+ messages in thread
From: Pascal J. Bourguignon @ 2015-06-15  9:57 UTC (permalink / raw)
  To: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

> have a bunch of subroutines which are useful in several modes - 
> beginning/end of expressions, string positions, comments etc.
>
> Now every mode should get its own prefix.

And every human shoud get its own brain, 
but apparently some are missed.

Just call your function (named as you wish) from the several modes, 
DO NOT DUPLICATE THEM!

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


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

* Re: Defining  functions on the fly
  2015-06-15  9:24 Defining functions on the fly Andreas Röhler
  2015-06-15  9:32 ` Dmitry Gutov
  2015-06-15  9:47 ` Alexis
@ 2015-06-15 10:00 ` Tassilo Horn
  2015-06-15 10:33   ` Andreas Röhler
       [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org>
  3 siblings, 1 reply; 43+ messages in thread
From: Tassilo Horn @ 2015-06-15 10:00 UTC (permalink / raw)
  To: Andreas Röhler; +Cc: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

Hi Andreas,

> have a bunch of subroutines which are useful in several modes - 
> beginning/end of expressions, string positions, comments etc.
>
> Now every mode should get its own prefix.

I don't quite get what you are trying to achieve.  If your
beginning-of-expression function is useful in a-mode, b-mode, and
c-mode, what's the purpose of defining it three times?

If you really want to have separate {a,b,c}-beginning-of-expression
functions, then you could do it by defining aliases.

  (dolist (prefix (list "a" "b" "c"))
    (defalias (intern (concat prefix "-beginning-of-expression"))
              #'beginning-of-expression))

Bye,
Tassilo



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

* Re: Defining  functions on the fly
  2015-06-15  9:47 ` Alexis
@ 2015-06-15 10:20   ` Andreas Röhler
  2015-06-15 10:37     ` Alexis
                       ` (2 more replies)
  0 siblings, 3 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-15 10:20 UTC (permalink / raw)
  To: help-gnu-emacs


Am 15.06.2015 um 11:47 schrieb Alexis:
>
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
>> Now every mode should get its own prefix. Can't write
>>
>> (defun (concat "current-prefix-" foo) ())
>>
>> as defun expects a symbol.
>
> i'm probably misunderstanding you, but does:
>
>    (defun (intern (concat "current-prefix-" foo) ...
>
> do what you need?
>
>
> Alexis.
>

Seems (intern... is not evaluated at this point:

(defvar pfxd "pfxd-")

(defun (intern (concat pfxd "-foo")) ())

-->

Debugger entered--Lisp error: (wrong-type-argument symbolp (intern 
(concat pfxd "-foo")))
   defalias((intern (concat pfxd "-foo")) (lambda nil nil))
   eval((defalias (quote (intern (concat pfxd "-foo"))) (function 
(lambda nil nil))) nil)
   eval-last-sexp-1(nil)
   eval-last-sexp(nil)
   call-interactively(eval-last-sexp nil nil)
   command-execute(eval-last-sexp)




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

* Re: Defining  functions on the fly
  2015-06-15 10:00 ` Tassilo Horn
@ 2015-06-15 10:33   ` Andreas Röhler
  0 siblings, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-15 10:33 UTC (permalink / raw)
  To: help-gnu-emacs


Am 15.06.2015 um 12:00 schrieb Tassilo Horn:
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
> Hi Andreas,
>
>> have a bunch of subroutines which are useful in several modes -
>> beginning/end of expressions, string positions, comments etc.
>>
>> Now every mode should get its own prefix.
> I don't quite get what you are trying to achieve.  If your
> beginning-of-expression function is useful in a-mode, b-mode, and
> c-mode, what's the purpose of defining it three times?

AFAIU tab-completion of mode's symbols requires it equally prefixed.

> If you really want to have separate {a,b,c}-beginning-of-expression
> functions, then you could do it by defining aliases.
>
>    (dolist (prefix (list "a" "b" "c"))
>      (defalias (intern (concat prefix "-beginning-of-expression"))
>                #'beginning-of-expression))
>
>

That works, thanks!



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

* Re: Defining  functions on the fly
  2015-06-15 10:20   ` Andreas Röhler
@ 2015-06-15 10:37     ` Alexis
  2015-06-15 10:41     ` Michael Heerdegen
  2015-06-15 10:42     ` Tassilo Horn
  2 siblings, 0 replies; 43+ messages in thread
From: Alexis @ 2015-06-15 10:37 UTC (permalink / raw)
  To: help-gnu-emacs


Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

> Seems (intern... is not evaluated at this point:
>
> (defvar pfxd "pfxd-")
>
> (defun (intern (concat pfxd "-foo")) ())

You're right, sorry! When i use `intern' like this, it's in the 
context of quasiquoting, e.g.:

    (eval `(defun ,(intern (concat "ewmctrl-select-window-" 
    chosen-char "-for-action")) () 
             ,(concat "Select window '" chosen-char "' for an 
             action.")  (interactive) (ewmctrl--dispatch-action 
             ,chosen-char)))


Alexis.



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

* Re: Defining  functions on the fly
  2015-06-15 10:20   ` Andreas Röhler
  2015-06-15 10:37     ` Alexis
@ 2015-06-15 10:41     ` Michael Heerdegen
  2015-06-15 10:42     ` Tassilo Horn
  2 siblings, 0 replies; 43+ messages in thread
From: Michael Heerdegen @ 2015-06-15 10:41 UTC (permalink / raw)
  To: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:


> Seems (intern... is not evaluated at this point:
>
> (defvar pfxd "pfxd-")
>
> (defun (intern (concat pfxd "-foo")) ())
>
> -->
>
> Debugger entered--Lisp error: (wrong-type-argument symbolp (intern

That's expected.  You need to use `defalias' if you want to specify the
function name at run time.  Or use a macro.

Michael.




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

* Re: Defining  functions on the fly
  2015-06-15 10:20   ` Andreas Röhler
  2015-06-15 10:37     ` Alexis
  2015-06-15 10:41     ` Michael Heerdegen
@ 2015-06-15 10:42     ` Tassilo Horn
  2015-06-15 11:01       ` Alexis
  2015-06-15 11:19       ` Michael Heerdegen
  2 siblings, 2 replies; 43+ messages in thread
From: Tassilo Horn @ 2015-06-15 10:42 UTC (permalink / raw)
  To: Andreas Röhler; +Cc: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

>> i'm probably misunderstanding you, but does:
>>
>>    (defun (intern (concat "current-prefix-" foo) ...
>>
>> do what you need?
>
> Seems (intern... is not evaluated at this point:
>
> (defvar pfxd "pfxd-")
>
> (defun (intern (concat pfxd "-foo")) ())
>
> -->
>
> Debugger entered--Lisp error: (wrong-type-argument symbolp (intern (concat pfxd
> "-foo")))
>   defalias((intern (concat pfxd "-foo")) (lambda nil nil))

This might depend on emacs version.  At least with the current git
version, `defalias' evaluates its first argument:

  (defalias (intern "foo-bar") #'forward-sexp) ;; Works fine

But as Pascal already said, duplicating your function is not a good
idea.  Defining aliases is a bit better if you persist on prefixed
versions although I the only benefit I can see is a slightly better
discoverability through C-h f <prefix>-TAB.

Bye,
Tassilo



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

* Re: Defining  functions on the fly
  2015-06-15 10:42     ` Tassilo Horn
@ 2015-06-15 11:01       ` Alexis
  2015-06-15 11:19       ` Michael Heerdegen
  1 sibling, 0 replies; 43+ messages in thread
From: Alexis @ 2015-06-15 11:01 UTC (permalink / raw)
  To: help-gnu-emacs


Tassilo Horn <tsdh@gnu.org> writes:

> But as Pascal already said, duplicating your function is not a 
> good idea.  Defining aliases is a bit better if you persist on 
> prefixed versions although I the only benefit I can see is a 
> slightly better discoverability through C-h f <prefix>-TAB.

Related: i created the snippet i pasted from `ewmctrl' so that 
when users do C-h m, they can read a helpfully-named function for 
a dynamically-generated keybinding, rather than "??".

i imagine there's probably a Better Way To Do It™, though. :-)


Alexis.



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

* Re: Defining  functions on the fly
  2015-06-15 10:42     ` Tassilo Horn
  2015-06-15 11:01       ` Alexis
@ 2015-06-15 11:19       ` Michael Heerdegen
  2015-06-15 11:24         ` Tassilo Horn
  1 sibling, 1 reply; 43+ messages in thread
From: Michael Heerdegen @ 2015-06-15 11:19 UTC (permalink / raw)
  To: help-gnu-emacs

Tassilo Horn <tsdh@gnu.org> writes:

> > (defvar pfxd "pfxd-")
> >
> > (defun (intern (concat pfxd "-foo")) ())
> >
> > -->
> >
> > Debugger entered--Lisp error: (wrong-type-argument symbolp (intern
> > (concat pfxd
> > "-foo")))
> >   defalias((intern (concat pfxd "-foo")) (lambda nil nil))
>
> This might depend on emacs version.  At least with the current git
> version, `defalias' evaluates its first argument:
>
>   (defalias (intern "foo-bar") #'forward-sexp) ;; Works fine

In the example above, in the expansion of the `defun' call the first
argument to defalias is the (unevaluated!) list:

  (intern (concat pfxd "-foo"))

The corresponding call to defalias will also fail on trunk.


Michael.




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

* Re: Defining  functions on the fly
  2015-06-15  9:57 ` Pascal J. Bourguignon
@ 2015-06-15 11:21   ` Andreas Röhler
  2015-06-15 11:52     ` Tassilo Horn
  0 siblings, 1 reply; 43+ messages in thread
From: Andreas Röhler @ 2015-06-15 11:21 UTC (permalink / raw)
  To: help-gnu-emacs


Am 15.06.2015 um 11:57 schrieb Pascal J. Bourguignon:

[ ... ]

Just call your function (named as you wish) from the several modes, DO 
NOT DUPLICATE THEM!

It's not about duplication, but derivation. The original DTRT in most cases.

Point of interest are the exceptions - see for example in Elixir

https://github.com/elixir-lang/emacs-elixir/issues/185

"\"foo\""  |>  String.strip(?")

Where the doublquote after question mark makes Emacs think it's a string-start - which isn't.

So have to tweak some routines when loading it.

BTW this seems an occasion to use eieio and inheritance, right?











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

* Re: Defining  functions on the fly
  2015-06-15 11:19       ` Michael Heerdegen
@ 2015-06-15 11:24         ` Tassilo Horn
  2015-06-15 11:31           ` Michael Heerdegen
  0 siblings, 1 reply; 43+ messages in thread
From: Tassilo Horn @ 2015-06-15 11:24 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs

Michael Heerdegen <michael_heerdegen@web.de> writes:

>> > Debugger entered--Lisp error: (wrong-type-argument symbolp (intern
>> > (concat pfxd
>> > "-foo")))
>> >   defalias((intern (concat pfxd "-foo")) (lambda nil nil))
>>
>> This might depend on emacs version.  At least with the current git
>> version, `defalias' evaluates its first argument:
>>
>>   (defalias (intern "foo-bar") #'forward-sexp) ;; Works fine
>
> In the example above, in the expansion of the `defun' call the first
> argument to defalias is the (unevaluated!) list:
>
>   (intern (concat pfxd "-foo"))
>
> The corresponding call to defalias will also fail on trunk.

Ah, yes, so that's basically as if

  (defalias '(intern (concat pfxd "-foo")) ...)

had been written.

Bye,
Tassilo



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

* Re: Defining  functions on the fly
  2015-06-15 11:24         ` Tassilo Horn
@ 2015-06-15 11:31           ` Michael Heerdegen
  0 siblings, 0 replies; 43+ messages in thread
From: Michael Heerdegen @ 2015-06-15 11:31 UTC (permalink / raw)
  To: help-gnu-emacs

Tassilo Horn <tsdh@gnu.org> writes:

> Ah, yes, so that's basically as if
>
>   (defalias '(intern (concat pfxd "-foo")) ...)
>
> had been written.

Yip: (macroexpand '(defun (concat "current-prefix-" foo) ())) ==>

(defalias
  '(concat "current-prefix-" foo)
  #'(lambda nil nil))

The "problem" is that the defun macro (intentionally) adds a quote, so
that

  (defun name ..)

expands to

  (defalias 'name ...)

and `name' doesn't get evaluated.  If the defun macro would not add that
quote, you would have to write

  (defun 'name ...)

but (defun (intern name) ...) would work then.


Michael.



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

* Re: Defining  functions on the fly
  2015-06-15 11:21   ` Andreas Röhler
@ 2015-06-15 11:52     ` Tassilo Horn
  2015-06-15 12:06       ` Andreas Röhler
  2015-06-15 12:43       ` Andreas Röhler
  0 siblings, 2 replies; 43+ messages in thread
From: Tassilo Horn @ 2015-06-15 11:52 UTC (permalink / raw)
  To: Andreas Röhler; +Cc: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

> It's not about duplication, but derivation. The original DTRT in most
> cases.
>
> Point of interest are the exceptions - see for example in Elixir
>
> https://github.com/elixir-lang/emacs-elixir/issues/185
>
> "\"foo\""  |>  String.strip(?")
>
> Where the doublquote after question mark makes Emacs think it's a
> string-start - which isn't.

String recognition in emacs is usually done using syntax tables, so get
the elixir syntax table right and then you don't need any workarounds.
In this case, it seems plain syntax tables aren't enough, though, so the
elisp docs explain how to override certain characters' syntax on demand.

,----[ (info "(elisp)Syntax Properties") ]
| When the syntax table is not flexible enough to specify the syntax of a
| language, you can override the syntax table for specific character
| occurrences in the buffer, by applying a ‘syntax-table’ text property.
| *Note Text Properties::, for how to apply text properties.
`----

So basically, you (or elixir-mode) will want to define a
`syntax-propertize-function' which finds occurrences of ?" and gives "/"
(character quote) syntax to the ? in which the usual "\"" (string
quotes) syntax of `"' would be ineffective for this single double quote.

,----[ (info "(elisp)Syntax Class Table") ]
| Character quotes: ‘/’
|      Characters used to quote the following character so that it loses
|      its normal syntactic meaning.  This differs from an escape
|      character in that only the character immediately following is ever
|      affected.
| 
|      Characters in this class count as part of words if
|      ‘words-include-escapes’ is non-‘nil’.  *Note Word Motion::.
`----

Bye,
Tassilo



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

* Re: Defining  functions on the fly
  2015-06-15 11:52     ` Tassilo Horn
@ 2015-06-15 12:06       ` Andreas Röhler
  2015-06-15 12:43       ` Andreas Röhler
  1 sibling, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-15 12:06 UTC (permalink / raw)
  To: help-gnu-emacs


Am 15.06.2015 um 13:52 schrieb Tassilo Horn:
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
>> It's not about duplication, but derivation. The original DTRT in most
>> cases.
>>
>> Point of interest are the exceptions - see for example in Elixir
>>
>> https://github.com/elixir-lang/emacs-elixir/issues/185
>>
>> "\"foo\""  |>  String.strip(?")
>>
>> Where the doublquote after question mark makes Emacs think it's a
>> string-start - which isn't.
> String recognition in emacs is usually done using syntax tables, so get
> the elixir syntax table right and then you don't need any workarounds.
> In this case, it seems plain syntax tables aren't enough, though, so the
> elisp docs explain how to override certain characters' syntax on demand.
>
> ,----[ (info "(elisp)Syntax Properties") ]
> | When the syntax table is not flexible enough to specify the syntax of a
> | language, you can override the syntax table for specific character
> | occurrences in the buffer, by applying a ‘syntax-table’ text property.
> | *Note Text Properties::, for how to apply text properties.
> `----
>
> So basically, you (or elixir-mode) will want to define a
> `syntax-propertize-function' which finds occurrences of ?" and gives "/"
> (character quote) syntax to the ? in which the usual "\"" (string
> quotes) syntax of `"' would be ineffective for this single double quote.
>
> ,----[ (info "(elisp)Syntax Class Table") ]
> | Character quotes: ‘/’
> |      Characters used to quote the following character so that it loses
> |      its normal syntactic meaning.  This differs from an escape
> |      character in that only the character immediately following is ever
> |      affected.
> |
> |      Characters in this class count as part of words if
> |      ‘words-include-escapes’ is non-‘nil’.  *Note Word Motion::.
> `----
>
> Bye,
> Tassilo

Thanks again. Will see if a better example comes across WRT original 
question.



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

* Re: Defining  functions on the fly
  2015-06-15 11:52     ` Tassilo Horn
  2015-06-15 12:06       ` Andreas Röhler
@ 2015-06-15 12:43       ` Andreas Röhler
  1 sibling, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-15 12:43 UTC (permalink / raw)
  To: help-gnu-emacs


This seems to work, some function going to char 1:

(dolist (ele (list "a" "b"))
   ;; think some conditions here, which will select the final lambda
   (fset (intern-soft (car (read-from-string ele))) #'(lambda 
()(goto-char 1))))




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

* Re: Defining  functions on the fly
       [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org>
@ 2015-06-15 12:52   ` Stefan Monnier
  2015-06-16  5:59     ` Andreas Röhler
       [not found]     ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 43+ messages in thread
From: Stefan Monnier @ 2015-06-15 12:52 UTC (permalink / raw)
  To: help-gnu-emacs

> i'm probably misunderstanding you, but does:
>    (defun (intern (concat "current-prefix-" foo) ...
> do what you need?

(defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
not with defun.  In any case, some concrete example of what he needs to
do would go a long way.


        Stefan


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

* Re: Defining  functions on the fly
       [not found] <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org>
  2015-06-15  9:57 ` Pascal J. Bourguignon
@ 2015-06-15 23:51 ` Gene
  2015-06-16  1:14   ` Stefan Monnier
  2015-06-16  5:47   ` Andreas Röhler
  1 sibling, 2 replies; 43+ messages in thread
From: Gene @ 2015-06-15 23:51 UTC (permalink / raw)
  To: help-gnu-emacs

On Monday, June 15, 2015 at 5:24:40 AM UTC-4, Andreas Röhler wrote:
> Hi,
> 
> have a bunch of subroutines which are useful in several modes - 
> beginning/end of expressions, string positions, comments etc.
> 
> Now every mode should get its own prefix.
> Can't write
> 
> (defun (concat "current-prefix-" foo) ())
> 
> as defun expects a symbol.
> 
> Exists "fset" - is there a recommended way to go?

I recommend using lambda to experimentally develop what you think of as a function of the sort defun is typically used typically used to define.

Once the function's actual definition is done via lambda it can be bound to a symbol via fset

(fset (function name-of-function)
 (lambda (arg)
  "docstring"
  ; Body goes here
 )
)

Of course the anonymous version of the function can be used via higher order functions such as `apply' and `mapcar' so function development and testing can be furthered before one gets around to deciding to keep it around and name it for convenient future use.

This strategy is pretty much applicable in Scheme as well

(define name-of-function
 (lambda (arg)
  ;body
 )
)

I hope this helps.

Gene



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

* Re: Defining  functions on the fly
  2015-06-15 23:51 ` Gene
@ 2015-06-16  1:14   ` Stefan Monnier
  2015-06-17  0:24     ` Gene
  2015-06-16  5:47   ` Andreas Röhler
  1 sibling, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2015-06-16  1:14 UTC (permalink / raw)
  To: help-gnu-emacs

> (fset (function name-of-function)
[...]
> (define name-of-function

Actually, `fset' is more like Scheme's `set!', so if it's the
*definition* of a function, you should use `defalias' which is more like
Scheme's `define'.


        Stefan


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

* Re: Defining  functions on the fly
  2015-06-15 23:51 ` Gene
  2015-06-16  1:14   ` Stefan Monnier
@ 2015-06-16  5:47   ` Andreas Röhler
  1 sibling, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16  5:47 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 01:51 schrieb Gene:
> On Monday, June 15, 2015 at 5:24:40 AM UTC-4, Andreas Röhler wrote:
>> Hi,
>>
>> have a bunch of subroutines which are useful in several modes -
>> beginning/end of expressions, string positions, comments etc.
>>
>> Now every mode should get its own prefix.
>> Can't write
>>
>> (defun (concat "current-prefix-" foo) ())
>>
>> as defun expects a symbol.
>>
>> Exists "fset" - is there a recommended way to go?
> I recommend using lambda to experimentally develop what you think of as a function of the sort defun is typically used typically used to define.
>
> Once the function's actual definition is done via lambda it can be bound to a symbol via fset
>
> (fset (function name-of-function)
>   (lambda (arg)
>    "docstring"
>    ; Body goes here
>   )
> )
>
> Of course the anonymous version of the function can be used via higher order functions such as `apply' and `mapcar' so function development and testing can be furthered before one gets around to deciding to keep it around and name it for convenient future use.
>
> This strategy is pretty much applicable in Scheme as well
>
> (define name-of-function
>   (lambda (arg)
>    ;body
>   )
> )
>
> I hope this helps.
>
> Gene
>

It does, thanks!



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

* Re: Defining  functions on the fly
  2015-06-15 12:52   ` Stefan Monnier
@ 2015-06-16  5:59     ` Andreas Röhler
  2015-06-16  7:01       ` Tassilo Horn
       [not found]     ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16  5:59 UTC (permalink / raw)
  To: help-gnu-emacs


Am 15.06.2015 um 14:52 schrieb Stefan Monnier:
>> i'm probably misunderstanding you, but does:
>>     (defun (intern (concat "current-prefix-" foo) ...
>> do what you need?
> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
> not with defun.  In any case, some concrete example of what he needs to
> do would go a long way.
>
>
>          Stefan

Currently Emacs provides some scheme to fontify source code and some 
basic moves: linewise, symbol, word, paragraph, sexp.

There is no idea of statement, block/loop or expression and a poor 
top-level --beginning/end-of-defun.

Just trying to implement a kind of default for this.




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

* Re: Defining  functions on the fly
  2015-06-16  5:59     ` Andreas Röhler
@ 2015-06-16  7:01       ` Tassilo Horn
  2015-06-16  9:22         ` Andreas Röhler
                           ` (3 more replies)
  0 siblings, 4 replies; 43+ messages in thread
From: Tassilo Horn @ 2015-06-16  7:01 UTC (permalink / raw)
  To: Andreas Röhler; +Cc: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

>>> i'm probably misunderstanding you, but does:
>>>     (defun (intern (concat "current-prefix-" foo) ...
>>> do what you need?
>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
>> not with defun.  In any case, some concrete example of what he needs to
>> do would go a long way.
>>
>>
>>          Stefan
>
> Currently Emacs provides some scheme to fontify source code and some
> basic moves: linewise, symbol, word, paragraph, sexp.
>
> There is no idea of statement, block/loop or expression and a poor
> top-level --beginning/end-of-defun.

There is: `forward-sexp' and `backward-sexp'.  Although the name sexp is
a bit lisp-specific, sexp-based motion has been implemented for more
C-like languages, too.  For example, it works well for shell scripts and
Ruby programs.

See (info "(elisp) SMIE") for how to add sexp-based motion to your
favorite programming language mode.

Bye,
Tassilo



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

* Re: Defining  functions on the fly
  2015-06-16  7:01       ` Tassilo Horn
@ 2015-06-16  9:22         ` Andreas Röhler
  2015-06-16 11:12           ` Tassilo Horn
  2015-06-16  9:42         ` Andreas Röhler
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16  9:22 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 09:01 schrieb Tassilo Horn:
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
>>>> i'm probably misunderstanding you, but does:
>>>>      (defun (intern (concat "current-prefix-" foo) ...
>>>> do what you need?
>>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
>>> not with defun.  In any case, some concrete example of what he needs to
>>> do would go a long way.
>>>
>>>
>>>           Stefan
>> Currently Emacs provides some scheme to fontify source code and some
>> basic moves: linewise, symbol, word, paragraph, sexp.
>>
>> There is no idea of statement, block/loop or expression and a poor
>> top-level --beginning/end-of-defun.
> There is: `forward-sexp' and `backward-sexp'.  Although the name sexp is
> a bit lisp-specific, sexp-based motion has been implemented for more
> C-like languages, too.  For example, it works well for shell scripts

Unfortunatly couldn't experience this. There are several common cases 
within shell-script, where calls to navigate sexp would raise an error.

That's why language-modes have to implement a couple of most basic 
things. See

http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html

###

vorhanden() {
     for i in "blah" "blub";
     do
         # some comment (note: for compatibility)
     if [ ! -x $i ]; then

###

with cursor last line "if", C-M-b jumps to "for", but should end at "do"
 From "for" ->

Debugger entered--Lisp error: (scan-error "Containing expression ends 
prematurely" 13 13)
   signal(scan-error ("Containing expression ends prematurely" 13 13))
   smie-forward-sexp-command(-1)
   forward-sexp(-1)
   backward-sexp(1)
   call-interactively(backward-sexp nil nil)
   command-execute(backward-sexp)

There are many more spots in this example to trigger error or unexpected 
moves.

Or take this:

###

if [ $# == 0 ]; then
     # some comment (note: for compatibility)
     set "" `find .  -maxdepth 1 -type f -name "*.txt" | sed 
's/..\(.*\)/\1/'`

     for i in $*; do
         # some comment (note: for compatibility)
     pass
     done

fi

###

With cursor at third line, "set", expression is not recognised at all, 
C-M-f stops at the end of symbol "set"

That's a fakir's mode :)





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

* Re: Defining  functions on the fly
  2015-06-16  7:01       ` Tassilo Horn
  2015-06-16  9:22         ` Andreas Röhler
@ 2015-06-16  9:42         ` Andreas Röhler
       [not found]         ` <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org>
       [not found]         ` <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org>
  3 siblings, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16  9:42 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 09:01 schrieb Tassilo Horn:
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
>>>> i'm probably misunderstanding you, but does:
>>>>      (defun (intern (concat "current-prefix-" foo) ...
>>>> do what you need?
>>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
>>> not with defun.  In any case, some concrete example of what he needs to
>>> do would go a long way.
>>>
>>>
>>>           Stefan
>> Currently Emacs provides some scheme to fontify source code and some
>> basic moves: linewise, symbol, word, paragraph, sexp.
>>
>> There is no idea of statement, block/loop or expression and a poor
>> top-level --beginning/end-of-defun.
> There is: `forward-sexp' and `backward-sexp'.

Expect sexp-navigation behaving the the following way:

- if inside a form, go to the end resp. start
- if at end of form, forward same level if form exist, or get level 
following point, or EOB
- if at beginning of form, backward same level if form exist, or get 
level preceding point, or BOB

Resp. when inside a literal, go to start resp. end.
When in inside a comment, leave it, treat it like whitespace, repeat the 
command.

Beside other shortcomings, for now docstring of forward-sexp says:

"This command assumes point is not in a string or comment."

A restriction, which is not acceptable.




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

* Re: Defining  functions on the fly
       [not found]         ` <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org>
@ 2015-06-16  9:50           ` Pascal J. Bourguignon
  2015-06-16 10:26             ` Andreas Röhler
       [not found]             ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 43+ messages in thread
From: Pascal J. Bourguignon @ 2015-06-16  9:50 UTC (permalink / raw)
  To: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

> Am 16.06.2015 um 09:01 schrieb Tassilo Horn:
>> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>>
>>>>> i'm probably misunderstanding you, but does:
>>>>>      (defun (intern (concat "current-prefix-" foo) ...
>>>>> do what you need?
>>>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
>>>> not with defun.  In any case, some concrete example of what he needs to
>>>> do would go a long way.
>>>>
>>>>
>>>>           Stefan
>>> Currently Emacs provides some scheme to fontify source code and some
>>> basic moves: linewise, symbol, word, paragraph, sexp.
>>>
>>> There is no idea of statement, block/loop or expression and a poor
>>> top-level --beginning/end-of-defun.
>> There is: `forward-sexp' and `backward-sexp'.  Although the name sexp is
>> a bit lisp-specific, sexp-based motion has been implemented for more
>> C-like languages, too.  For example, it works well for shell scripts
>
> Unfortunatly couldn't experience this. There are several common cases
> within shell-script, where calls to navigate sexp would raise an
> error.
>
> That's why language-modes have to implement a couple of most basic
> things. See
>
> http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html
>
> ###
>
> vorhanden() {
>     for i in "blah" "blub";
>     do
>         # some comment (note: for compatibility)
>     if [ ! -x $i ]; then
>
> ###
>
> with cursor last line "if", C-M-b jumps to "for", but should end at "do"
> From "for" ->
>
> Debugger entered--Lisp error: (scan-error "Containing expression ends
> prematurely" 13 13)
>   signal(scan-error ("Containing expression ends prematurely" 13 13))
>   smie-forward-sexp-command(-1)
>   forward-sexp(-1)
>   backward-sexp(1)
>   call-interactively(backward-sexp nil nil)
>   command-execute(backward-sexp)
>
> There are many more spots in this example to trigger error or
> unexpected moves.
>
> Or take this:
>
> ###
>
> if [ $# == 0 ]; then
>     # some comment (note: for compatibility)
>     set "" `find .  -maxdepth 1 -type f -name "*.txt" | sed
> s/..\(.*\)/\1/'`
>
>     for i in $*; do
>         # some comment (note: for compatibility)
>     pass
>     done
>
> fi
>
> ###
>
> With cursor at third line, "set", expression is not recognised at all,
> C-M-f stops at the end of symbol "set"
>
> That's a fakir's mode :)

There are hooks to customize those general commands to specific modes!
For example, instead of writing:

    bash-forward-sexp
    sh-forward-sexp
    pascal-forward-sexp
    ada-forward-sexp

etc, each mode will just bind a specific forward sexp function to the
hook variable:  forward-sexp-function, and forward-sexp will call it.


-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


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

* Re: Defining  functions on the fly
  2015-06-16  9:50           ` Pascal J. Bourguignon
@ 2015-06-16 10:26             ` Andreas Röhler
       [not found]             ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16 10:26 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 11:50 schrieb Pascal J. Bourguignon:
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
>> Am 16.06.2015 um 09:01 schrieb Tassilo Horn:
>>> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>>>
>>>>>> i'm probably misunderstanding you, but does:
>>>>>>       (defun (intern (concat "current-prefix-" foo) ...
>>>>>> do what you need?
>>>>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but
>>>>> not with defun.  In any case, some concrete example of what he needs to
>>>>> do would go a long way.
>>>>>
>>>>>
>>>>>            Stefan
>>>> Currently Emacs provides some scheme to fontify source code and some
>>>> basic moves: linewise, symbol, word, paragraph, sexp.
>>>>
>>>> There is no idea of statement, block/loop or expression and a poor
>>>> top-level --beginning/end-of-defun.
>>> There is: `forward-sexp' and `backward-sexp'.  Although the name sexp is
>>> a bit lisp-specific, sexp-based motion has been implemented for more
>>> C-like languages, too.  For example, it works well for shell scripts
>> Unfortunatly couldn't experience this. There are several common cases
>> within shell-script, where calls to navigate sexp would raise an
>> error.
>>
>> That's why language-modes have to implement a couple of most basic
>> things. See
>>
>> http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html
>>
>> ###
>>
>> vorhanden() {
>>      for i in "blah" "blub";
>>      do
>>          # some comment (note: for compatibility)
>>      if [ ! -x $i ]; then
>>
>> ###
>>
>> with cursor last line "if", C-M-b jumps to "for", but should end at "do"
>>  From "for" ->
>>
>> Debugger entered--Lisp error: (scan-error "Containing expression ends
>> prematurely" 13 13)
>>    signal(scan-error ("Containing expression ends prematurely" 13 13))
>>    smie-forward-sexp-command(-1)
>>    forward-sexp(-1)
>>    backward-sexp(1)
>>    call-interactively(backward-sexp nil nil)
>>    command-execute(backward-sexp)
>>
>> There are many more spots in this example to trigger error or
>> unexpected moves.
>>
>> Or take this:
>>
>> ###
>>
>> if [ $# == 0 ]; then
>>      # some comment (note: for compatibility)
>>      set "" `find .  -maxdepth 1 -type f -name "*.txt" | sed
>> s/..\(.*\)/\1/'`
>>
>>      for i in $*; do
>>          # some comment (note: for compatibility)
>>      pass
>>      done
>>
>> fi
>>
>> ###
>>
>> With cursor at third line, "set", expression is not recognised at all,
>> C-M-f stops at the end of symbol "set"
>>
>> That's a fakir's mode :)
> There are hooks to customize those general commands to specific modes!
> For example, instead of writing:
>
>      bash-forward-sexp
>      sh-forward-sexp
>      pascal-forward-sexp
>      ada-forward-sexp
>
> etc, each mode will just bind a specific forward sexp function to the
> hook variable:  forward-sexp-function, and forward-sexp will call it.
>
>

That's a consideration at the command- resp. key-binding level.
Nonetheless mode-specific functions are needed to bind then.

For now these language mode often invent very basic things in parallel: 
string-strip, in-string-p etc.
Also creating bugs and quirks that way.

Beyond that we can generalize top-level, block, expression and statement 
-- at least to some extend.



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

* Re: Defining  functions on the fly
  2015-06-16  9:22         ` Andreas Röhler
@ 2015-06-16 11:12           ` Tassilo Horn
  2015-06-16 11:40             ` Andreas Röhler
       [not found]             ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 43+ messages in thread
From: Tassilo Horn @ 2015-06-16 11:12 UTC (permalink / raw)
  To: Andreas Röhler; +Cc: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

>> There is: `forward-sexp' and `backward-sexp'.  Although the name sexp
>> is a bit lisp-specific, sexp-based motion has been implemented for
>> more C-like languages, too.  For example, it works well for shell
>> scripts
>
> Unfortunatly couldn't experience this. There are several common cases
> within shell-script, where calls to navigate sexp would raise an
> error.
>
> That's why language-modes have to implement a couple of most basic things. See
>
> http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html

I agree with Stefan and Arthur on this particular issue.

> ###
>
> vorhanden() {
>     for i in "blah" "blub";
>     do
>         # some comment (note: for compatibility)
>     if [ ! -x $i ]; then
>
> ###
>
> with cursor last line "if", C-M-b jumps to "for", but should end at
> "do"

No.  `do ... done' is no valid expression, i.e., it cannot stand on its
own but is only valid together with for, while, until, or repeat.

> From "for" ->
>
> Debugger entered--Lisp error: (scan-error "Containing expression ends
> prematurely" 13 13)
>   signal(scan-error ("Containing expression ends prematurely" 13 13))
>   smie-forward-sexp-command(-1)
>   forward-sexp(-1)
>   backward-sexp(1)
>   call-interactively(backward-sexp nil nil)
>   command-execute(backward-sexp)

Indeed, here I'd expect it to move to the beginning of the function
definition.

> Or take this:
>
> ###
>
> if [ $# == 0 ]; then
>     # some comment (note: for compatibility)
>     set "" `find .  -maxdepth 1 -type f -name "*.txt" | sed 's/..\(.*\)/\1/'`
>
>     for i in $*; do
>         # some comment (note: for compatibility)
>     pass
>     done
>
> fi
>
> ###
>
> With cursor at third line, "set", expression is not recognised at all,
> C-M-f stops at the end of symbol "set"

Well, "command arg arg arg" in shell scripts is equivalent to (command
arg arg arg) in lisp with the distinction that with the lisp syntax's
parentheses you have a choice to move over the complete expression (when
point is on the opening paren) or inside it (when point is on the
"command").  Because the shell syntax doesn't have delimiters for the
funcall or at least the argument list, there's not much you can do.

> That's a fakir's mode :)

Well, you can extend it quite easily and declaratively by modifying
`sh-smie-sh-grammar', and then your improvements are transparently
available to anything which uses sexp-based motion.  I don't see how you
can get the same benefits with tons and tons of special-case functions.

Bye,
Tassilo



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

* Re: Defining  functions on the fly
       [not found]             ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org>
@ 2015-06-16 11:35               ` Pascal J. Bourguignon
  0 siblings, 0 replies; 43+ messages in thread
From: Pascal J. Bourguignon @ 2015-06-16 11:35 UTC (permalink / raw)
  To: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

> Am 16.06.2015 um 11:50 schrieb Pascal J. Bourguignon:
>> There are hooks to customize those general commands to specific modes!
>> For example, instead of writing:
>>
>>      bash-forward-sexp
>>      sh-forward-sexp
>>      pascal-forward-sexp
>>      ada-forward-sexp
>>
>> etc, each mode will just bind a specific forward sexp function to the
>> hook variable:  forward-sexp-function, and forward-sexp will call it.
>>
>>
>
> That's a consideration at the command- resp. key-binding level.
> Nonetheless mode-specific functions are needed to bind then.

Of course, and mode-specific functions will have a mode-specific prefix
in their name.

But if you have functions that are not mode-specific, like,
    (generate-parser mode-specific-grammar), or
    (parse-to-point mode-specific-grammar), 
you DO NOT DUPLICATE those functions with names such as
    pascal-generate-parser  pascal-parse-to-point
    ada-generate-parser     ada-parse-to-point
    c-generate-parser       c-parse-to-point
    bash-generate-parser    bash-parse-to-point
This is dumb.

What you do is to call those general functions from your mode-specific
functions (that since they are specific and different for each mode, do
not contain duplicated code).

What you could do, for those generic functions, is to put them in a nice
re-usable library, give a name to the library, and prefix them by the
name of the library. Eg. if you name the library bovidae, then you will
have:

     bovidae-generate-parser
     bovidae-parse-to-point

but you would not duplicate those functions with names such as:
    pascal-bovidae-generate-parser  pascal-bovidae-parse-to-point
    ada-bovidae-generate-parser     ada-bovidae-parse-to-point
    c-bovidae-generate-parser       c-bovidae-parse-to-point
    bash-bovidae-generate-parser    bash-bovidae-parse-to-point
This would be dumb.


> For now these language mode often invent very basic things in
> parallel: string-strip, in-string-p etc.
> Also creating bugs and quirks that way.

Then factorize that out in a common library!


> Beyond that we can generalize top-level, block, expression and
> statement -- at least to some extend.

You already have a few such functions:

    beginning-of-defun
    end-of-defun
    indent-defun
    mark-defun
    narrow-to-defun


Also, I've noticed a remark in the thread.

Some languages distinguish statements and expressions (and sometimes
also declarations or definitions), but some other languages only have
expressions.  The laters are much more usable and agreable, and more
easily edited also.

When parsing a program, you naturally obtain parse trees labelled with
the kind statement, expression, definition, etc.  But when editing, you
might want to flatten all this down to expressions (sexp), as if you
were editing lisp, because it is easier.  But you could provide tools to
convert between statements and expressions.

For example, if you kill a C statement (selection shown with []):

   [ x=a+b; ]
     if(a==b){
       x=0;
     }else{
       y=42;
     }

then move into an expression context (point shown with |):

     if(|a==b){
       x=0;
     }else{
       y=42;
     }

and yank, the statement x=a+b; could be transformed into an expression
(semicolon removed):

     if((x=a+b),|(a==b)){
       x=0;
     }else{
       y=42;
     }

And backward, an expression:

   x=[ (a==b)?0:42 ];

killed and yanked into statement context:

   {
    |
   }

would transform it into a statment:

   {
    if(a==b){
     return 0;
    }else{
     return 42;
    }
  }   

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


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

* Re: Defining  functions on the fly
  2015-06-16 11:12           ` Tassilo Horn
@ 2015-06-16 11:40             ` Andreas Röhler
  2015-06-16 13:10               ` Tassilo Horn
       [not found]             ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16 11:40 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 13:12 schrieb Tassilo Horn:

>> ###
>>
>> vorhanden() {
>>      for i in "blah" "blub";
>>      do
>>          # some comment (note: for compatibility)
>>      if [ ! -x $i ]; then
>>
>> ###
>>
>> with cursor last line "if", C-M-b jumps to "for", but should end at
>> "do"
> No.  `do ... done' is no valid expression, i.e., it cannot stand on its
> own but is only valid together with for, while, until, or repeat.

It's not the point to care for that.

It's about editing, reading, understanding the source.

What about a single "return" statement in code?

Nonetheless, will reflect this case again WRT the mode in question.


>
>>  From "for" ->
>>
>> Debugger entered--Lisp error: (scan-error "Containing expression ends
>> prematurely" 13 13)
>>    signal(scan-error ("Containing expression ends prematurely" 13 13))
>>    smie-forward-sexp-command(-1)
>>    forward-sexp(-1)
>>    backward-sexp(1)
>>    call-interactively(backward-sexp nil nil)
>>    command-execute(backward-sexp)
> Indeed, here I'd expect it to move to the beginning of the function
> definition.
>
>> Or take this:
>>
>> ###
>>
>> if [ $# == 0 ]; then
>>      # some comment (note: for compatibility)
>>      set "" `find .  -maxdepth 1 -type f -name "*.txt" | sed 's/..\(.*\)/\1/'`
>>
>>      for i in $*; do
>>          # some comment (note: for compatibility)
>>      pass
>>      done
>>
>> fi
>>
>> ###
>>
>> With cursor at third line, "set", expression is not recognised at all,
>> C-M-f stops at the end of symbol "set"
> Well, "command arg arg arg" in shell scripts is equivalent to (command
> arg arg arg) in lisp with the distinction that with the lisp syntax's
> parentheses you have a choice to move over the complete expression (when
> point is on the opening paren) or inside it (when point is on the
> "command").  Because the shell syntax doesn't have delimiters for the
> funcall or at least the argument list, there's not much you can do.

Wrong. We have the language's syntax and may follow it.
Also these languages often are quite similar, thus aiming for some generics.


>
>> That's a fakir's mode :)
> Well, you can extend it quite easily and declaratively by modifying
> `sh-smie-sh-grammar', and then your improvements are transparently
> available to anything which uses sexp-based motion.

I'll look for that. For the moment see a couple of mode's out there with 
open smie-related bugs.
See at elixir-mode or tuareg-mode for example.

>   I don't see how you
> can get the same benefits with tons and tons of special-case functions.
>
>

These tons are not written by me but by the folks in language-modes.
Auto-generating some stuff would reduce the costs.




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

* Re: Defining  functions on the fly
  2015-06-16 11:40             ` Andreas Röhler
@ 2015-06-16 13:10               ` Tassilo Horn
  2015-06-16 15:46                 ` Andreas Röhler
       [not found]                 ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 43+ messages in thread
From: Tassilo Horn @ 2015-06-16 13:10 UTC (permalink / raw)
  To: Andreas Röhler; +Cc: help-gnu-emacs

Andreas Röhler <andreas.roehler@easy-emacs.de> writes:

>> No.  `do ... done' is no valid expression, i.e., it cannot stand on
>> its own but is only valid together with for, while, until, or repeat.
>
> It's not the point to care for that.

Well, when you say you want to move by expression or statement then it
seems legit to do exactly that and not move by half of a statement.

> It's about editing, reading, understanding the source.

I can understand that moving to the do wouldn't be bad with respect to
editing because it's nearer, e.g., two smaller steps might be better
than one large step which might already be too much.  But the same time
you argue that `forward-sexp' in a string should jump to its end instead
of moving word-wise in its contents first.

> What about a single "return" statement in code?

What's up with a single return statement in code?

> Nonetheless, will reflect this case again WRT the mode in question.

I don't get what you are trying to tell me.

>>> With cursor at third line, "set", expression is not recognised at
>>> all, C-M-f stops at the end of symbol "set"
>> Well, "command arg arg arg" in shell scripts is equivalent to
>> (command arg arg arg) in lisp with the distinction that with the lisp
>> syntax's parentheses you have a choice to move over the complete
>> expression (when point is on the opening paren) or inside it (when
>> point is on the "command").  Because the shell syntax doesn't have
>> delimiters for the funcall or at least the argument list, there's not
>> much you can do.
>
> Wrong.  We have the language's syntax and may follow it.

I don't get what you mean.

> Also these languages often are quite similar, thus aiming for some
> generics.

That's the whole purpose of SMIE: conveniently navigating/editing code
of different languages by defining what's a sexp in these languages
using a simple grammar.  Then the generic interface is just the set of
sexp-commands.

Bye,
Tassilo



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

* Re: Defining  functions on the fly
  2015-06-16 13:10               ` Tassilo Horn
@ 2015-06-16 15:46                 ` Andreas Röhler
       [not found]                 ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16 15:46 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 15:10 schrieb Tassilo Horn:
> Andreas Röhler <andreas.roehler@easy-emacs.de> writes:
>
>>> No.  `do ... done' is no valid expression, i.e., it cannot stand on
>>> its own but is only valid together with for, while, until, or repeat.
>> It's not the point to care for that.
> Well, when you say you want to move by expression or statement then it
> seems legit to do exactly that and not move by half of a statement.
>
>> It's about editing, reading, understanding the source.
> I can understand that moving to the do wouldn't be bad with respect to
> editing because it's nearer, e.g., two smaller steps might be better
> than one large step which might already be too much.  But the same time
> you argue that `forward-sexp' in a string should jump to its end instead
> of moving word-wise in its contents first.

Because forward-word is implemented already and forward-sexp is 
redundant in this circumstances,
while goto-end/start of string is missing.


[ ... ]



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

* Re: Defining  functions on the fly
       [not found]             ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org>
@ 2015-06-16 16:13               ` Pascal J. Bourguignon
  2015-06-16 18:30                 ` Andreas Röhler
  0 siblings, 1 reply; 43+ messages in thread
From: Pascal J. Bourguignon @ 2015-06-16 16:13 UTC (permalink / raw)
  To: help-gnu-emacs

Andreas, you might be interested in reading:

https://www.ics.uci.edu/~taylor/ics228/SynGen.pdf

and

    Teitelbaum, T.; T. Reps (September 1981). "The Cornell Program
    Synthesizer: A syntax-directed programming
    environment". Communications of the ACM 24 (9):
    563–573. doi:10.1145/358746.358755.

if you can get your hands on it.

Check also: https://en.wikipedia.org/wiki/Structure_editor

Basically, you could generate the whole mode all the structured editing
commands, from a grammar of the language you want to edit.

And since you could include in the grammar, grammars of other languages
when you have such escape, such as html scripts, or php, etc, you would
get automatically "multi-mode" structured editing modes.


Now, when you generate code (eg. a programming language compiler), it is
perfectly normal to have parts that are generated, and functions and
stubs that are written once for all for all the programs: a run-time
library.  

Your code generate would naturally bind mode commands whose name would
be prefixed by the name of the grammar (= the mode), but the run-time
library would be the same for all those generated mode, and would have a
library prefix instead.

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


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

* Re: Defining  functions on the fly
  2015-06-16 16:13               ` Pascal J. Bourguignon
@ 2015-06-16 18:30                 ` Andreas Röhler
  0 siblings, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-16 18:30 UTC (permalink / raw)
  To: help-gnu-emacs


Am 16.06.2015 um 18:13 schrieb Pascal J. Bourguignon:
> Andreas, you might be interested in reading:
>
> https://www.ics.uci.edu/~taylor/ics228/SynGen.pdf
>
> and
>
>      Teitelbaum, T.; T. Reps (September 1981). "The Cornell Program
>      Synthesizer: A syntax-directed programming
>      environment". Communications of the ACM 24 (9):
>      563–573. doi:10.1145/358746.358755.
>
> if you can get your hands on it.
>
> Check also: https://en.wikipedia.org/wiki/Structure_editor
>
> Basically, you could generate the whole mode all the structured editing
> commands, from a grammar of the language you want to edit.
>
> And since you could include in the grammar, grammars of other languages
> when you have such escape, such as html scripts, or php, etc, you would
> get automatically "multi-mode" structured editing modes.
>
>
> Now, when you generate code (eg. a programming language compiler), it is
> perfectly normal to have parts that are generated, and functions and
> stubs that are written once for all for all the programs: a run-time
> library.
>
> Your code generate would naturally bind mode commands whose name would
> be prefixed by the name of the grammar (= the mode), but the run-time
> library would be the same for all those generated mode, and would have a
> library prefix instead.
>

Thanks. Will not dig into further here, as it's a vast area - let's go 
back to the real thing :)




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

* Re: Defining  functions on the fly
       [not found]     ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org>
@ 2015-06-16 22:23       ` Stefan Monnier
  2015-06-17  6:13         ` Andreas Röhler
       [not found]         ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 43+ messages in thread
From: Stefan Monnier @ 2015-06-16 22:23 UTC (permalink / raw)
  To: help-gnu-emacs

> Currently Emacs provides some scheme to fontify source code and some basic
> moves: linewise, symbol, word, paragraph, sexp.
> There is no idea of statement, block/loop or expression and a poor
> top-level --beginning/end-of-defun.

Since we don't need to define functions dynamically for "linewise,
symbol, word, paragraph, sexp", I don't see how "statement, block/loop
or expression and a poor top-level --beginning/end-of-defun" would
require dynamic definition of functions.
IOW, I still don't really see what you're trying to do.


        Stefan


BTW: For languages that use SMIE, the sexp movement typically moves by
statement/subexpressions.


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

* Re: Defining  functions on the fly
       [not found]         ` <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org>
@ 2015-06-16 22:32           ` Stefan Monnier
  0 siblings, 0 replies; 43+ messages in thread
From: Stefan Monnier @ 2015-06-16 22:32 UTC (permalink / raw)
  To: help-gnu-emacs

> Expect sexp-navigation behaving the the following way:
> - if inside a form, go to the end resp. start
> - if at end of form, forward same level if form exist, or get level
> following point, or EOB
> - if at beginning of form, backward same level if form exist, or get level
> preceding point, or BOB

Indeed, the for/backward-sexp function is rather low-level (it's a bit
more focused on Elisp usage than on interactive usage) and it's very
reasonable to want to provide higher-level commands on top of it, that
"do what I mean" in more cases.


        Stefan


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

* Re: Defining  functions on the fly
       [not found]                 ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org>
@ 2015-06-16 22:34                   ` Stefan Monnier
  0 siblings, 0 replies; 43+ messages in thread
From: Stefan Monnier @ 2015-06-16 22:34 UTC (permalink / raw)
  To: help-gnu-emacs

> while goto-end/start of string is missing.

I think these would map naturally to a dwimish extension of
(backward-)up-list.  Actually, IIRC expand-region provides exactly that.


        Stefan


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

* Re: Defining  functions on the fly
  2015-06-16  1:14   ` Stefan Monnier
@ 2015-06-17  0:24     ` Gene
  2015-06-17  1:12       ` Stefan Monnier
  0 siblings, 1 reply; 43+ messages in thread
From: Gene @ 2015-06-17  0:24 UTC (permalink / raw)
  To: help-gnu-emacs

On Monday, June 15, 2015 at 9:14:56 PM UTC-4, Stefan Monnier wrote:
> > (fset (function name-of-function)
> [...]
> > (define name-of-function
> 
> Actually, `fset' is more like Scheme's `set!',

How so?
`define' is typically used if or when a symbol has yet to be bound to either a lambda function or value.
set! is used to destructively re-bind something to a symbol already bound to something.

> so if it's the *definition* of a function, you should use `defalias' 
> which is more like Scheme's `define'.

I don't see it that way, but if works to one's satisfaction then why not?

I've taken to developing functions via lambda, then -- when I've got things hammered out the way I want them I use fset -- typically insight a wrapper in which the name of the function is available as, say, `func-name' to programmatically name the previously anonymous function.

(let ; function forge
(
 (func-name 
  (quote 
    non-anon ; arbitrary name.  We could have used `gensym' to have emacs generate a symbol for us
 ))
)

(fset func-name
 (lambda
  (
   arg1 ; we can document the arg name this way
   arg2 ; This is a seperate line to document this arg
  )
  "docstring"
   (list arg1 arg2)
  );lambda
 );fset
 
 ;
  (if (functionp func-name) 
   (symbol-function func-name)
   (message (concat "function " func-name " not defined"))
  )

) ;let

> 
> 
>         Stefan

I tend to use defalias for functions which already have names.
When I'm dreaming up a new name which doesn't collide with an extant named function known to function-name space I have no problem with using fset as if scheme's `define' as per a pristine, virgin binding.

Gene


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

* Re: Defining  functions on the fly
  2015-06-17  0:24     ` Gene
@ 2015-06-17  1:12       ` Stefan Monnier
  0 siblings, 0 replies; 43+ messages in thread
From: Stefan Monnier @ 2015-06-17  1:12 UTC (permalink / raw)
  To: help-gnu-emacs

>> > (fset (function name-of-function)
>> [...]
>> > (define name-of-function
>> Actually, `fset' is more like Scheme's `set!',

> How so?

Exactly in the sense you describe:

> `define' is typically used if or when a symbol has yet to be bound to
> either a lambda function or value.
> set! is used to destructively re-bind something to a symbol already
> bound to something.

`defun' macroexpands to `defalias' rather than to `fset'.

>> so if it's the *definition* of a function, you should use `defalias' 
>> which is more like Scheme's `define'.
> I don't see it that way, but if works to one's satisfaction then why not?

Actually, they don't do the same thing.  E.g. fset will throw
away/override any advice you may have applied to that function, whereas
defalias will combine the new definition with the pieces of advice.


        Stefan


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

* Re: Defining  functions on the fly
  2015-06-16 22:23       ` Stefan Monnier
@ 2015-06-17  6:13         ` Andreas Röhler
       [not found]         ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-17  6:13 UTC (permalink / raw)
  To: help-gnu-emacs


Am 17.06.2015 um 00:23 schrieb Stefan Monnier:
>> Currently Emacs provides some scheme to fontify source code and some basic
>> moves: linewise, symbol, word, paragraph, sexp.
>> There is no idea of statement, block/loop or expression and a poor
>> top-level --beginning/end-of-defun.
> Since we don't need to define functions dynamically for "linewise,
> symbol, word, paragraph, sexp",

These are very basic things based on character-syntax tables.
Expression is limited that way - see the difficulties around 
triple-quoted-string.

> I don't see how "statement, block/loop
> or expression and a poor top-level --beginning/end-of-defun" would
> require dynamic definition of functions.

Because these functions depend on grammar of the goal-language.


[ ... ]




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

* Re: Defining  functions on the fly
       [not found]         ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org>
@ 2015-06-17 14:30           ` Stefan Monnier
  2015-06-17 16:40             ` Andreas Röhler
  0 siblings, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2015-06-17 14:30 UTC (permalink / raw)
  To: help-gnu-emacs

> Because these functions depend on grammar of the goal-language.

Indeed, that's why forward-sexp is supplemented by
forward-sexp-function, making it possible for the major mode to provide
an implementation that does a more sophisticated sort of parsing than
that supported by plain old syntax-tables.


        Stefan


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

* Re: Defining  functions on the fly
  2015-06-17 14:30           ` Stefan Monnier
@ 2015-06-17 16:40             ` Andreas Röhler
  0 siblings, 0 replies; 43+ messages in thread
From: Andreas Röhler @ 2015-06-17 16:40 UTC (permalink / raw)
  To: help-gnu-emacs


Am 17.06.2015 um 16:30 schrieb Stefan Monnier:
>> Because these functions depend on grammar of the goal-language.
> Indeed, that's why forward-sexp is supplemented by
> forward-sexp-function, making it possible for the major mode to provide
> an implementation that does a more sophisticated sort of parsing than
> that supported by plain old syntax-tables.
>
>
>          Stefan

BTW you may remember a discussion around beginning-of-defun resp. 
beginning-of-defun-raw.
The point was: once a beginning-of-defun-function is set by a language, 
let it go with it, don't interfere.



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

end of thread, other threads:[~2015-06-17 16:40 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-15  9:24 Defining functions on the fly Andreas Röhler
2015-06-15  9:32 ` Dmitry Gutov
2015-06-15  9:47 ` Alexis
2015-06-15 10:20   ` Andreas Röhler
2015-06-15 10:37     ` Alexis
2015-06-15 10:41     ` Michael Heerdegen
2015-06-15 10:42     ` Tassilo Horn
2015-06-15 11:01       ` Alexis
2015-06-15 11:19       ` Michael Heerdegen
2015-06-15 11:24         ` Tassilo Horn
2015-06-15 11:31           ` Michael Heerdegen
2015-06-15 10:00 ` Tassilo Horn
2015-06-15 10:33   ` Andreas Röhler
     [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org>
2015-06-15 12:52   ` Stefan Monnier
2015-06-16  5:59     ` Andreas Röhler
2015-06-16  7:01       ` Tassilo Horn
2015-06-16  9:22         ` Andreas Röhler
2015-06-16 11:12           ` Tassilo Horn
2015-06-16 11:40             ` Andreas Röhler
2015-06-16 13:10               ` Tassilo Horn
2015-06-16 15:46                 ` Andreas Röhler
     [not found]                 ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org>
2015-06-16 22:34                   ` Stefan Monnier
     [not found]             ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org>
2015-06-16 16:13               ` Pascal J. Bourguignon
2015-06-16 18:30                 ` Andreas Röhler
2015-06-16  9:42         ` Andreas Röhler
     [not found]         ` <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org>
2015-06-16  9:50           ` Pascal J. Bourguignon
2015-06-16 10:26             ` Andreas Röhler
     [not found]             ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org>
2015-06-16 11:35               ` Pascal J. Bourguignon
     [not found]         ` <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org>
2015-06-16 22:32           ` Stefan Monnier
     [not found]     ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org>
2015-06-16 22:23       ` Stefan Monnier
2015-06-17  6:13         ` Andreas Röhler
     [not found]         ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org>
2015-06-17 14:30           ` Stefan Monnier
2015-06-17 16:40             ` Andreas Röhler
     [not found] <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org>
2015-06-15  9:57 ` Pascal J. Bourguignon
2015-06-15 11:21   ` Andreas Röhler
2015-06-15 11:52     ` Tassilo Horn
2015-06-15 12:06       ` Andreas Röhler
2015-06-15 12:43       ` Andreas Röhler
2015-06-15 23:51 ` Gene
2015-06-16  1:14   ` Stefan Monnier
2015-06-17  0:24     ` Gene
2015-06-17  1:12       ` Stefan Monnier
2015-06-16  5:47   ` Andreas Röhler

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