hading / chordpro-mode Goto Github PK
View Code? Open in Web Editor NEWEmacs mode for editing chordpro files
License: MIT License
Emacs mode for editing chordpro files
License: MIT License
I am using quelpa/quelpa-use-package for package management and find that
(use-package chordpro
:quelpa ((chordpro-mode :fetcher github :repo "hading/chordpro-mode") :upgrade t))
results in this errror:
Debugger entered--Lisp error: (error "Package lacks a file header")
signal(error ("Package lacks a file header"))
error("Package lacks a file header")
The package loads with success after adding a dummy header, as in:
https://github.com/malcook/chordpro-mode/blob/master/chordpro-mode.el
For example, it uppercases the first letter of m
in G#m
and dim
in A#dim
, producing invalid chords.
Thanks for writing this mode. I wrote some font-lock regular expressions to perform more granular syntax highlighting and thought I'd share them in case you or other users are interested. This covers every directive listed in the spec at https://www.chordpro.org/chordpro/ChordPro-Directives.html. Here's a screenshot:
I'm not submitting this as a PR because it currently inherits from a bunch of random faces that I happened to have installed, so it's going to blow up for anyone but me in it's current condition. The real value is in the regular-expressions with groupings, though, and since everything has a defined face it's easy to tweak the inheritance.
;;; chordpro-init.el --- Customizations for chordpro-mode
;;; Commentary:
;; Expand the font-lock syntax highlighting in chordpro-mode.
;;; Code:
(require 'rx)
;; Regular expressions and faces for syntax highlighting
(defconst chordpro-comment-regexp
;; C-style comments, eg:
;; # my comment
(rx "#" (zero-or-more any)))
(defface chordpro-comment
'((t :inherit font-lock-comment-delimiter-face))
"Face for chordpro song chords."
:group 'chordpro)
(defconst chordpro-title-regexp
;; Title directives, eg:
;; {title: My Song}
;; {subtitle: My subtitle}
(rx (group "{")
(group (or "title:" "t:" "subtitle:" "st:" "new_song:" "ns:"))
(group (minimal-match (zero-or-more any)))
(group "}")))
(defface chordpro-title
'((t :inherit package-help-section-name))
"Face for chordpro song titles and subtitles."
:group 'chordpro)
(defconst chordpro-metadata-regexp
;; Metadata directives, eg:
;; {artist: me}
;; {capo: 3}
;; {meta: my-custom-key my-value}
(rx (group "{")
(group (or "artist:" "composer:" "lyricist:"
"album:" "year:" "copyright:"
"key:" "time:" "tempo:" "duration:"
"meta:"))
(group (minimal-match (zero-or-more any)))
(group "}")))
(defface chordpro-metadata
'((t :inherit js2-private-member))
"Face for chordpro song directives related to song metadata."
:group 'chordpro)
(defconst chordpro-font-and-output-regexp
;; Font and output directives, eg:
;; {new_page}
;; {columns: 2}
(rx (group "{")
(group (or "textfont:" "textsize:" "textcolour:"
"chordfont:" "chordsize:" "chordcolour:"
"tabfont:" "tabsize:" "tabcolour:"
"new_page" "np"
"new_physical_page" "npp"
"column_break" "cb"
"grid" "g" "no_grid" "ng"
"titles:"
"columns:" "col:"))
(group (minimal-match (zero-or-more any)))
(group "}")))
(defface chordpro-font-and-output
'((t :inherit shadow))
"Face for chordpro song directives related to fonts and output."
:group 'chordpro)
(defconst chordpro-verse-directive-regexp
;; Directives to start or end a verse, eg:
;; {start_of_verse}
;; {end_of_verse}
(rx (group "{")
(group (or "start_of_verse" "end_of_verse"))
(group "}")))
(defface chordpro-verse-directive
'((t :inherit anzu-match-1))
"Face for chordpro song directives mark the start of end of a verse."
:group 'chordpro)
(defconst chordpro-chorus-directive-regexp
;; Directives to start or end a chorus, eg:
;; {start_of_chorus}
;; {eoc}
(rx (group "{")
(group (or "start_of_chorus" "soc" "end_of_chorus" "eoc" "chorus"))
(group "}")))
(defface chordpro-chorus-directive
'((t :inherit ivy-minibuffer-match-face-2))
"Face for chordpro song directives mark the start of end of a chorus."
:group 'chordpro)
(defconst chordpro-tab-or-grid-directive-regexp
;; Directives to start or end a chorus, eg:
;; {start_of_chorus}
;; {eoc}
(rx (group "{")
(group (or "start_of_tab" "sot" "end_of_tab" "eot"
"start_of_grid" "end_of_grid"))
(group "}")))
(defface chordpro-tab-or-grid-directive
'((t :inherit tooltip))
"Face for chordpro song directives mark the start of end of a tab or grid."
:group 'chordpro)
(defconst chordpro-builtin-directive-regexp
;; Other built-In directives, eg:
;; {start_of_chorus}
;; {comment: hello}
(rx (group "{")
(group (or "comment:" "c:" "comment_italic:" "ci:" "comment_box:" "cb:"
"image:"
"define:" "chord:"))
(group (minimal-match (zero-or-more any)))
(group "}")))
(defface chordpro-builtin-directive-name
'((t :inherit font-lock-comment-face))
"Face for chordpro built-in directive names with no special highlighting."
:group 'chordpro)
(defface chordpro-builtin-directive-value
'((t :inherit font-lock-doc-face))
"Face for chordpro built-in directive values with no special highlighting."
:group 'chordpro)
(defface chordpro-directive-delimiter
'((t :inherit font-lock-constant-face))
"Face for chordpro song directive curly bracket delimiters."
:group 'chordpro)
(defconst chordpro-extension-directive-regexp
;; Extension directives, eg:
;; {x_boolean_extension}
;; {x_string_extension: hello}
(rx (group "{")
(group "x_"
(minimal-match (one-or-more any))
(zero-or-one ":"))
(group (minimal-match (zero-or-more any)))
(group "}")))
(defface chordpro-extension-directive-name
'((t :inherit chordpro-builtin-directive-name))
"Face for chordpro song directive names that conform to the extension spec."
:group 'chordpro)
(defface chordpro-extension-directive-value
'((t :inherit chordpro-extension-directive-value))
"Face for chordpro song directive values that conform to the extension spec."
:group 'chordpro)
(defconst chordpro-unrecognized-directive-regexp
;; Invalid directives, eg:
;; {invalid_example_directive}
(rx "{" (minimal-match (one-or-more any)) "}" ))
(defface chordpro-unrecognized-directive
'((t :inherit isearch-fail))
"Face for chordpro song directives that appear to be invalid."
:group 'chordpro)
(defconst chordpro-chord-regexp
;; Chords, eg:
;; [G]
;; [Am7]
(rx (group "[" )
(group (minimal-match (zero-or-more any)))
(group "]")))
(defface chordpro-chord
'((t :inherit flycheck-fringe-error))
"Face for chordpro song chords."
:group 'chordpro)
(defface chordpro-chord-delimiter
'((t :inherit flycheck-error-list-warning))
"Face for chordpro song chord square bracket delimiters."
:group 'chordpro)
;; Font lock settings for syntax highlighting
(add-hook 'chordpro-mode-hook
(lambda ()
(font-lock-add-keywords nil
;; Note that the backtickery in this section
;; is extremely fiddly:
;; - Backtick the whole list to quote it
;; but allow selective unquoting.
;; - Comma each regex to eval it
;; - Single-quote each face, also to
;; eval it. Maybe commas would work?
;; I cargo-culted this from:
;; https://emacs.stackexchange.com/a/3587
`((,chordpro-comment-regexp
0 'chordpro-comment)
(,chordpro-title-regexp
0 'chordpro-title)
(,chordpro-metadata-regexp
0 'chordpro-metadata)
(,chordpro-font-and-output-regexp
0 'chordpro-font-and-output)
(,chordpro-verse-directive-regexp
0 'chordpro-verse-directive)
(,chordpro-chorus-directive-regexp
0 'chordpro-chorus-directive)
(,chordpro-tab-or-grid-directive-regexp
0 'chordpro-tab-or-grid-directive)
(,chordpro-builtin-directive-regexp
(1 'chordpro-directive-delimiter)
(2 'chordpro-builtin-directive-name)
(3 'chordpro-builtin-directive-value)
(4 'chordpro-directive-delimiter))
(,chordpro-extension-directive-regexp
(1 'chordpro-directive-delimiter)
(2 'chordpro-extension-directive-name)
(3 'chordpro-directive-value)
(4 'chordpro-directive-delimiter))
;; Will match any directive, must be
;; preceded but other directive
;; highlighers.
(,chordpro-unrecognized-directive-regexp
0 'chordpro-unrecognized-directive)
(,chordpro-chord-regexp
(1 'chordpro-chord-delimiter)
(2 'chordpro-chord)
(3 'chordpro-chord-delimiter))
))))
(add-to-list 'auto-mode-alist '("\\.crd$" . chordpro-mode))
;;; chordpro-init.el ends here
Invoking chordpro directly from emacs, ideally with a live pdf preview in a vertical split would be handy.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.