Re: cross-platform coloured text in terminal

2010-04-19 Thread Jonathan Hartley
On Apr 17, 11:52 am, Jonathan Hartley  wrote:
> On Apr 16, 5:59 pm, Lie Ryan  wrote:
>
>
>
> > On 04/16/10 19:28, Jonathan Hartley wrote:
>
> > > I'm playing with ideas of what API to expose. My favourite one is to
> > > simply embed ANSI codes in the stream to be printed. Then this will
> > > work as-is on Mac and *nix. To make it work on Windows, printing could
> > > be done to a file0-like object which wraps stdout:
>
> > The problem with that is you're simply reinventing ANSI.SYS device driver.
>
> > An alternative API is you could override .__add__(), like so (completely
> > untested):
>
> > classColor(object):
> >    def __init__(self,color):
> >        self.color=  map_the_color(color)
> >        self.string = ""
> >    def __add__(self, string):
> >        self.string += string
> >        return self
> >    def __str__(self):
> >        if terminal_can_do_ansi_color:
> >            return ansicolorescape(self.string, self.color)
> >        elif windows:
> >            syscalltocolor(self.color)
> >            print self.string
> >            syscalltocolor(reset thecolor)
> >            return ""
>
> > GREEN =Color('green')
> > print GREEN + "Great" + "Good"
>
> > you can even go a bit further and allow chained calls (again, completely
> > untested, but you get the idea):
>
> > classColor(object):
> >    def __init__(self,color):
> >        self.color=  map_the_color(color)
> >        self.stack = []
> >    def __add__(self, string):
> >        if isinstance(string,Color):
> >            # not a string, chain the calls
> >            self.stack.append((string.color, []]))
> >        else:
> >            # a string,
> >            self.stack[-1][1].append(string)
> >        return self
> >    def __radd__(self, string):
> >        self.stack.append([self.default, string])
> >        return self
>
> >    def __str__(self):
> >        if ansi_capable:
> >            return colorescape(format, string)
> >        elif windows:
> >            for format, string in self.stack:
> >                syscalltocolor(color)
> >                print string
> >                return ""
>
> > GREEN =Color('green')
> > RED =Color('red')
>
> > print "Fairly" + GREEN + "Great" + RED + "Poor"
>
> > or something like that, and you will have an API that works
> > transparently on all platforms. The downside is that you cannot call
> > str(GREEN + "foo") on windows.
>
> Hey Lie,
>
> Thanks heaps for the reply!
>
> >> The problem with that is you're simply reinventing ANSI.SYS device driver.
>
> I don't see that as a problem - in fact I think it's exactly my
> goal! :-)
>
> The difference is that the ANSI driver requires installation and a
> reboot on the end-user's computer, which is a fiddly and intrusive
> thing for a Python developer to achieve. Whereas doing the same job in
> a Python module is easy to use for the Python developer - they just
> import the module, maybe call an 'init()' function, and then the ANSI
> functionality works on all platforms.
>
> Your ideas about generating and chaining the ANSI code strings are
> great. I worry though, about intermingling the code that generates
> ANSI escape sequences with the code which makes them work on Windows.
> The problem is that then, only applications which use your ANSI-
> generation library will work on Windows. Whereas if these two things
> are kept separate, then applications which use any other ANSI-
> generation techniques, such as using 'termcolor', or manaully printing
> raw ANSI sequences, these can also all work on Windows too, simply by
> adding an import and an 'init()' call to the start of the application.
>
> Am I making sense? Many thanks for your thoughts.
>
>   Jonathan


I have implemented these ideas here. It seems to work.
http://pypi.python.org/pypi/colorama
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cross-platform coloured text in terminal

