mirror of
https://github.com/coteditor/CotEditor.git
synced 2024-10-26 19:10:11 +03:00
Add "Delete Duplicates" action
This commit is contained in:
parent
fbc7b0af68
commit
ab1c79d635
@ -8,7 +8,7 @@ develop
|
||||
### New Features
|
||||
|
||||
- Introduce Auto Save and Versions as an option (in General pane).
|
||||
- Add new “Move Line Up”, “Move Line Down”, “Sort Lines”, “Reverse Lines” and “Delete Line” actions to new Text menu.
|
||||
- Add new actions handling selected lines to the new Text menu > Lines.
|
||||
- They are also added to the AppleScript terms.
|
||||
- Add “Spell Check” button to toolbar icon choices.
|
||||
- Customize toolbar to add it to your toolbar.
|
||||
|
@ -682,6 +682,12 @@
|
||||
<action selector="reverseLines:" target="-1" id="LXU-WT-T6K"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete Duplicates" id="bjv-m0-tZq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="deleteDuplicateLine:" target="-1" id="ldW-5W-PtK"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Dpo-h5-IyY"/>
|
||||
<menuItem title="Delete Line" id="sFn-3j-pY5">
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
|
@ -145,6 +145,9 @@
|
||||
<responds-to command="reverse lines">
|
||||
<cocoa method="handleReverseLinesScriptCommand:"/>
|
||||
</responds-to>
|
||||
<responds-to command="delete duplicate line">
|
||||
<cocoa method="handleDeleteDuplicateLineScriptCommand:"/>
|
||||
</responds-to>
|
||||
<responds-to command="comment out">
|
||||
<cocoa method="handleCommentOutScriptCommand:"/>
|
||||
</responds-to>
|
||||
@ -285,6 +288,11 @@
|
||||
<direct-parameter type="text selection" description="The selection to reverse"/>
|
||||
</command>
|
||||
|
||||
<command name="delete duplicate line" code="cEd1Dldp" description="Delete duplicate lines in selection">
|
||||
<access-group identifier="com.coteditor.CotEditor.edit" access="rw"/>
|
||||
<direct-parameter type="text selection" description="The selection to check duplication"/>
|
||||
</command>
|
||||
|
||||
<command name="comment out" code="cEd1Cout" description="Append comment delimiters to selected text if possible.">
|
||||
<access-group identifier="com.coteditor.CotEditor.edit" access="rw"/>
|
||||
<direct-parameter type="text selection" description="The selection to comment out"/>
|
||||
|
@ -86,6 +86,7 @@ typedef NS_ENUM(NSUInteger, CEUNFType) {
|
||||
- (void)handleMoveLineDownScriptCommand:(NSScriptCommand *)command;
|
||||
- (void)handleSortLinesAscendingScriptCommand:(NSScriptCommand *)command;
|
||||
- (void)handleReverseLinesScriptCommand:(NSScriptCommand *)command;
|
||||
- (void)handleDeleteDuplicateLineScriptCommand:(NSScriptCommand *)command;
|
||||
- (void)handleCommentOutScriptCommand:(NSScriptCommand *)command;
|
||||
- (void)handleUncommentScriptCommand:(NSScriptCommand *)command;
|
||||
- (void)handleChangeCaseScriptCommand:(NSScriptCommand *)command;
|
||||
|
@ -266,7 +266,7 @@
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// swap selected lines with the line just below
|
||||
/// sort selected lines ascending
|
||||
- (void)handleSortLinesAscendingScriptCommand:(NSScriptCommand *)command
|
||||
// ------------------------------------------------------
|
||||
{
|
||||
@ -275,7 +275,7 @@
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// swap selected lines with the line just below
|
||||
/// reverse selected lines
|
||||
- (void)handleReverseLinesScriptCommand:(NSScriptCommand *)command
|
||||
// ------------------------------------------------------
|
||||
{
|
||||
@ -283,6 +283,15 @@
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// delete duplicate lines in selection
|
||||
- (void)handleDeleteDuplicateLineScriptCommand:(NSScriptCommand *)command
|
||||
// ------------------------------------------------------
|
||||
{
|
||||
[[[[self document] editor] focusedTextView] deleteDuplicateLine:command];
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// comment-out the selection
|
||||
- (void)handleCommentOutScriptCommand:(NSScriptCommand *)command
|
||||
|
@ -128,6 +128,7 @@
|
||||
- (IBAction)moveLineDown:(nullable id)sender;
|
||||
- (IBAction)sortLinesAscending:(nullable id)sender;
|
||||
- (IBAction)reverseLines:(nullable id)sender;
|
||||
- (IBAction)deleteDuplicateLine:(nullable id)sender;
|
||||
- (IBAction)deleteLine:(nullable id)sender;
|
||||
|
||||
@end
|
||||
|
@ -2577,6 +2577,65 @@ static NSPoint kTextContainerOrigin;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// remove duplicate lines in selection
|
||||
- (IBAction)deleteDuplicateLine:(nullable id)sender
|
||||
// ------------------------------------------------------
|
||||
{
|
||||
if ([self selectedRange].length == 0) { return; }
|
||||
|
||||
NSMutableArray<NSValue *> *replacementRanges = [NSMutableArray array];
|
||||
NSMutableArray<NSString *> *replacementStrings = [NSMutableArray array];
|
||||
NSMutableOrderedSet<NSString *> *uniqueLines = [NSMutableOrderedSet orderedSet];
|
||||
NSUInteger processedCount = 0;
|
||||
|
||||
// collect duplicate lines
|
||||
for (NSValue *rangeValue in [self selectedRanges]) {
|
||||
NSRange range = [rangeValue rangeValue];
|
||||
NSRange lineRange = [[self string] lineRangeForRange:range];
|
||||
NSString *targetString = [[self string] substringWithRange:lineRange];
|
||||
NSArray<NSString *> *lines = [targetString componentsSeparatedByString:@"\n"];
|
||||
|
||||
// filter duplicate lines
|
||||
[uniqueLines addObjectsFromArray:lines];
|
||||
|
||||
NSRange targetLinesRange = NSMakeRange(processedCount, [uniqueLines count] - processedCount);
|
||||
processedCount += targetLinesRange.length;
|
||||
|
||||
// do nothing if no duplicate line exists
|
||||
if (targetLinesRange.length == [lines count]) { continue; }
|
||||
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:targetLinesRange];
|
||||
NSString *replacementString = [[uniqueLines objectsAtIndexes:indexSet] componentsJoinedByString:@"\n"];
|
||||
|
||||
// append last new line only if the original selected lineRange has a new line at the end
|
||||
if ([targetString hasSuffix:@"\n"]) {
|
||||
replacementString = [replacementString stringByAppendingString:@"\n"];
|
||||
}
|
||||
|
||||
[replacementStrings addObject:replacementString];
|
||||
[replacementRanges addObject:[NSValue valueWithRange:lineRange]];
|
||||
}
|
||||
|
||||
// return if no line to be removed
|
||||
if ([replacementRanges count] == 0) { return; }
|
||||
if (![self shouldChangeTextInRanges:replacementRanges replacementStrings:replacementStrings]) { return; }
|
||||
|
||||
// delete duplicate lines
|
||||
NSTextStorage *textStorage = [self textStorage];
|
||||
[replacementStrings enumerateObjectsWithOptions:NSEnumerationReverse
|
||||
usingBlock:^(NSString *_Nonnull replacementString, NSUInteger idx, BOOL * _Nonnull stop)
|
||||
{
|
||||
NSRange replacementRange = [replacementRanges[idx] rangeValue];
|
||||
[textStorage replaceCharactersInRange:replacementRange withString:replacementString];
|
||||
}];
|
||||
[self didChangeText];
|
||||
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"Delete Duplicate Lines", @"action name")];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// remove selected lines
|
||||
- (IBAction)deleteLine:(nullable id)sender
|
||||
|
@ -185,6 +185,7 @@
|
||||
"Move Line" = "Zeile verschieben";
|
||||
"Sort Lines" = "Zeilen sortieren";
|
||||
"Reverse Lines" = "Zeilen umdrehen";
|
||||
"Remove Duplicate Lines" = "Doppelte Zeilen löschen";
|
||||
"Delete Line" = "Zeile löschen";
|
||||
|
||||
// Menu items
|
||||
|
@ -327,6 +327,8 @@
|
||||
"OQl-Uo-yfn.title" = "Sortieren";
|
||||
/* Class = "NSMenuItem"; title = "Reverse"; ObjectID = "xhf-NR-D2Q"; */
|
||||
"xhf-NR-D2Q.title" = "Umdrehen";
|
||||
/* Class = "NSMenuItem"; title = "Delete Duplicates"; ObjectID = "bjv-m0-tZq"; */
|
||||
"bjv-m0-tZq.title" = "Doppelte löschen";
|
||||
/* Class = "NSMenuItem"; title = "Delete Line"; ObjectID = "sFn-3j-pY5"; */
|
||||
"sFn-3j-pY5.title" = "Zeile löschen";
|
||||
|
||||
|
@ -187,6 +187,7 @@
|
||||
"Move Line" = "行を移動";
|
||||
"Sort Lines" = "行をソート";
|
||||
"Reverse Lines" = "行を反転";
|
||||
"Remove Duplicate Lines" = "重複行を削除";
|
||||
"Delete Line" = "行を削除";
|
||||
|
||||
// Menu items
|
||||
|
@ -327,6 +327,8 @@
|
||||
"OQl-Uo-yfn.title" = "ソート";
|
||||
/* Class = "NSMenuItem"; title = "Reverse"; ObjectID = "xhf-NR-D2Q"; */
|
||||
"xhf-NR-D2Q.title" = "反転";
|
||||
/* Class = "NSMenuItem"; title = "Delete Duplicates"; ObjectID = "bjv-m0-tZq"; */
|
||||
"bjv-m0-tZq.title" = "重複を削除";
|
||||
/* Class = "NSMenuItem"; title = "Delete Line"; ObjectID = "sFn-3j-pY5"; */
|
||||
"sFn-3j-pY5.title" = "行を削除";
|
||||
|
||||
|
@ -184,6 +184,7 @@
|
||||
"Move Line" = "Move Line"; // FIXME: added
|
||||
"Sort Lines" = "Sort Lines"; // FIXME: added
|
||||
"Reverse Lines" = "Reverse Lines"; // FIXME: added
|
||||
"Remove Duplicate Lines" = "Remove Duplicate Lines"; // FIXME: added
|
||||
"Delete Line" = "Delete Line"; // FIXME: added
|
||||
|
||||
// Menu items
|
||||
|
@ -328,6 +328,8 @@
|
||||
"OQl-Uo-yfn.title" = "Sort"; // FIXME: added
|
||||
/* Class = "NSMenuItem"; title = "Reverse"; ObjectID = "xhf-NR-D2Q"; */
|
||||
"xhf-NR-D2Q.title" = "Reverse"; // FIXME: added
|
||||
/* Class = "NSMenuItem"; title = "Delete Duplicates"; ObjectID = "bjv-m0-tZq"; */
|
||||
"bjv-m0-tZq.title" = "Delete Duplicates"; // FIXME: added
|
||||
/* Class = "NSMenuItem"; title = "Delete Line"; ObjectID = "sFn-3j-pY5"; */
|
||||
"sFn-3j-pY5.title" = "Delete Line"; // FIXME: added
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user