]> Sergey Matveev's repositories - torn.git/blob - torn.zsh
Do not exit, it is not a script
[torn.git] / torn.zsh
1 # torn - Musical files renaming with russian language transliteration
2 # Copyright (C) 2021-2023 Sergey Matveev (stargrave@stargrave.org)
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, version 3 of the License.
7
8 # Initially this script was written on Perl, but now it is zsh function,
9 # that is intended to be used with zmv command. It is much more flexible
10 # to be used with zsh'es glob expansion.
11 #
12 # * transliterates everything
13 # * replaces non FAT-compatible characters with underscores
14 # * replaces spaces with underscores
15 # * lowercases file's extension
16 # * replaces "_-_" with single dash
17 # * removes spaces before and after brackets
18 # * removes space after comma
19 # * removes "[]" brackets
20 # * replaces ampersand with "and" word
21 #
22 # You can run like that:
23 #   $ fpath=(... $fpath)
24 #   $ autoload torn
25 #   $ zmv "*" '`torn $f`"
26 #
27 # Transliteration function is separate tornt(), so you can use only
28 # its abilities:
29 #   $ torn # assume that it is not autoloaded
30 #   $ zmv "*" '`tornt $f`'
31 #
32 # torna() replaces non FAT-compatible characters with underscores.
33 #
34 # Recursively dive into subdirectories:
35 #   $ zmv -Q "(**/)*(.)" '`torn $f`'
36
37 tornt() {
38     local n=$1
39     local rusS=абвгдеёзийклмнопрстуфхцьъыэ
40     local engS=abvgdeezijklmnoprstufhcjjye
41     for i ({1..${#rusS}}) {
42         eval n=\${n:gs/${rusS[$i]}/${engS[$i]}}
43         eval n=\${n:gs/${(U)rusS[$i]}/${(U)engS[$i]}}
44     }
45     local rusL=( ж  ч  ш   щ  я  ю  Ж  Ч  Ш   Щ  Я  Ю)
46     local engL=(zh ch sh sch ja ju Zh Ch Sh Sch Ja Ju)
47     for i ({1..${#rusL}}) eval n=\${n:gs/${rusL[$i]}/${engL[$i]}}
48     print -- $n
49 }
50
51 tornm() {
52     local n=$1
53     n=${n:gs/ /_}
54     n=${n//_[–-]_/-}
55     n=${n:gs/,_/,}
56     n=${n//[\[\]]/}
57     n=${n:gs/_(/(}
58     n=${n:gs/-(/-}
59     n=${n:gs/(_/(}
60     n=${n:gs/)_/-}
61     n=${n:gs/_)/)}
62     n=${n:gs/&/and}
63     [[ $n =~ "\." ]] && n=${n:r}.${(L)n:e}
64     [[ $n =~ "^([[:digit:]]+)[-.]_*(.+)$" ]] && n="$match[1].$match[2]"
65     print -- $n
66 }
67
68 torna() {
69     local n=$1
70     setopt REMATCH_PCRE
71     for i ({1..${#n}}) {
72         [[ ${n[$i]} =~ "[[:ascii:]]" ]] || n[$i]=_
73         [[ ${n[$i]} =~ "[[:print:]]" ]] || n[$i]=_
74         [[ ${n[$i]} =~ "[^,+/:;<=>?[]|]" ]] || n[$i]=_
75     }
76     print -- $n
77 }
78
79 [[ -n $1 ]] || return
80 local n=${1:t}
81 n=`tornm $n`
82 n=`tornt $n`
83 n=`torna $n`
84 print -- ${1:h}/$n