Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
1 Metadata-Version: 1.0
2 Name: blessings
3 Version: 1.3
4 Summary: A thin, practical wrapper around terminal formatting, positioning, and more
5 Home-page: https://github.com/erikrose/blessings
6 Author: Erik Rose
7 Author-email: erikrose@grinchcentral.com
8 License: MIT
9 Description: =========
10 Blessings
11 =========
13 Coding with Blessings looks like this... ::
15 from blessings import Terminal
17 t = Terminal()
19 print t.bold('Hi there!')
20 print t.bold_red_on_bright_green('It hurts my eyes!')
22 with t.location(0, t.height - 1):
23 print 'This is at the bottom.'
25 Or, for byte-level control, you can drop down and play with raw terminal
26 capabilities::
28 print '{t.bold}All your {t.red}bold and red base{t.normal}'.format(t=t)
29 print t.wingo(2)
31 The Pitch
32 =========
34 Blessings lifts several of curses_' limiting assumptions, and it makes your
35 code pretty, too:
37 * Use styles, color, and maybe a little positioning without clearing the whole
38 screen first.
39 * Leave more than one screenful of scrollback in the buffer after your program
40 exits, like a well-behaved command-line app should.
41 * Get rid of all those noisy, C-like calls to ``tigetstr`` and ``tparm``, so
42 your code doesn't get crowded out by terminal bookkeeping.
43 * Act intelligently when somebody redirects your output to a file, omitting the
44 terminal control codes the user doesn't want to see (optional).
46 .. _curses: http://docs.python.org/library/curses.html
48 Before And After
49 ----------------
51 Without Blessings, this is how you'd print some underlined text at the bottom
52 of the screen::
54 from curses import tigetstr, setupterm, tparm
55 from fcntl import ioctl
56 from os import isatty
57 import struct
58 import sys
59 from termios import TIOCGWINSZ
61 # If we want to tolerate having our output piped to other commands or
62 # files without crashing, we need to do all this branching:
63 if hasattr(sys.stdout, 'fileno') and isatty(sys.stdout.fileno()):
64 setupterm()
65 sc = tigetstr('sc')
66 cup = tigetstr('cup')
67 rc = tigetstr('rc')
68 underline = tigetstr('smul')
69 normal = tigetstr('sgr0')
70 else:
71 sc = cup = rc = underline = normal = ''
72 print sc # Save cursor position.
73 if cup:
74 # tigetnum('lines') doesn't always update promptly, hence this:
75 height = struct.unpack('hhhh', ioctl(0, TIOCGWINSZ, '\000' * 8))[0]
76 print tparm(cup, height - 1, 0) # Move cursor to bottom.
77 print 'This is {under}underlined{normal}!'.format(under=underline,
78 normal=normal)
79 print rc # Restore cursor position.
81 Phew! That was long and full of incomprehensible trash! Let's try it again,
82 this time with Blessings::
84 from blessings import Terminal
86 term = Terminal()
87 with term.location(0, term.height - 1):
88 print 'This is', term.underline('pretty!')
90 Much better.
92 What It Provides
93 ================
95 Blessings provides just one top-level object: ``Terminal``. Instantiating a
96 ``Terminal`` figures out whether you're on a terminal at all and, if so, does
97 any necessary terminal setup. After that, you can proceed to ask it all sorts
98 of things about the terminal. Terminal terminal terminal.
100 Simple Formatting
101 -----------------
103 Lots of handy formatting codes ("capabilities" in low-level parlance) are
104 available as attributes on a ``Terminal``. For example::
106 from blessings import Terminal
108 term = Terminal()
109 print 'I am ' + term.bold + 'bold' + term.normal + '!'
111 You can also use them as wrappers so you don't have to say ``normal``
112 afterward::
114 print 'I am', term.bold('bold') + '!'
116 Or, if you want fine-grained control while maintaining some semblance of
117 brevity, you can combine it with Python's string formatting, which makes
118 attributes easy to access::
120 print 'All your {t.red}base {t.underline}are belong to us{t.normal}'.format(t=term)
122 Simple capabilities of interest include...
124 * ``bold``
125 * ``reverse``
126 * ``underline``
127 * ``no_underline`` (which turns off underlining)
128 * ``blink``
129 * ``normal`` (which turns off everything, even colors)
130 * ``clear_eol`` (clear to the end of the line)
131 * ``clear_bol`` (clear to beginning of line)
132 * ``clear_eos`` (clear to end of screen)
134 Here are a few more which are less likely to work on all terminals:
136 * ``dim``
137 * ``italic`` and ``no_italic``
138 * ``shadow`` and ``no_shadow``
139 * ``standout`` and ``no_standout``
140 * ``subscript`` and ``no_subscript``
141 * ``superscript`` and ``no_superscript``
142 * ``flash`` (which flashes the screen once)
144 Note that, while the inverse of ``underline`` is ``no_underline``, the only way
145 to turn off ``bold`` or ``reverse`` is ``normal``, which also cancels any
146 custom colors. This is because there's no way to tell the terminal to undo
147 certain pieces of formatting, even at the lowest level.
149 You might notice that the above aren't the typical incomprehensible terminfo
150 capability names; we alias a few of the harder-to-remember ones for
151 readability. However, you aren't limited to these: you can reference any
152 string-returning capability listed on the `terminfo man page`_ by the name
153 under the "Cap-name" column: for example, ``term.rum``.
155 .. _`terminfo man page`: http://www.manpagez.com/man/5/terminfo/
157 Color
158 -----
160 16 colors, both foreground and background, are available as easy-to-remember
161 attributes::
163 from blessings import Terminal
165 term = Terminal()
166 print term.red + term.on_green + 'Red on green? Ick!' + term.normal
167 print term.bright_red + term.on_bright_blue + 'This is even worse!' + term.normal
169 You can also call them as wrappers, which sets everything back to normal at the
170 end::
172 print term.red_on_green('Red on green? Ick!')
173 print term.yellow('I can barely see it.')
175 The available colors are...
177 * ``black``
178 * ``red``
179 * ``green``
180 * ``yellow``
181 * ``blue``
182 * ``magenta``
183 * ``cyan``
184 * ``white``
186 You can set the background color instead of the foreground by prepending
187 ``on_``, as in ``on_blue``. There is also a ``bright`` version of each color:
188 for example, ``on_bright_blue``.
190 There is also a numerical interface to colors, which takes an integer from
191 0-15::
193 term.color(5) + 'Hello' + term.normal
194 term.on_color(3) + 'Hello' + term.normal
196 term.color(5)('Hello')
197 term.on_color(3)('Hello')
199 If some color is unsupported (for instance, if only the normal colors are
200 available, not the bright ones), trying to use it will, on most terminals, have
201 no effect: the foreground and background colors will stay as they were. You can
202 get fancy and do different things depending on the supported colors by checking
203 `number_of_colors`_.
205 .. _`number_of_colors`: http://packages.python.org/blessings/#blessings.Terminal.number_of_colors
207 Compound Formatting
208 -------------------
210 If you want to do lots of crazy formatting all at once, you can just mash it
211 all together::
213 from blessings import Terminal
215 term = Terminal()
216 print term.bold_underline_green_on_yellow + 'Woo' + term.normal
218 Or you can use your newly coined attribute as a wrapper, which implicitly sets
219 everything back to normal afterward::
221 print term.bold_underline_green_on_yellow('Woo')
223 This compound notation comes in handy if you want to allow users to customize
224 the formatting of your app: just have them pass in a format specifier like
225 "bold_green" on the command line, and do a quick ``getattr(term,
226 that_option)('Your text')`` when you do your formatting.
228 I'd be remiss if I didn't credit couleur_, where I probably got the idea for
229 all this mashing.
231 .. _couleur: http://pypi.python.org/pypi/couleur
233 Parametrized Capabilities
234 -------------------------
236 Some capabilities take parameters. Rather than making you dig up ``tparm()``
237 all the time, we simply make such capabilities into callable strings. You can
238 pass the parameters right in::
240 from blessings import Terminal
242 term = Terminal()
243 print term.move(10, 1)
245 Here are some of interest:
247 ``move``
248 Position the cursor elsewhere. Parameters are y coordinate, then x
249 coordinate.
250 ``move_x``
251 Move the cursor to the given column.
252 ``move_y``
253 Move the cursor to the given row.
255 You can also reference any other string-returning capability listed on the
256 `terminfo man page`_ by its name under the "Cap-name" column.
258 .. _`terminfo man page`: http://www.manpagez.com/man/5/terminfo/
260 Height and Width
261 ----------------
263 It's simple to get the height and width of the terminal, in characters::
265 from blessings import Terminal
267 term = Terminal()
268 height = term.height
269 width = term.width
271 These are newly updated each time you ask for them, so they're safe to use from
272 SIGWINCH handlers.
274 Temporary Repositioning
275 -----------------------
277 Sometimes you need to flit to a certain location, print something, and then
278 return: for example, when updating a progress bar at the bottom of the screen.
279 ``Terminal`` provides a context manager for doing this concisely::
281 from blessings import Terminal
283 term = Terminal()
284 with term.location(0, term.height - 1):
285 print 'Here is the bottom.'
286 print 'This is back where I came from.'
288 Parameters to ``location()`` are ``x`` and then ``y``, but you can also pass
289 just one of them, leaving the other alone. For example... ::
291 with term.location(y=10):
292 print 'We changed just the row.'
294 If you want to reposition permanently, see ``move``, in an example above.
296 Pipe Savvy
297 ----------
299 If your program isn't attached to a terminal, like if it's being piped to
300 another command or redirected to a file, all the capability attributes on
301 ``Terminal`` will return empty strings. You'll get a nice-looking file without
302 any formatting codes gumming up the works.
304 If you want to override this--like if you anticipate your program being piped
305 through ``less -r``, which handles terminal escapes just fine--pass
306 ``force_styling=True`` to the ``Terminal`` constructor.
308 In any case, there is an ``is_a_tty`` attribute on ``Terminal`` that lets you
309 see whether the attached stream seems to be a terminal. If it's false, you
310 might refrain from drawing progress bars and other frippery, since you're
311 apparently headed into a pipe::
313 from blessings import Terminal
315 term = Terminal()
316 if term.is_a_tty:
317 with term.location(0, term.height - 1):
318 print 'Progress: [=======> ]'
319 print term.bold('Important stuff')
321 Shopping List
322 =============
324 There are decades of legacy tied up in terminal interaction, so attention to
325 detail and behavior in edge cases make a difference. Here are some ways
326 Blessings has your back:
328 * Uses the terminfo database so it works with any terminal type
329 * Provides up-to-the-moment terminal height and width, so you can respond to
330 terminal size changes (SIGWINCH signals). (Most other libraries query the
331 ``COLUMNS`` and ``LINES`` environment variables or the ``cols`` or ``lines``
332 terminal capabilities, which don't update promptly, if at all.)
333 * Avoids making a mess if the output gets piped to a non-terminal
334 * Works great with standard Python string templating
335 * Provides convenient access to all terminal capabilities, not just a sugared
336 few
337 * Outputs to any file-like object, not just stdout
338 * Keeps a minimum of internal state, so you can feel free to mix and match with
339 calls to curses or whatever other terminal libraries you like
341 Blessings does not provide...
343 * Native color support on the Windows command prompt. However, it should work
344 when used in concert with colorama_.
346 .. _colorama: http://pypi.python.org/pypi/colorama/0.2.4
348 Bugs
349 ====
351 Bugs or suggestions? Visit the `issue tracker`_.
353 .. _`issue tracker`: https://github.com/erikrose/blessings/issues/new
355 License
356 =======
358 Blessings is under the MIT License. See the LICENSE file.
360 Version History
361 ===============
363 1.3
364 * Add ``number_of_colors``, which tells you how many colors the terminal
365 supports.
366 * Made ``color(n)`` and ``on_color(n)`` callable to wrap a string, like the
367 named colors can. Also, make them both fall back to the ``setf`` and
368 ``setb`` capabilities (like the named colors do) if the ANSI ``setaf`` and
369 ``setab`` aren't available.
370 * Allow ``color`` attr to act as an unparametrized string, not just a
371 callable.
372 * Make ``height`` and ``width`` examine any passed-in stream before falling
373 back to stdout. (This rarely if ever affects actual behavior; it's mostly
374 philosophical.)
375 * Make caching simpler and slightly more efficient.
376 * Get rid of a reference cycle between Terminals and FormattingStrings.
377 * Update docs to reflect that terminal addressing (as in ``location()``) is
378 0-based.
380 1.2
381 * Added support for Python 3! We need 3.2.3 or greater, because the curses
382 library couldn't decide whether to accept strs or bytes before that
383 (http://bugs.python.org/issue10570).
384 * Everything that comes out of the library is now unicode. This lets us
385 support Python 3 without making a mess of the code, and Python 2 should
386 continue to work unless you were testing types (and badly). Please file a
387 bug if this causes trouble for you.
388 * Changed to the MIT License for better world domination.
389 * Added Sphinx docs.
391 1.1
392 * Added nicely named attributes for colors.
393 * Introduced compound formatting.
394 * Added wrapper behavior for styling and colors.
395 * Let you force capabilities to be non-empty, even if the output stream is
396 not a terminal.
397 * Added the ``is_a_tty`` attribute for telling whether the output stream is a
398 terminal.
399 * Sugared the remaining interesting string capabilities.
400 * Let ``location()`` operate on just an x *or* y coordinate.
402 1.0
403 * Extracted Blessings from nose-progressive, my `progress-bar-having,
404 traceback-shortcutting, rootin', tootin' testrunner`_. It provided the
405 tootin' functionality.
407 .. _`progress-bar-having, traceback-shortcutting, rootin', tootin' testrunner`: http://pypi.python.org/pypi/nose-progressive/
409 Keywords: terminal,tty,curses,ncurses,formatting,style,color,console
410 Platform: UNKNOWN
411 Classifier: Intended Audience :: Developers
412 Classifier: Natural Language :: English
413 Classifier: Development Status :: 5 - Production/Stable
414 Classifier: Environment :: Console
415 Classifier: Environment :: Console :: Curses
416 Classifier: License :: OSI Approved :: MIT License
417 Classifier: Operating System :: POSIX
418 Classifier: Programming Language :: Python :: 2
419 Classifier: Programming Language :: Python :: 2.5
420 Classifier: Programming Language :: Python :: 2.6
421 Classifier: Programming Language :: Python :: 2.7
422 Classifier: Programming Language :: Python :: 3
423 Classifier: Programming Language :: Python :: 3.2
424 Classifier: Topic :: Software Development :: Libraries
425 Classifier: Topic :: Software Development :: User Interfaces
426 Classifier: Topic :: Terminals