Index: ChangeLog =================================================================== RCS file: /home/lilypond/lilypond/ChangeLog,v retrieving revision 1.55 diff -p -u -r1.55 ChangeLog --- ChangeLog 4 Apr 2002 22:05:50 -0000 1.55 +++ ChangeLog 6 Apr 2002 14:35:47 -0000 @@ -1,3 +1,9 @@ +2002-04-06 Chris Jackson + + * lilypond-indent.el: Support for blinking of matching parentheses + + * lilypond-font-lock.el: Fix fontification of closing > on its own line + 2002-04-05 Han-Wen * mf/cmbase.mf: remove file. -- do without s and z signs for now. Index: lilypond-font-lock.el =================================================================== RCS file: /home/lilypond/lilypond/lilypond-font-lock.el,v retrieving revision 1.10 diff -p -u -r1.10 lilypond-font-lock.el --- lilypond-font-lock.el 26 Mar 2002 15:12:18 -0000 1.10 +++ lilypond-font-lock.el 6 Apr 2002 14:35:47 -0000 @@ -9,8 +9,8 @@ ;; Author: 1995-1996 Barry A. Warsaw ;; 1992-1994 Tim Peters ;; Created: Feb 1992 -;; Version: 1.5.47 -;; Last Modified: 26MAR2002 +;; Version: 1.5.50 +;; Last Modified: 6APR2002 ;; Keywords: lilypond languages music notation ;; This software is provided as-is, without express or implied @@ -137,12 +137,14 @@ ;; highlight bracketing constructs '("\\([][}{]\\)" 0 font-lock-warning-face t) -;; these regexps allow angle-brackets to be highlighted, -;; but leave accented notes, e.g. a b c->, alone + ;; these regexps allow angle-brackets to be highlighted when and only when they delimit simultaneous music + ;; fontify open < but leave crescendos \< alone '("[^\\]\\(<\\)" 1 font-lock-warning-face t) - '("[_^-]\\s-*[-^]\\s-*\\(>\\)" 1 font-lock-warning-face t) - '("[^\\t\\n _^-]\\s-*\\(>\\)" 1 font-lock-warning-face t) - + ;; fontify the close-brackets in (tenuto) and (marcato) + '("[_^-]\\s-*[-^]\\s-*\\(>\\)" 1 font-lock-warning-face t) + ;; but leave a b c-> (accent) alone, accounting for whitespace + '("\\([^\\t\\n _^-]\\|^\\)\\s-*\\(>\\)" 2 font-lock-warning-face t) + ;; ties ~, slurs (), hairpins \<, \>, end-of-hairpin \!, '("\\([(~)]\\|\\\\<\\|\\\\!\\|\\\\>\\)" 0 font-lock-builtin-face t) ;; highlight comments (again) @@ -169,9 +171,9 @@ (lambda (x) (modify-syntax-entry (car x) (cdr x) LilyPond-mode-syntax-table))) '(( ?\( . "." ) ( ?\) . "." ) - ( ?\[ . "(]" ) ( ?\] . ")[" ) - ( ?\{ . "(}2b" ) - ( ?\} . "){4b" ) + ( ?\[ . "(]" ) ( ?\] . ")[" ) ;; all the other paren characters are now handled by + ( ?\{ . ".2b" ) ;; lily-specific indenting/matching code in lilypond-indent.el + ( ?\} . ".4b" ) ( ?\< . "." )( ?\> . ".") ( ?\$ . "." ) ( ?\% . "." ) ( ?\& . "." ) ( ?\* . "." ) ( ?\+ . "." ) Index: lilypond-indent.el =================================================================== RCS file: /home/lilypond/lilypond/lilypond-indent.el,v retrieving revision 1.1 diff -p -u -r1.1 lilypond-indent.el --- lilypond-indent.el 1 Feb 2002 16:44:12 -0000 1.1 +++ lilypond-indent.el 6 Apr 2002 14:35:47 -0000 @@ -249,27 +249,61 @@ Argument LIM limit." (current-column))))) -(defconst LilyPond-parens-regexp-alist - `(("[^\\]<" . "[^ \\n\\t_^-]\\s-*>\\|[_^-]\\s-*[-^]\\s-*>") - ;; a b c->, a b c^> and a b c_> are not close-angle-brackets, they're accents - ;; but a b c^-> and a b c^^> are close brackets with tenuto/marcato before them - ;; also \> and \< are hairpins - ("{" . "}"))) - - -(defconst LilyPond-parens-combined-regexp - (concat (mapconcat 'car LilyPond-parens-regexp-alist "\\|") - "\\|" - (mapconcat 'cdr LilyPond-parens-regexp-alist "\\|"))) - +;; Key: Type of bracket (character). +;; Value: Pair of regexps representing the corresponding open and close bracket" +;; () are treated specially (need to indent in Scheme but not in music), and [] +;; are handled by the syntax table -(defun LilyPond-beginning-of-containing-sexp () - "Move point to the beginning of the deepest parenthesis pair enclosing point." +(defconst LilyPond-parens-regexp-alist + `( ( ?> . ("[^\\]<" . "[^ \\n\\t_^-]\\s-*>\\|[_^-]\\s-*[-^]\\s-*>")) + ;; a b c->, a b c^> and a b c_> are not close-angle-brackets, they're accents + ;; but a b c^-> and a b c^^> are close brackets with tenuto/marcato before them + ;; also \> and \< are hairpins + ( ?} . ("{" . "}")) + )) + + +(defconst LilyPond-parens-alist + `( ( ?< . ?> ) + ( ?{ . ?} ) + ( ?\( . ?\) ) + )) + + +(defun LilyPond-matching-paren (bracket-type) + "Returns the open corresponding to the close specified by bracket-type, or vice versa" + (cond ( (memq bracket-type (mapcar 'car LilyPond-parens-alist)) + (cdr (assoc bracket-type LilyPond-parens-alist)) ) + ( (memq bracket-type (mapcar 'cdr LilyPond-parens-alist)) + (car (rassoc bracket-type LilyPond-parens-alist)) ) + nil)) + + +(defun LilyPond-beginning-of-containing-sexp (&optional bracket-type slur-paren-p) + "Move point to the beginning of the deepest parenthesis pair enclosing point. + +If the optional argument bracket-type, a character representing a +close bracket such as ) or }, is specified, then the parenthesis pairs +searched are limited to this type. + +If the optional argument slur-paren-p is non-nil, then slur +parentheses () are considered as matching pairs. Otherwise Scheme +parentheses are considered to be matching pairs, but slurs are not. +slur-paren-p defaults to nil. +" (interactive) - (let ((level 1)) + (let ( (level 1) + (regexp-alist LilyPond-parens-regexp-alist) + (oldpos (point) ) ) (if (LilyPond-inside-scheme-p) - (setq paren-regexp "(\\|)" inside-scheme t) - (setq paren-regexp LilyPond-parens-combined-regexp inside-scheme nil)) + (setq paren-regexp "(\\|)") + (if slur-paren-p + (setq regexp-alist (cons '( ?\) . ("(" . ")")) regexp-alist))) + (if (memq bracket-type (mapcar 'car regexp-alist)) + (progn (setq paren-regexp (cdr (assoc bracket-type regexp-alist))) + (setq paren-regexp (concat (car paren-regexp) "\\|" (cdr paren-regexp)))) + (setq paren-regexp (concat (mapconcat 'car (mapcar 'cdr regexp-alist) "\\|") "\\|" + (mapconcat 'cdr (mapcar 'cdr regexp-alist) "\\|"))))) (while (and (> level 0) (re-search-backward paren-regexp nil t) (setq match (char-before (match-end 0)))) @@ -285,9 +319,10 @@ Argument LIM limit." (looking-at ".\\s-+<\\|\\({\\|}\\|<\\|>\\|(\\|)\\)<")) (forward-char 1)))))) (if (looking-at ".<\\|.>") (forward-char 1)) - (if (/= level 1) + (if (= level 0) (point) - nil))) + (progn (goto-char oldpos) + nil)))) (defun LilyPond-inside-scheme-p () @@ -314,3 +349,92 @@ Argument LIM limit." (> level 0)))) t nil)))) + + +;;; Largely taken from the 'blink-matching-open' in lisp/simple.el in +;;; the Emacs distribution. + +(defun LilyPond-blink-matching-open (bracket-type) + "Move cursor momentarily to the beginning of the sexp before +point. In lilypond files this is used for closing ), } and >, whereas the +builtin 'blink-matching-open' is used for closing ], which is in +the syntax table" + (interactive) + (let ( (oldpos (point)) + (level 0) + (mismatch) ) + (save-restriction + (if blink-matching-paren-distance + (narrow-to-region (max (point-min) + (- (point) blink-matching-paren-distance)) + oldpos))) + (if (memq bracket-type '(?> ?})) + ;; < { need to be mutually balanced and nested, so search backwards for both of these bracket types + (LilyPond-beginning-of-containing-sexp nil nil) + ;; whereas ( ) slurs within music don't, so only need to search for ( ) + (LilyPond-beginning-of-containing-sexp bracket-type t)) + (setq blinkpos (point)) + (setq mismatch + (or (null (LilyPond-matching-paren (char-after blinkpos))) + (/= (char-after oldpos) + (LilyPond-matching-paren (char-after blinkpos))))) + (if mismatch (progn (setq blinkpos nil) + (message "Mismatched parentheses"))) + (if blinkpos + (if (pos-visible-in-window-p) + (and blink-matching-paren-on-screen + (sit-for blink-matching-delay)) + (message + "Matches %s" + ;; Show what precedes the open in its line, if anything. + (if (save-excursion + (skip-chars-backward " \t") + (not (bolp))) + (buffer-substring (progn (beginning-of-line) (point)) + (1+ blinkpos)) + ;; Show what follows the open in its line, if anything. + (if (save-excursion + (forward-char 1) + (skip-chars-forward " \t") + (not (eolp))) + (buffer-substring blinkpos + (progn (end-of-line) (point))) + ;; Otherwise show the previous nonblank line, + ;; if there is one. + (if (save-excursion + (skip-chars-backward "\n \t") + (not (bobp))) + (concat + (buffer-substring (progn + (skip-chars-backward "\n \t") + (beginning-of-line) + (point)) + (progn (end-of-line) + (skip-chars-backward " \t") + (point))) + ;; Replace the newline and other whitespace with `...'. + "..." + (buffer-substring blinkpos (1+ blinkpos))) + ;; There is nothing to show except the char itself. + (buffer-substring blinkpos (1+ blinkpos)))))))) + (goto-char oldpos))) + + +(defun LilyPond-electric-close-paren () + "Blink on the matching open paren when a > or ) is inserted" + (interactive) + (let ((oldpos (point))) + (self-insert-command 1) + (setq close-char (char-before (point))) + (if (and blink-matching-paren + (not (LilyPond-inside-string-or-comment-p)) + (save-excursion (re-search-backward + (concat (mapconcat 'cdr (mapcar 'cdr LilyPond-parens-regexp-alist) "\\|") "\\|)") nil t) + (eq oldpos (1- (match-end 0))))) + (progn (backward-char 1) + (LilyPond-blink-matching-open close-char) + (forward-char 1))))) + + +;;; TODO: +;;; emulate show-paren-mode Index: lilypond-mode.el =================================================================== RCS file: /home/lilypond/lilypond/lilypond-mode.el,v retrieving revision 1.28 diff -p -u -r1.28 lilypond-mode.el --- lilypond-mode.el 17 Mar 2002 18:22:19 -0000 1.28 +++ lilypond-mode.el 6 Apr 2002 14:35:48 -0000 @@ -487,6 +487,9 @@ command." (define-key LilyPond-mode-map "\C-cn" 'LilyPond-insert-tag-notes) (define-key LilyPond-mode-map "\C-cs" 'LilyPond-insert-tag-score) (define-key LilyPond-mode-map "\C-c;" 'comment-region) + (define-key LilyPond-mode-map ")" 'LilyPond-electric-close-paren) + (define-key LilyPond-mode-map ">" 'LilyPond-electric-close-paren) + (define-key LilyPond-mode-map "}" 'LilyPond-electric-close-paren) ) ;;; Menu Support