Fabulous¶
Version: | 0.1 |
---|---|
Copyright: | Copyright (c) 2010 J.A. Roberts Tunney |
Installation¶
Run the following commands:
sudo apt-get install python-imaging
sudo python setup.py install
Modules¶
fabulous.color¶
I implement support for standard 16-color color terminals.
-
class
fabulous.color.
ColorString
(*items)¶ 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
-
as_utf8
¶ A more readable way to say
unicode(color).encode('utf8')
-
-
fabulous.color.
complement
(color)¶ 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)
-
fabulous.color.
main
(args)¶ I provide a command-line interface for this module
-
fabulous.color.
parse_color
(color)¶ 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)
-
class
fabulous.color.
plain
(*items)¶ A passive wrapper that preserves proper length reporting
>>> len(plain("hello ", bold("kitty"))) 11
-
fabulous.color.
section
(title, bar=u'\u203e', strm=<open file '<stdout>', mode 'w'>)¶ Helper function for testing demo routines
fabulous.xterm256¶
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.
-
fabulous.xterm256.
compile_speedup
()¶ 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:
- Python >= 2.5 for ctypes library
-
fabulous.xterm256.
rgb_to_xterm
(r, g, b)¶ Quantize RGB values to an xterm 256-color ID
This works by envisioning the RGB values for all 256 xterm colors as 3D euclidean space and brute-force searching for the nearest neighbor.
This is very slow. If you’re very lucky,
compile_speedup()
will replace this function automatically with routines in _xterm256.c.
-
fabulous.xterm256.
xterm_to_rgb
(xcolor)¶ Convert xterm Color ID to an RGB value
All 256 values are precalculated and stored in
COLOR_TABLE
fabulous.logs¶
I provide utilities for making your logs look fabulous.
-
class
fabulous.logs.
TransientStreamHandler
(strm=<open file '<stderr>', mode 'w'>, level=30)¶ 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.
-
fabulous.logs.
basicConfig
(level=30, transient_level=0)¶ Shortcut for setting up transient logging
I am a replica of
logging.basicConfig
which installs a transient logging handler to stderr.
fabulous.text¶
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
.
-
exception
fabulous.text.
FontNotFound
¶ 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.
-
class
fabulous.text.
Text
(text, fsize=20, color='#0099ff', shadow=False, skew=None, font='IndUni-H-Bold')¶ 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:- Turning your text into an RGB-Alpha bitmap image using
PIL
- Applying way cool effects (if you choose to enable them)
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: - text – The text you want to display as a string.
- fsize – The font size in points. This obviously end up looking much larger because in fabulous a single character is treated as one horizontal pixel and two vertical pixels.
- color – The color (specified as you would in HTML/CSS) of
your text. For example Red could be specified as
follows:
red
,#00F
or#0000FF
. - shadow – If true, render a simple drop-shadow beneath text. The Fabulous logo uses this feature.
- skew – Skew size in pixels. This applies an affine transform to shift the top-most pixels to the right. The Fabulous logo uses a five pixel skew.
- font – The TrueType font you want. If this is not an absolute path, Fabulous will search for your font by globbing the specified name in various directories.
- Turning your text into an RGB-Alpha bitmap image using
-
fabulous.text.
get_font_files
()¶ 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)) ...
-
fabulous.text.
main
(args)¶ I provide a command-line interface for this module
-
fabulous.text.
resolve_font
(name)¶ 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
fabulous.image¶
-
class
fabulous.image.
Image
(path, width=None)¶ 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 askTerminalInfo
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.
-
convert
()¶ Yields xterm color codes for each pixel in image
-
reduce
(colors)¶ 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.
-
resize
(width=None)¶ Resizes image to fit inside terminal
Called by the constructor automatically.
-
size
¶ Returns size of image
-
-
fabulous.image.
main
(args)¶ I provide a command-line interface for this module
fabulous.utils¶
-
class
fabulous.utils.
TerminalInfo
(bgcolor='black')¶ 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)
-
dimensions
¶ 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)
.
-
height
¶ Returns height of terminal in lines
-
termfd
¶ 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.
-
width
¶ Returns width of terminal in characters
-
-
fabulous.utils.
memoize
(function)¶ 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.
-
fabulous.utils.
pil_check
()¶ Check for PIL library, printing friendly error if not found
We need PIL for the
fabulous.text
andfabulous.image
modules to work. Because PIL can be very tricky to install, it’s not listed in thesetup.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 :’(
fabulous.gotham¶
I implement functions to satisfy your darker side.
-
fabulous.gotham.
lorem_gotham
()¶ 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.
-
fabulous.gotham.
lorem_gotham_title
()¶ Names your poem
-
fabulous.gotham.
main
(args)¶ I provide a command-line interface for this module
fabulous.rotating_cube¶
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.
-
class
fabulous.rotating_cube.
Frame
¶ Canvas object for drawing a frame to be printed
-
fabulous.rotating_cube.
ellipse_point
(degrees, width, height)¶ I hate math so much :’(
-
fabulous.rotating_cube.
rotating_cube
(degree_change=3, frame_rate=10)¶ 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