unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Brittleness of called-interactively-p
@ 2015-07-12  5:00 Dmitri Paduchikh
  2015-07-12 13:53 ` Stefan Monnier
                   ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-12  5:00 UTC (permalink / raw)
  To: emacs-devel

Hello,

The documentation string of called-interactively-p states this:

> This function is very brittle, it may fail to return the intended result
> when the code is debugged, advised, or instrumented in some form. Some
> macros and special forms (such as `condition-case') may also sometimes
> wrap their bodies in a `lambda', so any call to `called-interactively-p'
> from those bodies will indicate whether that lambda (rather than the
> surrounding function) was called interactively.

I would like to make a suggestion. All these problems can be resolved by
introducing a special (dynamically bound) variable. Each call -- not only
interactive -- to an interactive function would rebind it to the value
providing all the necessary information about interactiveness of this call.
The called-interactively-p function would simply return this value. Of
course, this will change the meaning of called-interactively-p inside the
usual functions without interactive form, but previously it didn't make
sense to check called-interactively-p inside such functions anyway, so the
change shouldn't cause problems with existing code.

This will allow using called-interactively-p in those cases when changing of
function signature is undesirable for some reasons. For example, when
interactivity of call is insignificant for function interface and you don't
want to compromise the cleanness of function signature for such a little
reason. Or inside advices, when overriding function signature is undesirable
for compatibility reasons. And it even makes provision for some new uses,
e.g. inside function hooks.

Sorry if this idea has already been discussed here.



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

* Re: Brittleness of called-interactively-p
  2015-07-12  5:00 Brittleness of called-interactively-p Dmitri Paduchikh
@ 2015-07-12 13:53 ` Stefan Monnier
  2015-07-12 15:17   ` Dmitri Paduchikh
  2015-07-18 22:29   ` raman
  2015-07-12 21:59 ` Richard Stallman
  2015-07-17 20:35 ` Przemysław Wojnowski
  2 siblings, 2 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-07-12 13:53 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

> I would like to make a suggestion. All these problems can be resolved by
> introducing a special (dynamically bound) variable. Each call -- not only
> interactive -- to an interactive function would rebind it to the value
> providing all the necessary information about interactiveness of this call.

That's pretty much what we do.  It still breaks down when you
debug/advise it.


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-12 13:53 ` Stefan Monnier
@ 2015-07-12 15:17   ` Dmitri Paduchikh
  2015-07-12 23:26     ` Stefan Monnier
  2015-07-18 22:29   ` raman
  1 sibling, 1 reply; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-12 15:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> I would like to make a suggestion. All these problems can be resolved by
>> introducing a special (dynamically bound) variable. Each call -- not only
>> interactive -- to an interactive function would rebind it to the value
>> providing all the necessary information about interactiveness of this call.

SM> That's pretty much what we do.

No. Currently, called-interactively-p "returns t if the containing function
was called by `call-interactively'." I argue that functions not having
interactive form should not have effect on return value.



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

* Re: Brittleness of called-interactively-p
  2015-07-12  5:00 Brittleness of called-interactively-p Dmitri Paduchikh
  2015-07-12 13:53 ` Stefan Monnier
@ 2015-07-12 21:59 ` Richard Stallman
  2015-07-13 15:17   ` Dmitri Paduchikh
  2015-07-17 20:35 ` Przemysław Wojnowski
  2 siblings, 1 reply; 35+ messages in thread
From: Richard Stallman @ 2015-07-12 21:59 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > This function is very brittle, it may fail to return the intended result
  > when the code is debugged, advised, or instrumented in some form. Some
  > macros and special forms (such as `condition-case') may also sometimes
  > wrap their bodies in a `lambda', so any call to `called-interactively-p'
  > from those bodies will indicate whether that lambda (rather than the
  > surrounding function) was called interactively.

This is simply a bug.  We should fix it to work with the debugger,
and programs that advise or instrument code should have a documented
way to arrange for 'called-interactively-p' to keep working.

  > I would like to make a suggestion. All these problems can be resolved by
  > introducing a special (dynamically bound) variable. Each call -- not only
  > interactive -- to an interactive function would rebind it to the value
  > providing all the necessary information about interactiveness of this call.

This could work, but it would use the specpdl in an inefficient way,
making many bindings that will never be used.

There is also a speed issue: every function call would need to check
whether the called function has an interactive spec.  But maybe it won't
be very bad.

Here's another approach: give 'interactive' a way to specify a
variable to bind for this purpose.  That way, the variable would be
bound only in functions that want it, and it would not interfere with
the function's calling interface.

The variable could be written as the second argument of 'interactive'.

If we want to preserve the principle that 'interactive' has no effect
on actual execution of a call to the function, we could make a new
name so that (was-interactive foo) in the function body binds foo to a
suitable value for the rest of the function body.

To get the right results when advising or instrumenting code, we could
define (advised-interactive foo) as an alternative to use in wrappers.

(defun foo (y)
  (interactive)
  (was-interactive in-foo)
  ...)

(lambda (x) (advised-interactive in-foo) (message "I am at foo") (foo x))

When the lambda gets called, 'advised-interactive' will bind 'in-foo'
to say whether the call was interactive, and it will suppress the
'was-interactive' form in 'foo' from binding 'in-foo' (because they
bind the same variable).

We could also write them as

  (was-interactive (VAR) BODY...)
  (advised-interactive (VAR) BODY...)

This is cleaner in that the scope of VAR is shown explicitly,
but people would be surprised that these don't work when
nested inside any other construct.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




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

* Re: Brittleness of called-interactively-p
  2015-07-12 15:17   ` Dmitri Paduchikh
@ 2015-07-12 23:26     ` Stefan Monnier
  2015-07-13 15:17       ` Dmitri Paduchikh
  0 siblings, 1 reply; 35+ messages in thread
From: Stefan Monnier @ 2015-07-12 23:26 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

>>> I would like to make a suggestion. All these problems can be resolved by
>>> introducing a special (dynamically bound) variable. Each call -- not only
>>> interactive -- to an interactive function would rebind it to the value
>>> providing all the necessary information about interactiveness of this call.
SM> That's pretty much what we do.
> No. Currently, called-interactively-p "returns t if the containing function
> was called by `call-interactively'." I argue that functions not having
> interactive form should not have effect on return value.

You might be able to exploit this "ignore non-interactive functions" to
make the current code more robust, indeed.  It might be reasonably easy,
e.g. replace

  (memq (nth 1 frame) '(interactive-p 'byte-code))