2010-04-17 Thread Someone Something
That sounds like a nice idea, try it out and see what you make of it. (It
may have been done before but probably not as a standalone module as it
doesn't require that much code)

On Sat, Apr 17, 2010 at 6:52 AM, Jonathan Hartley wrote:

> On Apr 16, 5:59 pm, Lie Ryan  wrote:
> > On 04/16/10 19:28, Jonathan Hartley wrote:
> >
> > > I'm playing with ideas of what API to expose. My favourite one is to
> > > simply embed ANSI codes in the stream to be printed. Then this will
> > > work as-is on Mac and *nix. To make it work on Windows, printing could
> > > be done to a file0-like object which wraps stdout:
> >
> > The problem with that is you're simply reinventing ANSI.SYS device
> driver.
> >
> > An alternative API is you could override .__add__(), like so (completely
> > untested):
> >
> > class Color(object):
> >def __init__(self, color):
> >self.color =  map_the_color(color)
> >self.string = ""
> >def __add__(self, string):
> >self.string += string
> >return self
> >def __str__(self):
> >if terminal_can_do_ansi_color:
> >return ansicolorescape(self.string, self.color)
> >elif windows:
> >syscalltocolor(self.color)
> >print self.string
> >syscalltocolor(reset the color)
> >return ""
> >
> > GREEN = Color('green')
> > print GREEN + "Great" + "Good"
> >
> > you can even go a bit further and allow chained calls (again, completely
> > untested, but you get the idea):
> >
> > class Color(object):
> >def __init__(self, color):
> >self.color =  map_the_color(color)
> >self.stack = []
> >def __add__(self, string):
> >if isinstance(string, Color):
> ># not a string, chain the calls
> >self.stack.append((string.color, []]))
> >else:
> ># a string,
> >self.stack[-1][1].append(string)
> >return self
> >def __radd__(self, string):
> >self.stack.append([self.default, string])
> >return self
> >
> >def __str__(self):
> >if ansi_capable:
> >return colorescape(format, string)
> >elif windows:
> >for format, string in self.stack:
> >syscalltocolor(color)
> >print string
> >return ""
> >
> > GREEN = Color('green')
> > RED = Color('red')
> >
> > print "Fairly" + GREEN + "Great" + RED + "Poor"
> >
> > or something like that, and you will have an API that works
> > transparently on all platforms. The downside is that you cannot call
> > str(GREEN + "foo") on windows.
>
>
>
> Hey Lie,
>
> Thanks heaps for the reply!
>
> >> The problem with that is you're simply reinventing ANSI.SYS device
> driver.
>
> I don't see that as a problem - in fact I think it's exactly my
> goal! :-)
>
> The difference is that the ANSI driver requires installation and a
> reboot on the end-user's computer, which is a fiddly and intrusive
> thing for a Python developer to achieve. Whereas doing the same job in
> a Python module is easy to use for the Python developer - they just
> import the module, maybe call an 'init()' function, and then the ANSI
> functionality works on all platforms.
>
> Your ideas about generating and chaining the ANSI code strings are
> great. I worry though, about intermingling the code that generates
> ANSI escape sequences with the code which makes them work on Windows.
> The problem is that then, only applications which use your ANSI-
> generation library will work on Windows. Whereas if these two things
> are kept separate, then applications which use any other ANSI-
> generation techniques, such as using 'termcolor', or manaully printing
> raw ANSI sequences, these can also all work on Windows too, simply by
> adding an import and an 'init()' call to the start of the application.
>
> Am I making sense? Many thanks for your thoughts.
>
>  Jonathan
> --
> http://mail.python.org/mailman/listinfo/python-list
>
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cross-platform coloured text in terminal

