dotemacs/contrapunctus/cp-lily.el
2018-09-04 11:36:48 +05:30

170 lines
5.1 KiB
EmacsLisp

;;;; Hacks for Lilypond work
(autoload 'LilyPond-mode "../user/lilypond-mode.el")
(add-to-list 'auto-mode-alist '("\\.ly\\'" . LilyPond-mode))
(with-eval-after-load 'lilypond-mode
(add-hook 'LilyPond-mode-hook 'subword-mode)
(add-hook 'LilyPond-mode-hook 'god-local-mode)
(add-hook 'LilyPond-mode-hook (lambda () (setq truncate-lines 1)))
(cp-set-keys
:bindings
`((,(kbd "C-c C-i") 'LilyPond-info)
(,(kbd "M-]") 'cp-toggle-selective-display)))
(cp-set-keys
:keymap LilyPond-mode-map
:bindings
`((,(kbd "M-p") cp-backward-def)
(,(kbd "M-n") cp-forward-def)
(,(kbd "M-P") cp-upper-level)
(,(kbd "M-N") cp-lower-level)
(,(kbd "C-c C-w") cp-ly-wrap-para))))
(defun cp-toggle-selective-display ()
(interactive)
(set-selective-display (if selective-display nil 1)))
(defvar cp/ly-definition-rx
'(and bol
(1+ (any "a-z" "A-Z" "\\\\"))
(1+ (any "a-z" "A-Z" "\\\\" " "))
(any "{" "=" "#")))
(defun cp-backward-def ()
(interactive)
(unless (region-active-p)
(push-mark))
(re-search-backward (rx-to-string cp/ly-definition-rx)
nil t)
(beginning-of-line)
(recenter))
(defun cp-forward-def ()
(interactive)
(unless (region-active-p)
(push-mark))
;; (forward-char)
(if (not (re-search-forward (rx-to-string cp/ly-definition-rx)
nil t 2))
(re-search-forward "^}" nil t))
;; (re-search-forward "^[\\a-zA-Z]" nil t)
(beginning-of-line)
(recenter))
;; (defun cp-backward-def ()
;; (interactive)
;; (re-search-backward "\(^\\\\?[a-zA-Z]\|^ *\\[a-zA-Z]\)")
;; (beginning-of-line))
;; (defun cp-forward-def ()
;; (interactive)
;; (forward-char)
;; (re-search-forward "\(^\\\\?[a-zA-Z]\|^ *\\[a-zA-Z]\)")
;; (beginning-of-line))
(defun cp-upper-level ()
(interactive)
(re-search-backward "{"))
(defun cp-lower-level ()
(interactive)
(if (equal (string (char-after)) "{")
(forward-char))
(if (not (re-search-forward "{"))
(message "At deepest level."))
(backward-char))
;; (defun cp-lilypond-enclose-<< ()
;; (interactive)
;; (if (equal (string (char-after)) "\\")
;; (progn (insert "<< ")
;; (search-forward "{")
;; (backward-char)
;; (forward-sexp))))
;; if at a \new ... block - enclose expression
;; otherwise, enclose current position and after the first bar check
;; found
;; if region is active, enclose beginning and end
;; (defun cp-lilypond-enclose-<< ()
;; (interactive)
;; (if (equal (thing-at-point 'sexp)
;; "\\new")
;; (progn ;; (insert "<< ")
;; (newline-and-indent)
;; (search-forward "{")
;; (backward-char)
;; (forward-list)
;; ;; (forward-sexp))
;; )
;; ;; (let ((point1 (point)))
;; ;; (next-line)
;; ;; (goto-char point1))
;; ))
;; (define-key LilyPond-mode-map (kbd "<<")
;; 'cp-lilypond-enclose-<<)
;; If I change files, it's still main.ly that gets compiled; this is
;; good most of the time, but many times I want to compile a part-*
;; file instead. If we compile both main.ly and the respective part-*
;; file every time, it's wasteful. Having to select means giving up
;; the 'effortless-compilation' behaviour.
;; 2017-03-14T00:52:07+0530 - commented out, see cp/after-save
;; (defadvice LilyPond-save-buffer
;; (after lysb activate)
;; ;; (compile "make")
;; (cd (locate-dominating-file (buffer-file-name)
;; "main.ly"))
;; (compile (car compile-history)))
;;
;; (defadvice compile
;; (before compile activate)
;; (if (equal major-mode 'LilyPond-mode)
;; (cd (locate-dominating-file (buffer-file-name)
;; "main.ly"))))
;; TODO - refactor into one COND, with one case per operation.
;; TODO - operate on region as well.
(defun cp-ly-wrap-para (arg)
"Wrap current paragraph with -
\\relative c { ... } with no args,
\\repeat { ... } with universal argument,
and only braces - { ... } - with null argument.
Numeric arg wraps that many paragraphs.
TODO - wrap region if region active"
(interactive "P")
(let ((point-a (point)))
(beginning-of-line)
(unless (looking-at "[[:blank:]]*$")
;; go to start of paragraph or block, or previous blank line
(re-search-backward (rx (or (and bol (0+ blank) eol)
(and "{" eol))))
(end-of-line))
(newline-and-indent)
(insert (pcase arg
(`(,x) "\\repeat {")
(0 "{")
;; nil
(_ "\\relative c {")))
(let ((indent-start (point)))
(forward-paragraph (pcase arg
(`(,x) 1)
(_ (if (and arg (<= arg 0))
1 arg))))
(indent-region indent-start (point))
(insert "}")
(indent-for-tab-command)
(newline)
;; FIXME
(goto-char (pcase arg
(0 point-a)
(_ (- indent-start 2)))))))
;; TODO - cp-ly-new-var, bind to M-RET.
;; Exits current variable body, if in any, and inserts "| = \relative
;; c {\n\n \n}", where | is the cursor