
When coding in a POSIX-compliant environment, you can usually write special escape codes to the console to change the text colour and so forth. However, this does not work on Windows. (Ignore all references you see to enabling ANSI.SYS in your config.sys file; this applies only to 16-bit MS-DOS programs, *not* to 32-bit Windows programs.) However - to my surprise - apparently the Win32 API provides a set of function calls that do in fact allow 32-bit applications to change the colours of the console on a character-by-character basis. However - wait for it - those *particular* functions aren't in Haskell's System.Win32.Console module. :-( Obviously, I know nothing about C. However, after much hunting around, it turns out that for some reason, GHC appears to ship with a complete set of C header files for the Win32 API. (In other words, the necessary header file for accessing the functions I want is there.) After staggering through the (very unhelpful) FFI language specification, I was able to make it so that I can apparently call these functions from Haskell. I was not, however, able to find any way at all to import the symbolic constants necessary, so I was forced to reading through the source code of the raw C header files to find out what the numeric values of these are (!!!) The long and short of it is, I now have a small Haskell library that enables me to print things in trippy colours on the screen from a normal Haskell CLI program. Yay for me! (Actually, you can also change the title on the window - so you can make your program say "My Fantastic Tool" instead of "C:\Documents and Settings\foo\Haskell\MyTool\MyTool.exe" in the titlebar. Again, this is for a normal Haskell console application with nothing done to it.) Would anybody else be interested in having this code? (Obviously, it's pretty tiny.) For that matter, would the maintainer of System.Win32.Console be interested in adding the necessary dozen lines of code to that module? Actually, now that I think about it, it would be kind of nice to have a magic package that writes out escape codes or calls the Win32 API depending on which platform your program is compiled on - in the style of System.FilePath. I don't know how to do that though... A nice idea, guys?

On Tue, 2008-09-09 at 20:15 +0100, Andrew Coppin wrote:
When coding in a POSIX-compliant environment, you can usually write special escape codes to the console to change the text colour and so forth. However, this does not work on Windows.
(Ignore all references you see to enabling ANSI.SYS in your config.sys file; this applies only to 16-bit MS-DOS programs, *not* to 32-bit Windows programs.)
However - to my surprise - apparently the Win32 API provides a set of function calls that do in fact allow 32-bit applications to change the colours of the console on a character-by-character basis. However - wait for it - those *particular* functions aren't in Haskell's System.Win32.Console module. :-(
Obviously, I know nothing about C. However, after much hunting around, it turns out that for some reason, GHC appears to ship with a complete set of C header files for the Win32 API. (In other words, the necessary header file for accessing the functions I want is there.) After staggering through the (very unhelpful) FFI language specification, I was able to make it so that I can apparently call these functions from Haskell. I was not, however, able to find any way at all to import the symbolic constants necessary, so I was forced to reading through the source code of the raw C header files to find out what the numeric values of these are (!!!)
c2hs can do this; check out #const CONSTANT_NAME jcc

2008/9/9 Andrew Coppin
Actually, now that I think about it, it would be kind of nice to have a magic package that writes out escape codes or calls the Win32 API depending on which platform your program is compiled on - in the style of System.FilePath. I don't know how to do that though... A nice idea, guys?
I wrote this package a few weeks ago: check out http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ansi-terminal and it's companion http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ansi-wl-pprint Cheers, Max

Max Bolingbroke wrote:
2008/9/9 Andrew Coppin
: Actually, now that I think about it, it would be kind of nice to have a magic package that writes out escape codes or calls the Win32 API depending on which platform your program is compiled on - in the style of System.FilePath. I don't know how to do that though... A nice idea, guys?
I wrote this package a few weeks ago: check out http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ansi-terminal and it's companion http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ansi-wl-pprint
Ah, so somebody has already beaten me to it, eh? Looks like the only thing it doesn't do is let you change the title on the console window. (Because, obviously, that's only possible on Windows.) And what do you know, it installed out of the box without issue on my Windows system. Now that's pretty rare... Any ideas about the build log error that's preventing Hackage from autogenerating the documentation?

On 2008-09-12 20:29 +0100 (Fri), Andrew Coppin wrote:
Looks like the only thing it doesn't do is let you change the title on the console window. (Because, obviously, that's only possible on Windows.)
Right. Unless you send an ^[^H]0;foo^G sequence (^[ being ESC) to your
xterm. You'll find that the title changes to "foo".
cjs
--
Curt Sampson

On 2008 Sep 12, at 22:29, Curt Sampson wrote:
On 2008-09-12 20:29 +0100 (Fri), Andrew Coppin wrote:
Looks like the only thing it doesn't do is let you change the title on the console window. (Because, obviously, that's only possible on Windows.)
Right. Unless you send an ^[^H]0;foo^G sequence (^[ being ESC) to your xterm. You'll find that the title changes to "foo".
0 = both title and icon 1 = icon name 2 = titlebar text Most X11 terminal emulators use the same protocol. (ISTR that dtterm doesn't, but I don't think most people care any more.) One other gotcha is that Terminal.app on Leopard (dunno about Tiger) treats 0, 1, 2 the same way so if you set the icon name after the title you end up with the icon name in the titlebar. (OSX uses the titlebar text as the icon name when minimized.) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

2008/9/13 Brandon S. Allbery KF8NH
Right. Unless you send an ^[^H]0;foo^G sequence (^[ being ESC) to your xterm. You'll find that the title changes to "foo".
0 = both title and icon 1 = icon name 2 = titlebar text
Most X11 terminal emulators use the same protocol. (ISTR that dtterm doesn't, but I don't think most people care any more.) One other gotcha is that Terminal.app on Leopard (dunno about Tiger) treats 0, 1, 2 the same way so if you set the icon name after the title you end up with the icon name in the titlebar. (OSX uses the titlebar text as the icon name when minimized.)
Interesting information. I'll look into adding this to my package then: cheers! Max

Max Bolingbroke wrote:
2008/9/13 Max Bolingbroke
: Interesting information. I'll look into adding this to my package then: cheers!
Just FYI, I have now implemented and tested this feature. The new version, 0.5.0, is available on Hackage.
For both platforms? Out of interest, how do you get the correct package built on each platform?

2008/9/13 Andrew Coppin
Just FYI, I have now implemented and tested this feature. The new version, 0.5.0, is available on Hackage.
For both platforms?
Of course! My package promises to work cross-platform, after all.
Out of interest, how do you get the correct package built on each platform?
If you mean "how do I compile the ANSI emulator on Windows but the actual ANSI stuff on Unix", most of the magic is in the .cabal file: http://github.com/batterseapower/ansi-terminal/tree/master/ansi-terminal.cab.... I simply turn on the C-preprocessor (CPP) and then supply -DWINDOWS on Windows and -DUNIX on anything else. The actual use of CPP in my source is then confined to a single module (http://github.com/batterseapower/ansi-terminal/tree/master/System/Console/AN...) which either imports System.Console.ANSI.Windows or System.Console.ANSI.Unix depending on which of those two have been defined. Nothing to it, really. However, this is the stuff that is making the Hackage documentation generation choke currently because until recently Cabal forgot to supply the CPP flags to a Haddock 2 (but not Haddock 0.x) run. All the best, Max

Max Bolingbroke wrote:
2008/9/13 Andrew Coppin
: Just FYI, I have now implemented and tested this feature. The new version, 0.5.0, is available on Hackage.
For both platforms?
Of course! My package promises to work cross-platform, after all.
[rejoyce!]
Out of interest, how do you get the correct package built on each platform?
If you mean "how do I compile the ANSI emulator on Windows but the actual ANSI stuff on Unix", most of the magic is in the .cabal file:
I simply turn on the C-preprocessor (CPP) and then supply -DWINDOWS on Windows and -DUNIX on anything else. The actual use of CPP in my source is then confined to a single module which either imports System.Console.ANSI.Windows or System.Console.ANSI.Unix depending on which of those two have been defined.
Nothing to it, really. However, this is the stuff that is making the Hackage documentation generation choke currently because until recently Cabal forgot to supply the CPP flags to a Haddock 2 (but not Haddock 0.x) run.
Hmm, I wasn't aware you could use the C preprocessor on Haskell source code. That could be rather useful, e.g., for adding or removing debug code. Anyway, that still leaves one question: how do you figure out which platform you're on so you can set the right options?

On Sat, 2008-09-13 at 13:41 +0100, Andrew Coppin wrote:
If you mean "how do I compile the ANSI emulator on Windows but the actual ANSI stuff on Unix", most of the magic is in the .cabal file:
I simply turn on the C-preprocessor (CPP) and then supply -DWINDOWS on Windows and -DUNIX on anything else.
Anyway, that still leaves one question: how do you figure out which platform you're on so you can set the right options?
As Max suggested, look in the .cabal file. You'll find this snippet: if os(windows) Build-Depends: Win32 >= 2.0 Cpp-Options: -DWINDOWS [... other stuff ...] else -- We assume any non-Windows platform is Unix Build-Depends: unix >= 2.3.0.0 Cpp-Options: -DUNIX [... other stuff ...] Extensions: CPP Duncan

2008/9/12 Andrew Coppin
Any ideas about the build log error that's preventing Hackage from autogenerating the documentation?
That is a Cabal problem: Duncan Coutts tells me that it is fixed in HEAD, so documentation will be available on Hackage when they update the version of Cabal they are using. Cheers, Max

Hello Andrew, Tuesday, September 9, 2008, 11:15:08 PM, you wrote:
Haskell. I was not, however, able to find any way at all to import the symbolic constants necessary, so I was forced to reading through the source code of the raw C header files to find out what the numeric values of these are (!!!)
look into Win32 package sources, small example is: #{enum LoadLibraryFlags, , lOAD_LIBRARY_AS_DATAFILE = LOAD_LIBRARY_AS_DATAFILE , lOAD_WITH_ALTERED_SEARCH_PATH = LOAD_WITH_ALTERED_SEARCH_PATH } (in File.hsc) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Andrew Coppin wrote:
(Ignore all references you see to enabling ANSI.SYS in your config.sys file; this applies only to 16-bit MS-DOS programs, *not* to 32-bit Windows programs.)
You can add interpretation of ansi escape sequences to any win32 program by launching the application through ansicon: http://www.geocities.com/jadoxa/ansicon/index.html Works on 32 bit windows. Works on 64 bit windows when running a 32 bit application. Does not work for 64 bit application (since 64 bit windows does not allow hooking of win64 api calls IIRC). For support of 32 bit programs on win64 you may need to apply a patch I sent to Jason. He probably did not apply it (he did not respond to my email). Check with me if you want it. Peter.
participants (8)
-
Andrew Coppin
-
Brandon S. Allbery KF8NH
-
Bulat Ziganshin
-
Curt Sampson
-
Duncan Coutts
-
Jonathan Cast
-
Max Bolingbroke
-
Peter Hercek