emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

propertize when modification-hooks' value has function that is void and/


From: MON KEY
Subject: propertize when modification-hooks' value has function that is void and/or faulty lambda list
Date: Fri, 12 Jun 2009 18:26:30 -0400

Text propertized with modification-hooks which call a void hook function
or improperly formed lambda lists throw _hard_ to diagnose errors and
message without context.

 (defun bad-props-w-mod-hooks ()
   (let (padding)
     (setq padding
        (concat
         (propertize "\nlmb lmb" 'modification-hooks '(keep-one-space))
         (propertize " sp  sp\n" 'modification-hooks '((lambda (x) x y)))
         (propertize "sp  sp" 'modification-hooks '((lambda (y) x y)))
         (propertize "  lmb lmb" 'modification-hooks '(keep-one-space))))
     (newline)
     (insert padding)))

;; test-me: (bad-props-w-mod-hooks)

lmb lmb sp  sp
sp  sp  lmb lmb

To remedy the situation temporarily one can obviously:

  (setq inhibit-modification-hooks t)

  or,

  (remove-text-properties (bad-prop-start) (bad-prop-end) 'modification-hooks)

That said, shouldn't `propertize' and ilk have a way to test `functionp'
of the prop-val of `modification-hooks' before running/evaluating the
hooks' property value?

The problem is this, if a function `keep-one-space' is in fact named
`keep-one-space-p' even if the `keep-one-space-p' function _has_ a
properly established `inhibit-modification-hooks' wrapper,
modification-hooks won't see it (or doesn't report seeing it).

Which is to say, any function which has been inadvertently rebound, is
unbound, or otherwise mis-spelled, etc. will cause squeaky problems when
the propertizing form is evaluated.

Following is an error message returned when attempting to delete the
first "lmb" below:

;(bad-props-w-mod-hooks)

lmb lmb sp  sp
sp  sp  lmb lmb

"delete-char: Symbol's function definition is void: keep-one-space"

Assuming the correct remedy is a solution as mentioned above, i.e.
`inhibit-modification-hooks' and/or `remove-text-properties' then the
above error message doesn't entirely represent the nature of the
situation in that the given context of the message implies that the
remedy for this error involves finding and/or binding `keep-one-space'
when in fact such is neither the error nor the remedy.

Consider a like situation where the function value to to the
modification-hooks' property is a lambda list with only one arg (it
wants two). In this case the hooks value is similarly 'void' but we are
better informed as to the nature of the error (though the possible remedy
is prob. equally unclear) e.g.:

;(bad-props-w-mod-hooks)

lmb lmb sp  sp
sp  sp  lmb lmb

"delete-and-extract-region: Wrong number of arguments: (lambda (y) x y), 2"

With the former situation - i.e. where the error is of the type
"Symbol's function definition is void" - this might not pose too great a
problem esp. in simple interactive situations where presumably you might
have bound the function (or attempted to) so go fix it. However, what of
a situation with a busted lambda form which calls out to other
functions, macros etc... what then huh?

In either situation where such errors occur in the context of other
programmatically evaluated elisp the true nature of the error can be
more elusive esp. as no mention is given to the fact that it is the
modification-hooks property _not_ its value causing the problem:

Take for example a simple case using the function `sp-inhibit-read-only'
which temporarily inhibits the read-only property to do some work:

 (defun sp-inhibit-read-only (func-arg)
   (let ((re-inhibit (if (not inhibit-read-only) t nil)))
     (unwind-protect
         (progn
           (setq inhibit-read-only t)
           (eval `(,func-arg)))
       (when re-inhibit (setq inhibit-read-only nil)))))

Following are two back-trace having evaluated the form:

 (sp-inhibit-read-only 'kill-line)

with point at BOL of the first line of the concat'd propertized strings
per the `bad-props-w-mod-hooks' example above:

;(bad-props-w-mod-hooks)

lmb lmb sp  sp
sp  sp  lmb lmbw

{ YES. I understand that setting `inhibit-read-only' t has _no_ effect
on the modification-hooks' property or its value. My point is to show
how the error message has nothing relevant to say of the _real_ problem
or its origin. }

-------------------------------------------------------------------
Backtrace Example #1 | evaluated with point at BOL line 1 "lmb"
-------------------------------------------------------------------
Debugger entered--Lisp error: (wrong-number-of-arguments (lambda (x) x y) 2)
  (lambda (x) x y)(40974 40987)
  delete-and-extract-region(40974 40987)
  filter-buffer-substring(40974 40987 t)
  byte-code(" {...byte code ellided..} "
  [beg end string last-command yank-handler this-command
  filter-buffer-substring t kill-region kill-append kill-new nil] 5)
  kill-region(40974 40987)
  kill-line()
  eval((kill-line))
  (progn (setq inhibit-read-only t) (eval (\` ...)))
  (unwind-protect (progn (setq inhibit-read-only t) (eval ...))
  (when re-inhibit (setq inhibit-read-only nil)))
  (let ((re-inhibit ...)) (unwind-protect (progn ... ...) (when
re-inhibit ...)))
  sp-inhibit-read-only(kill-line)
  eval((sp-inhibit-read-only (quote kill-line)))
  eval-expression((sp-inhibit-read-only (quote kill-line)) nil)
  call-interactively(eval-expression nil nil)

-------------------------------------------------------------------
Backtrace Example #2 | Evaluated with point at BOL line 2 "sp"
-------------------------------------------------------------------
Debugger entered--Lisp error: (void-function keep-one-space)
  keep-one-space(40988 41001)
  delete-and-extract-region(40988 41001)
  filter-buffer-substring(40988 41001 t)
  byte-code(" {...byte code ellided..} "
  [beg end string last-command yank-handler this-command
  filter-buffer-substring t kill-region kill-append kill-new nil] 5)
  kill-region(40988 41001)
  kill-line()
  eval((kill-line))
  (progn (setq inhibit-read-only t) (eval (\` ...)))
  (unwind-protect (progn (setq inhibit-read-only t) (eval ...))
  (when re-inhibit (setq inhibit-read-only nil)))
  (let ((re-inhibit ...)) (unwind-protect (progn ... ...)
  (when re-inhibit ...)))
  sp-inhibit-read-only(kill-line)
  eval((sp-inhibit-read-only (quote kill-line)))
  eval-expression((sp-inhibit-read-only (quote kill-line)) nil)
  call-interactively(eval-expression nil nil)
-------------------------------------------------------------------

By contrast, with a like situation when evaluating
`sp-inhibit-read-only' in concert with the following
`sp-inhibit-modification-hooks' function:

 (defun sp-inhibit-modification-hooks (func-arg)
   (let ((re-inhibit (if (not inhibit-modification-hooks) t nil)))
     (unwind-protect
         (progn
           (setq inhibit-modification-hooks t)
           (eval `(,func-arg)))
       (when re-inhibit (setq inhibit-modification-hooks nil)))))

e.g. in a loop such as:

 (sp-inhibit-read-only
  (lambda ()
    (dotimes (i 4)
      (sp-inhibit-modification-hooks 'kill-line))))

;(bad-props-w-mod-hooks)

lmb lmb sp  sp
sp  sp  lmb lmb

we are not presented with _any_ visible indication that a problem
has occurred.  The error - while still present - is allowed to go more or
less under-reported, aside from the incorrect error message in
*Messages*, namely:

"delete-char: Symbol's function definition is void: keep-one-space".

Again, this isn't where/why the error has occurred.

;Cleanup
 (progn
   (unintern 'sp-inhibit-read-only)
   (unintern 'sp-inhibit-modification-hooks)
   (unintern 'bad-props-w-mod-hooks))

;;(setq inhibit-modification-hooks t)
;;(setq inhibit-modification-hooks nil)

s_P




reply via email to

[Prev in Thread] Current Thread [Next in Thread]