X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=elisp%2Flilypond-mode.el;h=d27487c6edb8c9cb12086a511f7b5f38665946e3;hb=6f664e0e318a1651f6fe9317a842bf9c7f476f08;hp=7eb59cec7160797d70f82befae6f16f6d5b32ab3;hpb=f23a0d9dcda87d3f6f072fba3addeae941cce4aa;p=lilypond.git diff --git a/elisp/lilypond-mode.el b/elisp/lilypond-mode.el index 7eb59cec71..d27487c6ed 100644 --- a/elisp/lilypond-mode.el +++ b/elisp/lilypond-mode.el @@ -1,15 +1,15 @@ -;;; -;;; 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 +;;;; +;;;; source file of the GNU LilyPond music typesetter +;;;; +;;;; (c) 1999--2006 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) ;;; Inspired on auctex @@ -19,7 +19,7 @@ (require 'easymenu) (require 'compile) -(defconst LilyPond-version "1.9.9" +(defconst LilyPond-version "2.5.20" "`LilyPond-mode' version number.") (defconst LilyPond-help-address "bug-lilypond@gnu.org" @@ -31,10 +31,13 @@ (defvar LilyPond-region-file-prefix "emacs-lily" "File prefix for commands on buffer or region.") +(defvar LilyPond-master-file nil + "Master file that Lilypond will be run on.") + ;; FIXME: find ``\score'' in buffers / make settable? -(defun LilyPond-master-file () - ;; duh - (buffer-file-name)) +(defun LilyPond-get-master-file () + (or LilyPond-master-file + (buffer-file-name))) (defvar LilyPond-kick-xdvi nil "If true, no simultaneous xdvi's are started, but reload signal is sent.") @@ -60,13 +63,13 @@ Finds file lilypond-words.el from load-path." (let ((fn nil) (lp load-path) - (words-file "lilypond.words.el")) + (words-file "lilypond-words.el")) (while (and (> (length lp) 0) (not fn)) (setq fn (concat (car lp) "/" words-file)) (if (not (file-readable-p fn)) (progn (setq fn nil) (setq lp (cdr lp))))) (if (not fn) - (progn (message "Warning: `lilypond.words.el' not found in `load-path'. See `lilypond-init.el'.") + (progn (message "Warning: `lilypond-words.el' not found in `load-path'. See `lilypond-init.el'.") (sit-for 5 0))) fn)) @@ -74,6 +77,16 @@ Finds file lilypond-words.el from load-path." "Contains all words: \keywords \Identifiers and ReservedWords." (nconc '(("" . 1)) x)) +(if (> emacs-major-version 20) + (defun get-buffer-size (b) (buffer-size b)) + (defun get-buffer-size (b) + (let (size (current-buffer (current-buffer))) + (set-buffer b) + (setq size (buffer-size)) + (set-buffer current-buffer) + size + ))) + ;; creates dictionary if empty (if (and (eq (length (LilyPond-add-dictionary-word ())) 1) (not (eq (LilyPond-words-filename) nil))) @@ -81,7 +94,7 @@ Finds file lilypond-words.el from load-path." (setq b (find-file-noselect (LilyPond-words-filename) t t)) (setq m (set-marker (make-marker) 1 (get-buffer b))) (setq i 1) - (while (> (buffer-size b) (marker-position m)) + (while (> (get-buffer-size b) (marker-position m)) (setq i (+ i 1)) (setq copy (copy-alist (list (eval (symbol-name (read m)))))) (setcdr copy i) @@ -276,7 +289,7 @@ in LilyPond-include-path." (interactive) (if (buffer-modified-p) (progn (save-buffer) - (setq LilyPond-command-default "LilyPond")))) + (setq LilyPond-command-next LilyPond-command-default)))) ;;; return (dir base ext) (defun split-file-name (name) @@ -299,6 +312,8 @@ in LilyPond-include-path." :type 'string) ;;;(make-variable-buffer-local 'LilyPond-command-last) +(defvar LilyPond-command-next LilyPond-command-default) + (defvar LilyPond-command-current 'LilyPond-command-master) ;;;(make-variable-buffer-local 'LilyPond-command-master) @@ -307,18 +322,29 @@ in LilyPond-include-path." ;; variable instead of quering the user. (defvar LilyPond-command-force nil) -(defcustom LilyPond-xdvi-command "xdvi" +(defcustom LilyPond-lilypond-command "lilypond" + "Command used to compile LY files." + :group 'LilyPond + :type 'string) + +(defcustom LilyPond-dvi-command "xdvi" "Command used to display DVI 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." @@ -334,13 +360,20 @@ in LilyPond-include-path." (defun LilyPond-command-current-midi () "Play midi corresponding to the current document." (interactive) - (LilyPond-command (LilyPond-command-menu "Midi") 'LilyPond-master-file)) + (LilyPond-command (LilyPond-command-menu "Midi") 'LilyPond-get-master-file)) (defun LilyPond-command-all-midi () "Play midi corresponding to the current document." (interactive) - (LilyPond-command (LilyPond-command-menu "MidiAll") 'LilyPond-master-file)) - + (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") @@ -348,7 +381,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." @@ -365,10 +398,10 @@ in LilyPond-include-path." (defun LilyPond-string-current-midi () "Check the midi file of the following midi-score in the current document." (let ((fnameprefix (if (eq LilyPond-command-current 'LilyPond-command-master) - (substring (LilyPond-master-file) 0 -3); suppose ".ly" + (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 @@ -379,9 +412,9 @@ in LilyPond-include-path." (defun LilyPond-string-all-midi () "Return the midi files of the current document in ascending order." (let ((fnameprefix (if (eq LilyPond-command-current 'LilyPond-command-master) - (substring (LilyPond-master-file) 0 -3); suppose ".ly" + (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 @@ -396,28 +429,26 @@ in LilyPond-include-path." ;; Should expand this to include possible keyboard shortcuts which ;; could then be mapped to define-key and menu. `( - ("LilyPond" . ("lilypond-bin %s" . "LaTeX")) - ("TeX" . ("tex '\\nonstopmode\\input %t'" . "View")) + ("LilyPond" . (,(concat LilyPond-lilypond-command " %s") "%s" "%l" "View")) + ("TeX" . ("tex '\\nonstopmode\\input %t'" "%t" "%d" "ViewDVI")) + ("2Dvi" . (,(concat LilyPond-lilypond-command " -b tex %s") "%s" "%d" "LaTeX")) + ("2PS" . (,(concat LilyPond-lilypond-command " -f ps %s") "%s" "%p" "ViewPS")) + ("2Gnome" . (,(concat LilyPond-lilypond-command " -b gnome %s"))) - ("2Dvi" . ("lilypond %s" . "View")) - ("2PS" . ("lilypond -P %s" . "ViewPS")) - ("2Midi" . ("lilypond -m %s" . "View")) - - ("Book" . ("lilypond-book %x" . "LaTeX")) - ("LaTeX" . ("latex '\\nonstopmode\\input %l'" . "View")) - - ;; point-n-click (arg: exits upop USR1) - ("SmartView" . ("xdvi %d" . "LilyPond")) + ("Book" . ("lilypond-book %x" "%x" "%l" "LaTeX")) + ("LaTeX" . ("latex '\\nonstopmode\\input %l'" "%l" "%d" "ViewDVI")) ;; refreshes when kicked USR1 - ("View" . (,(concat LilyPond-xdvi-command " %d") . "LilyPond")) - ("ViewPS" . (,(concat LilyPond-gv-command " %p") . "LilyPond")) + ("View" . (,(concat LilyPond-pdf-command " %f"))) + ("ViewPDF" . (,(concat LilyPond-pdf-command " %f"))) + ("ViewDVI" . (,(concat LilyPond-dvi-command " %d"))) + ("ViewPS" . (,(concat 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)) . "LilyPond" )) ; + ("Midi" . ("")) ; ;; - all-midi depends on number of midi-score. - ("MidiAll" . (,(concat LilyPond-all-midi-command " " (LilyPond-string-all-midi)) . "LilyPond")) + ("MidiAll" . ("")) ) "AList of commands to execute on the current document. @@ -447,6 +478,7 @@ LilyPond-expand-list. ("%s" . ".ly") ("%t" . ".tex") ("%d" . ".dvi") + ("%f" . ".pdf") ("%p" . ".ps") ("%l" . ".tex") ("%x" . ".tely") @@ -472,39 +504,39 @@ Must be the car of an entry in `LilyPond-command-alist'." :group 'LilyPond :type 'string) -(defun xLilyPond-compile-sentinel (process msg) - (if (and process - (= 0 (process-exit-status process))) - (setq LilyPond-command-default - (cddr (assoc LilyPond-command-default LilyPond-command-alist))))) - -;; FIXME: shouldn't do this for stray View/xdvi -(defun LilyPond-compile-sentinel (buffer msg) - (if (string-match "^finished" msg) - (setq LilyPond-command-default - (cddr (assoc LilyPond-command-default LilyPond-command-alist))))) - -;;(make-variable-buffer-local 'compilation-finish-function) -(setq compilation-finish-function 'LilyPond-compile-sentinel) +(defun LilyPond-find-required-command (command file) + "Find the first command in the chain that is needed to run + (input file is newer than the output file)" + (let* ((entry (cdr (assoc command LilyPond-command-alist))) + (next-command (nth 3 entry))) + (if (null next-command) + command + (let* ((src-string (nth 1 entry)) + (input (LilyPond-command-expand src-string file)) + (output (LilyPond-command-expand (nth 2 entry) file))) + (if (or (file-newer-than-file-p input output) + (and (equal "%s" src-string) + (not (equal (buffer-name) file)) + (file-newer-than-file-p (buffer-name) + output))) + command + (LilyPond-find-required-command next-command file)))))) (defun LilyPond-command-query (name) "Query the user for what LilyPond command to use." - (let* ((default (cond ((if (string-equal name LilyPond-region-file-prefix) - (LilyPond-check-files (concat name ".tex") - (list name) - (list LilyPond-file-extension)) - (if (verify-visited-file-modtime (current-buffer)) - (if (buffer-modified-p) - (if (y-or-n-p "Save buffer before next command? ") - (LilyPond-save-buffer))) - (if (y-or-n-p "The command will be invoked to an already saved buffer. Revert it? ") - (revert-buffer t t))) - ;;"LilyPond" - LilyPond-command-default)) - (t LilyPond-command-default))) - - (completion-ignore-case t) - + (cond ((string-equal name LilyPond-region-file-prefix) + (LilyPond-check-files (concat name ".tex") + (list name) + (list LilyPond-file-extension))) + ((verify-visited-file-modtime (current-buffer)) + (and (buffer-modified-p) + (y-or-n-p "Save buffer before next command? ") + (LilyPond-save-buffer))) + ((y-or-n-p "The command will be invoked to an already saved buffer. Revert it? ") + (revert-buffer t t))) + + (let* ((default (LilyPond-find-required-command LilyPond-command-next name)) + (completion-ignore-case t) (answer (or LilyPond-command-force (completing-read (concat "Command: (default " default ") ") @@ -521,50 +553,51 @@ Must be the car of an entry in `LilyPond-command-alist'." "Run command on the current document." (interactive) (LilyPond-command-select-master) - (LilyPond-command (LilyPond-command-query (LilyPond-master-file)) - 'LilyPond-master-file)) + (LilyPond-command (LilyPond-command-query (LilyPond-get-master-file)) + 'LilyPond-get-master-file)) (defun LilyPond-command-lilypond () "Run lilypond for the current document." (interactive) - (LilyPond-command (LilyPond-command-menu "LilyPond") 'LilyPond-master-file) + (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-master-file) + (LilyPond-command (LilyPond-command-menu "2Dvi") 'LilyPond-get-master-file) ) (defun LilyPond-command-formatps () "Format the ps output of the current document." (interactive) - (LilyPond-command (LilyPond-command-menu "2PS") 'LilyPond-master-file) + (LilyPond-command (LilyPond-command-menu "2PS") 'LilyPond-get-master-file) ) +(defun LilyPond-command-formatgnome () + "Format the gnome output of the current document." + (interactive) + (LilyPond-command (LilyPond-command-menu "2Gnome") 'LilyPond-get-master-file)) + (defun LilyPond-command-formatmidi () "Format the midi output of the current document." (interactive) - (LilyPond-command (LilyPond-command-menu "2Midi") 'LilyPond-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-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-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-master-file) -) + (LilyPond-command (LilyPond-command-menu "ViewPS") 'LilyPond-get-master-file)) ;; FIXME, this is broken (defun LilyPond-region-file (begin end) @@ -632,7 +665,7 @@ the extension to use on the file. Use the information in LilyPond-command-alist to determine how to run the command." - + (let ((entry (assoc name LilyPond-command-alist))) (if entry (let ((command (LilyPond-command-expand (cadr entry) @@ -642,6 +675,9 @@ command." (if (member name (list "View" "ViewPS")) ;; is USR1 a right signal for viewps? (let ((buffer-xdvi (get-buffer-create (concat "*" name "*")))) + ;; what if XEDITOR is set to gedit or so, should we steal it? + (if (not (getenv "XEDITOR")) + (setenv "XEDITOR" "emacsclient --no-wait +%l:%c %f")) (if LilyPond-kick-xdvi (let ((process-xdvi (get-buffer-process buffer-xdvi))) (if process-xdvi @@ -660,8 +696,8 @@ command." (LilyPond-kill-midi))) ; stop and start playing (if (and (member name (list "Midi" "MidiAll")) job-string) (if (file-newer-than-file-p - (LilyPond-master-file) - (concat (substring (LilyPond-master-file) 0 -3) ".midi")) + (LilyPond-get-master-file) + (concat (substring (LilyPond-get-master-file) 0 -3) ".midi")) (if (y-or-n-p "Midi older than source. Reformat midi?") (progn (LilyPond-command-formatmidi) @@ -684,7 +720,12 @@ command." (sit-for 0 100))) (setq job-string nil))))) - (setq LilyPond-command-default name) + (setq LilyPond-command-next + (let* ((entry (assoc name LilyPond-command-alist)) + (next-command (nth 3 (cdr entry)))) + (or next-command + LilyPond-command-default))) + (if (string-equal job-string "no jobs") (LilyPond-compile-file command name)))))))) @@ -723,12 +764,13 @@ command." (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-g" 'LilyPond-command-formatgnome) + (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) (define-key LilyPond-mode-map "\C-x\C-s" 'LilyPond-save-buffer) + (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 @@ -738,6 +780,7 @@ command." (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) + (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)) @@ -865,15 +908,15 @@ command." ;; find the place first (if (LilyPond-mark-active) (goto-char (min (mark-marker) (point-marker)))) - (while (and (not found) (> (buffer-size b) (marker-position m))) + (while (and (not found) (> (get-buffer-size b) (marker-position m))) (setq copy (car (copy-alist (list (eval (symbol-name (read m))))))) (if (string-equal word copy) (setq found t))) (if found (insert word)) - (if (> (buffer-size b) (marker-position m)) + (if (> (get-buffer-size b) (marker-position m)) (setq copy (car (copy-alist (list (eval (symbol-name (read m)))))))) (if (not (string-equal "-" copy)) (setq found nil)) - (while (and found (> (buffer-size b) (marker-position m))) + (while (and found (> (get-buffer-size b) (marker-position m))) ;; find next symbol (setq copy (car (copy-alist (list (eval (symbol-name (read m))))))) ;; check whether it is the word, or the word has been found @@ -938,15 +981,14 @@ 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-master-file) ]) + '([ "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-master-file) ]) - '([ "LaTeX" (LilyPond-command (LilyPond-command-menu "LaTeX") 'LilyPond-master-file) ]) + '([ "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]) '("-----") @@ -1062,7 +1104,7 @@ COMMANDS VARIABLES LilyPond-command-alist\t\talist from name to command -LilyPond-xdvi-command\t\tcommand to display dvi files -- bit superfluous" +LilyPond-dvi-command\t\tcommand to display dvi files -- bit superfluous" (interactive) ;; set up local variables (kill-all-local-variables) @@ -1152,6 +1194,17 @@ LilyPond-xdvi-command\t\tcommand to display dvi files -- bit superfluous" (load-library "lilypond-font-lock") (load-library "lilypond-indent") +(load-library "lilypond-what-beat") + +(defun LilyPond-guile () + (interactive) + (require 'ilisp) + (guile "lilyguile" (LilyPond-command-expand (cadr (assoc "2Dvi" 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))") + (comint-default-send (ilisp-process) "(use-modules (guile-user) (guile-ilisp))") + (comint-default-send (ilisp-process) "(newline)")) (provide 'lilypond-mode) ;;; lilypond-mode.el ends here