ncurses and white-on-black - python

I can't seem to get white-on-black to work in curses when in color mode. If I don't call start_color, I get white-on-black. As soon as I call start_color, things start outputting in grey-on-black.
If you run this script:
import sys
for i in xrange(30, 38):
print '\x1b[0;' + str(i) + 'm' + str(i) + ': Shiny colors \x1b[1m(bright)'
print '\x1b[0m...and this is normal.'
...you'll probably see a lot of pretty colors. The one I want, and can't get, is the last line: '...and this is normal.' Asking for color pair 0 or asking for COLOR_WHITE, COLOR_BLACK gets me the non-bright #37 from the script.
For reference, this is what I see in Gnome Terminal:
http://rpi.edu/~wellir/random/colors.png
I'm programming in Python (using the curses library), so my code is something like:
import curses
screen = curses.initscr()
curses.start_color()
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
screen.clear()
screen.attrset(0)
screen.addstr('Hello')
screen.attrset(curses.A_BOLD)
screen.addstr('Hello')
screen.attrset(curses.color_pair(1))
screen.addstr('Hello')
screen.refresh()
curses.napms(5000)
curses.endwin()
...which gets me 37, 37-bright, and 37.

curses.use_default_colors()

Your gnome terminal may have its own color scheme, which changes the colors of the default white to bright white, except when in curses mode. Check that gnome-terminal does not changes the colors, because this would make testing the colors difficult.

I was on gnome terminal too with the same problem.
I managed to solve it with:
right click on screen > profile > profile preferences > color > palette
I think this is what each of the 8 colors will map to.
for some reason, the built-in scheme Default that was selected mapped the first color to gray instead of black!
changing scheme to XTerm, or changing the first color to black solved my problem.
I am not using curses.use_default_colors.

Related

How do I detect the current background color of the terminal in which my python script was invoked?

I am using a xfce4 terminal and I want to be able to detect if the background color is set to either black or white (or presumably some other color)
My code looks like this:
def print_color(string, style, textColor, background):
string = "\033[{};{};{}m{}\033[m ".format(style,textColor,background,string)
print(string)
I would like to detect the current background color and use it instead of passing it in.
I've tried not setting it, like this:
def print_color(string, style, textColor):
string = "\033[{};{};m{}\033[m ".format(style,textColor,string)
print(string)
but that did not work as I expected.
XFCE4 terminal uses VTE, which lacks the ability to respond to queries of the colors. That would be the SGR flavor of DECRQSS, which is mostly unimplemented in VTE.
(The example shown wouldn't work anyway). This is unrelated to the GTK+ toolkit.

How to use python/pygame to turn off certain pixels on Windows 7

I have an old Windows 7 laptop that I want to turn into a simple clock. I used pygame to fill the screen with (0,0,0) black pixels, and then drew the time in light blue pixels over that.
The problem is, (0,0,0) black pixels aren’t the same as turned off pixels. As you can see in the picture, even with the brightness of the laptop as low as possible, the black pixels still have a brightness to them. This makes the clock act as a night light, which is not what I want.
I want those black pixels completely gone - like when the laptop is turned off and no brightness is coming from the screen - while keeping the blue pixels on. Any suggestions? Is this even possible?
If it is possible, I would guess the solution is either to change something in Windows 7 settings or do something I didn’t think of with pygame or another python library.
—Research Thus Far—
The top reply to this post claims it is impossible to “turn off” pixels on the computer side: https://superuser.com/questions/1155129/how-to-turn-off-make-black-certain-pixels-on-a-screen
Interesting suggestions such as changing the contrast settings in Windows or downloading a dimmer program, although the OP said neither idea made it dark enough: https://answers.microsoft.com/en-us/windows/forum/windows_7-desktop/how-do-i-dim-the-screen-brightness-further-than/ad7388af-e07a-4d9b-b71d-0e3f77a61c1c
Backlighting info: https://www.google.com/amp/s/amp.reddit.com/r/explainlikeimfive/comments/3hm6pd/eli5_why_dont_pixels_that_show_the_color_black/
While specific pixels cannot be turned on or off for an LED display, the light behind the display (backlight) can be controlled.
This means the clock can be on during the day and entirely turned off at night - although it, unfortunately, can never be partially on like the question was hoping for.
Python code to turn the backlight on and off (sleep is also an option for windows):
def backlight(argument):
if sys.platform.startswith('linux'): # expecting "on" or "off" as the argument
import os
os.system("xset dpms force " + argument)
elif sys.platform.startswith('win'): # expecting "on", "off", or "sleep" as the argument
import win32gui
import win32con
if argument == "on":
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SYSCOMMAND,
win32con.SC_MONITORPOWER, -1)
if argument == "off":
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SYSCOMMAND,
win32con.SC_MONITORPOWER, 2)
if argument == "sleep":
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SYSCOMMAND,
win32con.SC_MONITORPOWER, 1)

