diff --git a/MacDown/Code/Document/MPDocument.m b/MacDown/Code/Document/MPDocument.m index c3b2f68..58d8e1b 100644 --- a/MacDown/Code/Document/MPDocument.m +++ b/MacDown/Code/Document/MPDocument.m @@ -491,6 +491,16 @@ static NSString * const kMPMathJaxCDN = } } +- (IBAction)toggleUnorderedList:(id)sender +{ + [self.editor toggleBlockWithPattern:@"^[\\*\\+-] \\S" prefix:@"* "]; +} + +- (IBAction)toggleBlockquote:(id)sender +{ + [self.editor toggleBlockWithPattern:@"^> \\S" prefix:@"> "]; +} + - (IBAction)indent:(id)sender { NSString *padding = @"\t"; diff --git a/MacDown/Code/Extension/NSTextView+Autocomplete.h b/MacDown/Code/Extension/NSTextView+Autocomplete.h index 12ae9c2..ea3bc7f 100644 --- a/MacDown/Code/Extension/NSTextView+Autocomplete.h +++ b/MacDown/Code/Extension/NSTextView+Autocomplete.h @@ -26,6 +26,7 @@ - (BOOL)deleteMatchingCharactersAround:(NSUInteger)location; - (BOOL)unindentForSpacesBefore:(NSUInteger)location; - (BOOL)toggleForMarkupPrefix:(NSString *)prefix suffix:(NSString *)suffix; +- (void)toggleBlockWithPattern:(NSString *)pattern prefix:(NSString *)prefix; - (void)indentSelectedLinesWithPadding:(NSString *)padding; - (void)unindentSelectedLines; - (BOOL)insertMappedContent; diff --git a/MacDown/Code/Extension/NSTextView+Autocomplete.m b/MacDown/Code/Extension/NSTextView+Autocomplete.m index ebb634d..afa85f7 100644 --- a/MacDown/Code/Extension/NSTextView+Autocomplete.m +++ b/MacDown/Code/Extension/NSTextView+Autocomplete.m @@ -253,6 +253,71 @@ static NSString * const kMPListLineHeadPattern = return isOn; } +- (void)toggleBlockWithPattern:(NSString *)pattern prefix:(NSString *)prefix +{ + NSRegularExpression *regex = + [[NSRegularExpression alloc] initWithPattern:pattern options:0 + error:NULL]; + NSString *content = self.string; + NSRange selectedRange = self.selectedRange; + NSRange lineRange = [content lineRangeForRange:selectedRange]; + + NSString *toProcess = [content substringWithRange:lineRange]; + NSArray *lines = [toProcess componentsSeparatedByString:@"\n"]; + + BOOL isMarked = YES; + for (NSString *line in lines) + { + NSUInteger lineLength = line.length; + if (!lineLength) + continue; + NSRange matchRange = + [regex rangeOfFirstMatchInString:line options:0 + range:NSMakeRange(0, lineLength)]; + if (matchRange.location == NSNotFound) + { + isMarked = NO; + break; + } + } + + NSUInteger prefixLength = prefix.length; + NSMutableArray *modLines = [NSMutableArray arrayWithCapacity:lines.count]; + + __block NSUInteger totalShift = 0; + [lines enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) { + NSString *line = obj; + if (line.length) + { + totalShift += prefixLength; + if (!isMarked) + line = [prefix stringByAppendingString:line]; + else + line = [line substringFromIndex:prefixLength]; + } + [modLines addObject:line]; + }]; + NSString *processed = [modLines componentsJoinedByString:@"\n"]; + [self insertText:processed replacementRange:lineRange]; + + if (!isMarked) + { + selectedRange.location += prefixLength; + selectedRange.length += totalShift - prefixLength; + } + else + { + selectedRange.location -= prefixLength; + selectedRange.length -= totalShift - prefixLength; + if (selectedRange.location < lineRange.location) + { + selectedRange.length -= lineRange.location - selectedRange.location; + selectedRange.location = lineRange.location; + } + } + self.selectedRange = selectedRange; +} + - (void)indentSelectedLinesWithPadding:(NSString *)padding { NSString *content = self.string; diff --git a/MacDown/Localization/Base.lproj/MainMenu.xib b/MacDown/Localization/Base.lproj/MainMenu.xib index 33028e7..9640fc8 100644 --- a/MacDown/Localization/Base.lproj/MainMenu.xib +++ b/MacDown/Localization/Base.lproj/MainMenu.xib @@ -465,6 +465,19 @@ + + + + + + + + + + + + +