Skip to content
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

error parsing options: Option ‘t’ does not exist #34

Closed
mulderp opened this issue Dec 15, 2016 · 12 comments

Comments

@mulderp
Copy link

mulderp commented Dec 15, 2016

I get a strange strings when running this code without a valid option:

 options.add_options("")
	("a,aaaa", "aaaa type", cxxopts::value<std::string>()->default_value("bbbb"), "bbbb or cccc")
			("h,help", "Print help");
	options.parse(argc, argv);
	if (options.count("help"))
	{
		std::cout << options.help({ "", "Group" }) << std::endl;
		exit(0);
	}


Build is on Windows with MSVC community 15

@petewall
Copy link

Same here. When options.parse encounters an option that it doesn't recognize, it's throwing an option_not_exists_exception. The output of that exception (using what()) has the same text no matter which unknown argument I provide.

I'm on Visual Studio Basic 2015 on Windows 10 x64

@jarro2783
Copy link
Owner

Well that's different. Technically the output is not lying, but it's probably also not what you want 😛
I'll take a look.

@jarro2783
Copy link
Owner

Well this is going to make life difficult. I can't reproduce this on Linux, and I don't have access to a Windows machine.

Do you have a tool like Valgrind that you can run it with? That or if you're able to run it in a debugger and provide me with some more output then that will help me track this down.

@petewall
Copy link

I can do some debugging later (maybe tomorrow).

@petewall
Copy link

Ok, so actually, the option name isn't being trashed, but instead, it's the and the beginning of the string. Notice after the "£" is the character "x", which is the option I used to test with:
Option ‘x’ does not exist

@mulderp 's message (Option ‘t’ ) shows a "t", so he must have been testing with the character "t".

Looking at how that string is constructed, we see this:

class option_not_exists_exception : public OptionParseException
  {
    public:
    option_not_exists_exception(const std::string& option)
    : OptionParseException(u8"Option ‘" + option + u8"’ does not exist")
    {
    }
  };

if I step in, the debugger goes the operator+ function for the string. The left operand is "Option ‘" and the right operand is "x".

This makes me think that Windows, VS2015, or both, do not like the single quote's that are a part of the exception string. After replacing the with ', it works:

Option 'x' does not exist

I'll make the changes and submit a pull request.

@mulderp
Copy link
Author

mulderp commented Dec 20, 2016

nice - indeed removing the quotes solves it on windows :)

@jarro2783
Copy link
Owner

Windows is clearly deficient at displaying UTF-8 encoded code points. Is this running in the command prompt or in your IDE? Can you set the encoding somewhere and see if it makes any difference?

If it's as difficult as stack overflow suggests, then expecting Windows to behave sensibly is next to impossible.

I don't really want to throw out the nice quotes just because Windows doesn't know how to display them. A better fix would be to use normal quotes just for Windows.

@crusader-mike
Copy link

crusader-mike commented May 13, 2017

Hi. Someone mentioned this little lib on reddit.com/r/cpp and I decided to have a look. Of course, I am following gospel of http://utf8everywhere.org and of course I immediately ran into this issue on Windows. Anyways, after spending an hour digging in this solution was found. Here is it for your convenience and enlightenment:

  • ensure that compiler uses correct encoding when parsing your source code -- this can be done via multiple ways (/source-charset cmdline option, related pragma, BOM mark or simply /utf-8 (MSVC2015+))
  • ensure that compiler properly encodes your strings in your binary -- /execution-charset, related pragma or simply /utf-8 (MSVC2015+)
  • now you know for a fact that your string literal in memory has correct encoding and your char const* strings are exactly what they should be. If you pipe output of your console app into a file and open it in Notepad (on Vista+) you should see what you expect to see. But console output is still garbage.
  • at the beginning of main() call this with correct codepage:
    SetConsoleOutputCP(CP_UTF8); // needs include<windows.h>
  • this should make things little better, but not completely -- by default console uses raster font, which supports very few characters. Got to default console settings and change font to any TrueType font. Everything should look great now.

So, for greatest simplicity -- just use utf-8 everywhere:

  • always keep your source in utf-8 (ideally with BOM on windows)
  • add /utf-8 to compiler cmdline, it'll warn you about any non-valid utf-8 sequence in your source code (fix these warnings)
  • add SetConsoleOutputCP(CP_UTF8)
  • change console font to one that supports your charset/plane (keep in mind that not all TrueType fonts are equal -- yours might not be good enough for some asian languages)

Read up on all this here:
https://blogs.msdn.microsoft.com/vcblog/2016/02/22/new-options-for-managing-character-sets-in-the-microsoft-cc-compiler/

P.S. Keep in mind that your editor still could be retarded. For example, MSVC2015 can't copy paste that fancy "quote" character used by this library -- it mangles it (verified with binary editor). Maybe because it was working with my file expecting Latin-1 encoding. I should try adding BOM to it and try again.

P.P.S. I went back and checked that copy-paste problem -- when Visual Studio detects correct encoding (as identified by selection in File/Advanced Save Options...) copy-paste works fine. But if file (you are pasting to) was open using some other encoding -- it'll likely mangle it (will try to convert symbols from source file encoding to target file encoding).

@jarro2783
Copy link
Owner

Thanks for the details. I'll close this issue shortly given that 1. Windows uses retarded defaults, and 2. there are ways to make it work properly.

That said, is there anything I can do in this code to help? Would putting a BOM in help here? I use UTF-8 everywhere, but in Linux it just works.

@crusader-mike
Copy link

On Linux it works because by default everything is considered to be utf-8 encoded. Windows carries a lot of baggage from the past -- I bet they'll need at least two more major releases to get rid of it.

No, adding BOM to your file won't help. MSVC (and it's compiler) already recognizes utf-8 encoding when it stumbles upon your magical quote symbols. Your users need to be aware of how to deal with this (i.e. they need to go through steps I mentioned).

@jarro2783
Copy link
Owner

Ok thanks for the info.

@crusader-mike
Copy link

crusader-mike commented Jun 5, 2018

Turned out you also need this (starting from Windows 10):

setvbuf(stderr, NULL, _IOFBF, 1024);    // on Windows 10+ we need buffering or console will get data 1 byte at a time (screwing up utf-8 encoding)
setvbuf(stdout, NULL, _IOFBF, 1024);    // alas, line-buffering doesn't work on windows

Unfortunately this also means that there is still a chance of screwing up your output if you fill buffer completely before next flush. Proper solution -- flush it manually (endl or fflush()) after every string sent to output (assuming each string is less than 1024). If only MS supported line-buffering...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants