gnu-emacs-sources
[Top][All Lists]
Advanced

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

sh-beg-end.el 1.1


From: Andreas Röhler
Subject: sh-beg-end.el 1.1
Date: Tue, 27 Nov 2007 11:03:43 +0100
User-agent: KMail/1.9.5

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

;; Version 1.1

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

;;; Changes to previous version:

;; Bug fixed which occured when `narrow-to-defun' was
;; called

;;; Commentary:

;; sh-beg-end addresses the writers side of point:
;; provide predictable moves through shell-scripts
;; while writing it, i.e. it don't require things,
;; which might not be finished, not be written
;; yet.

;; C-M-a, C-M-e: jump to the beginning or end of a
;; top-level-form in sh-mode -
;; "Shell-script"-mode.  Repeated execution forward
;; or backward.  With argument as many times.

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

;; Thanks to Stefan Monnier and Richard Stallman
;; being helpful.  Errors are mine, any comments
;; welcome.

;;; Code:

(defcustom sh-beginning-of-form-regexp "^[A-Za-z_][A-Za-z_0-9]*"
  "Regexp indicating the beginning of a form to edit."
  :type 'regexp
  :group 'lisp)

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

(defun sh-end-of-form (&optional arg)
  "Move forward to end of a top-level-form or command in sh-script.
With numeric ARG, do it that many times."
  (interactive "p")
  (let ((arg (or arg 1))
        (pos (point)))
    ;; between forms, skip next beginning
    (when (eq 0 (car (parse-partial-sexp (point-min) (point))))
      (setq arg (1+ arg)))
    (let ((erf
           (re-search-forward sh-beginning-of-form-regexp nil t arg)))
      (goto-char (match-beginning 0))
      (unless erf
        ;; already last top level form
        (goto-char (point-max)))
      (skip-chars-backward " \t\r\n\f"))
    ;; skip comments
    (while
        (progn
          (comment-normalize-vars) (comment-beginning))
      (forward-line -1)
      (end-of-line)
      (skip-chars-backward " \t\r\n\f"))
    (when (eq pos (point))
      (setq arg (+ 2 arg))
      (sh-end-of-form arg))))

(defun sh-set-beginning-of-form ()
  "Set `sh-beginning-of-form' as `beginning-of-defun-function'."
  (interactive)
  (set 
(make-local-variable 'beginning-of-defun-function) 'sh-beginning-of-form))

(defun sh-set-end-of-form ()
  "Set `sh-end-of-form' as `end-of-defun-function'."
  (interactive)
  (set (make-local-variable 'end-of-defun-function) 'sh-end-of-form))

(defun sh-beginning-of-command (&optional arg)
  "Move point to ARG 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 ARG 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")))

(defcustom empty-line-p-chars "^[ \t\f\r]*$"
  "Empty-line-p-chars."
 :type 'regexp
 :group 'convenience)

(defun empty-line-p (&optional ispec)
  "Returns t if cursor is at an empty line, nil otherwise."
  (interactive "p")
  (save-excursion
    (beginning-of-line)
    (when ispec
      (message "%s" (looking-at empty-line-p-chars)))
    (looking-at empty-line-p-chars)))

(defconst sh-beg-end-version "1.1"
  "Version number of this sh-beg-end.el.")

(defun sh-beg-end-version (&optional ispec)
  "Print and/or return sh-beg-end-version."
  (interactive "p")
  (when ispec
    (message "%s" sh-beg-end-version))
  sh-beg-end-version)

(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]