From 65e14cf348d49a848f02602fc66ba41f969311d1 Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 5 Aug 2021 23:11:06 +0200 Subject: [PATCH] batch-rename: add functions and presets --- README.md | 8 +++- copyparty/web/browser.css | 1 + copyparty/web/browser.js | 80 ++++++++++++++++++++++++++++++++++----- 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 47b6710c..8e3e0be5 100644 --- a/README.md +++ b/README.md @@ -387,9 +387,13 @@ in advanced mode, * `[case]` toggles case-sensitive regex * `regex` is the regex pattern to apply to the original filename; any files which don't match will be skipped * `format` is the new filename, taking values from regex capturing groups and/or from file tags - * very loosely based on foobar2000 syntax, no functions yet tho + * very loosely based on foobar2000 syntax * `presets` lets you save rename rules for later +available functions: +* `$lpad(text, length, pad_char)` +* `$rpad(text, length, pad_char)` + so, say you have a file named [`meganeko - Eclipse - 07 Sirius A.mp3`](https://www.youtube.com/watch?v=-dtb0vDPruI) (absolutely fantastic album btw) and the tags are: `Album:Eclipse`, `Artist:meganeko`, `Title:Sirius A`, `tn:7` @@ -408,6 +412,8 @@ or a mix of both since it doesn't have functions yet (for example to add leading * `format` = `(1). (artist) - (title).(ext)` * `output` = `07. meganeko - Sirius A.mp3` +the metadata keys you can use in the format field are the ones in the file-browser table header (whatever is collected with `-mte` and `-mtp`) + ## markdown viewer diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index 2628f04c..2a7ca839 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -807,6 +807,7 @@ input.eq_gain { #wrap { margin-top: 2em; min-height: 90vh; + padding-bottom: 5em; } #tree { display: none; diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 7a6fc5d2..53cb7d8e 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -1463,17 +1463,18 @@ function play_linked() { function fmt_ren(re, md, fmt) { var ptr = 0; - function dive() { + function dive(stop_ch) { var ret = '', ng = 0; while (ptr < fmt.length) { - var ch = fmt[ptr++]; + var dbg = fmt.slice(ptr), + ch = fmt[ptr++]; if (ch == '\\') { ret += fmt[ptr++]; continue; } - if (ch == ')' || ch == ']') + if (ch == ')' || ch == ']' || ch == stop_ch) return [ng, ret]; if (ch == '[') { @@ -1484,7 +1485,7 @@ function fmt_ren(re, md, fmt) { else if (ch == '(') { var end = fmt.indexOf(')', ptr); if (end < 0) - throw 'the $( was never closed: ' + fmt.slice(0, ptr); + throw 'the ( was never closed: ' + fmt.slice(0, ptr); var arg = fmt.slice(ptr, end), v = null; ptr = end + 1; @@ -1511,7 +1512,33 @@ function fmt_ren(re, md, fmt) { throw 'no function name after the $ here: ' + fmt.slice(0, ptr); var fun = fmt.slice(ptr - 1, end); - throw 'function not implemented: "' + fun + '"'; + ptr = end + 1; + + if (fun == "lpad") { + var str = dive(',')[1]; + var len = dive(',')[1]; + var chr = dive()[1]; + if (!len || !chr) + throw 'invalid arguments to ' + fun; + + while (str.length < len) + str = chr + str; + + ret += str; + } + else if (fun == "rpad") { + var str = dive(',')[1]; + var len = dive(',')[1]; + var chr = dive()[1]; + if (!len || !chr) + throw 'invalid arguments to ' + fun; + + while (str.length < len) + str += chr; + + ret += str; + } + else throw 'function not implemented: "' + fun + '"'; } else ret += ch; } @@ -1717,7 +1744,44 @@ var fileman = (function () { ifmt = ebi('rn_fmt'), ipre = ebi('rn_pre'), idel = ebi('rn_pdel'), - inew = ebi('rn_pnew'); + inew = ebi('rn_pnew'), + presets = jread("rn_pre", {}); + + function spresets() { + var keys = Object.keys(presets), o; + keys.sort(); + ipre.innerHTML = ''; + for (var a = 0; a < keys.length; a++) { + o = mknod('option'); + o.setAttribute('value', keys[a]); + o.textContent = keys[a]; + ipre.appendChild(o); + } + } + inew.onclick = function () { + var name = prompt('provide a name for your new preset', ifmt.value); + if (!name) + return toast.warn(3, 'aborted'); + + presets[name] = [ire.value, ifmt.value]; + jwrite('rn_pre', presets); + spresets(); + ipre.value = name; + }; + idel.onclick = function () { + delete presets[ipre.value]; + jwrite('rn_pre', presets); + spresets(); + }; + ipre.oninput = function () { + var cfg = presets[ipre.value]; + if (cfg) { + ire.value = cfg[0]; + ifmt.value = cfg[1]; + } + ifmt.oninput(); + }; + spresets(); ire.oninput = ifmt.oninput = function (e) { var ptn = ire.value, @@ -1755,7 +1819,7 @@ var fileman = (function () { }; function rn_apply() { - while (f.length && !f[0].ok) + while (f.length && (!f[0].ok || f[0].ofn == f[0].inew.value)) f.shift(); if (!f.length) { @@ -1779,8 +1843,6 @@ var fileman = (function () { f.shift().inew.value = '( OK )'; return rn_apply(); - - } var xhr = new XMLHttpRequest();