with something like (not (commandp (nth 1 frame)).  But note that the
situation for advised functions is still tricky: the outer advice is called
with funcall-interactively (and it interactive) but inner advices and the
original function are always called with `apply' or `funcall' rather
than with funcall-interactively, so called-interactively-p still has to
work harder to try and figure out that "the inner function is actually,
conceptually, called interactively, even though technically it's not".


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-12 21:59 ` Richard Stallman
@ 2015-07-13 15:17   ` Dmitri Paduchikh
  2015-07-13 23:03     ` Richard Stallman
  2015-08-06 22:36     ` Stefan Monnier
  0 siblings, 2 replies; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-13 15:17 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

RS> Here's another approach: give 'interactive' a way to specify a variable
RS> to bind for this purpose. That way, the variable would be bound only in
RS> functions that want it, and it would not interfere with the function's
RS> calling interface.

It is not clear for me whether this approach will help to solve the current
problem of macros wrapping fragments of code in lambdas.

[...]

RS> To get the right results when advising or instrumenting code, we could
RS> define (advised-interactive foo) as an alternative to use in wrappers.

RS> (defun foo (y)
RS>   (interactive)
RS>   (was-interactive in-foo)
RS>   ...)

RS> (lambda (x) (advised-interactive in-foo) (message "I am at foo") (foo x))

RS> When the lambda gets called, 'advised-interactive' will bind 'in-foo'
RS> to say whether the call was interactive, and it will suppress the
RS> 'was-interactive' form in 'foo' from binding 'in-foo' (because they
RS> bind the same variable).

If I understand right, an instrumenting code must be aware of the variable
name used internally by a function. That is, when writing defadvice I should
look inside foo in order to figure out that internally it's using in-foo,
and then add (advised-interactive in-foo) in the defadvice code. After this
I will be able to determine whether advised function was called
interactively or not. Is it right? If so then it doesn't seem very good
since coupling with the internal state isn't good.



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

* Re: Brittleness of called-interactively-p
  2015-07-12 23:26     ` Stefan Monnier
@ 2015-07-13 15:17       ` Dmitri Paduchikh
  2015-07-14 23:24         ` Stefan Monnier
                           ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-13 15:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

SM> You might be able to exploit this "ignore non-interactive functions" to
SM> make the current code more robust, indeed.  It might be reasonably easy,
SM> e.g. replace

SM>   (memq (nth 1 frame) '(interactive-p 'byte-code))

SM> with something like (not (commandp (nth 1 frame)).  But note that the
SM> situation for advised functions is still tricky: the outer advice is called
SM> with funcall-interactively (and it interactive) but inner advices and the
SM> original function are always called with `apply' or `funcall' rather
SM> than with funcall-interactively, so called-interactively-p still has to
SM> work harder to try and figure out that "the inner function is actually,
SM> conceptually, called interactively, even though technically it's not".

These calls are internal to the advice mechanism and, of course, they cannot
be considered conceptually interactive. Only the call to the whole advised
function matters if that function is interactive. Other advice-specific
calls should be ignored as well as calls to non-interactive functions. They
can be filtered out, for example, by labelling advice-specific symbols by
special property during advice creation and then checking for this property
inside called-interactively-p. Such symbols as ad-Advice-* are intended to
be used internally by advice only, so ignoring them inside
called-interactively-p should not cause much harm.



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

* Re: Brittleness of called-interactively-p
  2015-07-13 15:17   ` Dmitri Paduchikh
@ 2015-07-13 23:03     ` Richard Stallman
  2015-08-06 22:36     ` Stefan Monnier
  1 sibling, 0 replies; 35+ messages in thread
From: Richard Stallman @ 2015-07-13 23:03 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > If I understand right, an instrumenting code must be aware of the variable
  > name used internally by a function. That is, when writing defadvice I should
  > look inside foo in order to figure out that internally it's using in-foo,

Yes.  However, there needs to be a way to find that out
in order for calls to the function to bind that variable.

If we provide a convenient function to get that variable name, perhaps
called called-interactively-binding-variable, it will be easy
for advising and other instrumenters to do what is needed.

Advising has to do SOMETHING about this, because if the advice makes a
wrapper, and it is necessary for that wrapper to bind the variable (or
whatever is used) _instead_ of the original function.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




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

* Re: Brittleness of called-interactively-p
  2015-07-13 15:17       ` Dmitri Paduchikh
@ 2015-07-14 23:24         ` Stefan Monnier
  2015-07-16 15:57           ` raman
  2015-08-06 22:30         ` Stefan Monnier
  2015-08-06 22:33         ` Stefan Monnier
  2 siblings, 1 reply; 35+ messages in thread
From: Stefan Monnier @ 2015-07-14 23:24 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

> inside called-interactively-p. Such symbols as ad-Advice-* are intended to

There are no such symbols in the new advice system.


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-14 23:24         ` Stefan Monnier
@ 2015-07-16 15:57           ` raman
  2015-07-16 17:36             ` Drew Adams
  2015-07-16 22:55             ` Stefan Monnier
  0 siblings, 2 replies; 35+ messages in thread
From: raman @ 2015-07-16 15:57 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Dmitri Paduchikh, emacs-devel

Speaking from the perspective of developing Emacspeak:

Emacspeak uses the "is this an interactive call" heavily  -- it provides
spoken feedback only if the call is interactive. 

I originally implemented emacspeak starting in late 1994 and used the
test 
(when (interactive-p)...)
in all my code.

When interactive-p was deprecated and we moved to the new
called-interactive-p -- I was unable to get the behavior I wanted using
(called-interactive-p 'interactive) as  the test;  --  the code ended up
chasing its tail given the heavy use of advice.

I worked around the problem by defining my own version of the
interactive test -- see http://github.com/tvraman/emacspeak --
specifically the implementation of function ems-interactive-p.

-- 



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

* RE: Brittleness of called-interactively-p
  2015-07-16 15:57           ` raman
@ 2015-07-16 17:36             ` Drew Adams
  2015-07-16 17:58               ` T.V Raman
  2015-07-16 22:55             ` Stefan Monnier
  1 sibling, 1 reply; 35+ messages in thread
From: Drew Adams @ 2015-07-16 17:36 UTC (permalink / raw)
  To: raman, Stefan Monnier; +Cc: Dmitri Paduchikh, emacs-devel

> Speaking from the perspective of developing Emacspeak:
> 
> Emacspeak uses the "is this an interactive call" heavily  -- it provides
> spoken feedback only if the call is interactive.
> 
> I originally implemented emacspeak starting in late 1994 and used the
> test (when (interactive-p)...) in all my code.
> 
> When interactive-p was deprecated and we moved to the new
> called-interactive-p -- I was unable to get the behavior I wanted using
> (called-interactive-p 'interactive) as  the test;  --  the code ended up
> chasing its tail given the heavy use of advice.
> 
> I worked around the problem by defining my own version of the
> interactive test -- see http://github.com/tvraman/emacspeak --
> specifically the implementation of function ems-interactive-p.

You might want to say which of the many (!) files in that directory
contains the definition of `ems-interactive-p'.  And perhaps tell us
why you mention it and, in particular, what is the "behavior [you]
wanted", and why.  You mention that `called-interactively-p' doesn't
work well enough for you when advice is involved, but some more info
about `ems-interactive-p' might be helpful.

FWIW, I still use `interactive-p' in much of my code, because the code
needs to work also with older Emacs versions.  And because I have never
noticed any problem, for this code anyway, with `interactive-p'.

What's more, the doc for `interactive-p' does not really tell you how
to replace it - it just says to use `called-interactively-p', without
any mention of which argument gives you the behavior you had previously
with `interactive-p' or similar-but-somehow-improved behavior.

`interactive-p' was indeed used heavily, over decades.  And it is no
doubt still in use quite a bit.  Too bad there is next-to-no guidance
on how to use `called-interactively-p' to replace it.



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

* RE: Brittleness of called-interactively-p
  2015-07-16 17:36             ` Drew Adams
@ 2015-07-16 17:58               ` T.V Raman
  2015-07-17  1:55                 ` Richard Stallman
  0 siblings, 1 reply; 35+ messages in thread
From: T.V Raman @ 2015-07-16 17:58 UTC (permalink / raw)
  To: drew.adams; +Cc: dpaduchikh, emacs-devel, monnier, raman


Apologies, the emacspeak implementation of  ems-interactive-p is in 
lisp/emacspeak-load-path.el it's fairly short and I'll append it here.

Re what failed with called-interactive-p -- from memory,  things like
ruby-mode that use backward-sexp internally during editting started
entering a recursive loop in that the emacspeak advice kept triggering
(and itself called backward-sexp again ) -- that was technically not
supposed to happen since the  advice was guarded by a
called-interactively-p check.

(defvar ems-called-interactively-p nil
  "Flag recording interactive calls.")

;; Record interactive calls:

(defsubst ems-record-interactive-p (f)
  "Predicate to test if we need to record interactive calls of
this function. Memoizes result for future use by placing a
property 'emacspeak on the function."
  (cond
   ((not (symbolp f)) nil)
   ((get f 'emacspeak) t)
   ((ad-find-some-advice f 'any  "emacspeak")
    (put f 'emacspeak t))
   ((string-match "^\\(dt\\|emacspea\\)k" (symbol-name f))
    (put f 'emacspeak t))
   (t nil)))

(defadvice call-interactively (around emacspeak  pre act comp)
  "Set emacspeak  interactive flag if there is an advice."
  (let ((ems-called-interactively-p ems-called-interactively-p))
    (when (ems-record-interactive-p (ad-get-arg 0))
      (setq ems-called-interactively-p (ad-get-arg 0)))
    ad-do-it))

(defsubst ems-interactive-p ()
  "Check our interactive flag.
Return T if set and we are called from the advice for the current
interactive command. Turn off the flag once used."
  (when ems-called-interactively-p      ; interactive call
    (let ((caller (second (backtrace-frame 1)))
          (caller-advice (ad-get-advice-info-field ems-called-interactively-p  'advicefunname))
          (result nil))
      (setq result
            (or (eq caller caller-advice) ; called from our advice
                (eq ems-called-interactively-p caller ))) ; called from call-interactively
      (when result
        (setq ems-called-interactively-p nil) ; turn off now that we used  it
        result))))

Drew Adams writes:
 > > Speaking from the perspective of developing Emacspeak:
 > > 
 > > Emacspeak uses the "is this an interactive call" heavily  -- it provides
 > > spoken feedback only if the call is interactive.
 > > 
 > > I originally implemented emacspeak starting in late 1994 and used the
 > > test (when (interactive-p)...) in all my code.
 > > 
 > > When interactive-p was deprecated and we moved to the new
 > > called-interactive-p -- I was unable to get the behavior I wanted using
 > > (called-interactive-p 'interactive) as  the test;  --  the code ended up
 > > chasing its tail given the heavy use of advice.
 > > 
 > > I worked around the problem by defining my own version of the
 > > interactive test -- see http://github.com/tvraman/emacspeak --
 > > specifically the implementation of function ems-interactive-p.
 > 
 > You might want to say which of the many (!) files in that directory
 > contains the definition of `ems-interactive-p'.  And perhaps tell us
 > why you mention it and, in particular, what is the "behavior [you]
 > wanted", and why.  You mention that `called-interactively-p' doesn't
 > work well enough for you when advice is involved, but some more info
 > about `ems-interactive-p' might be helpful.
 > 
 > FWIW, I still use `interactive-p' in much of my code, because the code
 > needs to work also with older Emacs versions.  And because I have never
 > noticed any problem, for this code anyway, with `interactive-p'.
 > 
 > What's more, the doc for `interactive-p' does not really tell you how
 > to replace it - it just says to use `called-interactively-p', without
 > any mention of which argument gives you the behavior you had previously
 > with `interactive-p' or similar-but-somehow-improved behavior.
 > 
 > `interactive-p' was indeed used heavily, over decades.  And it is no
 > doubt still in use quite a bit.  Too bad there is next-to-no guidance
 > on how to use `called-interactively-p' to replace it.

-- 

-- 



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

* Re: Brittleness of called-interactively-p
  2015-07-16 15:57           ` raman
  2015-07-16 17:36             ` Drew Adams
@ 2015-07-16 22:55             ` Stefan Monnier
  2015-07-17 18:10               ` raman
  2015-07-18  4:39               ` Dmitri Paduchikh
  1 sibling, 2 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-07-16 22:55 UTC (permalink / raw)
  To: raman; +Cc: Dmitri Paduchikh, emacs-devel

> When interactive-p was deprecated and we moved to the new
> called-interactive-p -- I was unable to get the behavior I wanted using
> (called-interactive-p 'interactive) as  the test;

Are you sure?

(interactive-p) is 99.9% equivalent to (called-interactively-p
'interactive), including interactions with advice and whatnot.
More recently both functions have been reimplemented, and the new
implementation should work about as well as the old one in most cases.
The new advice library interacts differently (and that appeared
at the same time as the new called-interactively-p implementation), so
that can be mistaken as a consequence of the new called-interactively-p
implementation, but mostly the new implementation of
called-interactively-p mostly handles more cases.


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-16 17:58               ` T.V Raman
@ 2015-07-17  1:55                 ` Richard Stallman
  2015-07-17  4:52                   ` Dmitri Paduchikh
  2015-07-17 18:14                   ` raman
  0 siblings, 2 replies; 35+ messages in thread
From: Richard Stallman @ 2015-07-17  1:55 UTC (permalink / raw)
  To: T.V Raman; +Cc: dpaduchikh, raman, monnier, drew.adams, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

What is the behavior you want from ems-interactively-p?
That implementation is ad-hoc and not the way we'd want to do it,
but we need to give you what you need.  Ideally we should make
called-interactively-p work correctly for you.

Can you try using called-interactively-p and provide a bug report
showing concretely how it fails?

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




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

* Re: Brittleness of called-interactively-p
  2015-07-17  1:55                 ` Richard Stallman
@ 2015-07-17  4:52                   ` Dmitri Paduchikh
  2015-07-17 13:36                     ` Dmitri Paduchikh
  2015-07-17 18:15                     ` raman
  2015-07-17 18:14                   ` raman
  1 sibling, 2 replies; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-17  4:52 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel, monnier, drew.adams, T.V Raman

Richard Stallman <rms@gnu.org> writes:

RS> Can you try using called-interactively-p and provide a bug report
RS> showing concretely how it fails?

The following is probably similar to what T. V. Raman describes.

Debugger entered--Lisp error: (quit)
  funcall((closure ((i . 11809182) (frame2) (frame1) (origi . 3) t) nil (setq frame1 frame2) (setq frame2 (backtrace-frame i (function called-interactively-p))) (setq i (1+ i))))
  (progn (funcall get-next-frame) (not (and (eq (nth 1 frame2) (quote apply)) (eq (nth 3 frame2) inneradvice))))
  (while (progn (funcall get-next-frame) (not (and (eq (nth 1 frame2) (quote apply)) (eq (nth 3 frame2) inneradvice)))))
  (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p (indirect-function (nth 1 frame2))))) (funcall get-next-frame) (while (progn (funcall get-next-frame) (not (and (eq (nth 1 frame2) (quote apply)) (eq (nth 3 frame2) inneradvice))))) (funcall get-next-frame) (funcall get-next-frame))
  (let ((inneradvice (nth 1 frame1))) (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p (indirect-function (nth 1 frame2))))) (funcall get-next-frame) (while (progn (funcall get-next-frame) (not (and (eq (nth 1 frame2) (quote apply)) (eq (nth 3 frame2) inneradvice))))) (funcall get-next-frame) (funcall get-next-frame)))
  (while (advice--p (nth 1 frame1)) (let ((inneradvice (nth 1 frame1))) (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p (indirect-function (nth 1 frame2))))) (funcall get-next-frame) (while (progn (funcall get-next-frame) (not (and (eq ... ...) (eq ... inneradvice))))) (funcall get-next-frame) (funcall get-next-frame))))
  (progn (funcall get-next-frame) (while (advice--p (nth 1 frame1)) (let ((inneradvice (nth 1 frame1))) (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p (indirect-function ...)))) (funcall get-next-frame) (while (progn (funcall get-next-frame) (not (and ... ...)))) (funcall get-next-frame) (funcall get-next-frame)))) (- i origi 1))
  (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p (indirect-function (nth 1 frame2))))) (progn (funcall get-next-frame) (while (advice--p (nth 1 frame1)) (let ((inneradvice (nth 1 frame1))) (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p ...))) (funcall get-next-frame) (while (progn (funcall get-next-frame) (not ...))) (funcall get-next-frame) (funcall get-next-frame)))) (- i origi 1)))
  (let* ((i origi) (get-next-frame (function (lambda nil (setq frame1 frame2) (setq frame2 (backtrace-frame i (function called-interactively-p))) (setq i (1+ i)))))) (if (and (eq (nth 1 frame2) (quote apply)) (progn (funcall get-next-frame) (advice--p (indirect-function (nth 1 frame2))))) (progn (funcall get-next-frame) (while (advice--p (nth 1 frame1)) (let ((inneradvice (nth 1 frame1))) (if (and (eq ... ...) (progn ... ...)) (funcall get-next-frame) (while (progn ... ...)) (funcall get-next-frame) (funcall get-next-frame)))) (- i origi 1))))
  advice--called-interactively-skip(3 (t ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1) (t apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1))
  run-hook-with-args-until-success(advice--called-interactively-skip 3 (t ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1) (t apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1))
  called-interactively-p(interactive)
  ad-Advice-backward-sexp(#[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1)
  apply(ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1)
  #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"](1)
  #[0 "\300\301!\210\302\207" [#[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] 1 nil] 2 "\n\n(fn)"]()
  funcall(#[0 "\300\301!\210\302\207" [#[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] 1 nil] 2 "\n\n(fn)"])
  #[0 "\304\242;\205.\0\306\304\242.\"AC\304\307\240\210`\300 \306.\r\"A\211\204X.\310.G!\203$.\311\312\313\314\315\316\317\301!\320\"\321\322%D\323\312\313\324\325\316\317.\v!\326\"\327\330%\311EDC\217\210.`=\203$.\331\332\333`D\"\210\202$.\303.!\247\204t.\302.!\247\204l.\334\335\336C\"\210\211.B\262.\202$.\x03\203\212.\303.!\302.@!W\203\212.\x03A\262.\202t.\x03\204\266.\304\242\203\242.\302.!\247\203\242.\211.B\262.\202$.\331\332\302.!\206\253.\333`.E.b\210\"\210\202$.\x03\211\203\313.\303.!\302.\x06@!U\203\313.\x04A\262.\x04\203\336.\302.!\247\203#.\x01.B\262.\202#.\302.!\247\204\361.\331\332\307`.\x06E\"\210\202#.\337.!\204\377.\x01.B\262.\202#.\211\203 .\337.@!\203 .\331\332\302.!\206.\x01\333`.\x06E.\x06b\210\"\210\202#.\211\262.\210.\266\203\2051.\304\307\240\210\202.\0\207" [#[0 "\304 \305`[!\210n\203*.o\204*.\306`S!\307\232\203*.\310\311 8\204*.\312.\313\314!\210)\315\202\225.`.W\203K.\316 \203=.\314u\210	 \202\225.\317 \203F.\315\202\225.	 \202\225.\320\n\304 \321#\203^.\322\224b\210\323\322!\202\225.\324 \211\325\232\203j.\326\202\223.\211\327\232\203t.\330\202\223.\211\203\222.\331\332.\"\203\222.\333.\v\"\203\222.\212\334.!)\204\222.\335\202\223.\211\262.\207" [forward-sexp-function smie-backward-token-function sh-smie--sh-operators-back-re smie-grammar line-beginning-position forward-comment syntax-after (15) 3 syntax-ppss nil forward-sexp -1 ";" sh-smie--looking-back-at-continuation-p sh-smie--newline-semi-p looking-back greedy 1 match-string-no-properties sh-smie--default-backward-token ")" "case-)" "(" "case-(" string-match "\\`[a-z]" assoc sh-smie--sh-keyword-p " word "] 5 "\n\n(fn)"] #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] #<subr car> #[257 "\211A@\207" [] 2 1636664] (halfsexp) smie-grammar assoc nil zerop err funcall make-byte-code 0 "\300\301!\210\302\207" vconcat vector [1 nil] 2 "\n\n(fn)" scan-error 257 "\301.8`.X\203.\0\302.8\202.\0\211\300b\210\303\304\305.\306.\211`.\bW\203%.\307\202&.\310\\\"E\"\207" [2 3 throw return t buffer-substring-no-properties -1 1] 12 "\n\n(fn ERR)" throw return t signal cl-assertion-failed (numberp (funcall op-forw toklevels)) smie--associative-p] 14 "\n\n(fn)"]()
  funcall(#[0 "\304\242;\205.\0\306\304\242.\"AC\304\307\240\210`\300 \306.\r\"A\211\204X.\310.G!\203$.\311\312\313\314\315\316\317\301!\320\"\321\322%D\323\312\313\324\325\316\317.\v!\326\"\327\330%\311EDC\217\210.`=\203$.\331\332\333`D\"\210\202$.\303.!\247\204t.\302.!\247\204l.\334\335\336C\"\210\211.B\262.\202$.\x03\203\212.\303.!\302.@!W\203\212.\x03A\262.\202t.\x03\204\266.\304\242\203\242.\302.!\247\203\242.\211.B\262.\202$.\331\332\302.!\206\253.\333`.E.b\210\"\210\202$.\x03\211\203\313.\303.!\302.\x06@!U\203\313.\x04A\262.\x04\203\336.\302.!\247\203#.\x01.B\262.\202#.\302.!\247\204\361.\331\332\307`.\x06E\"\210\202#.\337.!\204\377.\x01.B\262.\202#.\211\203 .\337.@!\203 .\331\332\302.!\206.\x01\333`.\x06E.\x06b\210\"\210\202#.\211\262.\210.\266\203\2051.\304\307\240\210\202.\0\207" [#[0 "\304 \305`[!\210n\203*.o\204*.\306`S!\307\232\203*.\310\311 8\204*.\312.\313\314!\210)\315\202\225.`.W\203K.\316 \203=.\314u\210	 \202\225.\317 \203F.\315\202\225.	 \202\225.\320\n\304 \321#\203^.\322\224b\210\323\322!\202\225.\324 \211\325\232\203j.\326\202\223.\211\327\232\203t.\330\202\223.\211\203\222.\331\332.\"\203\222.\333.\v\"\203\222.\212\334.!)\204\222.\335\202\223.\211\262.\207" [forward-sexp-function smie-backward-token-function sh-smie--sh-operators-back-re smie-grammar line-beginning-position forward-comment syntax-after (15) 3 syntax-ppss nil forward-sexp -1 ";" sh-smie--looking-back-at-continuation-p sh-smie--newline-semi-p looking-back greedy 1 match-string-no-properties sh-smie--default-backward-token ")" "case-)" "(" "case-(" string-match "\\`[a-z]" assoc sh-smie--sh-keyword-p " word "] 5 "\n\n(fn)"] #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] #<subr car> #[257 "\211A@\207" [] 2 1636664] (halfsexp) smie-grammar assoc nil zerop err funcall make-byte-code 0 "\300\301!\210\302\207" vconcat vector [1 nil] 2 "\n\n(fn)" scan-error 257 "\301.8`.X\203.\0\302.8\202.\0\211\300b\210\303\304\305.\306.\211`.\bW\203%.\307\202&.\310\\\"E\"\207" [2 3 throw return t buffer-substring-no-properties -1 1] 12 "\n\n(fn ERR)" throw return t signal cl-assertion-failed (numberp (funcall op-forw toklevels)) smie--associative-p] 14 "\n\n(fn)"])
  smie-next-sexp(#[0 "\304 \305`[!\210n\203*.o\204*.\306`S!\307\232\203*.\310\311 8\204*.\312.\313\314!\210)\315\202\225.`.W\203K.\316 \203=.\314u\210	 \202\225.\317 \203F.\315\202\225.	 \202\225.\320\n\304 \321#\203^.\322\224b\210\323\322!\202\225.\324 \211\325\232\203j.\326\202\223.\211\327\232\203t.\330\202\223.\211\203\222.\331\332.\"\203\222.\333.\v\"\203\222.\212\334.!)\204\222.\335\202\223.\211\262.\207" [forward-sexp-function smie-backward-token-function sh-smie--sh-operators-back-re smie-grammar line-beginning-position forward-comment syntax-after (15) 3 syntax-ppss nil forward-sexp -1 ";" sh-smie--looking-back-at-continuation-p sh-smie--newline-semi-p looking-back greedy 1 match-string-no-properties sh-smie--default-backward-token ")" "case-)" "(" "case-(" string-match "\\`[a-z]" assoc sh-smie--sh-keyword-p " word "] 5 "\n\n(fn)"] #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] #<subr car> #[257 "\211A@\207" [] 2 1636664] halfsexp)
  smie-backward-sexp(halfsexp)
  smie-forward-sexp-command(-1)
  #[256 "\211\204\a.\301\262.\b\203.\0\b.!\207\302`.\"\206.\0\303.!b\210\211\304W\205#.\305 \207" [forward-sexp-function 1 scan-sexps buffer-end 0 backward-prefix-chars] 4 2389495 "^p"](-1)
  ad-Advice-forward-sexp(#[256 "\211\204\a.\301\262.\b\203.\0\b.!\207\302`.\"\206.\0\303.!b\210\211\304W\205#.\305 \207" [forward-sexp-function 1 scan-sexps buffer-end 0 backward-prefix-chars] 4 2389495 "^p"] -1)
  apply(ad-Advice-forward-sexp #[256 "\211\204\a.\301\262.\b\203.\0\b.!\207\302`.\"\206.\0\303.!b\210\211\304W\205#.\305 \207" [forward-sexp-function 1 scan-sexps buffer-end 0 backward-prefix-chars] 4 2389495 "^p"] -1)
  forward-sexp(-1)
  #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"](1)
  ad-Advice-backward-sexp(#[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1)
  apply(ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] 1)
  #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"](1)
  #[0 "\300\301!\210\302\207" [#[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] 1 nil] 2 "\n\n(fn)"]()
  funcall(#[0 "\300\301!\210\302\207" [#[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] 1 nil] 2 "\n\n(fn)"])
  #[0 "\304\242;\205.\0\306\304\242.\"AC\304\307\240\210`\300 \306.\r\"A\211\204X.\310.G!\203$.\311\312\313\314\315\316\317\301!\320\"\321\322%D\323\312\313\324\325\316\317.\v!\326\"\327\330%\311EDC\217\210.`=\203$.\331\332\333`D\"\210\202$.\303.!\247\204t.\302.!\247\204l.\334\335\336C\"\210\211.B\262.\202$.\x03\203\212.\303.!\302.@!W\203\212.\x03A\262.\202t.\x03\204\266.\304\242\203\242.\302.!\247\203\242.\211.B\262.\202$.\331\332\302.!\206\253.\333`.E.b\210\"\210\202$.\x03\211\203\313.\303.!\302.\x06@!U\203\313.\x04A\262.\x04\203\336.\302.!\247\203#.\x01.B\262.\202#.\302.!\247\204\361.\331\332\307`.\x06E\"\210\202#.\337.!\204\377.\x01.B\262.\202#.\211\203 .\337.@!\203 .\331\332\302.!\206.\x01\333`.\x06E.\x06b\210\"\210\202#.\211\262.\210.\266\203\2051.\304\307\240\210\202.\0\207" [#[0 "\304 \305`[!\210n\203*.o\204*.\306`S!\307\232\203*.\310\311 8\204*.\312.\313\314!\210)\315\202\225.`.W\203K.\316 \203=.\314u\210	 \202\225.\317 \203F.\315\202\225.	 \202\225.\320\n\304 \321#\203^.\322\224b\210\323\322!\202\225.\324 \211\325\232\203j.\326\202\223.\211\327\232\203t.\330\202\223.\211\203\222.\331\332.\"\203\222.\333.\v\"\203\222.\212\334.!)\204\222.\335\202\223.\211\262.\207" [forward-sexp-function smie-backward-token-function sh-smie--sh-operators-back-re smie-grammar line-beginning-position forward-comment syntax-after (15) 3 syntax-ppss nil forward-sexp -1 ";" sh-smie--looking-back-at-continuation-p sh-smie--newline-semi-p looking-back greedy 1 match-string-no-properties sh-smie--default-backward-token ")" "case-)" "(" "case-(" string-match "\\`[a-z]" assoc sh-smie--sh-keyword-p " word "] 5 "\n\n(fn)"] #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] #<subr car> #[257 "\211A@\207" [] 2 1636664] (nil) smie-grammar assoc nil zerop err funcall make-byte-code 0 "\300\301!\210\302\207" vconcat vector [1 nil] 2 "\n\n(fn)" scan-error 257 "\301.8`.X\203.\0\302.8\202.\0\211\300b\210\303\304\305.\306.\211`.\bW\203%.\307\202&.\310\\\"E\"\207" [2 3 throw return t buffer-substring-no-properties -1 1] 12 "\n\n(fn ERR)" throw return t signal cl-assertion-failed (numberp (funcall op-forw toklevels)) smie--associative-p] 14 "\n\n(fn)"]()
  funcall(#[0 "\304\242;\205.\0\306\304\242.\"AC\304\307\240\210`\300 \306.\r\"A\211\204X.\310.G!\203$.\311\312\313\314\315\316\317\301!\320\"\321\322%D\323\312\313\324\325\316\317.\v!\326\"\327\330%\311EDC\217\210.`=\203$.\331\332\333`D\"\210\202$.\303.!\247\204t.\302.!\247\204l.\334\335\336C\"\210\211.B\262.\202$.\x03\203\212.\303.!\302.@!W\203\212.\x03A\262.\202t.\x03\204\266.\304\242\203\242.\302.!\247\203\242.\211.B\262.\202$.\331\332\302.!\206\253.\333`.E.b\210\"\210\202$.\x03\211\203\313.\303.!\302.\x06@!U\203\313.\x04A\262.\x04\203\336.\302.!\247\203#.\x01.B\262.\202#.\302.!\247\204\361.\331\332\307`.\x06E\"\210\202#.\337.!\204\377.\x01.B\262.\202#.\211\203 .\337.@!\203 .\331\332\302.!\206.\x01\333`.\x06E.\x06b\210\"\210\202#.\211\262.\210.\266\203\2051.\304\307\240\210\202.\0\207" [#[0 "\304 \305`[!\210n\203*.o\204*.\306`S!\307\232\203*.\310\311 8\204*.\312.\313\314!\210)\315\202\225.`.W\203K.\316 \203=.\314u\210	 \202\225.\317 \203F.\315\202\225.	 \202\225.\320\n\304 \321#\203^.\322\224b\210\323\322!\202\225.\324 \211\325\232\203j.\326\202\223.\211\327\232\203t.\330\202\223.\211\203\222.\331\332.\"\203\222.\333.\v\"\203\222.\212\334.!)\204\222.\335\202\223.\211\262.\207" [forward-sexp-function smie-backward-token-function sh-smie--sh-operators-back-re smie-grammar line-beginning-position forward-comment syntax-after (15) 3 syntax-ppss nil forward-sexp -1 ";" sh-smie--looking-back-at-continuation-p sh-smie--newline-semi-p looking-back greedy 1 match-string-no-properties sh-smie--default-backward-token ")" "case-)" "(" "case-(" string-match "\\`[a-z]" assoc sh-smie--sh-keyword-p " word "] 5 "\n\n(fn)"] #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] #<subr car> #[257 "\211A@\207" [] 2 1636664] (nil) smie-grammar assoc nil zerop err funcall make-byte-code 0 "\300\301!\210\302\207" vconcat vector [1 nil] 2 "\n\n(fn)" scan-error 257 "\301.8`.X\203.\0\302.8\202.\0\211\300b\210\303\304\305.\306.\211`.\bW\203%.\307\202&.\310\\\"E\"\207" [2 3 throw return t buffer-substring-no-properties -1 1] 12 "\n\n(fn ERR)" throw return t signal cl-assertion-failed (numberp (funcall op-forw toklevels)) smie--associative-p] 14 "\n\n(fn)"])
  smie-next-sexp(#[0 "\304 \305`[!\210n\203*.o\204*.\306`S!\307\232\203*.\310\311 8\204*.\312.\313\314!\210)\315\202\225.`.W\203K.\316 \203=.\314u\210	 \202\225.\317 \203F.\315\202\225.	 \202\225.\320\n\304 \321#\203^.\322\224b\210\323\322!\202\225.\324 \211\325\232\203j.\326\202\223.\211\327\232\203t.\330\202\223.\211\203\222.\331\332.\"\203\222.\333.\v\"\203\222.\212\334.!)\204\222.\335\202\223.\211\262.\207" [forward-sexp-function smie-backward-token-function sh-smie--sh-operators-back-re smie-grammar line-beginning-position forward-comment syntax-after (15) 3 syntax-ppss nil forward-sexp -1 ";" sh-smie--looking-back-at-continuation-p sh-smie--newline-semi-p looking-back greedy 1 match-string-no-properties sh-smie--default-backward-token ")" "case-)" "(" "case-(" string-match "\\`[a-z]" assoc sh-smie--sh-keyword-p " word "] 5 "\n\n(fn)"] #[128 "\300\301\302.#\207" [apply ad-Advice-backward-sexp #[256 "\211\204\a.\300\262.\301.[!\207" [1 forward-sexp] 3 2389807 "^p"] nil] 5 nil "^p"] #<subr car> #[257 "\211A@\207" [] 2 1636664] ";")
  smie-backward-sexp(";")
  smie-indent-keyword()
  run-hook-with-args-until-success(smie-indent-keyword)
  smie-indent-calculate()
  smie-indent-virtual()
  smie-indent-after-keyword()
  run-hook-with-args-until-success(smie-indent-after-keyword)
  smie-indent-calculate()
  #[0 "\212\301y\210\302\303w\210`\300\242Y\203.\0\300\303\240\210\304 \206.\0\301)\207" [(941) 0 " 	" nil smie-indent-calculate] 2 "\n\n(fn)"]()
  funcall(#[0 "\212\301y\210\302\303w\210`\300\242Y\203.\0\300\303\240\210\304 \206.\0\301)\207" [(941) 0 " 	" nil smie-indent-calculate] 2 "\n\n(fn)"])
  smie-indent-line()
  #[256 "\304 \203\f.\305\306 \307 \"\207\b\310=\204#.	\204'.i\311 V\204#.\n\v=\203'.\312.!\207\313 `\311 \b \210	\314=\203G.\x01`=\203G.\x02\313 =\203G.\315 \202r.\x03\205r.\212\316y\210\317 \210\320 )\311 .Z\212\321y\210\322.!?\205o.`.W\205o.\323`.\x03#)\266\202\207" [indent-line-function tab-always-indent this-command last-command use-region-p indent-region region-beginning region-end indent-to-left-margin current-indentation insert-tab buffer-chars-modified-tick complete completion-at-point 0 forward-sexp point-marker 1 zerop indent-rigidly] 10 2133678 "P"](nil)
  ad-Advice-indent-for-tab-command(#[256 "\304 \203\f.\305\306 \307 \"\207\b\310=\204#.	\204'.i\311 V\204#.\n\v=\203'.\312.!\207\313 `\311 \b \210	\314=\203G.\x01`=\203G.\x02\313 =\203G.\315 \202r.\x03\205r.\212\316y\210\317 \210\320 )\311 .Z\212\321y\210\322.!?\205o.`.W\205o.\323`.\x03#)\266\202\207" [indent-line-function tab-always-indent this-command last-command use-region-p indent-region region-beginning region-end indent-to-left-margin current-indentation insert-tab buffer-chars-modified-tick complete completion-at-point 0 forward-sexp point-marker 1 zerop indent-rigidly] 10 2133678 "P"] nil)
  apply(ad-Advice-indent-for-tab-command #[256 "\304 \203\f.\305\306 \307 \"\207\b\310=\204#.	\204'.i\311 V\204#.\n\v=\203'.\312.!\207\313 `\311 \b \210	\314=\203G.\x01`=\203G.\x02\313 =\203G.\315 \202r.\x03\205r.\212\316y\210\317 \210\320 )\311 .Z\212\321y\210\322.!?\205o.`.W\205o.\323`.\x03#)\266\202\207" [indent-line-function tab-always-indent this-command last-command use-region-p indent-region region-beginning region-end indent-to-left-margin current-indentation insert-tab buffer-chars-modified-tick complete completion-at-point 0 forward-sexp point-marker 1 zerop indent-rigidly] 10 2133678 "P"] nil)
  indent-for-tab-command(nil)
  call-interactively(indent-for-tab-command nil nil)
  command-execute(indent-for-tab-command)



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

* Re: Brittleness of called-interactively-p
  2015-07-17  4:52                   ` Dmitri Paduchikh
@ 2015-07-17 13:36                     ` Dmitri Paduchikh
       [not found]                       ` <jwvpp3qp9dn.fsf-monnier+emacs@gnu.org>
  2015-07-17 18:15                     ` raman
  1 sibling, 1 reply; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-17 13:36 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel, monnier, drew.adams, T.V Raman

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

I have prepared a simple example to reproduce the problem. In the
attachment is a small elisp file testfile.el. Save it and execute:

emacs -q -l testfile.el

In the started Emacs open some shell script and press TAB. Observe
infinite loop running inside advice--called-interactively-skip. I have
pressed TAB on an empty line, though probably any other will work as
well.


[-- Attachment #2: testfile.el --]
[-- Type: application/emacs-lisp, Size: 274 bytes --]

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

* Re: Brittleness of called-interactively-p
  2015-07-16 22:55             ` Stefan Monnier
@ 2015-07-17 18:10               ` raman
  2015-07-18  0:57                 ` Stefan Monnier
  2015-07-18  4:39               ` Dmitri Paduchikh
  1 sibling, 1 reply; 35+ messages in thread
From: raman @ 2015-07-17 18:10 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Dmitri Paduchikh, emacs-devel

Hi Stefan,

You're right that the two transitions -- called-interactively-p and
nadvice happened at around the same time. However emacspeak still uses
 advice.el, not nadvice.el.

I dont quite remember the error pattern that caused me to  create the
implementation of ems-interactive-p that I posted, but there was
definitely a bizarre error that things like ruby-mode triggered. 

Trying to reconstruct from memory:

Certain edit actions in ruby-mode called backward-sexp
(non-interactively of course)..

The spoken feedback emacspeak generated on those edit actions also
relied on calling backward-sexp (again, non-interactively)  to compute
what to speak. Somewhere in all of that, I got an error from  one of the
new advice related functions --

-- 



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

* Re: Brittleness of called-interactively-p
  2015-07-17  1:55                 ` Richard Stallman
  2015-07-17  4:52                   ` Dmitri Paduchikh
@ 2015-07-17 18:14                   ` raman
  2015-07-17 19:31                     ` Drew Adams
  1 sibling, 1 reply; 35+ messages in thread
From: raman @ 2015-07-17 18:14 UTC (permalink / raw)
  To: Richard Stallman; +Cc: dpaduchikh, monnier, drew.adams, emacs-devel

I'd love to get rid of my implementation of ems-interactive-p:-)

The behavior I need is best illustrated by a prototypical use case.

When the user presses M-C-f, I want to speak the sexp you moved over.

So I achieve this with an advice on backward-sexp (around advice that:

A. remembers point, 
B. Lets backward-sexp do its work
C Speaks the region between point and the saved position.

Now this advice should only get called when the user presses M-C-f -- or
if it's called by some function by doing (call-interactively
#'backward-sexp )

So in my advice -- and this is consistent in all of emacspeak's advice I
do
(when (ems-interactive-p) ...)

The old interactive-p did this perfectly.

I'm happy to go back and try interactive-p again since Stefan says the
implementations are nearly equivalent between it and
called-interactive-p.

As Drew said earlier on this thread, called-interactively-p is confusing
with respect to how it should be used, and specifically for the
emacspeak use-case, it's unclear   how one calls called-interactively-p
with respect to what args to pass it.
-- 



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

* Re: Brittleness of called-interactively-p
  2015-07-17  4:52                   ` Dmitri Paduchikh
  2015-07-17 13:36                     ` Dmitri Paduchikh
@ 2015-07-17 18:15                     ` raman
  1 sibling, 0 replies; 35+ messages in thread
From: raman @ 2015-07-17 18:15 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: drew.adams, Richard Stallman, monnier, emacs-devel

Looks familiar:-) Though I also remember seeing an Ad-<xx> type function
in the backtrace,
-- 



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

* RE: Brittleness of called-interactively-p
  2015-07-17 18:14                   ` raman
@ 2015-07-17 19:31                     ` Drew Adams
  2015-07-17 23:25                       ` raman
  2015-07-20 12:19                       ` Andreas Röhler
  0 siblings, 2 replies; 35+ messages in thread
From: Drew Adams @ 2015-07-17 19:31 UTC (permalink / raw)
  To: raman, Richard Stallman; +Cc: dpaduchikh, monnier, emacs-devel

> The old interactive-p did this perfectly.

Perhaps it still does. ;-)  Have you tried it?



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

* Re: Brittleness of called-interactively-p
  2015-07-12  5:00 Brittleness of called-interactively-p Dmitri Paduchikh
  2015-07-12 13:53 ` Stefan Monnier
  2015-07-12 21:59 ` Richard Stallman
@ 2015-07-17 20:35 ` Przemysław Wojnowski
  2 siblings, 0 replies; 35+ messages in thread
From: Przemysław Wojnowski @ 2015-07-17 20:35 UTC (permalink / raw)
  To: Dmitri Paduchikh, emacs-devel

W dniu 12.07.2015 o 07:00, Dmitri Paduchikh pisze:
> I would like to make a suggestion. All these problems can be resolved by
...removing the function at all.

Interactive functions are like Controllers, which should only take input 
from users and pass to Model (core functions) for further processing. If 
it is separated this way any other code can call Model directly and 
nobody needs to know what was called "interactively" or not - 
Interactive function already knows that.

IMHO "interactive-p" invites (maybe not best word - sorry, I'm not 
native English speaker) people to do poor design.



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

* Re: Brittleness of called-interactively-p
  2015-07-17 19:31                     ` Drew Adams
@ 2015-07-17 23:25                       ` raman
  2015-07-18  1:47                         ` Drew Adams
  2015-07-20 12:19                       ` Andreas Röhler
  1 sibling, 1 reply; 35+ messages in thread
From: raman @ 2015-07-17 23:25 UTC (permalink / raw)
  To: Drew Adams; +Cc: dpaduchikh, emacs-devel, Richard Stallman, monnier

Drew,
Yes, the old interactive-p did it perfectly, but it also broke for me
somewhere in the advice transition, actually it took me a while to
realize that it was broken; from memory I tracked down the problem after
one of the emacspeak users reported a recursive hang/crash in ruby-mode.


-- 



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

* Re: Brittleness of called-interactively-p
  2015-07-17 18:10               ` raman
@ 2015-07-18  0:57                 ` Stefan Monnier
  0 siblings, 0 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-07-18  0:57 UTC (permalink / raw)
  To: raman; +Cc: Dmitri Paduchikh, emacs-devel

> You're right that the two transitions -- called-interactively-p and
> nadvice happened at around the same time.

No, they didn't: "interactive-p is ... obsolete since 23.2" so
called-interactively-p was introduced in 23.2, whereas nadvice was
introduced in 24.4.  What is also new in 24.4 is that
called-interactively-p (and interactive-p) were rewritten in Elisp.


        Stefan



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

* RE: Brittleness of called-interactively-p
  2015-07-17 23:25                       ` raman
@ 2015-07-18  1:47                         ` Drew Adams
  0 siblings, 0 replies; 35+ messages in thread
From: Drew Adams @ 2015-07-18  1:47 UTC (permalink / raw)
  To: raman; +Cc: dpaduchikh, emacs-devel, Richard Stallman, monnier

> Drew,
> Yes, the old interactive-p did it perfectly, but it also broke for me
> somewhere in the advice transition, actually it took me a while to
> realize that it was broken; from memory I tracked down the problem after
> one of the emacspeak users reported a recursive hang/crash in ruby-mode.

By "in the advice transition" I guess you mean the change to using the
new advice system.  Does `interactive-p' still work OK with the "old"
advice system?

If so, perhaps you could use that, and perhaps file a bug or feature
enhancement request for the new advice system.

IOW, if it hurts to do that ("upgrade"), consider not doing it. ;-)



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

* Re: Brittleness of called-interactively-p
  2015-07-16 22:55             ` Stefan Monnier
  2015-07-17 18:10               ` raman
@ 2015-07-18  4:39               ` Dmitri Paduchikh
  2015-07-20 12:22                 ` Andreas Röhler
  2015-07-20 22:23                 ` Stefan Monnier
  1 sibling, 2 replies; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-18  4:39 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel, raman

Stefan Monnier <monnier@iro.umontreal.ca> writes:

SM> (interactive-p) is 99.9% equivalent to (called-interactively-p
SM> 'interactive), including interactions with advice and whatnot.

By the way, the interface of called-interactively-p seems somewhat
non-intuitive. Since calling it with 'interactive is intended to replace
`(interactive-p)' it would be more convenient to make `kind' an optional
argument having the default meaning of 'interactive.

(called-interactively-p)		; instead of 'interactive
(called-interactively-p 'ever)		; instead of 'any

Just a side note.



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

* Re: Brittleness of called-interactively-p
       [not found]                       ` <jwvpp3qp9dn.fsf-monnier+emacs@gnu.org>
@ 2015-07-18  5:16                         ` Dmitri Paduchikh
  0 siblings, 0 replies; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-07-18  5:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

SM> Could you send this via M-x report-emacs-bug instead of here, so we get
SM> a tracking number for this bug?

OK, it's accessible at http://debbugs.gnu.org/cgi/bugreport.cgi?bug=21083



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

* Re: Brittleness of called-interactively-p
  2015-07-12 13:53 ` Stefan Monnier
  2015-07-12 15:17   ` Dmitri Paduchikh
@ 2015-07-18 22:29   ` raman
  1 sibling, 0 replies; 35+ messages in thread
From: raman @ 2015-07-18 22:29 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Dmitri Paduchikh, emacs-devel

Hi Stefan,

See this message on the Emacspeak mailing list:
http://www.cs.vassar.edu/~priestdo/emacspeak/2015/msg00086.html

At the time I also posted the problem report to bug-emacs.

That gives some background  on why I had to move away from called-interactive-p and
implement my own version of the ems-interactive-p check.

Here are the relevant bits from that message:

Hi,

I've used a check of the form 
(when (interactive-p) ...)
within advice forms in emacspeak to speak *if and only if* a
command is
  called  by the user -- as opposed from within other lisp
function. When we transitioned to Emacs 24, I replaced that
check with (when (called-interactively-p 'interactive) ..)
and this has again worked without any issues --- until now.

We're seeing a  problem now in ruby-mode when command
electric-newline-and-maybe-indent is invoked -- that function for
ruby-mode goes through a complex dance with smie-next-sexp.

The long and short of it is that we eventually deadlock within a
call to advice--called-interactively-skip -- the comments in
nadvice.el where that function is implemented looks pretty scary.

What emacspeak really needs is a clean way of checking whether
something is called interactively, and this is the  first time
in 20 years that the test is failing.

-- 



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

* Re: Brittleness of called-interactively-p
  2015-07-17 19:31                     ` Drew Adams
  2015-07-17 23:25                       ` raman
@ 2015-07-20 12:19                       ` Andreas Röhler
  1 sibling, 0 replies; 35+ messages in thread
From: Andreas Röhler @ 2015-07-20 12:19 UTC (permalink / raw)
  To: emacs-devel


Am 17.07.2015 um 21:31 schrieb Drew Adams:
>> The old interactive-p did this perfectly.
> Perhaps it still does. ;-)  Have you tried it?
>
>

Might it be possible to remove the deprecated-flag from interactive-p?

Beside the isues discussed here interactive-p is much easier to write 
and use.

For now the compiler clutters the log with related warnings.

Shortly replaced interactive-p solely for the sake of a readable log.



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

* Re: Brittleness of called-interactively-p
  2015-07-18  4:39               ` Dmitri Paduchikh
@ 2015-07-20 12:22                 ` Andreas Röhler
  2015-07-20 22:23                 ` Stefan Monnier
  1 sibling, 0 replies; 35+ messages in thread
From: Andreas Röhler @ 2015-07-20 12:22 UTC (permalink / raw)
  To: emacs-devel


Am 18.07.2015 um 06:39 schrieb Dmitri Paduchikh:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
> SM> (interactive-p) is 99.9% equivalent to (called-interactively-p
> SM> 'interactive), including interactions with advice and whatnot.
>
> By the way, the interface of called-interactively-p seems somewhat
> non-intuitive. Since calling it with 'interactive is intended to replace
> `(interactive-p)' it would be more convenient to make `kind' an optional
> argument having the default meaning of 'interactive.
>
> (called-interactively-p)		; instead of 'interactive
>

+1



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

* Re: Brittleness of called-interactively-p
  2015-07-18  4:39               ` Dmitri Paduchikh
  2015-07-20 12:22                 ` Andreas Röhler
@ 2015-07-20 22:23                 ` Stefan Monnier
  1 sibling, 0 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-07-20 22:23 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel, raman

> By the way, the interface of called-interactively-p seems somewhat
> non-intuitive. Since calling it with 'interactive is intended to replace
> `(interactive-p)' it would be more convenient to make `kind' an optional
> argument having the default meaning of 'interactive.

That would defeat the whole purpose (which is to force the author
to make a choice between the two kinds, rather than to use one without
knowing that there's a choice).


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-13 15:17       ` Dmitri Paduchikh
  2015-07-14 23:24         ` Stefan Monnier
@ 2015-08-06 22:30         ` Stefan Monnier
  2015-08-06 22:33         ` Stefan Monnier
  2 siblings, 0 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-08-06 22:30 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

> inside called-interactively-p. Such symbols as ad-Advice-* are intended to
> be used internally by advice only, so ignoring them inside
> called-interactively-p should not cause much harm.

There are no such symbols (in nadvice.el).  They're only used in
advice.el, which is the older advice mechanism (which is now
implemented on top of the nadvice.el).


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-13 15:17       ` Dmitri Paduchikh
  2015-07-14 23:24         ` Stefan Monnier
  2015-08-06 22:30         ` Stefan Monnier
@ 2015-08-06 22:33         ` Stefan Monnier
  2015-08-07 13:35           ` Dmitri Paduchikh
  2 siblings, 1 reply; 35+ messages in thread
From: Stefan Monnier @ 2015-08-06 22:33 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: emacs-devel

> These calls are internal to the advice mechanism and, of course, they cannot
> be considered conceptually interactive.

If the original function uses called-interactively-p and the "whole
advised function" is called interactively, then called-interactively-p
should return t, yet this call is inside an interactive function which
is called non-interactively.


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-07-13 15:17   ` Dmitri Paduchikh
  2015-07-13 23:03     ` Richard Stallman
@ 2015-08-06 22:36     ` Stefan Monnier
  1 sibling, 0 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-08-06 22:36 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: Richard Stallman, emacs-devel

> It is not clear for me whether this approach will help to solve the current
> problem of macros wrapping fragments of code in lambdas.

BTW, the real solution, which is simple and reliable is to not use
called-interactively-p at all, and use an argument instead:

   (defun foo (bar &optional called-interactively)
     (interactive (list toto t))
     ...here.I.can.use.called-interactively...)

called-interactively-p is fundamentally a kludge and is better avoided.


        Stefan



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

* Re: Brittleness of called-interactively-p
  2015-08-06 22:33         ` Stefan Monnier
@ 2015-08-07 13:35           ` Dmitri Paduchikh
  2015-08-07 17:18             ` Stefan Monnier
  0 siblings, 1 reply; 35+ messages in thread
From: Dmitri Paduchikh @ 2015-08-07 13:35 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Richard Stallman, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> These calls are internal to the advice mechanism and, of course, they
>> cannot be considered conceptually interactive.

SM> If the original function uses called-interactively-p and the "whole
SM> advised function" is called interactively, then called-interactively-p
SM> should return t, yet this call is inside an interactive function which
SM> is called non-interactively.

Exactly, see above. I thought that may be it is better to associate
interactive form with function symbol rather than with function itself. This
would solve issues with calls that are internal to advice system. When
advised, the original function becomes non-interactive automatically. There
can be other issues with such approach though. The most obvious one is that
it is not longer possible to use interactive lambdas. Personally I think
that they are not so necessary and are better to be avoided when defining
key bindings because symbols look better in help output. Also there is
problem with idiom like this:

(call-interactively (lambda (b e) (interactive "r") ...))

But note that conceptually this is not a interactive call of command. It is
about reusing the feature of interactive calls to obtain values for
arguments. So it probably can be replaced with something like

(call-with-interactive-args "r" (lambda (b e) ...))

>> It is not clear for me whether this approach will help to solve the current
>> problem of macros wrapping fragments of code in lambdas.

SM> BTW, the real solution, which is simple and reliable is to not use
SM> called-interactively-p at all, and use an argument instead:

SM>    (defun foo (bar &optional called-interactively)
SM>      (interactive (list toto t))

Yes, indeed, and this method is described in the doc string of
called-interactively-p. This means however that one odd argument is added to
the function interface which plays only technical role. And also advices
which need this information will have to modify the argument list of the
original function if it does not provide it already.

RMS had an idea to make sort of separate argument for this purpose which
does not belong to function interface. My comment above was directed to him.
As you can see I was confused, since in theory it can work with macros and
lambdas no worse than your recommendation of using special argument. I have
not ideas about this approach, so do not comment it further.

I will be away for next ten days, and so won't be able to participate in the
discussion in the case you or somebody else is interested.



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

* Re: Brittleness of called-interactively-p
  2015-08-07 13:35           ` Dmitri Paduchikh
@ 2015-08-07 17:18             ` Stefan Monnier
  0 siblings, 0 replies; 35+ messages in thread
From: Stefan Monnier @ 2015-08-07 17:18 UTC (permalink / raw)
  To: Dmitri Paduchikh; +Cc: Richard Stallman, emacs-devel

> Exactly, see above. I thought that may be it is better to associate
> interactive form with function symbol rather than with function itself.

That'd be a major change.

> Yes, indeed, and this method is described in the doc string of
> called-interactively-p. This means however that one odd argument is added to
> the function interface which plays only technical role.

That's one way to look at it.  The way I look at it, instead, is that
this extra argument is just as important as the others and that it
shouldn't be called `called-interactively' or `interactive' but instead
it should have a name that describes how it affects the behavior of the
command, e.g. `emit-message' if it is used to decide whether or not to
call `message'.

> And also advices which need this information will have to modify the
> argument list of the original function if it does not provide
> it already.

By default advices preserve all arguments already, so that's
no problem.  The novelty is that advices can now decide whether the
inner function will behave as if called interactively or not.


        Stefan



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

end of thread, other threads:[~2015-08-07 17:18 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-12  5:00 Brittleness of called-interactively-p Dmitri Paduchikh
2015-07-12 13:53 ` Stefan Monnier
2015-07-12 15:17   ` Dmitri Paduchikh
2015-07-12 23:26     ` Stefan Monnier
2015-07-13 15:17       ` Dmitri Paduchikh
2015-07-14 23:24         ` Stefan Monnier
2015-07-16 15:57           ` raman
2015-07-16 17:36             ` Drew Adams
2015-07-16 17:58               ` T.V Raman
2015-07-17  1:55                 ` Richard Stallman
2015-07-17  4:52                   ` Dmitri Paduchikh
2015-07-17 13:36                     ` Dmitri Paduchikh
     [not found]                       ` <jwvpp3qp9dn.fsf-monnier+emacs@gnu.org>
2015-07-18  5:16                         ` Dmitri Paduchikh
2015-07-17 18:15                     ` raman
2015-07-17 18:14                   ` raman
2015-07-17 19:31                     ` Drew Adams
2015-07-17 23:25                       ` raman
2015-07-18  1:47                         ` Drew Adams
2015-07-20 12:19                       ` Andreas Röhler
2015-07-16 22:55             ` Stefan Monnier
2015-07-17 18:10               ` raman
2015-07-18  0:57                 ` Stefan Monnier
2015-07-18  4:39               ` Dmitri Paduchikh
2015-07-20 12:22                 ` Andreas Röhler
2015-07-20 22:23                 ` Stefan Monnier
2015-08-06 22:30         ` Stefan Monnier
2015-08-06 22:33         ` Stefan Monnier
2015-08-07 13:35           ` Dmitri Paduchikh
2015-08-07 17:18             ` Stefan Monnier
2015-07-18 22:29   ` raman
2015-07-12 21:59 ` Richard Stallman
2015-07-13 15:17   ` Dmitri Paduchikh
2015-07-13 23:03     ` Richard Stallman
2015-08-06 22:36     ` Stefan Monnier
2015-07-17 20:35 ` Przemysław Wojnowski

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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