emacs-devel
[Top][All Lists]
Advanced

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

Re: sh-script beg-end of function


From: Andreas Röhler
Subject: Re: sh-script beg-end of function
Date: Fri, 23 Nov 2007 16:33:36 +0100
User-agent: KMail/1.9.5

Am Donnerstag, 22. November 2007 22:49 schrieb Stefan Monnier:
> > Your code adresses a function in it's literally sence,
> > whereas my code adresses "top-level-form", a more
> > abstract thing. A "top-level-form" form BTW already
> > is adressed by Emacs-Lisp `end-of-defun' or
> > `beginning-of-defun' and I already remarked the naming
> > as somehow misleading therefore, but that's a matter
> > from the past.
>
> I understand, but the way I see it, either you're in an sh buffer which
> has functions, in which case the defun-prompt-regexp will work fine, or
> you're in an sh buffer which basically only contains "unstructured"
> "straight-line" code.  You want to cater to this latter case as well.
>
> It might be OK, but in my experience which units are useful in this case
> is hard to know in general because it depends a lot on the writing style
> used (which is anything but standardized sadly).  In many cases
> paragraph-based navigation will work best.
>

That's true. Took your hint to make changes rely on paragraph-.

> I don't claim that my defun-prompt-regexp setting is the
> end-all-be-all here.  It's just a good starting point.  But also any
> replacement should be at least as good.  Most importantly: jumping to
> the end of a real function should jump to the closing "}".
>
Not, if exists usually no closing "}" while writing. I prefer to
set closings last and manually - the reports I get then
are more valuable than possible savings before.

> If you want to submit an improvement, please send it as a patch against
> the current sh-script.el code.  This will make it easier for us to
> integrate your code.

Here a small diff to enable modes to set beginning-of-defun-function without 
disturbing each other:

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

diff -c emacs-lisp/lisp.el lisp.el
*** /emacs-lisp/lisp.el 2007-07-26 07:26:47.000000000 +0200
--- lisp.el     2007-11-23 15:49:52.000000000 +0100
***************
*** 178,183 ****
--- 178,184 ----
  The function (of no args) should go to the line on which the current
  defun starts, and return non-nil, or should return nil if it can't
  find the beginning.")
