Make these two calls at the beginning of your program and UTF-8 will look great. Unfortunately, it leaves the code page and font changed on your console, which might effect other programs that are expecting default behavior. The nice thing to do is change it back. However, as soon as you do that any text still displaying in the console will revert to the old font as well, and you'll lose all your beautiful UTF-8 text. A little bit of a catch-22 there.
> I used a very similar approach for a port of plan9port to
> Windows. Inside open(), or elsewhere when setting
> up a file descriptor based on a Handler, GetConsoleMode() would
> be called on the handler to check whether it should be
> treated special, i.e. a translation using ReadConsoleW
> and WriteConsoleW should take place.
>
> Perhaps the Go runtime on Windows could do
> something like this when setting
> up os.Stdin, -out, and -err during init.
As far as I can tell file descriptors in Go for Windows are plain simple file handles. Therefore this could be only implemented in syscall.Write() and syscall.Read() in my opinion. I have an example for syscall.Write() but supposedly syscall.Read() would be just as easy to write. Only I could not actually test it, because I have not yet figured out how to compile Go on Windows. Perhaps I should simply cross compile it within a Linux Virtual Machine.
> If a file `test.txt' contains the UTF-8 characters
> 'β ≥ ‰ б', and a program `cat.exe' exists
> which works the way described, a command `cat.exe <
> test.txt' would make these characters visible in the
> console window (as I just checked), even if its codepage
> is configured as `850'. Similarly, `cat.exe > test2.txt' would read
> console (cp850) input and correctly write UTF-8 characters
> to "test2.txt".
I suspect cat.exe simply uses the ReadConsoleW/WriteConsoleW so it so it does not have to care about encodings at all. But thanks for the info, I will give it a try, too.
--Attila
The only minor objection is, that syscall.Write(syscall.Stdout, "hello 世界!") would not work with it, but I do not think this is a big problem.
For the record, I came up with a third possible solution: on Windows syscall.Stdin/out/err could point to pipes, that could be handled in goroutines implementing the ReadConsoleW/WriteConsoleW API. This way even syscall.Read/Write would work, but I guess this would complicate things too much.
So in the end it is perhaps you, who should follow the Contribution Guidelines as Alex suggested :)
Best regards
I happened to implement the Write part using an anonymous
pipe before trying the os-based approach of my previous
posting. I liked the fact that it could be hidden within
pkg syscall -- the write handle of the pipe would simply
replace the original console handle.
A problem I observed with this approach is that some of
the output might still be in the pipe when a program exits.
If it is only printing a few lines (e.g. on os.Stderr),
and then exits, one would see no output. Some way of
synchronization code would be needed, making this
approach more complex.
> So in the end it is perhaps you, who should follow the Contribution
> Guidelines as Alex suggested :)
Nice. For the nonce I updated the tar file
specified in my previous posting. The console read
and write functions have been wrapped within
goroutines now to avoid problems in case of concurrent
access. I'll need to do some more tests for edge cases,
then, probably at the end of January, try the next
steps.
Regards,
Michael
> Am 08.12.2010 14:04, schrieb Tajti Attila:
>> For the record, I came up with a third possible solution: on Windows
>> syscall.Stdin/out/err could point to pipes, that could be handled in
>> goroutines implementing the ReadConsoleW/WriteConsoleW API. This way
>> even syscall.Read/Write would work, but I guess this would complicate
>> things too much.
>
> I happened to implement the Write part using an anonymous
> pipe before trying the os-based approach of my previous
> posting. I liked the fact that it could be hidden within
> pkg syscall -- the write handle of the pipe would simply
> replace the original console handle.
>
> A problem I observed with this approach is that some of
> the output might still be in the pipe when a program exits.
> If it is only printing a few lines (e.g. on os.Stderr),
> and then exits, one would see no output. Some way of
> synchronization code would be needed, making this
> approach more complex.
In the end I like the implementation being in the higher level os package. This way os.File always work in UTF8 mode when accessing the console, but one can still use syscall if a specific codepag is necessary.
>> So in the end it is perhaps you, who should follow the Contribution
>> Guidelines as Alex suggested :)
>
> Nice. For the nonce I updated the tar file
> specified in my previous posting. The console read
> and write functions have been wrapped within
> goroutines now to avoid problems in case of concurrent
> access. I'll need to do some more tests for edge cases,
> then, probably at the end of January, try the next
> steps.
I have no idea whether goroutines or closures are better in this case, I like them both.
There are only two things I noticed: the goto statement in consoleWrite() could be replaced with a break [1] if the outer for loop had a label.
The second thing is the introduction of the newFile function, is this really necessary? Is it unreasonable to replace both of the read and write functions if GetConsoleMode() returns TRUE? When relying on newFile() something like os.Open("$CONOUT", O_WRONLY) would not work.
[1] http://golang.org/doc/go_spec.html#Break_statements
Best regards
Attila