Add "Delete Duplicates" action

This commit is contained in:
1024jp 2015-10-16 14:11:00 +09:00
parent fbc7b0af68
commit ab1c79d635
13 changed files with 96 additions and 3 deletions

View File

@ -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.

View File

@ -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">

View File

@ -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"/>

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -187,6 +187,7 @@
"Move Line" = "行を移動";
"Sort Lines" = "行をソート";
"Reverse Lines" = "行を反転";
"Remove Duplicate Lines" = "重複行を削除";
"Delete Line" = "行を削除";
// Menu items

View File

@ -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" = "行を削除";

View File

@ -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

View File

@ -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