2010-04-17 Thread Jonathan Hartley
On Apr 16, 5:59 pm, Lie Ryan  wrote:
> On 04/16/10 19:28, Jonathan Hartley wrote:
>
> > I'm playing with ideas of what API to expose. My favourite one is to
> > simply embed ANSI codes in the stream to be printed. Then this will
> > work as-is on Mac and *nix. To make it work on Windows, printing could
> > be done to a file0-like object which wraps stdout:
>
> The problem with that is you're simply reinventing ANSI.SYS device driver.
>
> An alternative API is you could override .__add__(), like so (completely
> untested):
>
> class Color(object):
>    def __init__(self, color):
>        self.color =  map_the_color(color)
>        self.string = ""
>    def __add__(self, string):
>        self.string += string
>        return self
>    def __str__(self):
>        if terminal_can_do_ansi_color:
>            return ansicolorescape(self.string, self.color)
>        elif windows:
>            syscalltocolor(self.color)
>            print self.string
>            syscalltocolor(reset the color)
>            return ""
>
> GREEN = Color('green')
> print GREEN + "Great" + "Good"
>
> you can even go a bit further and allow chained calls (again, completely
> untested, but you get the idea):
>
> class Color(object):
>    def __init__(self, color):
>        self.color =  map_the_color(color)
>        self.stack = []
>    def __add__(self, string):
>        if isinstance(string, Color):
>            # not a string, chain the calls
>            self.stack.append((string.color, []]))
>        else:
>            # a string,
>            self.stack[-1][1].append(string)
>        return self
>    def __radd__(self, string):
>        self.stack.append([self.default, string])
>        return self
>
>    def __str__(self):
>        if ansi_capable:
>            return colorescape(format, string)
>        elif windows:
>            for format, string in self.stack:
>                syscalltocolor(color)
>                print string
>                return ""
>
> GREEN = Color('green')
> RED = Color('red')
>
> print "Fairly" + GREEN + "Great" + RED + "Poor"
>
> or something like that, and you will have an API that works
> transparently on all platforms. The downside is that you cannot call
> str(GREEN + "foo") on windows.



Hey Lie,

Thanks heaps for the reply!

>> The problem with that is you're simply reinventing ANSI.SYS device driver.

I don't see that as a problem - in fact I think it's exactly my
goal! :-)

The difference is that the ANSI driver requires installation and a
reboot on the end-user's computer, which is a fiddly and intrusive
thing for a Python developer to achieve. Whereas doing the same job in
a Python module is easy to use for the Python developer - they just
import the module, maybe call an 'init()' function, and then the ANSI
functionality works on all platforms.

Your ideas about generating and chaining the ANSI code strings are
great. I worry though, about intermingling the code that generates
ANSI escape sequences with the code which makes them work on Windows.
The problem is that then, only applications which use your ANSI-
generation library will work on Windows. Whereas if these two things
are kept separate, then applications which use any other ANSI-
generation techniques, such as using 'termcolor', or manaully printing
raw ANSI sequences, these can also all work on Windows too, simply by
adding an import and an 'init()' call to the start of the application.

Am I making sense? Many thanks for your thoughts.

  Jonathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cross-platform coloured text in terminal

2010-04-16 Thread Lie Ryan
On 04/16/10 19:28, Jonathan Hartley wrote:
> I'm playing with ideas of what API to expose. My favourite one is to
> simply embed ANSI codes in the stream to be printed. Then this will
> work as-is on Mac and *nix. To make it work on Windows, printing could
> be done to a file0-like object which wraps stdout:

The problem with that is you're simply reinventing ANSI.SYS device driver.

An alternative API is you could override .__add__(), like so (completely
untested):

class Color(object):
   def __init__(self, color):
   self.color =  map_the_color(color)
   self.string = ""
   def __add__(self, string):
   self.string += string
   return self
   def __str__(self):
   if terminal_can_do_ansi_color:
   return ansicolorescape(self.string, self.color)
   elif windows:
   syscalltocolor(self.color)
   print self.string
   syscalltocolor(reset the color)
   return ""

GREEN = Color('green')
print GREEN + "Great" + "Good"

you can even go a bit further and allow chained calls (again, completely
untested, but you get the idea):

