diff --git a/lib/arb/intl_en.arb b/lib/arb/intl_en.arb index 562fcde..bcb95f2 100755 --- a/lib/arb/intl_en.arb +++ b/lib/arb/intl_en.arb @@ -101,9 +101,12 @@ "caseSensitive": "Case sensitive", "isRegex": "Is regex", "language": "Language: ", - "selectionLength": "Selection length", + "indexOne": "First character index", + "indexTwo": "Second character index", + "toLast": "-to-last", "goingForward": "Going forward", - "keepCharacters": "Keep characters", + "keepCharacters": "Keep characters between them", + "removeCharacters": "Remove characters between them", "metadataParserNotProvided": "Contains metadata tag while MetadataParser was not provided.", "replaceToString": "Replace \"{targetString}\" with \"{replacementString}\".", "@replaceToString": { @@ -176,22 +179,22 @@ } } }, - "truncateToString": "Truncate: {keepType, plural, =0{remove} =1{keep} other{}} {length} characters starting from the char #{startIndex}{location, plural, =0{-to-end} =1{} other{}} going {direction, plural, =0{backward} =1{forward} other{}}.", + "truncateToString": "Truncate: {keepType, plural, =0{keep only} =1{remove} other{}} characters between the {i1}th{i1toEnd, plural, =0{-to-end} =1{} other{}} character and the {i2}th{i2toEnd, plural, =0{-to-end} =1{} other{}}.", "@truncateToString": { "placeholders": { "keepType": { "type": "num" }, - "location":{ + "i1toEnd":{ "type": "num" }, - "direction":{ + "i2toEnd":{ "type": "num" }, - "length": { + "i1": { "type": "num" }, - "startIndex": { + "i2": { "type": "num" } } diff --git a/lib/arb/intl_zh.arb b/lib/arb/intl_zh.arb index 3f07858..60c418c 100644 --- a/lib/arb/intl_zh.arb +++ b/lib/arb/intl_zh.arb @@ -101,9 +101,13 @@ "caseSensitive": "区分大小写", "isRegex": "使用正则表达式", "language": "语言:", + "indexOne": "第一处位置", + "indexTwo": "第二处位置", + "toLast": "倒数", "selectionLength": "所选内容长度", "goingForward": "向前", - "keepCharacters": "保留字符", + "keepCharacters": "保留二者之间的字符", + "removeCharacters": "移除二者之间的字符", "metadataParserNotProvided": "包含元数据标签,但未提供元数据解析器。", "replaceToString": "替换:将“{targetString}”替换为“{replacementString}”。", "@replaceToString": { @@ -176,22 +180,22 @@ } } }, - "truncateToString": "截取:从{location, plural, =0{倒数的} =1{} other{}}第{startIndex}个字符开始,向{direction, plural, =0{后} =1{前} other{other}}{keepType, plural, =0{移除} =1{保留} other{other}}{length}个字符。", + "truncateToString": "截取:{keepType, plural, =0{仅保留} =1{移除} other{}}从{i1toEnd, plural, =0{倒数的} =1{} other{}}第{i1}个字符至{i2toEnd, plural, =0{倒数的} =1{} other{}}第{i2}个字符之间的内容。", "@truncateToString": { "placeholders": { "keepType": { "type": "num" }, - "location":{ + "i1toEnd":{ "type": "num" }, - "direction":{ + "i2toEnd":{ "type": "num" }, - "length": { + "i1": { "type": "num" }, - "startIndex": { + "i2": { "type": "num" } } diff --git a/lib/dialogs/truncate_dialog.dart b/lib/dialogs/truncate_dialog.dart index bef4312..6815300 100644 --- a/lib/dialogs/truncate_dialog.dart +++ b/lib/dialogs/truncate_dialog.dart @@ -23,16 +23,12 @@ class TruncateDialog extends StatefulWidget { } class _TruncateDialogState extends State { - TextEditingController startController = TextEditingController( - text: '0', - ); - TextEditingController lengthController = TextEditingController( - text: '0', - ); - bool fromStart = true; // true: count from start, false: count from end. - bool direction = true; // truncate direction + TextEditingController i1Controller = TextEditingController(text: '0'); + TextEditingController i2Controller = TextEditingController(text: '0'); + bool i1toEnd = false; // true: negative (Xth-to-last), false: positive (Xth) + bool i2toEnd = false; // true: negative (Xth-to-last), false: positive (Xth) bool ignoreExtension = true; - bool keep = true; // true: keep chars in ranges, false: remove in range + bool keepBetween = true; // true: keep chars in ranges, false: remove in range @override Widget build(BuildContext context) { @@ -41,50 +37,62 @@ class _TruncateDialogState extends State { content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - TextFormField( - controller: startController, - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp('[0-9]')), // 只允许数字 + Row( + children: [ + Expanded(child: TextFormField( + controller: i1Controller, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9]')), // 只允许数字 + ], + decoration: InputDecoration(labelText: L10n.current.indexOne), + ),), + TextButton( + child: Text(L10n.current.toLast, style: TextStyle( + color: i1toEnd ? null : Colors.grey, + ),), + onPressed: () { + setState(() { + i1toEnd = !i1toEnd; + }); + }, + ), ], - decoration: InputDecoration(labelText: L10n.current.startIndex), ), box, - TextFormField( - controller: lengthController, - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp('[0-9]')), // 只允许数字 + Row( + children: [ + Expanded(child: TextFormField( + controller: i2Controller, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9]')), // 只允许数字 + ], + decoration: InputDecoration(labelText: L10n.current.indexTwo), + ),), + TextButton( + child: Text(L10n.current.toLast, style: TextStyle( + color: i2toEnd ? null : Colors.grey, + ),), + onPressed: () { + setState(() { + i2toEnd = !i2toEnd; + }); + }, + ), ], - decoration: InputDecoration(labelText: L10n.current.selectionLength), ), - CheckboxTile( - title: Text(L10n.current.fromStart), - value: fromStart, - onChanged: (value) { - setState(() { - fromStart = value ?? fromStart; - }); - }, - ), - CheckboxTile( - title: Text(L10n.current.goingForward), - value: direction, - onChanged: (value) { - setState(() { - direction = value ?? direction; - }); - }, - ), - CheckboxTile( - title: Text(L10n.current.keepCharacters), - value: keep, - onChanged: (value) { - setState(() { - keep = value ?? keep; - }); - }, + ListTile( + title: TextButton( + child: Text(keepBetween ? L10n.current.keepCharacters : L10n.current.removeCharacters), + onPressed: () { + setState(() { + keepBetween = !keepBetween; + }); + }, + ), ), CheckboxTile( title: Text(L10n.current.ignoreExtension), @@ -107,16 +115,16 @@ class _TruncateDialogState extends State { ), TextButton( onPressed: () { - int startIndex = int.tryParse(startController.text) ?? 0; - int length = int.tryParse(lengthController.text) ?? 0; + int index1 = int.tryParse(i1Controller.text) ?? 0; + int index2 = int.tryParse(i2Controller.text) ?? 0; final Rule rule = RuleTruncate( - startIndex, - fromStart, - direction, - length, + index1, + index2, + i1toEnd, + i2toEnd, ignoreExtension, - keep, + keepBetween, ); widget.onSave.call(rule); diff --git a/lib/l10n/intl/messages_en.dart b/lib/l10n/intl/messages_en.dart index a6138ba..c8b37e0 100644 --- a/lib/l10n/intl/messages_en.dart +++ b/lib/l10n/intl/messages_en.dart @@ -38,8 +38,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m6(langName, type) => "Transliterate: convert ${langName} ${type}."; - static String m7(keepType, location, direction, length, startIndex) => - "Truncate: ${Intl.plural(keepType, zero: 'remove', one: 'keep', other: '')} ${length} characters starting from the char #${startIndex}${Intl.plural(location, zero: '-to-end', one: '', other: '')} going ${Intl.plural(direction, zero: 'backward', one: 'forward', other: '')}."; + static String m7(keepType, i1toEnd, i2toEnd, i1, i2) => + "Truncate: ${Intl.plural(keepType, zero: 'keep only', one: 'remove', other: '')} characters between the ${i1}th${Intl.plural(i1toEnd, zero: '-to-end', one: '', other: '')} character and the ${i2}th${Intl.plural(i2toEnd, zero: '-to-end', one: '', other: '')}."; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -96,6 +96,10 @@ class MessageLookup extends MessageLookupByLibrary { "incrementToString": m0, "indexIncrementalStep": MessageLookupByLibrary.simpleMessage("Index incremental step"), + "indexOne": + MessageLookupByLibrary.simpleMessage("First character index"), + "indexTwo": + MessageLookupByLibrary.simpleMessage("Second character index"), "insert": MessageLookupByLibrary.simpleMessage("Insert"), "insertBeforeIndex": MessageLookupByLibrary.simpleMessage("Insert before index"), @@ -106,8 +110,8 @@ class MessageLookup extends MessageLookupByLibrary { "insertedText": MessageLookupByLibrary.simpleMessage("Text to be inserted"), "isRegex": MessageLookupByLibrary.simpleMessage("Is regex"), - "keepCharacters": - MessageLookupByLibrary.simpleMessage("Keep characters"), + "keepCharacters": MessageLookupByLibrary.simpleMessage( + "Keep characters between them"), "language": MessageLookupByLibrary.simpleMessage("Language: "), "limit": MessageLookupByLibrary.simpleMessage("limit"), "lowercaseAppName": MessageLookupByLibrary.simpleMessage("renamer"), @@ -173,6 +177,8 @@ class MessageLookup extends MessageLookupByLibrary { "rearrangeToString": m2, "remove": MessageLookupByLibrary.simpleMessage("Remove"), "removeAll": MessageLookupByLibrary.simpleMessage("Remove all"), + "removeCharacters": MessageLookupByLibrary.simpleMessage( + "Remove characters between them"), "removeRenamed": MessageLookupByLibrary.simpleMessage("Remove renamed"), "removeRules": MessageLookupByLibrary.simpleMessage("Remove rules after renaming"), @@ -184,13 +190,12 @@ class MessageLookup extends MessageLookupByLibrary { "ru": MessageLookupByLibrary.simpleMessage("Russian"), "save": MessageLookupByLibrary.simpleMessage("Save"), "selectAll": MessageLookupByLibrary.simpleMessage("Select All"), - "selectionLength": - MessageLookupByLibrary.simpleMessage("Selection length"), "sourceCode": MessageLookupByLibrary.simpleMessage("Source code"), "sr": MessageLookupByLibrary.simpleMessage("Serbian"), "startIndex": MessageLookupByLibrary.simpleMessage("Start index"), "target": MessageLookupByLibrary.simpleMessage("target"), "tj": MessageLookupByLibrary.simpleMessage("Tajik"), + "toLast": MessageLookupByLibrary.simpleMessage("-to-last"), "transliterate": MessageLookupByLibrary.simpleMessage("Transliterate"), "transliterateCyrillic2Latin": MessageLookupByLibrary.simpleMessage( "Cyrillic characters to Latin"), diff --git a/lib/l10n/intl/messages_zh.dart b/lib/l10n/intl/messages_zh.dart index 20c489b..b2ac909 100644 --- a/lib/l10n/intl/messages_zh.dart +++ b/lib/l10n/intl/messages_zh.dart @@ -36,8 +36,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m6(langName, type) => "转写:将${langName}${type}。"; - static String m7(keepType, location, direction, length, startIndex) => - "截取:从${Intl.plural(location, zero: '倒数的', one: '', other: '')}第${startIndex}个字符开始,向${Intl.plural(direction, zero: '后', one: '前', other: 'other')}${Intl.plural(keepType, zero: '移除', one: '保留', other: 'other')}${length}个字符。"; + static String m7(keepType, i1toEnd, i2toEnd, i1, i2) => + "截取:${Intl.plural(keepType, zero: '仅保留', one: '移除', other: '')}从${Intl.plural(i1toEnd, zero: '倒数的', one: '', other: '')}第${i1}个字符至${Intl.plural(i2toEnd, zero: '倒数的', one: '', other: '')}第${i2}个字符之间的内容。"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -85,6 +85,8 @@ class MessageLookup extends MessageLookupByLibrary { "increment": MessageLookupByLibrary.simpleMessage("递增"), "incrementToString": m0, "indexIncrementalStep": MessageLookupByLibrary.simpleMessage("索引递增量"), + "indexOne": MessageLookupByLibrary.simpleMessage("第一处位置"), + "indexTwo": MessageLookupByLibrary.simpleMessage("第二处位置"), "insert": MessageLookupByLibrary.simpleMessage("插入"), "insertBeforeIndex": MessageLookupByLibrary.simpleMessage("在插入位置前侧插入"), "insertIndex": MessageLookupByLibrary.simpleMessage("插入位置"), @@ -93,7 +95,7 @@ class MessageLookup extends MessageLookupByLibrary { "insertToString": m1, "insertedText": MessageLookupByLibrary.simpleMessage("要插入的文本"), "isRegex": MessageLookupByLibrary.simpleMessage("使用正则表达式"), - "keepCharacters": MessageLookupByLibrary.simpleMessage("保留字符"), + "keepCharacters": MessageLookupByLibrary.simpleMessage("保留二者之间的字符"), "language": MessageLookupByLibrary.simpleMessage("语言:"), "limit": MessageLookupByLibrary.simpleMessage("次数"), "lowercaseAppName": MessageLookupByLibrary.simpleMessage("批量重命名"), @@ -146,6 +148,7 @@ class MessageLookup extends MessageLookupByLibrary { "rearrangeToString": m2, "remove": MessageLookupByLibrary.simpleMessage("删除"), "removeAll": MessageLookupByLibrary.simpleMessage("移除全部"), + "removeCharacters": MessageLookupByLibrary.simpleMessage("移除二者之间的字符"), "removeRenamed": MessageLookupByLibrary.simpleMessage("移除已重命名文件"), "removeRules": MessageLookupByLibrary.simpleMessage("重命名后移除所有规则"), "removeToString": m3, @@ -156,12 +159,12 @@ class MessageLookup extends MessageLookupByLibrary { "ru": MessageLookupByLibrary.simpleMessage("俄语"), "save": MessageLookupByLibrary.simpleMessage("保存"), "selectAll": MessageLookupByLibrary.simpleMessage("全选"), - "selectionLength": MessageLookupByLibrary.simpleMessage("所选内容长度"), "sourceCode": MessageLookupByLibrary.simpleMessage("源代码"), "sr": MessageLookupByLibrary.simpleMessage("塞尔维亚语"), "startIndex": MessageLookupByLibrary.simpleMessage("起始索引"), "target": MessageLookupByLibrary.simpleMessage("目标"), "tj": MessageLookupByLibrary.simpleMessage("塔吉克语"), + "toLast": MessageLookupByLibrary.simpleMessage("倒数"), "transliterate": MessageLookupByLibrary.simpleMessage("转写"), "transliterateCyrillic2Latin": MessageLookupByLibrary.simpleMessage("从西里尔字符转为拉丁字符"), diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index af59189..4cc479d 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -1060,11 +1060,31 @@ class L10n { ); } - /// `Selection length` - String get selectionLength { + /// `First character index` + String get indexOne { return Intl.message( - 'Selection length', - name: 'selectionLength', + 'First character index', + name: 'indexOne', + desc: '', + args: [], + ); + } + + /// `Second character index` + String get indexTwo { + return Intl.message( + 'Second character index', + name: 'indexTwo', + desc: '', + args: [], + ); + } + + /// `-to-last` + String get toLast { + return Intl.message( + '-to-last', + name: 'toLast', desc: '', args: [], ); @@ -1080,16 +1100,26 @@ class L10n { ); } - /// `Keep characters` + /// `Keep characters between them` String get keepCharacters { return Intl.message( - 'Keep characters', + 'Keep characters between them', name: 'keepCharacters', desc: '', args: [], ); } + /// `Remove characters between them` + String get removeCharacters { + return Intl.message( + 'Remove characters between them', + name: 'removeCharacters', + desc: '', + args: [], + ); + } + /// `Contains metadata tag while MetadataParser was not provided.` String get metadataParserNotProvided { return Intl.message( @@ -1170,14 +1200,14 @@ class L10n { ); } - /// `Truncate: {keepType, plural, =0{remove} =1{keep} other{}} {length} characters starting from the char #{startIndex}{location, plural, =0{-to-end} =1{} other{}} going {direction, plural, =0{backward} =1{forward} other{}}.` + /// `Truncate: {keepType, plural, =0{keep only} =1{remove} other{}} characters between the {i1}th{i1toEnd, plural, =0{-to-end} =1{} other{}} character and the {i2}th{i2toEnd, plural, =0{-to-end} =1{} other{}}.` String truncateToString( - num keepType, num location, num direction, num length, num startIndex) { + num keepType, num i1toEnd, num i2toEnd, num i1, num i2) { return Intl.message( - 'Truncate: ${Intl.plural(keepType, zero: 'remove', one: 'keep', other: '')} $length characters starting from the char #$startIndex${Intl.plural(location, zero: '-to-end', one: '', other: '')} going ${Intl.plural(direction, zero: 'backward', one: 'forward', other: '')}.', + 'Truncate: ${Intl.plural(keepType, zero: 'keep only', one: 'remove', other: '')} characters between the ${i1}th${Intl.plural(i1toEnd, zero: '-to-end', one: '', other: '')} character and the ${i2}th${Intl.plural(i2toEnd, zero: '-to-end', one: '', other: '')}.', name: 'truncateToString', desc: '', - args: [keepType, location, direction, length, startIndex], + args: [keepType, i1toEnd, i2toEnd, i1, i2], ); } diff --git a/lib/rules/rule_truncate.dart b/lib/rules/rule_truncate.dart index 26c87d7..d0fb26d 100644 --- a/lib/rules/rule_truncate.dart +++ b/lib/rules/rule_truncate.dart @@ -2,56 +2,45 @@ part of 'rule.dart'; class RuleTruncate implements Rule { RuleTruncate( - this.startIndex, - this.fromStart, - this.direction, - this.length, + this.index1, + this.index2, + this.i1toEnd, + this.i2toEnd, this.ignoreExtension, - this.keep, + this.keepBetween, ); - final int startIndex; // count from - final bool fromStart; // true: count from start, false: count from end. - final bool direction; // truncate direction - final int length; // truncate length + final int index1; + final int index2; + final bool i1toEnd; + final bool i2toEnd; final bool ignoreExtension; - final bool keep; // true: keep chars in ranges, false: keep out of range + final bool keepBetween; // true: keep chars between 2 indexes, false: keep chars around them @override String newName(String oldName, {FileMetadata? metadata}) { String newName, extension; (newName, extension) = splitFileName(oldName, ignoreExtension); - int index = startIndex; + int start = index1; - if (!fromStart) { - index = newName.length - index + 1; + if (i1toEnd) { + start = newName.length + start; } - int start; - int end; + int end = index2; - if (direction) { - start = index - 1; - end = index + length - 1; - } else { - start = index - length; - end = index; - } - - if (start < 0) { - start = 0; - } else if (start >= newName.length) { - start = newName.length; + if (i2toEnd) { + end = newName.length + end; } - if (end < 0) { - end = 0; - } else if (end >= newName.length) { - end = newName.length; + if (start > end) { + final temp = start; + start = end; + end = temp; } - if (keep) { + if (keepBetween) { newName = newName.substring(start, end); } else { newName = newName.replaceRange(start, end, ''); @@ -63,11 +52,11 @@ class RuleTruncate implements Rule { @override String toString() { return L10n.current.truncateToString( - keep ? 1 : 0, - fromStart ? 1 : 0, - direction ? 1 : 0, - length, - startIndex, + keepBetween ? 0 : 1, + i1toEnd ? 0 : 1, + i2toEnd ? 0 : 1, + index1, + index2, ); } }