+ (make-variable-buffer-local 'beginning-of-defun-function)
  
  (defun beginning-of-defun (&optional arg)
    "Move backward to the beginning of a defun.
***************
*** 291,296 ****
--- 292,298 ----
  This is used to find the end of the defun instead of using the normal
  recipe (see `end-of-defun').  Major modes can define this if the
  normal method is not appropriate.")
+ (make-variable-buffer-local 'end-of-defun-function)
  
  (defun buffer-end (arg)
    "Return the \"far end\" position of the buffer, in direction ARG.

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

> BTW, `end-of-defun-function' seems to be used in end-of-defun in
> a ... weird way, so maybe you'll want to fix that first. 

This should be done with this diff above.

Remaining bugs AFAIS occur occasionally but are deep-rooted
from underlying move-functions and not to adress here.

> Maybe I'll 
> post a suggestion about it on this list later.
>
>
>         Stefan
>
>
> PS: Comments about your original code:
> - the "defcustom beginning-of-defun-function" is wrong: you can only
>   use defcustom for variable you *create* (that are your own), not to set
>   variables defined in other packages.

OK, thanks. Dropped that part.

> - The docstring of sh-beginning-of-function is unusable.  It could
>   instead explain what is considered as a "defun".

Changed.

> - Instead of (parse-partial-sexp (point-min) (point)), you can use
>   syntax-ppss.

Dropped that part of code completely. 

BTW, reading doku of `syntax-ppss'
"The returned value is the same as `parse-partial-sexp'
except that the 2nd and 6th values of the returned
state cannot be relied upon." 
I say: so let's take `parse-partial-sexp' and rely
upon... Maybe I'm wrong here?

> - the docstring of `comment-beginning' says "Find the beginning of the
>   enclosing comment" so I'm wondering why you decided to use that in
>   a context where you have no idea whether or not you're inside
>   a comment.  Why don't you just use (forward-comment (- (point-max)))

Thanks. Simply wasn't aware of that. Rewrote the
code. Changed "function" to "form" too in order to avoid
misunderstandings.

>   and skip the 
>   newcomment madness  
Wouldn't dare to speak that out :)
...

Thanks again

Andreas Röhler


;;; sh-beg-end.el --- Something for C-M-a,
;;; C-M-e, M-a and M-e in shell-script-mode

;; Copyright (C) 2007 by Andreas Röhler
;; <address@hidden>

;; Keywords: languages

;; This file is free software; you can redistribute it
;; and/or modify it under the terms of the GNU General
;; Public License as published by the Free Software
;; Foundation; either version 3, or (at your option)
;; any later version.

;; This file is distributed in the hope that it will be
;; useful, but WITHOUT ANY WARRANTY; without even the
;; implied warranty of MERCHANTABILITY or FITNESS FOR A
;; PARTICULAR PURPOSE.  See the GNU General Public
;; License for more details.

;; You should have received a copy of the GNU General
;; Public License along with GNU Emacs; see the file
;; COPYING.  If not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary: 

;; C-M-a, C-M-e: jump to the beginning or end of a
;; top-level-form in sh-mode - "Shell-script"-mode. 

;; M-a, M-e: jump to the beginning or end of command in
;; a given line, forward or backward next beginning or
;; end with. With argument do this as many times.

;;; Code:


;; this belongs into sh-script.el
(make-variable-buffer-local 'beginning-of-defun-function)
(make-variable-buffer-local 'end-of-defun-function)
 
(defcustom sh-beginning-of-form-regexp "^[A-Za-z_][A-Za-z_0-9]*"
  " "
  :type 'regexp
  :group 'lisp)

(defun sh-beginning-of-form ()
  "Move to the beginning of a top-level-form in sh-script.
With numeric argument, do it that many times."
  (interactive)
  (re-search-backward sh-beginning-of-form-regexp nil t 1))

(defun sh-end-of-form (&optional arg)
  "Move to the end of a top-level-form in sh-script.
With numeric argument, do it that many times."
  (interactive "p")
  (let ((arg (or arg 1)))
    (while (forward-comment 1) (forward-comment 1))
    (unless (looking-back "^[ \t]*")
      (setq arg (1+ arg)))
    (forward-paragraph arg)
    (skip-chars-backward " \t\r\n\f")
    (unless (looking-at "}")
      (back-to-indentation))
    (if (looking-back "^[ \t]+")
        (progn 
          (end-of-line) 
          (sh-end-of-form))
      (end-of-line)
      (skip-chars-backward " \t\r\n\f"))))
    
(defun sh-set-beginning-of-form ()
  "'sh-beginning-of-form"
  (interactive)
 (setq beginning-of-defun-function 'sh-beginning-of-form))

(defun sh-set-end-of-form ()
  "'sh-end-of-form"
  (interactive)
  (setq end-of-defun-function 'sh-end-of-form))

(defun sh-beginning-of-command (&optional arg) 
  "Move point to successive beginnings of commands."
  (interactive "p")
  (let ((arg (or arg 1))
        (pos (point)))
    (back-to-indentation)
    (unless (eq pos (point))
      (setq arg (1- arg)))
    (while (< 0 arg)
      (forward-line (- arg))
      (setq arg (1- arg))
      ;; skip comments and empty lines and closing braces
      (let ((pos (point)))
        (if (forward-comment -1)
            (while (forward-comment -1) (forward-comment -1))
          (goto-char pos)))
      (while (or (empty-line-p)
                 (looking-at "}"))
        (forward-line -1))
      (back-to-indentation))))

(defun sh-end-of-command (&optional arg) 
  "Move point to successive ends of commands."
  (interactive "p")
  (let ((arg (or arg 1))
        (pos (point)))
    (end-of-line)
    (skip-chars-backward " \t\r\n\f" (line-beginning-position))
    (unless (eq pos (point))
      (setq arg (1- arg)))
    (while (< 0 arg)
      (forward-line arg)
      (setq arg (1- arg)))
    (end-of-line)
    (skip-chars-backward " \t\r\n\f" (line-beginning-position))
    (while (or
            (empty-line-p)
            (forward-comment 1)) 
      (forward-line 1)
      (end-of-line))
    (skip-chars-backward " \t\r\n\f")))

(add-hook 'sh-mode-hook 'sh-set-beginning-of-form)
(add-hook 'sh-mode-hook 'sh-set-end-of-form)

(provide 'sh-beg-end)

;;; sh-beg-end.el ends here




reply via email to

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