Finished the first draft (I think). Added options to documentation.
This commit is contained in:
parent
36d8db1f86
commit
a1dd0a8313
18
README
18
README
|
@ -1,4 +1,20 @@
|
||||||
This is a distribution of mp_suggest, an organization tool for MP3 libraries
|
This is a distribution of mp_suggest, an organization tool for MP3
|
||||||
|
libraries. It was written primarily as an experiment in learning Hy.
|
||||||
|
Hy is a lisp-like programming language that runs on top of the Python VM
|
||||||
|
and exploits Python's access to the running AST in order to build
|
||||||
|
working Python programs.
|
||||||
|
|
||||||
|
Writing mp_suggest was an interesting exercise in returning to Lisp
|
||||||
|
after all these years. I find that I really enjoyed it (although,
|
||||||
|
honestly, Hy's debugging facilities leave a lot to be desired). The
|
||||||
|
style used inside mp_suggest is most definitely not Lispy; looking
|
||||||
|
through it, with its persistent use of cheap anonymous functions and
|
||||||
|
closures and its function-level metaprogramming, I guess the best
|
||||||
|
language I could compare it to is Coffeescript. I like Coffeescript a
|
||||||
|
lot, but I don't get many opportunities to use it professionally, but
|
||||||
|
the sensibilities of Coffeescript (especially Reginald Braithwaite's
|
||||||
|
Ristrettology and his other books on functional programming) heavily
|
||||||
|
influenced the design decisions I made in mp_suggest.
|
||||||
|
|
||||||
* Licensing
|
* Licensing
|
||||||
|
|
||||||
|
|
|
@ -17,35 +17,39 @@
|
||||||
|
|
||||||
(defn print-version []
|
(defn print-version []
|
||||||
(print (.format "mp_suggest (hy version {})" *version*))
|
(print (.format "mp_suggest (hy version {})" *version*))
|
||||||
(sys.exit 0))
|
(print "Copyright (c) 2008, 2014 Elf M. Sternberg <elf.sternberg@gmail.com>")
|
||||||
|
(sys.exit))
|
||||||
|
|
||||||
(defn print-help []
|
(defn print-help []
|
||||||
(print "Usage:")
|
(print "Usage:")
|
||||||
(ap-each optlist (print (.format " -{} --{} {}" (get it 0) (get it 1) (get it 3))))
|
(ap-each optlist (print (.format " -{} --{} {}" (get it 0) (get it 1) (get it 3))))
|
||||||
(sys.exit 0))
|
(sys.exit))
|
||||||
|
|
||||||
; Given a set of command-line arguments, compare that to a mapped
|
; Given a set of command-line arguments, compare that to a mapped
|
||||||
; version of the optlist and return a canonicalized dictionary of all
|
; version of the optlist and return a canonicalized dictionary of all
|
||||||
; the arguments that have been set.
|
; the arguments that have been set.
|
||||||
|
|
||||||
(defn find-opt-reducer [acc it]
|
(defn make-opt-assoc [prefix pos]
|
||||||
(let [[(, o a) it]
|
(fn [acc it] (assoc acc (+ prefix (get it pos)) (get it 1)) acc))
|
||||||
[optmap (ap-reduce (do (assoc acc (+ "-" (. it [0])) (. it [1])) acc) optlist {})]]
|
|
||||||
(if (.has_key optmap o) (let [[full (car (get optmap o))]
|
(defn make-options-rationalizer [optlist]
|
||||||
[hasargs (car (cdr (get optmap o)))]]
|
(let [
|
||||||
(assoc acc full (if hasargs a true))))
|
[short-opt-assoc (make-opt-assoc "-" 0)]
|
||||||
acc))
|
[long-opt-assoc (make-opt-assoc "--" 1)]
|
||||||
|
[fullset
|
||||||
|
(ap-reduce (-> (short-opt-assoc acc it)
|
||||||
|
(long-opt-assoc it)) optlist {})]]
|
||||||
|
(fn [acc it] (do (assoc acc (get fullset (get it 0)) (get it 1)) acc))))
|
||||||
|
|
||||||
; Assuming the directory name looked like "Artist - Album", return the
|
; Assuming the directory name looked like "Artist - Album", return the
|
||||||
; two names separately. If only one name is here, assume a compilation
|
; two names separately. If only one name is here, assume a compilation
|
||||||
; or mixtape album and default to "VA" (Various Artists).
|
; or mixtape album and default to "VA" (Various Artists).
|
||||||
|
|
||||||
(defn artist-album []
|
(defn artist-album []
|
||||||
(let [[aa (.split (. (.split (.getcwd os) "/") [-1]) " - ")]
|
(let [[aa (-> (.getcwd os) (.split "/") (get -1) (.split " - "))]]
|
||||||
[sp (fn [i] (.strip i))]]
|
|
||||||
(if (= (len aa) 1)
|
(if (= (len aa) 1)
|
||||||
(, "VA" (get aa 0))
|
(, "VA" (get aa 0))
|
||||||
(, (sp (get aa 0)) (sp (get aa 1))))))
|
(, (.strip (get aa 0)) (.strip (get aa 1))))))
|
||||||
|
|
||||||
; A long list of substitutions intended to turn a filename into a
|
; A long list of substitutions intended to turn a filename into a
|
||||||
; human-readable strategy. This operation is the result of weeks
|
; human-readable strategy. This operation is the result of weeks
|
||||||
|
@ -64,7 +68,6 @@
|
||||||
; filesystem access is a point of failure, but this is mostly
|
; filesystem access is a point of failure, but this is mostly
|
||||||
; reliable.
|
; reliable.
|
||||||
|
|
||||||
|
|
||||||
(defn tag-deriver [usefilenames]
|
(defn tag-deriver [usefilenames]
|
||||||
(fn [mp3s]
|
(fn [mp3s]
|
||||||
(defn derive-tag [pos mp3]
|
(defn derive-tag [pos mp3]
|
||||||
|
@ -146,23 +149,39 @@
|
||||||
[artist
|
[artist
|
||||||
(if (.has_key opts "artist")
|
(if (.has_key opts "artist")
|
||||||
(get opts "artist")
|
(get opts "artist")
|
||||||
(sfix loc_artist))]]
|
(sfix loc_artist))]
|
||||||
|
|
||||||
(print genre album artist)))
|
[format-string
|
||||||
|
(string.join ["id3v2 -T \"{}\""
|
||||||
|
"--album \"{}\""
|
||||||
|
"--artist \"{}\""
|
||||||
|
"--genre \"{}\""
|
||||||
|
"--song \"{}\""
|
||||||
|
"\"{}\""] " ")]]
|
||||||
|
|
||||||
|
(ap-each mp3s
|
||||||
|
(print (.format format-string (get it 5) album artist genre (get it 4) (get it 0))))))
|
||||||
|
|
||||||
(defmain [&rest args]
|
(defmain [&rest args]
|
||||||
(try
|
(try
|
||||||
(let [[optstringsshort
|
(let [[optstringsshort
|
||||||
(string.join (ap-map (. it [0]) optlist) ":")]
|
(string.join (ap-map (+ (. it [0]) (cond [(. it [2]) ":"] [true ""])) optlist) "")]
|
||||||
|
|
||||||
[optstringslong
|
[optstringslong
|
||||||
(list (ap-map (+ (. it [1]) (cond [(. it [2]) "="] [true ""])) optlist))]
|
(list (ap-map (+ (. it [1]) (cond [(. it [2]) "="] [true ""])) optlist))]
|
||||||
|
|
||||||
[(, opt arg)
|
[(, opt arg)
|
||||||
(getopt.getopt (slice args 1) optstringsshort optstringslong)]
|
(getopt.getopt (slice args 1) optstringsshort optstringslong)]
|
||||||
|
|
||||||
|
[rationalize-options
|
||||||
|
(make-options-rationalizer optlist)]
|
||||||
|
|
||||||
[options
|
[options
|
||||||
(ap-reduce (find-opt-reducer acc it) opt {})]]
|
(ap-reduce (rationalize-options acc it) opt {})]]
|
||||||
(cond [(.has_key options "h") (print-help)]
|
|
||||||
[(.has_key options "v") (print-version)]
|
(cond [(.has_key options "help") (print-help)]
|
||||||
[true (suggest options)]))))
|
[(.has_key options "version") (print-version)]
|
||||||
|
[true (suggest options)]))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,35 @@ commands can be tweaked, and all of them override the techniques
|
||||||
This is probably completely idiosyncratic to the way I do things in my
|
This is probably completely idiosyncratic to the way I do things in my
|
||||||
own music archive, but as an exercise in writing Hy, it was fun.
|
own music archive, but as an exercise in writing Hy, it was fun.
|
||||||
|
|
||||||
|
\section{Options}
|
||||||
|
%%%%%%%%%%%%%%%%%
|
||||||
|
\begin{Description}
|
||||||
|
\item[\OptArg{--genre}{genre}] Set the genre manually from the command
|
||||||
|
line. This overrides any settings found in the ID3 tag. A short form
|
||||||
|
of this tag is ``-g''
|
||||||
|
|
||||||
|
\item[\OptArg{--album}{album}] Set the album manually from the command
|
||||||
|
line. This overrides any settings found in the ID3 tag. A short form
|
||||||
|
of this tag is ``-a''
|
||||||
|
|
||||||
|
\item[\OptArg{--artist}{artist}] Set the artist manually from the command
|
||||||
|
line. This overrides any settings found in the ID3 tag. A short form
|
||||||
|
of this tag is ``-r''
|
||||||
|
|
||||||
|
\item[\Opt{--usedir}] Use the directory name for artist and album
|
||||||
|
information. This overrides anything found in the ID3 tags. A short
|
||||||
|
form of this tag is ``-n''.
|
||||||
|
|
||||||
|
\item[\Opt{--usefilename}] Use the filename as the song title. This
|
||||||
|
overrides anything found in the ID3 tags. A short form of this tag is
|
||||||
|
``-t''.
|
||||||
|
|
||||||
|
\item[\Opt{--help}] Print a short help message. A short form of this
|
||||||
|
tag is ``-h''
|
||||||
|
|
||||||
|
\item[\Opt{--version}] Print the version information. A short form of this
|
||||||
|
tag is ``-v''
|
||||||
|
|
||||||
\section{Requirements}
|
\section{Requirements}
|
||||||
%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue