Ver código fonte

*** empty log message ***

David Rose 22 anos atrás
pai
commit
dea75b3cd0
1 arquivos alterados com 324 adições e 0 exclusões
  1. 324 0
      direct/src/directscripts/flashparen.el

+ 324 - 0
direct/src/directscripts/flashparen.el

@@ -0,0 +1,324 @@
+;;; flashparen.el --- flash matching parens a la Zmacs
+
+;; Copyright (C) 1995 Noah S. Friedman
+
+;; Author: Noah Friedman <[email protected]>
+;; Maintainer: [email protected]
+;; Keywords: extensions
+;; Status: Works in Emacs 19
+;; Created: 1995-03-03
+
+;; LCD Archive Entry:
+;; flashparen|Noah Friedman|[email protected]|
+;; flash matching parens a la Zmacs|
+;; 12-Nov-1995|1.8|~/misc/flashparen.el.gz|
+
+;; $Id$
+
+;; This program 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 2, or (at your option)
+;; any later version.
+;;
+;; This program 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 this program; if not, you can either send email to this
+;; program's maintainer or write to: The Free Software Foundation,
+;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA.
+
+;;; Commentary:
+
+;; Loading this makes emacs's paren blinking behavior more closely
+;; approximate the behavior of Zmacs.  It should work under X or on ascii
+;; terminals.
+
+;; Note that in XEmacs, blink-paren.el implements this functionality in a
+;; more reliable manner, so use that instead of this program.
+
+;; To use this program, load this file and do
+;;
+;;    (flash-matching-mode 1)
+;;
+;; It is vitally important that flash-matching-char be the *last* hook on
+;; post-command-hook.  If anything comes after it, it won't get run until
+;; flash-matching-char is interrupted by user input, which is almost
+;; certainly undesirable.  As a consequence, the function
+;; flash-matching-mode will make sure this is the case whenever it is run.
+;; The real solution is to get the flashing function off the command hook
+;; entirely, but since emacs has no builtin timers there seems to be no
+;; readily apparent way to accomplish this efficiently.
+
+;;; Code:
+
+(defvar flash-matching-mode nil
+  "*If non-nil, then flash corresponding matching character on display.
+It's best to call the function of the same name, since there are other
+things to be done by side effect when enabling this feature.")
+
+(defvar flash-matching-delay
+  (cond (window-system 0.2)
+        ((> baud-rate 19200) 0.2)
+        ((>= baud-rate 9600) 0.5)
+        (t 1))
+  "Interval (in seconds) for flash delay.
+This number may be a floating-point number in instances of emacs that
+support floating point arguments to `sit-for'.")
+
+
+;;;###autoload
+(defun flash-matching-mode (&optional prefix)
+  "*If non-nil, then flash corresponding matching character on display."
+  (interactive "P")
+
+  ;; Make sure flash-matching-char is last on post-command-hook or
+  ;; post-command-idle-hook.  The latter is defined in Emacs 19.30 and later.
+  (let* ((hook (if (boundp 'post-command-idle-hook)
+                   'post-command-idle-hook
+                 'post-command-hook))
+         (h (memq 'flash-matching-char (symbol-value hook))))
+    (cond ((null h)
+           (add-hook hook 'flash-matching-char 'append))
+          ((cdr h)
+           (remove-hook hook 'flash-matching-char)
+           (add-hook hook 'flash-matching-char 'append))))
+
+  (setq flash-matching-mode
+        (>= (prefix-numeric-value prefix) 0))
+  (and (interactive-p)
+       (if flash-matching-mode
+           (message "flash-matching-mode is enabled")
+         (message "flash-matching-mode is disabled")))
+  flash-matching-mode)
+
+;; Verify that an even number of quoting characters precede char at point.
+(defsubst flash-matching-even-quoting-p (point)
+  (let ((p (point)))
+    (if (= point (point-min))
+        t
+      (= 1 (logand 1 (- point
+                        (progn
+                          (goto-char point)
+                          (forward-char -1)
+                          (skip-syntax-backward "/\\" (point-min))
+                          (prog1
+                              (point)
+                            (goto-char p)))))))))
+
+(defun flash-matching-char ()
+  (and flash-matching-mode
+       ;; prefix args do strange things with commands; it seems that
+       ;; running post-command-hook after invoking one of these is delayed
+       ;; until the command is finished, then the hook is run twice.
+       ;; It's undesirable to wait for user input twice before returning to
+       ;; the top command loop, so skip this the first time.
+       (not (memq this-command '(digit-argument universal-argument)))
+       ;; keyboard macros run a sequence of interactive commands, each one
+       ;; of which will cause a call to post-command-hook; so as long as
+       ;; the keyboard macro is still executing, do nothing.
+       (null executing-macro)
+       (let* ((saved-point (point))
+              (cho (char-after saved-point))
+              (chc (char-after (1- saved-point)))
+              ch)
+         (cond
+          ((or (and (numberp cho)
+                    (= (char-syntax cho) ?\()
+                    (< saved-point (window-end))
+                    (flash-matching-even-quoting-p saved-point)
+                    (setq ch cho))
+               (and (numberp chc)
+                    (= (char-syntax chc) ?\))
+                    (> saved-point (window-start))
+                    (flash-matching-even-quoting-p saved-point)
+                    (setq ch chc)))
+
+           (let ((parse-sexp-ignore-comments t)
+                 ;; this beginning of line is not necessarily the same as
+                 ;; the one of the matching char `line-beg', below.
+                 (bol-point (progn
+                              (beginning-of-line)
+                              (point)))
+                 match-point)
+
+             ;; should be at bol now
+             ;; If we're inside a comment already, turn off ignoring comments.
+             (and comment-start
+                  (looking-at (concat "^[ \t]*" (regexp-quote comment-start)))
+                  (setq parse-sexp-ignore-comments nil))
+
+             ;; Find matching paren position, but don't search any further
+             ;; than the visible window.
+             (save-restriction
+               (condition-case ()
+                   (progn
+                     (narrow-to-region (window-start) (window-end))
+                     (cond
+                      ((= (char-syntax ch) ?\()
+                       (setq match-point (1- (scan-sexps saved-point 1))))
+                      (t
+                       (setq match-point (scan-sexps saved-point -1)))))
+                 (error nil)))
+
+             ;; Matched char must be the corresponding character for the
+             ;; char at the saved point, not just another paired delimiter.
+             ;; This can happen when parens and brackets are mismatched,
+             ;; for example.  Also don't be fooled by things in an
+             ;; open/close syntax class but with no defined matching
+             ;; character.
+             (and match-point
+                  (flashparen-matching-paren ch)
+                  (not (= (char-after match-point)
+                          (flashparen-matching-paren ch)))
+                  (setq match-point nil))
+
+             ;; match char must be horizontally visible on display.
+             ;; Unfortunately we cannot just use pos-visible-in-window-p
+             ;; since that returns t for things that are actually off the
+             ;; display horizontally.
+             (and truncate-lines
+                  match-point
+                  (let ((window-hstart (window-hscroll))
+                        (match-column (progn
+                                        (goto-char match-point)
+                                        (current-column))))
+                    (if (or (< match-column window-hstart)
+                            (> match-column (+ window-hstart (window-width))))
+                        (setq match-point nil))))
+
+             (cond (match-point
+                    ;; I added this to remove messages left over from
+                    ;; blink-matching-open, but it also causes messages
+                    ;; returned by eval-expression, etc. not to appear if
+                    ;; point is right after a sexp, which is too annoying.
+                    ;;(message nil)
+                    (flash-matching-do-flash saved-point match-point))
+                   (t
+                    (goto-char saved-point)
+                    (and chc
+                         (= (char-syntax chc) ?\))
+                         ;; blink-matching-open can sometimes signal an
+                         ;; error if the function name is outside of a
+                         ;; narrowed region---this can happen in C, perl,
+                         ;; and other languages where the function label is
+                         ;; outside the starting block character, depending
+                         ;; on how one's narrow-to-defun function is defined.
+                         (condition-case ()
+                             (blink-matching-open)
+                           (error nil)))))))))))
+
+(defun flash-matching-do-flash (flash-matching-opoint flash-matching-mpoint)
+  ;; Deactivate the mark now if deactivate-mark is set in transient mark
+  ;; mode.  Normally the command loop does this itself, but because this
+  ;; function is on post-command-hook, deactivation is delayed and causes
+  ;; noticable, undesirable effects on the display.
+  ;; The only time I've noticed this to be of consequence is when point is
+  ;; right before a sexp and you insert a character.  Otherwise, this
+  ;; function doesn't get called again because after modifying the buffer,
+  ;; point is no longer at the beginning or end of a sexp.
+  (and transient-mark-mode
+       deactivate-mark
+       (deactivate-mark))
+
+  (let ((modp (buffer-modified-p))
+        (buffer-file-name buffer-file-name)
+        (buffer-auto-save-file-name buffer-auto-save-file-name)
+        (auto-save-hook (and (boundp 'auto-save-hook)
+                             auto-save-hook))
+
+        ;; Don't make any undo records while flashing.
+        ;; If this is nil, new undo records are appended.
+        ;; Setting it to t avoids consing any records at all.
+        (buffer-undo-list t)
+
+        (before-change-function nil)
+        (after-change-function nil)
+        ;; buffer modification messes with transient mark mode.
+        (deactivate-mark nil)
+
+        ;; These variables have long names because they may be referenced
+        ;; by a function in the auto-save-hook even if the current buffer
+        ;; isn't this one (e.g. because a process filter was running at the
+        ;; time).
+        (flash-matching-buffer (current-buffer))
+        (flash-matching-char (char-after flash-matching-mpoint))
+        (flash-matching-visible-p t))
+
+    (cond
+     ((null buffer-file-name))
+     (modp
+      ;; If buffer is already modified, do not try to disable locking or
+      ;; autosaving, but make sure flashed char is in the buffer exactly
+      ;; when autosaving occurs.
+      (add-hook 'auto-save-hook
+                (function
+                 (lambda ()
+                   (or flash-matching-visible-p
+                       (save-excursion
+                         (set-buffer flash-matching-buffer)
+                         (let ((buffer-read-only nil))
+                           (goto-char flash-matching-mpoint)
+                           (insert-before-markers-and-inherit
+                            flash-matching-char)
+                           (goto-char flash-matching-mpoint)
+                           (delete-char -1)
+                           (setq flash-matching-visible-p t)
+                           (goto-char flash-matching-opoint))))))))
+     (t
+      ;; Defeat file locking.  Don't try this at home, kids!
+      (setq buffer-file-name nil)
+      (setq buffer-auto-save-file-name nil)))
+
+    ;; We insert-before-markers-and-inherit one char after the one to
+    ;; delete, just in case things like window-start, process-mark,
+    ;; etc. are at the point of interest.
+    (setq flash-matching-mpoint (1+ flash-matching-mpoint))
+    (goto-char flash-matching-opoint)
+    (unwind-protect
+        (while (sit-for flash-matching-delay)
+          (let ((buffer-read-only nil))
+            (goto-char flash-matching-mpoint)
+            ;; Insert char before deleting existing one, to avoid
+            ;; complications having to do with overlays and text
+            ;; properties on a region.
+            (if flash-matching-visible-p
+                (insert-before-markers-and-inherit 32)
+              (insert-before-markers-and-inherit flash-matching-char))
+            (goto-char flash-matching-mpoint)
+            (delete-char -1)
+            (setq flash-matching-visible-p
+                  (not flash-matching-visible-p))
+
+            ;; Hide fact of temporary modification during redisplay, if
+            ;; buffer was unmodified originally.
+            (or modp
+                (set-buffer-modified-p modp))
+
+            (goto-char flash-matching-opoint)))
+      (or flash-matching-visible-p
+          (let ((buffer-read-only nil))
+            (goto-char flash-matching-mpoint)
+            (insert-before-markers-and-inherit flash-matching-char)
+            (goto-char flash-matching-mpoint)
+            (delete-char -1)
+            (or modp
+                (set-buffer-modified-p modp))
+            (goto-char flash-matching-opoint))))))
+
+;; matching-paren wasn't defined in emacs until version 19.26.
+(if (fboundp 'matching-paren)
+    (defalias 'flashparen-matching-paren 'matching-paren)
+  (defun flashparen-matching-paren (c)
+    (and (memq (char-syntax c) '(?\( ?\)))
+         (lsh (aref (syntax-table) c) -8))))
+
+(provide 'flashparen)
+
+;; local variables:
+;; vc-make-backup-files: t
+;; end:
+
+;;; flashparen.el ends here