]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-1.5.29
authorfred <fred>
Wed, 27 Mar 2002 02:05:06 +0000 (02:05 +0000)
committerfred <fred>
Wed, 27 Mar 2002 02:05:06 +0000 (02:05 +0000)
GNUmakefile.in
lilypond-indent.el [new file with mode: 0644]

index 1d8180ac5e0e80eb3065cc3b25ab306e1f26514e..9b7cdd7ed328fba1fdb3cce703539f58b78c0ff4 100644 (file)
@@ -20,7 +20,7 @@ SCRIPTS = configure aclocal.m4
 README_FILES =  ChangeLog CHANGES COPYING DEDICATION NEWS README.mandrake ROADMAP
 README_TXT_FILES = AUTHORS.txt README.txt INSTALL.txt FAQ.txt
 IN_FILES := $(wildcard *.in)
-EXTRA_DIST_FILES = lilypond-font-lock.el lilypond-mode.el lilypond-init.el vimrc VERSION $(README_FILES)  $(SCRIPTS) $(IN_FILES)  emacsclient.patch lexer-gcc-3.0.patch .cvsignore
+EXTRA_DIST_FILES = $(wildcard *.el) vimrc VERSION $(README_FILES)  $(SCRIPTS) $(IN_FILES)  emacsclient.patch lexer-gcc-3.0.patch .cvsignore
 NON_ESSENTIAL_DIST_FILES = $(README_TXT_FILES)
 INSTALLATION_DIR=$(datadir)
 INSTALLATION_FILES=$(configuration) VERSION
