Let RMateServer use OakDocumentController API

This commit is contained in:
Allan Odgaard
2016-09-22 10:30:44 +02:00
parent dc5028f039
commit 9e7aa55ac2

View File

@@ -1,10 +1,12 @@
#include <oak/oak.h>
#include <text/parse.h>
#include <text/hexdump.h>
#include <document/collection.h>
#include <document/OakDocument.h>
#include <document/OakDocumentController.h>
#include <oak/debug.h>
#include <authorization/authorization.h>
#include <io/io.h>
#include <ns/ns.h>
#include <OakAppKit/IOAlertPanel.h>
OAK_DEBUG_VAR(RMateServer);
@@ -259,43 +261,38 @@ struct record_t
namespace // wrap in anonymous namespace to avoid clashing with other callbacks named the same
{
struct base_t : document::document_t::callback_t
struct base_t
{
WATCH_LEAKS(base_t);
virtual void save_document (document::document_ptr document) { }
virtual void close_document (document::document_t* document) { }
void document_will_delete (document::document_t* document)
base_t (OakDocument* document)
{
close_and_delete(document);
_close_observer = [[NSNotificationCenter defaultCenter] addObserverForName:OakDocumentWillCloseNotification object:document queue:nil usingBlock:^(NSNotification*){
this->close_document(document);
delete this;
}];
_save_observer = [[NSNotificationCenter defaultCenter] addObserverForName:OakDocumentDidSaveNotification object:document queue:nil usingBlock:^(NSNotification*){
this->save_document(document);
}];
}
void handle_document_event (document::document_ptr document, event_t event)
virtual ~base_t ()
{
if(event == did_change_load_status && !document->is_loaded())
{
D(DBF_RMateServer, bug("%p\n", this););
close_and_delete(document.get());
}
else if(event == did_save)
{
save_document(document);
}
[[NSNotificationCenter defaultCenter] removeObserver:_save_observer];
[[NSNotificationCenter defaultCenter] removeObserver:_close_observer];
}
virtual void save_document (OakDocument* document) { }
virtual void close_document (OakDocument* document) { }
private:
void close_and_delete (document::document_t* document)
{
document->remove_callback(this);
close_document(document);
delete this;
}
id _save_observer;
id _close_observer;
};
struct retain_temp_file_callback_t : base_t
{
retain_temp_file_callback_t (temp_file_ptr file) : file(file) { }
retain_temp_file_callback_t (OakDocument* document, temp_file_ptr file) : base_t(document), file(file) { }
temp_file_ptr file;
};
@@ -303,14 +300,14 @@ namespace // wrap in anonymous namespace to avoid clashing with other callbacks
{
WATCH_LEAKS(save_close_callback_t);
save_close_callback_t (std::string const& path, socket_t const& socket, bool data_on_save, bool data_on_close, std::string const& token) : path(path), socket(socket), data_on_save(data_on_save), data_on_close(data_on_close), token(token)
save_close_callback_t (OakDocument* document, std::string const& path, socket_t const& socket, bool data_on_save, bool data_on_close, std::string const& token) : base_t(document), path(path), socket(socket), data_on_save(data_on_save), data_on_close(data_on_close), token(token)
{
D(DBF_RMateServer, bug("%p\n", this););
}
void save_document (document::document_ptr document)
void save_document (OakDocument* document)
{
D(DBF_RMateServer, bug("%s\n", document->path().c_str()););
D(DBF_RMateServer, bug("%s\n", document.path.UTF8String););
bool res = true;
res = res && write(socket, "save\r\n", 6) == 6;
res = res && write_token();
@@ -318,12 +315,12 @@ namespace // wrap in anonymous namespace to avoid clashing with other callbacks
res = res && write_data();
res = res && write(socket, "\r\n", 2) == 2;
if(!res)
fprintf(stderr, "*** rmate: callback failed to save %s\n", document->display_name().c_str());
fprintf(stderr, "*** rmate: callback failed to save %s\n", document.displayName.UTF8String);
}
void close_document (document::document_t* document)
void close_document (OakDocument* document)
{
D(DBF_RMateServer, bug("%s\n", document->path().c_str()););
D(DBF_RMateServer, bug("%s\n", document.path.UTF8String););
bool res = true;
res = res && write(socket, "close\r\n", 7) == 7;
res = res && write_token();
@@ -331,7 +328,7 @@ namespace // wrap in anonymous namespace to avoid clashing with other callbacks
res = res && write_data();
res = res && write(socket, "\r\n", 2) == 2;
if(!res)
fprintf(stderr, "*** rmate: callback failed while closing %s\n", document->display_name().c_str());
fprintf(stderr, "*** rmate: callback failed while closing %s\n", document.displayName.UTF8String);
}
private:
@@ -370,7 +367,7 @@ namespace // wrap in anonymous namespace to avoid clashing with other callbacks
std::string token;
};
struct reactivate_callback_t : base_t
struct reactivate_callback_t
{
WATCH_LEAKS(reactivate_callback_t);
@@ -380,17 +377,18 @@ namespace // wrap in anonymous namespace to avoid clashing with other callbacks
_terminal = [[NSWorkspace sharedWorkspace] frontmostApplication];
}
void watch_document (document::document_ptr document)
void watch_document (OakDocument* document)
{
++*shared_count;
document->add_callback(new reactivate_callback_t(*this));
}
auto counter = shared_count;
NSRunningApplication* terminal = _terminal;
void close_document (document::document_t* document)
{
D(DBF_RMateServer, bug("%zu → %zu\n", *shared_count, *shared_count - 1););
if(--*shared_count == 0)
[_terminal activateWithOptions:NSApplicationActivateIgnoringOtherApps];
++*counter;
__weak __block id observerId = [[NSNotificationCenter defaultCenter] addObserverForName:OakDocumentWillCloseNotification object:document queue:nil usingBlock:^(NSNotification*){
D(DBF_RMateServer, bug("%zu → %zu\n", *shared_count, *shared_count - 1););
if(--*counter == 0)
[terminal activateWithOptions:NSApplicationActivateIgnoringOtherApps];
[[NSNotificationCenter defaultCenter] removeObserver:observerId];
}];
}
private:
@@ -519,7 +517,7 @@ struct socket_observer_t
{
reactivate_callback_t reactivate_callback;
std::vector<document::document_ptr> documents;
NSMutableArray<OakDocument*>* documents = [NSMutableArray array];
for(auto& record : records)
{
std::map<std::string, std::string>& args = record.arguments;
@@ -530,61 +528,61 @@ struct socket_observer_t
bool reActivate = args["re-activate"] == "yes";
std::string fileType = args.find("file-type") == args.end() ? NULL_STR : args["file-type"];
document::document_ptr doc;
OakDocument* doc;
if(args.find("path") != args.end())
{
if(path::is_directory(args["path"]))
{
document::show_browser(args["path"]);
[OakDocumentController.sharedInstance showFileBrowserAtPath:to_ns(args["path"])];
continue;
}
doc = document::create(args["path"]);
doc = [OakDocumentController.sharedInstance documentWithPath:to_ns(args["path"])];
}
else if(args.find("uuid") != args.end())
{
if(!(doc = document::find(args["uuid"])))
if(!(doc = [OakDocumentController.sharedInstance findDocumentWithIdentifier:[[NSUUID alloc] initWithUUIDString:to_ns(args["uuid"])]]))
continue;
}
else if(args.find("data") != args.end())
{
if(writeBackOnSave || writeBackOnClose)
{
doc = document::create(args["data"]);
doc->set_recent_tracking(false);
doc = [OakDocumentController.sharedInstance documentWithPath:to_ns(args["data"])];
doc.recentTrackingDisabled = YES;
}
else
{
doc = document::from_content(path::content(args["data"]), fileType);
doc = [OakDocument documentWithData:[NSData dataWithContentsOfFile:to_ns(args["data"])] fileType:to_ns(fileType) customName:nil];
}
}
else
{
doc = document::create();
doc = [OakDocumentController.sharedInstance untitledDocument];
}
if(fileType != NULL_STR)
doc->set_file_type(fileType);
doc.fileType = to_ns(fileType);
if(args.find("real-path") != args.end())
{
D(DBF_RMateServer, bug("set documents virtual path: %s\n", args["real-path"].c_str()););
doc->set_virtual_path(args["real-path"]);
doc.virtualPath = to_ns(args["real-path"]);
}
if(!args["display-name"].empty())
doc->set_custom_name(args["display-name"]);
doc.customName = to_ns(args["display-name"]);
if(!args["selection"].empty())
doc->set_selection(args["selection"]);
doc.selection = to_ns(args["selection"]);
if(args["add-to-recents"] != "yes")
doc->set_recent_tracking(false);
doc.recentTrackingDisabled = YES;
if(wait || writeBackOnSave || writeBackOnClose)
doc->add_callback(new save_close_callback_t(doc->path(), socket, writeBackOnSave, writeBackOnClose, token));
new save_close_callback_t(doc, to_s(doc.path), socket, writeBackOnSave, writeBackOnClose, token);
if(args.find("data") != args.end() && (writeBackOnSave || writeBackOnClose))
doc->add_callback(new retain_temp_file_callback_t(record.file));
new retain_temp_file_callback_t(doc, record.file);
if(reActivate)
reactivate_callback.watch_document(doc);
@@ -594,16 +592,16 @@ struct socket_observer_t
// bool bring_to_front;
if(args.find("authorization") != args.end())
doc->set_authorization(args["authorization"]);
doc.authorization = args["authorization"];
if(oak::uuid_t::is_valid(args["project-uuid"]))
document::show(doc, args["project-uuid"]);
else documents.push_back(doc);
[OakDocumentController.sharedInstance showDocument:doc inProject:[[NSUUID alloc] initWithUUIDString:to_ns(args["project-uuid"])] bringToFront:YES];
else [documents addObject:doc];
}
if(documents.empty())
[NSApp activateIgnoringOtherApps:YES];
else document::show(documents);
if(documents.count)
[OakDocumentController.sharedInstance showDocuments:documents];
else [NSApp activateIgnoringOtherApps:YES];
}
void handle_marks (socket_t const& socket)
@@ -615,11 +613,11 @@ struct socket_observer_t
auto& args = record.arguments;
document::document_ptr doc;
OakDocument* doc;
if(args.find("uuid") != args.end())
doc = document::find(args["uuid"]);
doc = [OakDocumentController.sharedInstance findDocumentWithIdentifier:[[NSUUID alloc] initWithUUIDString:to_ns(args["uuid"])]];
else if(args.find("path") != args.end())
doc = document::create(args["path"]);
doc = [OakDocumentController.sharedInstance documentWithPath:to_ns(args["path"])];
text::pos_t line = args.find("line") != args.end() ? text::pos_t(args["line"]) : text::pos_t::undefined;
std::string mark = args.find("mark") != args.end() ? args["mark"] : NULL_STR;
@@ -627,14 +625,14 @@ struct socket_observer_t
if(record.command == "clear-mark")
{
if(doc)
doc->remove_mark(line, mark);
else document::remove_marks(mark);
[doc removeMarkOfType:to_ns(mark) atPosition:line];
else [OakDocument removeAllMarksOfType:to_ns(mark)];
}
else if(record.command == "set-mark")
{
std::string::size_type n = mark.find(':');
if(doc)
doc->add_mark(line, n == std::string::npos ? mark : mark.substr(0, n), n == std::string::npos ? std::string() : mark.substr(n+1));
[doc setMarkOfType:to_ns(n == std::string::npos ? mark : mark.substr(0, n)) atPosition:line content:n == std::string::npos ? nil : to_ns(mark.substr(n+1))];
else fprintf(stderr, "set-mark: no document\n");
}
}