diff --git a/src/App.cpp b/src/App.cpp index 88768d6..5513a01 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -71,7 +71,7 @@ App::~App() void -App::Init() +App::Init(bool suppressWindow) { BPath settingsPath; find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath); @@ -88,6 +88,8 @@ App::Init() EditorWindow::SetPreferences(fPreferences); Languages::LoadLanguages(); + + fSuppressInitialWindow = suppressWindow; } @@ -200,36 +202,12 @@ App::QuitRequested() void App::ReadyToRun() { - if(CountWindows() == 0 && fSuppressInitialWindow == false) { + if(fSuppressInitialWindow == false && CountWindows() == 0) { PostMessage(WINDOW_NEW); } } -void -App::ArgvReceived(int32 argc, char** argv) -{ - BMessage* message = CurrentMessage(); - BString cwd = message->GetString("cwd", "~"); - std::unique_ptr windowStack; - for(int32 i = 1; i < argc; ++i) { - std::string arg = argv[i]; - // FIXME: this should be handled in main.cpp probably - if(arg == "-w" || arg == "--wait" || arg == "-h" || arg == "--help") - continue; - int32 line, column; - std::string filename = ParseFileArgument(argv[i], &line, &column); - if(filename.find('/') != 0) { - BPath absolute(cwd.String(), filename.c_str(), true); - filename = absolute.Path(); - } - entry_ref ref; - BEntry(filename.c_str()).GetRef(&ref); - _ActivateOrCreateWindow(message, ref, line, column, windowStack); - } -} - - void App::RefsReceived(BMessage* message) { @@ -248,8 +226,8 @@ App::RefsReceived(BMessage* message) trackerMessage.AddRef("refs", &ref); continue; } - const int32 line = message->GetInt32("be:line", -1); - const int32 column = message->GetInt32("be:column", -1); + const int32 line = message->GetInt32("be:line", i, -1); + const int32 column = message->GetInt32("be:column", i, -1); _ActivateOrCreateWindow(message, ref, line, column, windowStack); } } @@ -263,9 +241,6 @@ void App::MessageReceived(BMessage* message) { switch(message->what) { - case SUPPRESS_INITIAL_WINDOW: { - fSuppressInitialWindow = true; - } break; case ACTIVATE_WINDOW: { BWindow* window = nullptr; if(message->FindPointer("window", (void**) &window) == B_OK && window != nullptr) { diff --git a/src/App.h b/src/App.h index f15ccfe..22965d1 100644 --- a/src/App.h +++ b/src/App.h @@ -24,7 +24,6 @@ class Styler; enum { - SUPPRESS_INITIAL_WINDOW = 'Siwn', WINDOW_NEW_WITH_QUIT_REPLY = 'NWwn', ACTIVATE_WINDOW = 'actw' }; @@ -38,12 +37,11 @@ class App : public BApplication { App(); ~App(); - void Init(); + void Init(bool suppressWindow); void AboutRequested(); bool QuitRequested(); void ReadyToRun(); - void ArgvReceived(int32 argc, char** argv); void RefsReceived(BMessage* message); void MessageReceived(BMessage* message); diff --git a/src/main.cpp b/src/main.cpp index c9feffe..81b1f9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,75 +5,137 @@ #include "App.h" -#include - #include +#include +#include + +#include "EditorWindow.h" #include "Utils.h" +void +_PrintUsage() +{ + std::cerr + << "Usage: Koder [options] file..." << std::endl + << "Options:" << std::endl + << " -h, --help\t\tPrints this message." << std::endl + << " -w, --wait\t\tWait for the window to quit before returning." << std::endl + << "\t\t\tOpening in window stacks is not supported in this mode." << std::endl + << "\t\t\tCurrently accepts only one filename." << std::endl; +} + + +void +_RunApp(bool suppressWindow) +{ + App* app = new App(); + app->Init(suppressWindow); + app->Run(); + delete app; +} + + int main(int argc, char** argv) { - std::string arg1 = argc > 1 ? argv[1] : ""; - if(argc > 1 && (arg1 == "-h" || arg1 == "--help")) { - fprintf(stderr, "Usage: Koder [options] file...\n"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -h, --help\t\tPrints this message.\n"); - fprintf(stderr, " -w, --wait\t\tWait for the window to quit before " - "returning.\n" - "\t\t\tOpening in window stacks is not supported in this mode.\n" - "\t\t\tCurrently accepts only one filename.\n"); + // start the app immediately if we're being launched from the GUI in case we need to handle + // an initial BMessage, otherwise the message will be lost when we Launch() in the background + if(isatty(STDOUT_FILENO) == 0) { + _RunApp(false); + return 0; + } + + int option_index = 0; + struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"wait", no_argument, 0, 'w'}, + {"launchkoderapp", no_argument, 0, 0}, + {0, 0, 0, 0}}; + + bool waitForExit = false; + int c; + while((c = getopt_long(argc, argv, "hw", long_options, &option_index)) != -1) { + switch(c) { + case 'w': { + waitForExit = true; + } break; + case 'h': { + _PrintUsage(); + return 1; + } break; + case 0: { + if(strcmp(long_options[option_index].name, "launchkoderapp") == 0) { + _RunApp(true); + return 0; + } + return 1; + } break; + default: + _PrintUsage(); + return 1; + } + } + + if(waitForExit == true && argc - optind > 1) { + std::cerr << "Error: Only one filename allowed when using --wait." << std::endl; return 1; } - if(argc > 1 && (arg1 == "-w" || arg1 == "--wait")) { - if(argc > 3) { - fprintf(stderr, "Koder accepts only one filename when launching " - "in --wait mode.\n"); + BMessage windowMessage; + if(waitForExit == true) { + windowMessage.what = WINDOW_NEW_WITH_QUIT_REPLY; + } else if(waitForExit == false && optind == argc) { + // no file arguments, open a blank window + windowMessage.what = WINDOW_NEW; + } else { + windowMessage.what = B_REFS_RECEIVED; + } + + while(optind < argc) { + int32 line, column; + BPath filePath(ParseFileArgument(argv[optind++], &line, &column).c_str(), nullptr, true); + if(filePath.InitCheck() != B_OK) { + std::cerr << "Error: Invalid file path specified." << std::endl; return 1; } - BRoster roster; - team_id team = roster.TeamFor(gAppMime); - if(team == B_ERROR) { - BMessage* suppressMessage = new BMessage(SUPPRESS_INITIAL_WINDOW); - status_t status = roster.Launch(gAppMime, suppressMessage, &team); - delete suppressMessage; - if(status != B_OK && status != B_ALREADY_RUNNING) { - fprintf(stderr, "An issue occured while trying to launch Koder.\n"); - return 1; - } + + entry_ref ref; + BEntry entry(filePath.Path(), true); + if(entry.InitCheck() != B_OK || (entry.Exists() == true && entry.IsFile() == false)) { + std::cerr << "Error: Specified path is not a regular file." << std::endl; + return 1; } - BMessage windowMessage(WINDOW_NEW_WITH_QUIT_REPLY); - // parse filename if any - // TODO: support -- for piping - if(argc > 2) { - int32 line, column; - std::string filename = ParseFileArgument(argv[2], &line, &column); - if(filename.find('/') != 0) { - BPath absolute(".", filename.c_str(), true); - filename = absolute.Path(); - } - entry_ref ref; - BEntry(filename.c_str()).GetRef(&ref); - windowMessage.AddRef("refs", &ref); - if(line != -1) { - windowMessage.AddInt32("be:line", line); - } - if(column != -1) { - windowMessage.AddInt32("be:column", column); - } + if(entry.GetRef(&ref) != B_OK) { + std::cerr << "Error: Unable to get entry_ref for path." << std::endl; + return 1; } - BMessenger messenger(gAppMime, team); - BMessage reply; - messenger.SendMessage(&windowMessage, &reply); - return 0; - } else { - App* app = new App(); - app->Init(); - app->Run(); - delete app; + // always add column and line so that the count is the same as the number of refs + windowMessage.AddRef("refs", &ref); + windowMessage.AddInt32("be:column", column); + windowMessage.AddInt32("be:line", line); + } - return 0; + entry_ref appRef; + if(get_ref_for_path(argv[0], &appRef) != B_OK) { + std::cerr << "Error: Unable to determine Koder application path." << std::endl; + return 1; } + + BRoster roster; + team_id team; + const char* args[] = { "--launchkoderapp", nullptr }; + // Use the entry_ref version of Launch() to make sure B_SINGLE_LAUNCH works correctly + status_t status = roster.Launch(&appRef, 1, args, &team); + if(status != B_OK && status != B_ALREADY_RUNNING) { + std::cerr << "Error: Unable to launch Koder." << std::endl; + return 1; + } + + BMessenger messenger(gAppMime, team); + BMessage reply; + messenger.SendMessage(&windowMessage, &reply); + + return 0; }