X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=elisp%2Flilypond-mode.el;h=0bf05408e2075240253a54efb23876dc2d3ff236;hb=97a0169312a260933246ab224e4f8b0969871dd5;hp=9e11820557d4fc51793bce2a2103ca7082aa7c97;hpb=f017b6d1866a570f1234fabcc54e02e434d51cce;p=lilypond.git diff --git a/elisp/lilypond-mode.el b/elisp/lilypond-mode.el index 9e11820557..0bf05408e2 100644 --- a/elisp/lilypond-mode.el +++ b/elisp/lilypond-mode.el @@ -1,15 +1,26 @@ -;;; -;;; lilypond-mode.el --- Major mode for editing GNU LilyPond music scores -;;; -;;; source file of the GNU LilyPond music typesetter -;;; -;;; (c) 1999--2004 Jan Nieuwenhuizen -;;; -;;; Changed 2001--2003 Heikki Junes -;;; * Add PS-compilation, PS-viewing and MIDI-play (29th Aug 2001) -;;; * Keyboard shortcuts (12th Sep 2001) -;;; * Inserting tags, inspired on sgml-mode (11th Oct 2001) -;;; * Autocompletion & Info (23rd Nov 2002) +;;;; lilypond-mode.el -- Major mode for editing GNU LilyPond music scores +;;;; This file is part of LilyPond, the GNU music typesetter. +;;;; +;;;; Copyright (C) 1999--2015 Jan Nieuwenhuizen +;;;; Changed 2001--2003 Heikki Junes +;;;; * Add PS-compilation, PS-viewing and MIDI-play (29th Aug 2001) +;;;; * Keyboard shortcuts (12th Sep 2001) +;;;; * Inserting tags, inspired on sgml-mode (11th Oct 2001) +;;;; * Autocompletion & Info (23rd Nov 2002) +;;;; +;;;; LilyPond 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 of the License, or +;;;; (at your option) any later version. +;;;; +;;;; LilyPond 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 LilyPond. If not, see . + ;;; Inspired on auctex @@ -19,7 +30,7 @@ (require 'easymenu) (require 'compile) -(defconst LilyPond-version "2.3.17" +(defconst LilyPond-version "2.5.20" "`LilyPond-mode' version number.") (defconst LilyPond-help-address "bug-lilypond@gnu.org" @@ -32,7 +43,7 @@ "File prefix for commands on buffer or region.") (defvar LilyPond-master-file nil - "Master file that Lilypond will be run on.") + "Master file that LilyPond will be run on.") ;; FIXME: find ``\score'' in buffers / make settable? (defun LilyPond-get-master-file () @@ -230,7 +241,7 @@ in LilyPond-include-path." (defun LilyPond-running () "Check the currently running LilyPond compiling jobs." - (let ((process-names (list "lilypond" "tex" "2dvi" "2ps" "2midi" + (let ((process-names (list "lilypond" "tex" "2ps" "2midi" "book" "latex")) (running nil)) (while (setq process-name (pop process-names)) @@ -275,15 +286,14 @@ in LilyPond-include-path." (defun LilyPond-compile-file (command name) ;; We maybe should know what we run here (Lily, lilypond, tex) ;; and adjust our error-matching regex ? - (compile-internal + (compilation-start (if (eq LilyPond-command-current 'LilyPond-command-master) command ;; use temporary directory for Commands on Buffer/Region ;; hm.. the directory is set twice, first to default-dir - (concat "cd " (LilyPond-temp-directory) "; " command)) - "No more errors" name)) + (concat "cd " (LilyPond-temp-directory) "; " command)))) -;; do we still need this, now that we're using compile-internal? +;; do we still need this, now that we're using compilation-start? (defun LilyPond-save-buffer () "Save buffer and set default command for compiling." (interactive) @@ -322,18 +332,23 @@ in LilyPond-include-path." ;; variable instead of quering the user. (defvar LilyPond-command-force nil) -(defcustom LilyPond-xdvi-command "xdvi" - "Command used to display DVI files." - +(defcustom LilyPond-lilypond-command "lilypond" + "Command used to compile LY files." :group 'LilyPond :type 'string) -(defcustom LilyPond-gv-command "gv -watch" +(defcustom LilyPond-ps-command "gv --watch" "Command used to display PS files." :group 'LilyPond :type 'string) +(defcustom LilyPond-pdf-command "xpdf" + "Command used to display PDF files." + + :group 'LilyPond + :type 'string) + (defcustom LilyPond-midi-command "timidity" "Command used to play MIDI files." @@ -356,6 +371,13 @@ in LilyPond-include-path." (interactive) (LilyPond-command (LilyPond-command-menu "MidiAll") 'LilyPond-get-master-file)) +(defun count-matches-as-number (re) + "Count-matches in emacs 22 backwards-incompatibly returns a number" + (let ((result (count-matches re))) + (if (stringp result) + (string-to-number result) + result))) + (defun count-rexp (start end rexp) "Print number of found regular expressions in the region." (interactive "r") @@ -363,7 +385,7 @@ in LilyPond-include-path." (save-restriction (narrow-to-region start end) (goto-char (point-min)) - (count-matches rexp)))) + (count-matches-as-number rexp)))) (defun count-midi-words () "Check number of midi-scores before the curser." @@ -382,8 +404,8 @@ in LilyPond-include-path." (let ((fnameprefix (if (eq LilyPond-command-current 'LilyPond-command-master) (substring (LilyPond-get-master-file) 0 -3); suppose ".ly" LilyPond-region-file-prefix)) - (allcount (string-to-number (substring (count-midi-words) 0 -12))) - (count (string-to-number (substring (count-midi-words-backwards) 0 -12)))) + (allcount (count-midi-words)) + (count (count-midi-words-backwards))) (concat fnameprefix (if (and (> allcount 1) (> count 0)) ; not first score (if (eq count allcount) ; last score @@ -396,7 +418,7 @@ in LilyPond-include-path." (let ((fnameprefix (if (eq LilyPond-command-current 'LilyPond-command-master) (substring (LilyPond-get-master-file) 0 -3); suppose ".ly" LilyPond-region-file-prefix)) - (allcount (string-to-number (substring (count-midi-words) 0 -12)))) + (allcount (count-midi-words))) (concat (if (> allcount 0) ; at least one midi-score (concat fnameprefix ".midi ")) (if (> allcount 1) ; more than one midi-score @@ -410,29 +432,22 @@ in LilyPond-include-path." (defcustom LilyPond-command-alist ;; Should expand this to include possible keyboard shortcuts which ;; could then be mapped to define-key and menu. - `( - ("LilyPond" . ("lilypond -ftex %s" "%s" "%l" "View")) - ("TeX" . ("tex '\\nonstopmode\\input %t'" "%t" "%d" "View")) - - ("2Dvi" . ("lilypond -f tex %s" "%s" "%d" "LaTeX")) - ("2PS" . ("lilypond -f ps %s" "%s" "%p" "ViewPS")) - ("2Midi" . ("lilypond -m %s" "%s" "%m" "Midi")) - + '( + ("LilyPond" . ((LilyPond-lilypond-command " %s") "%s" "%l" "View")) + ("2PS" . ((LilyPond-lilypond-command " -f ps %s") "%s" "%p" "ViewPS")) ("Book" . ("lilypond-book %x" "%x" "%l" "LaTeX")) - ("LaTeX" . ("latex '\\nonstopmode\\input %l'" "%l" "%d" "View")) - - ;; point-n-click (arg: exits upop USR1) - ("SmartView" . ("xdvi %d")) + ("LaTeX" . ("latex '\\nonstopmode\\input %l'" "%l" "%d" "ViewDVI")) ;; refreshes when kicked USR1 - ("View" . (,(concat LilyPond-xdvi-command " %d"))) - ("ViewPS" . (,(concat LilyPond-gv-command " %p"))) + ("View" . ((LilyPond-pdf-command " %f"))) + ("ViewPDF" . ((LilyPond-pdf-command " %f"))) + ("ViewPS" . ((LilyPond-ps-command " %p"))) ;; The following are refreshed in LilyPond-command: ;; - current-midi depends on cursor position and - ("Midi" . (,(concat LilyPond-midi-command " " (LilyPond-string-current-midi)))) ; + ("Midi" . ("")) ; ;; - all-midi depends on number of midi-score. - ("MidiAll" . (,(concat LilyPond-all-midi-command " " (LilyPond-string-all-midi)))) + ("MidiAll" . ("")) ) "AList of commands to execute on the current document. @@ -462,6 +477,7 @@ LilyPond-expand-list. ("%s" . ".ly") ("%t" . ".tex") ("%d" . ".dvi") + ("%f" . ".pdf") ("%p" . ".ps") ("%l" . ".tex") ("%x" . ".tely") @@ -545,12 +561,6 @@ Must be the car of an entry in `LilyPond-command-alist'." (LilyPond-command (LilyPond-command-menu "LilyPond") 'LilyPond-get-master-file) ) -(defun LilyPond-command-formatdvi () - "Format the dvi output of the current document." - (interactive) - (LilyPond-command (LilyPond-command-menu "2Dvi") 'LilyPond-get-master-file) -) - (defun LilyPond-command-formatps () "Format the ps output of the current document." (interactive) @@ -560,26 +570,22 @@ Must be the car of an entry in `LilyPond-command-alist'." (defun LilyPond-command-formatmidi () "Format the midi output of the current document." (interactive) - (LilyPond-command (LilyPond-command-menu "2Midi") 'LilyPond-get-master-file) -) + (LilyPond-command (LilyPond-command-menu "2Midi") 'LilyPond-get-master-file)) -(defun LilyPond-command-smartview () - "View the dvi output of current document." +(defun LilyPond-command-view () + "View the output of current document." (interactive) - (LilyPond-command (LilyPond-command-menu "SmartView") 'LilyPond-get-master-file) -) + (LilyPond-command-viewpdf)) -(defun LilyPond-command-view () - "View the dvi output of current document." +(defun LilyPond-command-viewpdf () + "View the ps output of current document." (interactive) - (LilyPond-command (LilyPond-command-menu "View") 'LilyPond-get-master-file) -) + (LilyPond-command (LilyPond-command-menu "ViewPDF") 'LilyPond-get-master-file)) (defun LilyPond-command-viewps () "View the ps output of current document." (interactive) - (LilyPond-command (LilyPond-command-menu "ViewPS") 'LilyPond-get-master-file) -) + (LilyPond-command (LilyPond-command-menu "ViewPS") 'LilyPond-get-master-file)) ;; FIXME, this is broken (defun LilyPond-region-file (begin end) @@ -610,24 +616,35 @@ Must be the car of an entry in `LilyPond-command-alist'." (LilyPond-command-select-buffer) (LilyPond-command-region (point-min) (point-max))) -(defun LilyPond-command-expand (string file) - (let ((case-fold-search nil)) - (if (string-match "%" string) - (let* ((b (match-beginning 0)) - (e (+ b 2)) - (l (split-file-name file)) - (dir (car l)) - (base (cadr l))) - (LilyPond-command-expand - (concat (substring string 0 b) - dir - base - (let ((entry (assoc (substring string b e) - LilyPond-expand-alist))) - (if entry (cdr entry) "")) - (substring string e)) - file)) - string))) +(defun LilyPond-command-expand (arg file) + (cond + ((listp arg) + (mapconcat (lambda (arg) (LilyPond-command-expand arg file)) + arg + "")) + ((and (symbolp arg) (boundp arg) + ;; Avoid self-quoting symbols + (not (eq (symbol-value arg) arg))) + (LilyPond-command-expand (symbol-value arg) file)) + ((stringp arg) + (let ((case-fold-search nil)) + (if (string-match "%" arg) + (let* ((b (match-beginning 0)) + (e (+ b 2)) + (l (split-file-name file)) + (dir (car l)) + (base (cadr l))) + (concat (substring arg 0 b) + (shell-quote-argument (concat dir base)) + (LilyPond-command-expand + (concat + (let ((entry (assoc (substring arg b e) + LilyPond-expand-alist))) + (if entry (cdr entry) "")) + (substring arg e)) + file))) + arg))) + (t (error "Bad expansion `%S'" arg)))) (defun LilyPond-shell-process (name buffer command) (let ((old (current-buffer))) @@ -686,7 +703,7 @@ command." (while (LilyPond-running) (message "Starts playing midi once it is built.") (sit-for 0 100)))))) - (if (member name (list "LilyPond" "TeX" "2Midi" "2PS" "2Dvi" + (if (member name (list "LilyPond" "TeX" "2Midi" "2PS" "Book" "LaTeX")) (if (setq jobs (LilyPond-running)) (progn @@ -744,10 +761,8 @@ command." (define-key LilyPond-mode-map "\C-c\C-k" 'LilyPond-kill-jobs) (define-key LilyPond-mode-map "\C-c\C-c" 'LilyPond-command-master) (define-key LilyPond-mode-map "\C-cm" 'LilyPond-command-formatmidi) - (define-key LilyPond-mode-map "\C-c\C-d" 'LilyPond-command-formatdvi) (define-key LilyPond-mode-map "\C-c\C-f" 'LilyPond-command-formatps) - (define-key LilyPond-mode-map "\C-c\C-s" 'LilyPond-command-smartview) - (define-key LilyPond-mode-map "\C-c\C-v" 'LilyPond-command-view) + (define-key LilyPond-mode-map "\C-c\C-s" 'LilyPond-command-view) (define-key LilyPond-mode-map "\C-c\C-p" 'LilyPond-command-viewps) (define-key LilyPond-mode-map [(control c) return] 'LilyPond-command-current-midi) (define-key LilyPond-mode-map [(control c) (control return)] 'LilyPond-command-all-midi) @@ -755,7 +770,7 @@ command." (define-key LilyPond-mode-map "\C-cb" 'LilyPond-what-beat) (define-key LilyPond-mode-map "\C-cf" 'font-lock-fontify-buffer) (define-key LilyPond-mode-map "\C-ci" 'LilyPond-insert-tag-current) - ;; the following will should be overriden by Lilypond Quick Insert Mode + ;; the following will should be overridden by LilyPond Quick Insert Mode (define-key LilyPond-mode-map "\C-cq" 'LilyPond-quick-insert-mode) (define-key LilyPond-mode-map "\C-c;" 'LilyPond-comment-region) (define-key LilyPond-mode-map ")" 'LilyPond-electric-close-paren) @@ -765,7 +780,7 @@ command." (define-key LilyPond-mode-map "|" 'LilyPond-electric-bar) (if (string-match "XEmacs\\|Lucid" emacs-version) (define-key LilyPond-mode-map [iso-left-tab] 'LilyPond-autocompletion) - (define-key LilyPond-mode-map [iso-lefttab] 'LilyPond-autocompletion)) + (define-key LilyPond-mode-map [(shift iso-lefttab)] 'LilyPond-autocompletion)) (define-key LilyPond-mode-map "\C-c\t" 'LilyPond-info-index-search) ) @@ -963,15 +978,12 @@ command." ;;; Some kind of mapping which includes :keys might be more elegant ;;; Put keys to LilyPond-command-alist and fetch them from there somehow. '([ "LilyPond" LilyPond-command-lilypond t]) - '([ "TeX" (LilyPond-command (LilyPond-command-menu "TeX") 'LilyPond-get-master-file) ]) - '([ "2Dvi" LilyPond-command-formatdvi t]) '([ "2PS" LilyPond-command-formatps t]) '([ "2Midi" LilyPond-command-formatmidi t]) '([ "Book" (LilyPond-command (LilyPond-command-menu "Book") 'LilyPond-get-master-file) ]) '([ "LaTeX" (LilyPond-command (LilyPond-command-menu "LaTeX") 'LilyPond-get-master-file) ]) '([ "Kill jobs" LilyPond-kill-jobs t]) '("-----") - '([ "SmartView" LilyPond-command-smartview t]) '([ "View" LilyPond-command-view t]) '([ "ViewPS" LilyPond-command-viewps t]) '("-----") @@ -986,17 +998,17 @@ command." (defun LilyPond-menu-keywords () "Make Insert Tag menu. -The Insert Tag -menu is splitted into parts if it is long enough." +The Insert Tag -menu is split into parts if it is long enough." (let ((li (mapcar 'LilyPond-menu-keywords-item LilyPond-menu-keywords)) (w (round (sqrt (length LilyPond-menu-keywords)))) - (splitted '()) + (split '()) (imin 0) imax lw rw) (while (< imin (length LilyPond-menu-keywords)) (setq imax (- (min (+ imin w) (length LilyPond-menu-keywords)) 1)) (setq lw (nth imin LilyPond-menu-keywords)) (setq rw (nth imax LilyPond-menu-keywords)) - (add-to-list 'splitted + (add-to-list 'split (let ((l (list (concat (substring lw 0 (min 7 (length lw))) " ... " (substring rw 0 (min 7 (length rw))))))) @@ -1004,7 +1016,7 @@ The Insert Tag -menu is splitted into parts if it is long enough." (add-to-list 'l (nth imin li)) (setq imin (1+ imin))) (reverse l)))) - (if (> (length LilyPond-menu-keywords) 12) (reverse splitted) li))) + (if (> (length LilyPond-menu-keywords) 12) (reverse split) li))) ;;; LilyPond-mode-menu should not be interactive, via "M-x LilyPond-" (easy-menu-define LilyPond-mode-menu @@ -1086,8 +1098,7 @@ COMMANDS \\{LilyPond-mode-map} VARIABLES -LilyPond-command-alist\t\talist from name to command -LilyPond-xdvi-command\t\tcommand to display dvi files -- bit superfluous" +LilyPond-command-alist\t\talist from name to command" (interactive) ;; set up local variables (kill-all-local-variables) @@ -1147,11 +1158,12 @@ LilyPond-xdvi-command\t\tcommand to display dvi files -- bit superfluous" ;; Use Command on Region even for inactive mark (region). (if (string-match "XEmacs\\|Lucid" emacs-version) - (setq zmacs-regions nil) + (progn + (setq zmacs-regions nil) + (make-local-hook 'post-command-hook)) ; XEmacs requires (setq mark-even-if-inactive t)) ;; Context dependent syntax tables in LilyPond-mode - (make-local-hook 'post-command-hook) ; XEmacs requires (add-hook 'post-command-hook 'LilyPond-mode-context-set-syntax-table nil t) ;; Turn on paren-mode buffer-locally, i.e., in LilyPond-mode @@ -1182,7 +1194,7 @@ LilyPond-xdvi-command\t\tcommand to display dvi files -- bit superfluous" (defun LilyPond-guile () (interactive) (require 'ilisp) - (guile "lilyguile" (LilyPond-command-expand (cadr (assoc "2Dvi" LilyPond-command-alist)) + (guile "lilyguile" (LilyPond-command-expand (cadr (assoc "LilyPond" LilyPond-command-alist)) (funcall 'LilyPond-get-master-file))) (comint-default-send (ilisp-process) "(define-module (*anonymous-ly-0*))") (comint-default-send (ilisp-process) "(set! %load-path (cons \"/usr/share/ilisp/\" %load-path))")