diff --git a/lilypond-indent.el b/lilypond-indent.el
new file mode 100644 (file)
index 0000000..5c2e3be
--- /dev/null
@@ -0,0 +1,316 @@
+;;; lilypond-indent.el --- Auto-indentation for lilypond code
+;;;
+;;; Chris Jackson <chris@fluffhouse.org.uk>
+;;; some code is taken from ESS (Emacs Speaks Statistics) S-mode by A.J.Rossini <rossini@biostat.washington.edu>
+
+;;; Variables for customising indentation style
+
+(defcustom LilyPond-indent-level 4
+  "*Indentation of lilypond statements with respect to containing block.")
+
+(defcustom LilyPond-brace-offset 0
+  "*Extra indentation for open braces.
+Compares with other text in same context.")
+
+(defcustom LilyPond-angle-offset 0
+  "*Extra indentation for open angled brackets .
+Compares with other text in same context.")
+
+(defcustom LilyPond-scheme-paren-offset 0
+  "*Extra indentation for open scheme parens .
+Compares with other text in same context.")
+
+(defcustom LilyPond-close-brace-offset 0
+  "*Extra indentation for closing braces.")
+
+(defcustom LilyPond-close-angle-offset 0
+  "*Extra indentation for closing angle brackets.")
+
+(defcustom LilyPond-close-scheme-paren-offset 0
+  "*Extra indentation for closing scheme parens.")
+
+(defcustom LilyPond-fancy-comments t
+  "*Non-nil means distiguish between %, %%, and %%% for indentation.")
+
+
+(defun LilyPond-calculate-indent ()
+  "Return appropriate indentation for current line as lilypond code.
+In usual case returns an integer: the column to indent to.
+Returns nil if line starts inside a string"
+  (save-excursion
+    (beginning-of-line)
+    (let ((indent-point (point))
+         (case-fold-search nil)
+         state)
+      (setq containing-sexp (save-excursion (LilyPond-beginning-of-containing-sexp)))
+      (beginning-of-defun)
+      (while (< (point) indent-point)
+       (setq state (parse-partial-sexp (point) indent-point 0)))
+      ;; (setq containing-sexp (car (cdr state))) is the traditional way for languages
+      ;; with simpler parenthesis delimiters
+      (cond ((nth 3 state) 
+            ;; point is in the middle of a string 
+            nil)
+           ((nth 4 state)
+            ;; point is in the middle of a block comment
+            (LilyPond-calculate-indent-within-blockcomment))
+           ((null containing-sexp)
+            ;; Line is at top level - no indent
+            (beginning-of-line)
+            0)
+           (t
+            ;; Find previous non-comment character.
+            (goto-char indent-point)
+            (LilyPond-backward-to-noncomment containing-sexp)
+            ;; Now we get the answer.
+            ;; Position following last unclosed open.
+            (goto-char containing-sexp)
+            (or
+             ;; Is line first statement after an open brace or bracket?
+             ;; If no, find that first statement and indent like it.
+             (save-excursion
+               (forward-char 1)
+               ;; Skip over comments following open brace.
+               (skip-chars-forward " \t\n")
+               (cond ((looking-at "%{")
+                      (while  (progn 
+                                (and (not (looking-at "%}"))
+                                     (< (point) (point-max))))
+                        (forward-line 1)
+                        (skip-chars-forward " \t\n"))
+                      (forward-line 1)
+                      (skip-chars-forward " \t\n"))
+                     ((looking-at "%")
+                      (while (progn (skip-chars-forward " \t\n")
+                                    (looking-at "%"))
+                        (forward-line 1))))
+               ;; The first following code counts
+               ;; if it is before the line we want to indent.
+               (and (< (point) indent-point)
+                    (current-column)))
+             ;; If no previous statement,
+             ;; indent it relative to line brace is on.
+             ;; For open brace in column zero, don't let statement
+             ;; start there too.  If LilyPond-indent-level is zero, use
+             ;; LilyPond-brace-offset instead
+             (+ (if (and (bolp) (zerop LilyPond-indent-level))
+                    (cond ((= (following-char) ?{) 
+                           LilyPond-brace-offset)
+                          ((= (following-char) ?<) 
+                           LilyPond-angle-offset)
+                          ((= (following-char) ?\))
+                           LilyPond-scheme-paren-offset)
+                          (t
+                           0))
+                  LilyPond-indent-level)
+                (progn
+                  (skip-chars-backward " \t")
+                  (current-indentation)))))))))
+
+
+
+(defun LilyPond-indent-line ()
+  "Indent current line as lilypond code.
+Return the amount the indentation changed by."
+  (let ((indent (LilyPond-calculate-indent))
+       beg shift-amt
+       (case-fold-search nil)
+       (pos (- (point-max) (point))))
+    (beginning-of-line)
+    (setq beg (point))
+    (cond ((eq indent nil)
+          (setq indent (current-indentation)))
+         (t
+          (skip-chars-forward " \t")
+          (if (and LilyPond-fancy-comments (looking-at "%%%\\|%{\\|%}"))
+              (setq indent 0))
+          (if (and LilyPond-fancy-comments
+                   (looking-at "%")
+                   (not (looking-at "%%\\|%{\\|%}")))
+              (setq indent comment-column)
+            (if (eq indent t) (setq indent 0))
+            (if (listp indent) (setq indent (car indent)))
+            (cond
+             ((= (following-char) ?})
+              (setq indent  (+ indent (- LilyPond-close-brace-offset LilyPond-indent-level))))
+             ((= (following-char) ?>)
+              (setq indent  (+ indent (- LilyPond-close-angle-offset LilyPond-indent-level))))
+             ((and (= (following-char) ?\)) (LilyPond-inside-scheme-p))
+              (setq indent  (+ indent (- LilyPond-close-scheme-paren-offset LilyPond-indent-level))))
+             ((= (following-char) ?{)
+              (setq indent  (+ indent LilyPond-brace-offset)))
+             ((= (following-char) ?<)
+              (setq indent  (+ indent LilyPond-angle-offset)))
+             ((and (= (following-char) ?\() (LilyPond-inside-scheme-p))
+              (setq indent  (+ indent LilyPond-scheme-paren-offset)))
+             ))))
+    (skip-chars-forward " \t")
+    (setq shift-amt (- indent (current-column)))
+    (if (zerop shift-amt)
+       (if (> (- (point-max) pos) (point))
+           (goto-char (- (point-max) pos)))
+      (delete-region beg (point))
+      (indent-to indent)
+      ;; If initial point was within line's indentation,
+      ;; position after the indentation.
+      ;; Else stay at same point in text.
+      (if (> (- (point-max) pos) (point))
+         (goto-char (- (point-max) pos))))
+    shift-amt))
+
+
+(defun LilyPond-inside-comment-p ()
+  "Return non-nil if point is inside a line or block comment"
+  (setq this-point (point))
+  (or (save-excursion (beginning-of-line)
+                     (skip-chars-forward " \t")
+                     (looking-at "%"))
+      (save-excursion 
+       ;; point is in the middle of a block comment
+       (setq lastopen  (save-excursion (re-search-backward "%{[ \\t]*" (point-min) t)))
+       (setq lastclose (save-excursion (re-search-backward "%}[ \\t]*" (point-min) t)))
+       (if (or (and (= (char-before) ?%) (= (char-after) ?{))
+               (and (= (char-after)  ?%) (= (char-after (1+ (point))) ?{)))
+           (setq lastopen (save-excursion (backward-char) (point))))
+       (and 
+        lastopen
+        (or (not lastclose)
+            (<= lastclose lastopen))))
+      ))
+
+
+(defun LilyPond-inside-string-or-comment-p ()
+  "Test if point is inside a string or a comment"
+  (setq this-point (point))
+  (or (save-excursion (beginning-of-line)
+                     (skip-chars-forward " \t")
+                     (looking-at "%"))
+      (save-excursion 
+       (beginning-of-defun)
+       (while (< (point) this-point)
+         (setq state (parse-partial-sexp (point) this-point 0)))
+       (cond ((nth 3 state) 
+              ;; point is in the middle of a string 
+              t )
+             ((nth 4 state)
+              ;; point is in the middle of a block comment
+              t ) 
+             (t
+              nil)))))
+
+
+(defun LilyPond-backward-over-blockcomments (lim)
+  "Move point back to closest non-whitespace character not part of a block comment"
+  (setq lastopen  (save-excursion (re-search-backward "%{[ \\t]*" lim t)))
+  (setq lastclose (save-excursion (re-search-backward "%}[ \\t]*" lim t)))
+  (if lastopen
+      (if lastclose
+         (if (<= lastclose lastopen)
+             (goto-char lastopen))
+       (goto-char lastopen)))
+  (skip-chars-backward " %\t\n\f"))
+
+
+(defun LilyPond-backward-over-linecomments (lim)
+  "Move point back to the closest non-whitespace character not part of a line comment.
+Argument LIM limit."
+  (let (opoint stop)
+    (while (not stop)
+      (skip-chars-backward " \t\n\f" lim)
+      (setq opoint (point))
+      (beginning-of-line)
+      (search-forward "%" opoint 'move)
+      (skip-chars-backward " \t%")
+      (setq stop (or (/= (preceding-char) ?\n) (<= (point) lim)))
+      (if stop (point)
+       (beginning-of-line)))))
+
+
+(defun LilyPond-backward-to-noncomment (lim)
+  "Move point back to closest non-whitespace character not part of a comment"
+  (LilyPond-backward-over-linecomments lim)
+  (LilyPond-backward-over-blockcomments lim))
+
+
+(defun LilyPond-calculate-indent-within-blockcomment ()
+  "Return the indentation amount for line inside a block comment."
+  (let (end percent-start)
+    (save-excursion
+      (beginning-of-line)
+      (skip-chars-forward " \t")
+      (skip-chars-backward " \t\n")
+      (setq end (point))
+      (beginning-of-line)
+      (skip-chars-forward " \t")
+      (and (re-search-forward "%{[ \t]*" end t)
+          (goto-char (1+ (match-beginning 0))))
+      (if (and (looking-at "[ \t]*$") (= (preceding-char) ?\%))
+         (1+ (current-column))
+       (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 "\\|")))
+
+
+(defun LilyPond-beginning-of-containing-sexp ()
+  "Move point to the beginning of the deepest parenthesis pair enclosing point."
+  (interactive)
+  (let ((level 1))
+    (if (LilyPond-inside-scheme-p)
+       (setq paren-regexp "(\\|)" inside-scheme t)
+      (setq paren-regexp LilyPond-parens-combined-regexp inside-scheme nil))
+    (while (and (> level 0) 
+               (re-search-backward paren-regexp nil t)
+               (setq match (char-before (match-end 0))))
+      (if (not (save-excursion (goto-char (match-end 0)) 
+                              (LilyPond-inside-string-or-comment-p)))
+         (if (memq match '(?} ?> ?\)))
+             (progn (setq level (1+ level))
+                    (if (and (= match ?>) 
+                             (looking-at ".\\s-+>\\|\\({\\|}\\|<\\|>\\|(\\|)\\)>"))
+                        (forward-char 1)))
+           (progn (setq level (1- level))
+                  (if (and (= match ?<)
+                           (looking-at ".\\s-+<\\|\\({\\|}\\|<\\|>\\|(\\|)\\)<"))
+                      (forward-char 1))))))
+    (if (looking-at ".<\\|.>") (forward-char 1))
+    (if (/= level 1) 
+       (point)
+      nil)))
+
+
+(defun LilyPond-inside-scheme-p ()
+  "Tests if point is inside embedded Scheme code"
+  (interactive)
+  (let ( (test-point (point))
+        (level 0) )
+    (save-excursion 
+      (if (or (and (= (char-after (point)) ?\()
+                  (or (= (char-after (- (point) 1)) ?#)
+                      (and (= (char-after (- (point) 2)) ?#)
+                           (= (char-after (- (point) 1)) ?`))))
+             (and (re-search-backward "#(\\|#`(" nil t)
+                  (progn 
+                    (search-forward "(")
+                    (setq level 1)
+                    (while (and (> level 0)
+                                (re-search-forward "(\\|)" test-point t)
+                                (setq match (char-after (match-beginning 0)))
+                                (<= (point) test-point))
+                      (if (= match ?\()
+                          (setq level (1+ level))
+                        (setq level (1- level))))
+                    (> level 0))))
+         t
+       nil))))