class Color(object):
   def __init__(self, color):
   self.color =  map_the_color(color)
   self.stack = []
   def __add__(self, string):
   if isinstance(string, Color):
   # not a string, chain the calls
   self.stack.append((string.color, []]))
   else:
   # a string,
   self.stack[-1][1].append(string)
   return self
   def __radd__(self, string):
   self.stack.append([self.default, string])
   return self

   def __str__(self):
   if ansi_capable:
   return colorescape(format, string)
   elif windows:
   for format, string in self.stack:
   syscalltocolor(color)
   print string
   return ""

GREEN = Color('green')
RED = Color('red')

print "Fairly" + GREEN + "Great" + RED + "Poor"

or something like that, and you will have an API that works
transparently on all platforms. The downside is that you cannot call
str(GREEN + "foo") on windows.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cross-platform coloured text in terminal

2010-04-16 Thread Jonathan Hartley
On Apr 16, 10:28 am, Jonathan Hartley  wrote:
> Hi,
>
> It irks me that I know of no simple cross-platform way to print
> colored terminal text from Python.
>
> As I understand it, printing ANSI escape codes (as wrapped nicely by
> module termcolor and others) works on Macs and *nix, but only works on
> Windows if one has installed the ANSI.SYS device driver, which most
> users have not. However, on Windows, there is an alternative method,
> which is to make win32 calls via ctypes.
>
> I'd like to try and unite these different implementations under a
> single cross-platform API. Has this been done already? I understand
> that the detailed capabilities of the two implementations (eg. dim/
> bright colors) might not map neatly, but at least for simple colored
> text, it should be OK.
>
> I'm playing with ideas of what API to expose. My favourite one is to
> simply embed ANSI codes in the stream to be printed. Then this will
> work as-is on Mac and *nix. To make it work on Windows, printing could
> be done to a file0-like object which wraps stdout:
>
> class ColorStream(object):
>
>     def __init__(self, wrapped):
>         self.wrapped = wrapped
>
>     def write(self, text):
>         # magic goes here
>         self.wrapped.write(text)
>
>     def __getattr__(self, name):
>         return getattr(self.wrapped, name)
>
> term = ColorTerm(sys.stdout)
> print <
> The idea being that in place of 'magic goes here', there will be code
> that, on Windows, searches 'text' for ANSI escape codes, strips them
> from the text, and converts them into the appropriate win32 calls.
>
> For extra nasty magic, either the module or the user of the module
> could wrap sys.stdout globally:
>
> sys.stdout = ColoredStream(sys.stdout)
>
> Then print statements in the user's code would simply be:
>
> print ANSI.GREEN + "hello"
>
> and this would work on all platforms.
>
> No doubt there are many problems with these ideas. I would love to
> hear about them. Many thanks.


Sorry, I forgot to mention: The reason I like this idea is that, in
theory, all existing libraries like termcolor will then work,
unmodified, on all platforms.
-- 
http://mail.python.org/mailman/listinfo/python-list


cross-platform coloured text in terminal

2010-04-16 Thread Jonathan Hartley
Hi,

It irks me that I know of no simple cross-platform way to print
colored terminal text from Python.

As I understand it, printing ANSI escape codes (as wrapped nicely by
module termcolor and others) works on Macs and *nix, but only works on
Windows if one has installed the ANSI.SYS device driver, which most
users have not. However, on Windows, there is an alternative method,
which is to make win32 calls via ctypes.

I'd like to try and unite these different implementations under a
single cross-platform API. Has this been done already? I understand
that the detailed capabilities of the two implementations (eg. dim/
bright colors) might not map neatly, but at least for simple colored
text, it should be OK.

I'm playing with ideas of what API to expose. My favourite one is to
simply embed ANSI codes in the stream to be printed. Then this will
work as-is on Mac and *nix. To make it work on Windows, printing could
be done to a file0-like object which wraps stdout:


class ColorStream(object):

def __init__(self, wrapped):
self.wrapped = wrapped

def write(self, text):
# magic goes here
self.wrapped.write(text)

def __getattr__(self, name):
return getattr(self.wrapped, name)

term = ColorTerm(sys.stdout)
print