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