-
Notifications
You must be signed in to change notification settings - Fork 15
Switch to getopt for command line parsing #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
There is an intermittent bug when calling |
1234773 to
e596938
Compare
|
The intermittent bug seems unrelated to my changes since I can reproduce it on my other computer without these changes. I like this version better because Koder always forks to the background unless --wait is used. Without this change, the first instance of Koder will always block even without --wait. Reading data from stdin and sending it to the app might be complex and require a shared memory buffer or something, but that was already the case before this change. |
src/main.cpp
Outdated
| default: | ||
| _PrintUsage(); | ||
| return 1; | ||
| break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary break
|
I may end up closing this pull request and thinking about the problem more. I keep running into issues with whichever method I use. The most recent version is broken when being launched by Tracker and other apps. It's possible Koder may need a small companion app to handle some command line options, similar to |
What is the problem with this behavior? It's predictable - you want it to wait you use -w. EDIT: Unless I misunderstood and it currently blocks the first time - that's not how I remember coding it though.
I don't like the companion app solution because it's not very discoverable. Can you document the issues you ran into here so it can be taken into account when changing this part of code. |
Yes, it currently blocks the first time when
The short version is that it's difficult to fork the first instance of a BApplication into the background when launched by command line, while still allowing it to have access to any initial B_REFS_RECEIVED message when launched by GUI. I had a small conversation with waddlesplash in IRC to see if I could find a way around the problem. |
|
I still need to do some testing and cleanup but the latest version works well. I would have preferred to do things a bit differently but I think it's acceptable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About companion app: I'd agree to support it if this was a generic app. I'm pretty sure other apps might want to capture stdin or stdout and support blocking when launched from command line, so extracting it out of Pe and providing some kind of common protocol might make sense. Users could then add aliases like lpe (or those could be provided by the app) to their shell for each app.
| App::ReadyToRun() | ||
| { | ||
| if(CountWindows() == 0 && fSuppressInitialWindow == false) { | ||
| if(fSuppressInitialWindow == false && CountWindows() == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reversing the order is meaningful here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first this was done accidentally because I removed it in one change and then put it back in a later change. Technically this would be more efficient because the first test is a simple boolean variable comparison and so it wouldn't need to proceed with a function call and whatever else CountWindows() does.
|
|
||
|
|
||
| void | ||
| App::ArgvReceived(int32 argc, char** argv) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason behind removing this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think handling command line arguments in two places complicates the startup process and possibly introduces code duplication, so it would be nice to do it in one place or the other. If the arguments are processed inside main() then we can do validity checks on the arguments before we even create the BApplication object. This makes it easier to return proper exit codes when run from the command line. It can also prevent the situation where you create the BApplication, have errors during ArgvReceived, and have to destroy/Quit() the BApplication right away if there are no other windows.
| void | ||
| _PrintUsage() | ||
| { | ||
| std::cerr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this is output from --help it should be printed to stdout (std::cout). If it's a result of unknown option or other error case it should go to std::cerr.
| _PrintUsage() | ||
| { | ||
| std::cerr | ||
| << "Usage: Koder [options] file..." << std::endl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using std::endl is doubly wrong here. std::endl besides adding a newline also flushes the stream but:
std::cerris unbuffered and will flush after any output that is sent to it.- Flushing after every newline usually only degrades performance, with no benefit.
Flushing is useful if you are outputting text before very long operation (the OS might not show the output without flush until after the operations ends).
Change endls to "\n".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I can't remember if I usually use endl of '\n' in my own apps, it's probably a 50/50 split.
Of course, if you'd like I can switch back to the c-style fprintf too, don't hesitate to ask for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's good to change to C++.
| return 0; | ||
| } | ||
|
|
||
| int option_index = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| int option_index = 0; | |
| int optionIndex = 0; |
| return 0; | ||
| } | ||
| return 1; | ||
| } break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant break
| case 'h': { | ||
| _PrintUsage(); | ||
| return 1; | ||
| } break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant break
| 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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); | |
| auto args = std::to_array<const char*>{ "--launchkoderapp", nullptr }; | |
| // Use the entry_ref version of Launch() to make sure B_SINGLE_LAUNCH works correctly | |
| status_t status = roster.Launch(&appRef, args.size(), args.data(), &team); |
| return 1; | ||
| } break; | ||
| case 0: { | ||
| if(strcmp(long_options[option_index].name, "launchkoderapp") == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the use case for this option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was trying to avoid the "secret switch" thing. To be consistent, Koder should always fork to the background unless --wait is used. So, we can use BRoster::Launch to do that, but we need to tell the newly launched copy of the application that it should start the BApplication process and prepare to receive one of the three message types below.
In some ways this is similar to the isatty() == 0 situation except that when running from the command line, the newly launched copy may have a stdout file descriptor.
Fixes #144