From bcc3e4c1fbd3affc8313dcc99c40733fccadba3a Mon Sep 17 00:00:00 2001 From: Allan Odgaard Date: Thu, 25 Apr 2013 16:38:16 +0700 Subject: [PATCH] Fix refresh/undo for commands causing document saving MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since saving is asynchronous the scoped refresh/undo helper would do “cleanup” before the command ran and potentially made document changes. Commands executed at a lower level (i.e. by editor_t via macros) presently still has this issue. This should be fixed when macros are refactored (this isn’t the only issue related to macros). Closes #450. --- .../DocumentWindow/src/DocumentController.mm | 35 +++++++++++++++++++ Frameworks/OakTextView/src/OakTextView.h | 1 + Frameworks/OakTextView/src/OakTextView.mm | 18 +++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Frameworks/DocumentWindow/src/DocumentController.mm b/Frameworks/DocumentWindow/src/DocumentController.mm index af3e04e8..b61d6f7f 100644 --- a/Frameworks/DocumentWindow/src/DocumentController.mm +++ b/Frameworks/DocumentWindow/src/DocumentController.mm @@ -925,6 +925,41 @@ namespace [DocumentSaveHelper trySaveDocuments:documentsToSave forWindow:self.window defaultDirectory:self.untitledSavePath completionHandler:nil]; } +- (void)bundleItemPreExec:(pre_exec::type)preExec completionHandler:(void(^)(BOOL success))callback +{ + std::vector documentsToSave; + switch(preExec) + { + case pre_exec::save_document: + { + if(_selectedDocument && (_selectedDocument->is_modified() || !_selectedDocument->is_on_disk())) + documentsToSave.push_back(_selectedDocument); + } + break; + + case pre_exec::save_project: + { + for(auto document : _documents) + { + if(document->is_modified() && document->path() != NULL_STR) + documentsToSave.push_back(document); + } + } + break; + } + + if(!documentsToSave.empty()) + { + [DocumentSaveHelper trySaveDocuments:documentsToSave forWindow:self.window defaultDirectory:self.untitledSavePath completionHandler:^(BOOL success){ + callback(success); + }]; + } + else + { + callback(YES); + } +} + // ================ // = Window Title = // ================ diff --git a/Frameworks/OakTextView/src/OakTextView.h b/Frameworks/OakTextView/src/OakTextView.h index 0453b615..7515f17d 100644 --- a/Frameworks/OakTextView/src/OakTextView.h +++ b/Frameworks/OakTextView/src/OakTextView.h @@ -24,6 +24,7 @@ enum OTVFontSmoothing : NSUInteger @protocol OakTextViewDelegate @optional +- (void)bundleItemPreExec:(pre_exec::type)preExec completionHandler:(void(^)(BOOL success))callback; - (NSString*)scopeAttributes; @end diff --git a/Frameworks/OakTextView/src/OakTextView.mm b/Frameworks/OakTextView/src/OakTextView.mm index 6a00d940..24354adc 100644 --- a/Frameworks/OakTextView/src/OakTextView.mm +++ b/Frameworks/OakTextView/src/OakTextView.mm @@ -1104,7 +1104,23 @@ doScroll: case bundles::kItemTypeCommand: { [self recordSelector:@selector(executeCommandWithOptions:) withArgument:ns::to_dictionary(item->plist())]; - document::run(parse_command(item), document->buffer(), editor->ranges(), document); + + auto command = parse_command(item); + if([self.delegate respondsToSelector:@selector(bundleItemPreExec:completionHandler:)]) + { + [self.delegate bundleItemPreExec:command.pre_exec completionHandler:^(BOOL success){ + if(success) + { + AUTO_REFRESH; + document::run(command, document->buffer(), editor->ranges(), document); + } + }]; + } + else + { + command.pre_exec = pre_exec::nop; + document::run(command, document->buffer(), editor->ranges(), document); + } } break;