emacs-pretest-bug
[Top][All Lists]
Advanced

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

Re: [Fwd: Re: beginning-of-defun]


From: Andreas Roehler
Subject: Re: [Fwd: Re: beginning-of-defun]
Date: Fri, 14 Jul 2006 09:20:06 +0200
User-agent: Thunderbird 1.5.0.4 (X11/20060516)

Thien-Thi Nguyen schrieb:
   From: Andreas Roehler <address@hidden>
   Date: Mon, 10 Jul 2006 15:46:02 +0200

   It's not just for fun I entered this matter. `beginning-of-defun' is
   buggy - and a lot of forms which rely on it.

given the discussion so far i remain unconvinced there is a bug.  note
however: i'm not stopping you from continuing, personally.  if you post
code as the way to propose the bug fix, it that will be easier to
evaluate its merits.  remember to not break callers (both included w/
emacs and external) of `beginning-of-defun'.

thi


Below a first draft with `beginning-of-function' aiming
to work more precisely in Emacs Lisp.

As already mentioned in the sources, to write a
reliable `beginning-of-top-level-form' it's necessary
to scan from the beginning of the buffer. This has been
written, is the code available somewhere?

`beginning-of-function' calls `beginning-of-defun' if
not in Emacs Lisp. So it should work in all
circumstances.

New Features:

- Customization of return value possible - t or value
 of point if successful.

- Returns nil at the end or beginning of buffer. No
 push-mark then.

- If starting with the searched form at place, just
 sends return value, moves only after repeated action
 or arg different from 1

Please have a look on it.

Thanks

__
Andreas Roehler

Some examples I checked it with

(defun bar ()
 " "
 (interactive "*")
 (message "%s" "bar"))

(defun bar ()
 " "
 (interactive "*"))

 (defun bar ()
 " "
 (interactive "*"))

   (defun foo ()
 "`beginning-of-function' should not pick a \" (defun\"
 construct inside a documentation string"
 (interactive)
 (message "%s" "bar"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; The mode should set this, if possible
(defcustom modefunction-beginning-of-func nil
 "If defined, specify your mode function to identify the
beginning of a function"
 :group 'lisp
 :type 'sexp)

;; The mode should set this
(defcustom beginning-of-function-regexp "^[ \t]*(defun\\S(+\\s(\\S(*\\s)"
"Regexp used by `beginning-of-function' to determine the beginning of a function"
 :type '(choice (const nil)
        regexp)
 :group 'lisp)
;; (make-variable-buffer-local 'beginning-of-function-regexp)

;; The mode should set this, if possible
(defcustom beginning-of-function-return-value t
"Specify the return value if function succeeds: either t or the value of point"
 :group 'lisp
   :type '(choice (const t)
          (sexp :tag "Return function" (point))))

(defcustom use-modefunction-beginning-of-func t
"Set it to nil, if `modefunction-beginning-of-func' doesn't work properly or is not defined. This takes only effect, if `modefunction-beginning-of-func' is defined in this mode. Otherwise it will be ignored."

:type 'boolean
:group 'lisp)

(defcustom beginning-of-function-eob-return-nil t
"If t, `beginning-of-function' will return nil if called at the beginning or the end of buffer. Also it will not set the mark then."

:type 'boolean
:group 'lisp)

;; The mode should set this, if possible
(defcustom force-beginning-of-function-regexp nil
"Set it to t, if `beginning-of-function-regexp' should be used
in any case,
ie if you are not in Emacs Lisp, but the reg-exp is OK. You may customize `beginning-of-function-regexp')."
:type 'boolean
:group 'lisp)

(defun beginning-of-function (&optional arg)
 "Move backward to the beginning of a function.
With ARG, do it that many times.  Negative arg -N
means move forward to Nth following beginning of function.
Returns t unless search stops due to beginning or end of buffer.
If Variables `use-modefunction-beginning-of-func' `modefunction-beginning-of-func' is non-nil, its value
is called as a function to find the function's beginning.
If not in Emacs Lisp-mode, `beginning-of-defun' is called anyway.
"
 (interactive "p")
 ;; mark questions
 (or (not (eq this-command 'beginning-of-function))
     (eq last-command 'beginning-of-function)
     (and transient-mark-mode mark-active)
     (when beginning-of-function-eob-return-nil
   (and (< 0 arg) (bobp))
   (and (> 0 arg) (eobp)))
     (push-mark))
 (beginning-of-function-raw arg))

(defun beginning-of-function-raw (&optional arg)
 "Move point to the character that starts a function.
If variable `beginning-of-function-func' is non-nil, its value
is called as a function to find the function's beginning.
If not in Emacs Lisp-mode, `beginning-of-defun' is called anyway."
 (interactive "p")
 (let ((arg (or arg 1)))
   (if (and modefunction-beginning-of-func
        use-modefunction-beginning-of-func)
   (if (> (setq arg (or arg 1)) 0)
       (dotimes (i arg)
         (funcall modefunction-beginning-of-func))
     (end-of-function (- arg)))
     (and
      (not (eobp))
      (< arg 1)
      (forward-char -1))
     (if (or
      ;; while developing: specify here a list with
      ;; modes already provided with an new
      ;; `beginning-of-function-regexp'
      (string= major-mode "emacs-lisp-mode")
      force-beginning-of-function-regexp)
     (progn
       (unless
       (eq last-command 'beginning-of-function)
         (if
         (< (point) (position-of-indent))
         (progn (forward-line -1) (end-of-line))
       (end-of-line)))
       (re-search-backward beginning-of-function-regexp nil 'move arg)
       (forward-to-indentation 0)
       (cond ((bobp)
          nil)
         ((eobp)
          nil)
         (t
          (prog1 (eval beginning-of-function-return-value)
            (message "%s" (eval beginning-of-function-return-value))))))
(message "%s" "Using old `beginning-of-defun': new mode-function and/or `beginning-of-function-regexp' probably not defined for this mode.")
   (funcall 'beginning-of-defun arg)))))

(defun beginning-of-function-position ()
 "Print beginning-of-function-position in Message Buffer"
 (interactive "*")
 (save-excursion
 (message "%s" (progn (beginning-of-function) (point)))))

(defun position-of-indent ()
 "Return the position of first indented char in current line"
 (interactive)
 (save-excursion
   (beginning-of-line)
   (skip-syntax-forward " " (line-end-position))
   (point)))

;;; end





reply via email to

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