Text appears mangled when bkgd char is curses.ACS_CKBOARD

I'm trying to use a "haze" character - ACS_CKBOARD - as a background, with a custom foreground and background color.
This appears to work okay, but when I call addstr to show text on top of the background, the text is garbled. It appears to be a selection of "alternate characters" in place of my "Hello, world!", except of course that some few normal letters show through.
Here's a small screen capture:
I'm assuming that something has jammed up inside curses. Does anyone know how I can get the correct text to display against this background?
Here's some code that produces the behavior:
import curses
import locale
def main(scr):
curses.init_color(2, 650, 407, 160) # brown
curses.init_color(6, 149, 113, 78) # tan
curses.init_pair(1, 2, 6)
scr.bkgd(curses.ACS_CKBOARD, curses.color_pair(1))
scr.clear()
scr.addstr(10, 0, 'Hello, world!', curses.color_pair(0))
scr.getch()
if __name__ == "__main__":
locale.setlocale(locale.LC_ALL, '')
curses.wrapper(main)
FWIW: I'm using iTerm2 on a Mac, Python version 3.5.3. If I run the same code in Terminal, I get a similar result with the wrong color:
Update:
After reading Thomas Dickey's answer, I tried to implement what he suggested. I tried setting the bkgd followed by both clear and erase followed by another call to set the bkgd. That didn't work- I got the color without the background characters. Looking at the documentation for bkgd, it does specify that "The change is then applied to every character position in that window", so that's right out!
Then I found window.bkgdset(char[, attr]), which does not immediately apply it's setting to every character position. Instead, it just applies to newly-drawn bits. With that function, I modified my code as follows:
curses.init_pair(1, 2, 6)
scr.bkgd(curses.ACS_CKBOARD, curses.color_pair(1))
scr.erase()
scr.bkgdset(' ', curses.color_pair(1))
scr.addstr(10, 0, 'Hello, world!', curses.color_pair(0))
And that works! Here's a screenshot to show the result:
Thanks, Thomas, for the suggestion about resetting the background after the paint!
The background character (which you have set with scr.bkgd) is a combination of video attribute, color pair and character which is merged with other characters added to the screen, e.g., via scr.addstr.
For what it's worth, X/Open Curses documents the feature in Rendition of Characters Placed into a Window.
The alternate character set aspect is one of those video attributes, and as documented by X/Open Curses:
the attributes specified, OR-ed with the window attributes.
If you don't want that, you can
temporarily set the background, erase the window (filling the background) and reset the background without the alternate character set, e.g.,
scr.bkgd(curses.ACS_NORMAL, curses.color_pair(1))
use a different method for adding characters to the screen. The underlying curses library waddchstr passes the video attributes directly (no merging). But it does not appear to be part of the Python binding (nothing similar in the reference manual). The attr parameter of addstr likely refers to the window attribute (set with a similar function (in X/Open curses, the "window colour").
Given the available functions (and limitations of the binding), calls with scr.bkgd are the way to solve the problem.

How do I print colored output to the terminal in Python?

Is there a Python equivalent of Perl's
print color 'red';
print <something>;
print color 'reset';
available?
I am using this approach:
"\x1b[1;%dm" % (<color code>) + "ERROR: log file does not exist" + "\x1b[0m"
what I want is I should be able to set color for all print messages like,
print color 'red'
function_print_something(<some message>)
print color 'reset'
Here 'function_print_something' is my python function which will print some formatted log messages on to the screen.
Would the Python termcolor module do? This would be a rough equivalent for some uses.
from termcolor import colored
print colored('hello', 'red'), colored('world', 'green')
The example is right from this post, which has a lot more. Here is a part of the example from docs
import sys
from termcolor import colored, cprint
text = colored('Hello, World!', 'red', attrs=['reverse', 'blink'])
print(text)
cprint('Hello, World!', 'green', 'on_red')
A specific requirement was to set the color, and presumably other terminal attributes, so that all following prints are that way. While I stated in the original post that this is possible with this module I now don't think so. See the last section for a way to do that.
However, most of the time we print short segments of text in color, a line or two. So the interface in these examples may be a better fit than to 'turn on' a color, print, and then turn it off. (Like in the Perl example shown.) Perhaphs you can add optional argument(s) to your print function for coloring the output as well, and in the function use module's functions to color the text. This also makes it easier to resolve occasional conflicts between formatting and coloring. Just a thought.
Here is a basic approach to set the terminal so that all following prints are rendered with a given color, attributes, or mode.
Once an appropriate ANSI sequence is sent to the terminal, all following text is rendered that way. Thus if we want all text printed to this terminal in the future to be bright/bold red, print ESC[ followed by the codes for "bright" attribute (1) and red color (31), followed by m
# print "\033[1;31m" # this would emit a new line as well
import sys
sys.stdout.write("\033[1;31m")
print "All following prints will be red ..."
To turn off any previously set attributes use 0 for attribute, \033[0;35m (magenta).
To suppress a new line in python 3 use print('...', end=""). The rest of the job is about packaging this for modular use (and for easier digestion).
File colors.py
RED = "\033[1;31m"
BLUE = "\033[1;34m"
CYAN = "\033[1;36m"
GREEN = "\033[0;32m"
RESET = "\033[0;0m"
BOLD = "\033[;1m"
REVERSE = "\033[;7m"
I recommend a quick read through some references on codes. Colors and attributes can be combined and one can put together a nice list in this package. A script
import sys
from colors import *
sys.stdout.write(RED)
print "All following prints rendered in red, until changed"
sys.stdout.write(REVERSE + CYAN)
print "From now on change to cyan, in reverse mode"
print "NOTE: 'CYAN + REVERSE' wouldn't work"
sys.stdout.write(RESET)
print "'REVERSE' and similar modes need be reset explicitly"
print "For color alone this is not needed; just change to new color"
print "All normal prints after 'RESET' above."
If the constant use of sys.stdout.write() is a bother it can be be wrapped in a tiny function, or the package turned into a class with methods that set terminal behavior (print ANSI codes).
Some of the above is more of a suggestion to look it up, like combining reverse mode and color. (This is available in the Perl module used in the question, and is also sensitive to order and similar.)
A convenient list of escape codes is surprisingly hard to find, while there are many references on terminal behavior and how to control it. The Wiki page on ANSI escape codes has all information but requires a little work to bring it together. Pages on Bash prompt have a lot of specific useful information. Here is another page with straight tables of codes.
There is much more out there.
This can be used alongside a module like termocolor.
I suggest sty. It's similar to colorama, but less verbose and it supports 8bit and 24bit colors. You can also extend the color register with your own colors.
Examples:
from sty import fg, bg, ef, rs
foo = fg.red + 'This is red text!' + fg.rs
bar = bg.blue + 'This has a blue background!' + bg.rs
baz = ef.italic + 'This is italic text' + rs.italic
qux = fg(201) + 'This is pink text using 8bit colors' + fg.rs
qui = fg(255, 10, 10) + 'This is red text using 24bit colors.' + fg.rs
# Add custom colors:
from sty import Style, RgbFg
fg.orange = Style(RgbFg(255, 150, 50))
buf = fg.orange + 'Yay, Im orange.' + fg.rs
print(foo, bar, baz, qux, qui, buf, sep='\n')
Demo:
For python 3.6.1 and above I would recommend using Rich. To install Rich and try it out, type the following in the terminal
pip3 install rich
python -m rich
If you don't want to use Rich,
you can try this with python 3:
from termcolor import colored
print(colored('Hello, World!', 'green', 'on_red'))
If you are using the Windows operating system, the above code may not work for you. Then you can try this code:
from colorama import init
from termcolor import colored
# use Colorama to make Termcolor work on Windows too
init()
# then use Termcolor for all colored text output
print(colored('Hello, World!', 'green', 'on_red'))
Hope that helps.
Compared to the methods listed here, I prefer the method that comes with the system.
Here, I provide a better method without third-party libraries.
class colors: # You may need to change color settings
RED = '\033[31m'
ENDC = '\033[m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
BLUE = '\033[34m'
print(colors.RED + "something you want to print in red color" + colors.ENDC)
print(colors.GREEN + "something you want to print in green color" + colors.ENDC)
print("something you want to print in system default color")
More color code , ref to : Printing Colored Text in Python
Enjoy yourself!
A side note: Windows users should run os.system('color') first, otherwise you would see some ANSI escape sequences rather than a colored output.
There are a few libraries that help out here. For cmdline tools I sometimes use colorama.
e.g.
from colorama import init, Fore, Back, Style
init()
def cprint(msg, foreground = "black", background = "white"):
fground = foreground.upper()
bground = background.upper()
style = getattr(Fore, fground) + getattr(Back, bground)
print(style + msg + Style.RESET_ALL)
cprint("colorful output, wohoo", "red", "black")
But instead of using strings, you might want to use an enum and/or add a few checks. Not the prettiest solution, but works on osx/linux and windows and is easy to use.
Other threads about this topic and cross-platform support: e.g. here.
What about the ansicolors library? You can simple do:
from colors import color, red, blue
# common colors
print(red('This is red'))
print(blue('This is blue'))
# colors by name or code
print(color('Print colors by name or code', 'white', '#8a2be2'))
Color_Console library is comparatively easier to use. Install this library and the following code would help you.
from Color_Console import *
ctext("This will be printed" , "white" , "blue")
The first argument is the string to be printed, The second argument is the color of
the text and the last one is the background color.
The latest version of Color_Console allows you to pass a list or dictionary of colors which would change after a specified delay time.
Also, they have good documentation on all of their functions.
Visit https://pypi.org/project/Color-Console/ to know more.

Resizing the curses terminal doesn't resize the program window

I'm on Windows, where the curses module is not native, so I am using the Windows curses module for python 3.2, found here.
My goal is to resize the terminal, which is currently at a small 25 lines x 80 columns size. First I tried the curses.resizeterm(lines, cols) command, which is apparently not found in the windows curses module (and hasattr(curses, 'resizeterm') returned false). So I look at the alternative module unicurses, which is also for windows, but that doesn't even have a resize command.
So I do more reading and learn about the environment variables 'LINES' and 'COLS' which, when set by os.environ, should resize the terminal. And they do, kind of. The terminal itself gets resized, but the Windows program displaying the terminal is still the same size as before, 25 x 80. I have confirmed that the two variables have indeed been changed, writing a little thing to display them in the top left corner. In addition, the box() function does draw a border around the screen as if it the variables were changed.
So, can anyone explain either 1) how to resize the "Windows window" to match the terminal or 2) how to get resizeterm() to work on my python installation? The relevant code of my program and a picture of how it looks are attached below.
import random, sys, math, curses, os
from curses import *
curses.use_env(True)
os.environ['LINES'] = "80"
os.environ['COLS'] = "60"
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
stdscr.keypad(1)
curses.curs_set(0)
LINES, COLS = stdscr.getmaxyx()
This code might help:
import curses
screen = curses.initscr()
# Check if screen was re-sized (True or False)
resize = curses.is_term_resized(y, x)
# Action in loop if resize is True:
if resize is True:
y, x = screen.getmaxyx()
screen.clear()
curses.resizeterm(y, x)
screen.refresh()

Categories

Resources