Version: | 0.1 |
---|---|
Copyright: | Copyright (c) 2010 J.A. Roberts Tunney |
Run the following commands:
sudo apt-get install python-imaging
sudo python setup.py install
I implement support for standard 16-color color terminals.
A colorized string-like object that gives correct length
If anyone knows a way to be able to make this behave like a string object without creating a bug minefield let me know:
>>> str(red("hello"))
'\x1b[31mhello\x1b[39m'
>>> len(red("hello"))
5
>>> len(str(red("hello")))
15
>>> str(bold(red("hello")))
'\x1b[1m\x1b[31mhello\x1b[39m\x1b[22m'
>>> len(bold(red("hello")))
5
>>> len(bold("hello ", red("world")))
11
A more readable way to say unicode(color).encode('utf8')
Gives you the polar opposite of your color
This isn’t guaranteed to look good >_> (especially with brighter, higher intensity colors.)
>>> complement('red')
(0, 255, 76)
>>> complement((0, 100, 175))
(175, 101, 0)
I provide a command-line interface for this module
Turns a color into an (r, g, b) tuple
>>> parse_color('white')
(255, 255, 255)
>>> parse_color('#ff0000')
(255, 0, 0)
>>> parse_color('#f00')
(255, 0, 0)
>>> parse_color((255, 0, 0))
(255, 0, 0)
>>> import grapefruit
>>> parse_color(grapefruit.Color((0.0, 1.0, 0.0)))
(0, 255, 0)
A passive wrapper that preserves proper length reporting
>>> len(plain("hello ", bold("kitty")))
11
Helper function for testing demo routines
Implements Support for the 256 colors supported by xterm as well as quantizing 24-bit RGB color to xterm color ids.
Color quantization is very very slow so when this module is loaded, it’ll attempt to automatically compile a speedup module using gcc. A logging message will be emitted if it fails and we’ll fallback on the Python code.
Tries to compile/link the C version of this module
Like it really makes a huge difference. With a little bit of luck this should just work for you.
You need:
I provide utilities for making your logs look fabulous.
Standard Python logging Handler for Transient Console Logging
Logging transiently means that verbose logging messages like DEBUG will only appear on the last line of your terminal for a short period of time and important messages like WARNING will scroll like normal text.
This allows you to log lots of messages without the important stuff getting drowned out.
This module integrates with the standard Python logging module.
Shortcut for setting up transient logging
I am a replica of logging.basicConfig which installs a transient logging handler to stderr.
I let you print TrueType text to your terminal. The easiest way to get started with me is by running:
jart@compy:~$ python -m fabulous.text --help
To make things simple, Fabulous comes with my favorite serif, non-serif, and monospace fonts:
IndUni-H-Bold: Open Source Helvetica Bold clone (sans-serif)
This is the real deal and not some cheap ripoff like Verdana. IndUni-H-Bold is the default because not only does it look great, but also renders perfectly. and is also used for the Fabulous logo. Commonly found on stret signs.
This font is licensed under the GPL. If you’re developing proprietary software you might want to ask its author or a lawyer if Fabulous’ use of IndUni-H would be considered a “GPL Barrier.”
cmr10: Computer Modern (serif)
Donald Knuth wrote 23,000 lines for the sole purpose of bestowing this jewel upon the world. This font is commonly seen in scholarly papers.
DejaVuSansMono: DejaVu Sans Mono (formerly Bitstream Vera Sans Mono)
At point size 8, this is my favorite programming/terminal font.
For other fonts, I’ll try my best to figure out where your font files are stored. If I have trouble finding your font, try using an absolute path with the extension. You could also try putting the font in your ~/.fonts folder and running fc-cache -fv ~/.fonts.
I get raised when the font-searching hueristics fail
This class extends the standard ValueError exception so you don’t have to import me if you don’t want to.
Renders TrueType Text to Terminal
I’m a sub-class of fabulous.image.Image. My job is limited to simply getting things ready. I do this by:
For example:
>>> assert Text("Fabulous", shadow=True, skew=5)
>>> txt = Text("lorem ipsum", font="IndUni-H-Bold")
>>> len(str(txt)) > 0
True
>>> txt = Text("lorem ipsum", font="cmr10")
>>> len(str(txt)) > 0
True
>>> txt = Text("lorem ipsum", font="DejaVuSansMono")
>>> len(str(txt)) > 0
True
Parameters: |
|
---|
Returns a list of all font files we could find
Returned as a list of dir/files tuples:
get_font_files() -> [('/some/dir', ['font1.ttf', ...]), ...]
For example:
>>> fabfonts = os.path.join(os.path.dirname(__file__), 'fonts')
>>> 'IndUni-H-Bold.ttf' in get_font_files()[fabfontdir]
True
>>> 'DejaVuSansMono.ttf' in get_font_files()[fabfontdir]
True
>>> 'cmr10.ttf' in get_font_files()[fabfontdir]
True
>>> assert len(get_font_files()) > 0
>>> for dirname, filename in get_font_files():
... assert os.path.exists(os.path.join(dirname, filename))
...
I provide a command-line interface for this module
Sloppy way to turn font names into absolute filenames
This isn’t intended to be a proper font lookup tool but rather a dirty tool to not have to specify the absolute filename every time.
For example:
>>> path = resolve_font('IndUni-H-Bold')
>>> fontdir = os.path.join(os.path.dirname(__file__), 'fonts')
>>> indunih_path = os.path.join(fontdir, 'IndUni-H-Bold.ttf')
>>> assert path == indunih_path
This isn’t case-sensitive:
>>> assert resolve_font('induni-h') == indunih_path
Raises FontNotFound on failure:
>>> resolve_font('blahahaha')
Traceback (most recent call last):
...
FontNotFound: Can't find 'blahahaha' :'( Try adding it to ~/.fonts
Printing image files to a terminal
I use PIL to turn your image file into a bitmap, resize it so it’ll fit inside your terminal, and implement methods so I can behave like a string or iterable.
When resizing, I’ll assume that a single character on the terminal display is one pixel wide and two pixels tall. For most fonts this is the best way to preserve the aspect ratio of your image.
All colors are are quantized by fabulous.xterm256 to the 256 colors supported by modern terminals. When quantizing semi-transparant pixels (common in text or PNG files) I’ll ask TerminalInfo for the background color I should use to solidify the color. Fully transparent pixels will be rendered as a blank space without color so we don’t need to mix in a background color.
I also put a lot of work into optimizing the output line-by-line so it needs as few ANSI escape sequences as possible. If your terminal is kinda slow, you’re gonna want to buy me a drink ;) You can use DebugImage to visualize these optimizations.
The generated output will only include spaces with different background colors. In the future routines will be provided to overlay text on top of these images.
Yields xterm color codes for each pixel in image
Converts color codes into optimized text
This optimizer works by merging adjacent colors so we don’t have to repeat the same escape codes for each pixel. There is no loss of information.
Parameters: | colors – Iterable yielding an xterm color code for each pixel, None to indicate a transparent pixel, or 'EOL' to indicate th end of a line. |
---|---|
Returns: | Yields lines of optimized text. |
Resizes image to fit inside terminal
Called by the constructor automatically.
Returns size of image
I provide a command-line interface for this module
Quick and easy access to some terminal information
I’ll tell you the terminal width/height and it’s background color.
You don’t need to use me directly. Just access the global term instance:
>>> assert term.width > 0
>>> assert term.height > 0
It’s important to know the background color when rendering PNG images with semi-transparency. Because there’s no way to detect this, black will be the default:
>>> term.bgcolor
(0.0, 0.0, 0.0, 1.0)
>>> import grapefruit
>>> isinstance(term.bgcolor, grapefruit.Color)
True
If you use a white terminal, you’ll need to manually change this:
>>> term.bgcolor = 'white'
>>> term.bgcolor
(1.0, 1.0, 1.0, 1.0)
>>> term.bgcolor = grapefruit.Color.NewFromRgb(0.0, 0.0, 0.0, 1.0)
>>> term.bgcolor
(0.0, 0.0, 0.0, 1.0)
Returns terminal dimensions
Don’t save this information for long periods of time because the user might resize their terminal.
Returns: | Returns (width, height). If there’s no terminal to be found, we’ll just return (79, 40). |
---|
Returns height of terminal in lines
Returns file descriptor number of terminal
This will look at all three standard i/o file descriptors and return whichever one is actually a TTY in case you’re redirecting i/o through pipes.
Returns width of terminal in characters
A very simple memoize decorator to optimize pure-ish functions
Don’t use this unless you’ve examined the code and see the potential risks.
Check for PIL library, printing friendly error if not found
We need PIL for the fabulous.text and fabulous.image modules to work. Because PIL can be very tricky to install, it’s not listed in the setup.py requirements list.
Not everyone is going to have PIL installed so it’s best that we offer as much help as possible so they don’t have to suffer like I have in the past :’(
I implement functions to satisfy your darker side.
Cheesy Gothic Poetry Generator
Uses Python generators to yield eternal angst.
When you need to generate random verbiage to test your code or typographic design, let’s face it... Lorem Ipsum and “the quick brown fox” are old and boring!
What you need is something with flavor, the kind of thing a depressed teenager with a lot of black makeup would write.
Names your poem
I provide a command-line interface for this module
Completely pointless terminal renderer of rotating cube
Uses a faux 2D rendering technique to create what appears to be a wireframe 3d cube.
This doesn’t use the curses library, but rather prints entire frames sized to fill the entire terminal display.
Canvas object for drawing a frame to be printed
I hate math so much :’(
Rotating cube program
How it works:
- Create two imaginary ellipses
- Sized to fit in the top third and bottom third of screen
- Create four imaginary points on each ellipse
- Make those points the top and bottom corners of your cube
- Connect the lines and render
- Rotate the points on the ellipses and repeat