|
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 ========= |
|
12 |
|
13 Coding with Blessings looks like this... :: |
|
14 |
|
15 from blessings import Terminal |
|
16 |
|
17 t = Terminal() |
|
18 |
|
19 print t.bold('Hi there!') |
|
20 print t.bold_red_on_bright_green('It hurts my eyes!') |
|
21 |
|
22 with t.location(0, t.height - 1): |
|
23 print 'This is at the bottom.' |
|
24 |
|
25 Or, for byte-level control, you can drop down and play with raw terminal |
|
26 capabilities:: |
|
27 |
|
28 print '{t.bold}All your {t.red}bold and red base{t.normal}'.format(t=t) |
|
29 print t.wingo(2) |
|
30 |
|
31 The Pitch |
|
32 ========= |
|
33 |
|
34 Blessings lifts several of curses_' limiting assumptions, and it makes your |
|
35 code pretty, too: |
|
36 |
|
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). |
|
45 |
|
46 .. _curses: http://docs.python.org/library/curses.html |
|
47 |
|
48 Before And After |
|
49 ---------------- |
|
50 |
|
51 Without Blessings, this is how you'd print some underlined text at the bottom |
|
52 of the screen:: |
|
53 |
|
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 |
|
60 |
|
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. |
|
80 |
|
81 Phew! That was long and full of incomprehensible trash! Let's try it again, |
|
82 this time with Blessings:: |
|
83 |
|
84 from blessings import Terminal |
|
85 |
|
86 term = Terminal() |
|
87 with term.location(0, term.height - 1): |
|
88 print 'This is', term.underline('pretty!') |
|
89 |
|
90 Much better. |
|
91 |
|
92 What It Provides |
|
93 ================ |
|
94 |
|
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. |
|
99 |
|
100 Simple Formatting |
|
101 ----------------- |
|
102 |
|
103 Lots of handy formatting codes ("capabilities" in low-level parlance) are |
|
104 available as attributes on a ``Terminal``. For example:: |
|
105 |
|
106 from blessings import Terminal |
|
107 |
|
108 term = Terminal() |
|
109 print 'I am ' + term.bold + 'bold' + term.normal + '!' |
|
110 |
|
111 You can also use them as wrappers so you don't have to say ``normal`` |
|
112 afterward:: |
|
113 |
|
114 print 'I am', term.bold('bold') + '!' |
|
115 |
|
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:: |
|
119 |
|
120 print 'All your {t.red}base {t.underline}are belong to us{t.normal}'.format(t=term) |
|
121 |
|
122 Simple capabilities of interest include... |
|
123 |
|
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) |
|
133 |
|
134 Here are a few more which are less likely to work on all terminals: |
|
135 |
|
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) |
|
143 |
|
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. |
|
148 |
|
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``. |
|
154 |
|
155 .. _`terminfo man page`: http://www.manpagez.com/man/5/terminfo/ |
|
156 |
|
157 Color |
|
158 ----- |
|
159 |
|
160 16 colors, both foreground and background, are available as easy-to-remember |
|
161 attributes:: |
|
162 |
|
163 from blessings import Terminal |
|
164 |
|
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 |
|
168 |
|
169 You can also call them as wrappers, which sets everything back to normal at the |
|
170 end:: |
|
171 |
|
172 print term.red_on_green('Red on green? Ick!') |
|
173 print term.yellow('I can barely see it.') |
|
174 |
|
175 The available colors are... |
|
176 |
|
177 * ``black`` |
|
178 * ``red`` |
|
179 * ``green`` |
|
180 * ``yellow`` |
|
181 * ``blue`` |
|
182 * ``magenta`` |
|
183 * ``cyan`` |
|
184 * ``white`` |
|
185 |
|
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``. |
|
189 |
|
190 There is also a numerical interface to colors, which takes an integer from |
|
191 0-15:: |
|
192 |
|
193 term.color(5) + 'Hello' + term.normal |
|
194 term.on_color(3) + 'Hello' + term.normal |
|
195 |
|
196 term.color(5)('Hello') |
|
197 term.on_color(3)('Hello') |
|
198 |
|
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`_. |
|
204 |
|
205 .. _`number_of_colors`: http://packages.python.org/blessings/#blessings.Terminal.number_of_colors |
|
206 |
|
207 Compound Formatting |
|
208 ------------------- |
|
209 |
|
210 If you want to do lots of crazy formatting all at once, you can just mash it |
|
211 all together:: |
|
212 |
|
213 from blessings import Terminal |
|
214 |
|
215 term = Terminal() |
|
216 print term.bold_underline_green_on_yellow + 'Woo' + term.normal |
|
217 |
|
218 Or you can use your newly coined attribute as a wrapper, which implicitly sets |
|
219 everything back to normal afterward:: |
|
220 |
|
221 print term.bold_underline_green_on_yellow('Woo') |
|
222 |
|
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. |
|
227 |
|
228 I'd be remiss if I didn't credit couleur_, where I probably got the idea for |
|
229 all this mashing. |
|
230 |
|
231 .. _couleur: http://pypi.python.org/pypi/couleur |
|
232 |
|
233 Parametrized Capabilities |
|
234 ------------------------- |
|
235 |
|
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:: |
|
239 |
|
240 from blessings import Terminal |
|
241 |
|
242 term = Terminal() |
|
243 print term.move(10, 1) |
|
244 |
|
245 Here are some of interest: |
|
246 |
|
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. |
|
254 |
|
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. |
|
257 |
|
258 .. _`terminfo man page`: http://www.manpagez.com/man/5/terminfo/ |
|
259 |
|
260 Height and Width |
|
261 ---------------- |
|
262 |
|
263 It's simple to get the height and width of the terminal, in characters:: |
|
264 |
|
265 from blessings import Terminal |
|
266 |
|
267 term = Terminal() |
|
268 height = term.height |
|
269 width = term.width |
|
270 |
|
271 These are newly updated each time you ask for them, so they're safe to use from |
|
272 SIGWINCH handlers. |
|
273 |
|
274 Temporary Repositioning |
|
275 ----------------------- |
|
276 |
|
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:: |
|
280 |
|
281 from blessings import Terminal |
|
282 |
|
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.' |
|
287 |
|
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... :: |
|
290 |
|
291 with term.location(y=10): |
|
292 print 'We changed just the row.' |
|
293 |
|
294 If you want to reposition permanently, see ``move``, in an example above. |
|
295 |
|
296 Pipe Savvy |
|
297 ---------- |
|
298 |
|
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. |
|
303 |
|
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. |
|
307 |
|
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:: |
|
312 |
|
313 from blessings import Terminal |
|
314 |
|
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') |
|
320 |
|
321 Shopping List |
|
322 ============= |
|
323 |
|
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: |
|
327 |
|
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 |
|
340 |
|
341 Blessings does not provide... |
|
342 |
|
343 * Native color support on the Windows command prompt. However, it should work |
|
344 when used in concert with colorama_. |
|
345 |
|
346 .. _colorama: http://pypi.python.org/pypi/colorama/0.2.4 |
|
347 |
|
348 Bugs |
|
349 ==== |
|
350 |
|
351 Bugs or suggestions? Visit the `issue tracker`_. |
|
352 |
|
353 .. _`issue tracker`: https://github.com/erikrose/blessings/issues/new |
|
354 |
|
355 License |
|
356 ======= |
|
357 |
|
358 Blessings is under the MIT License. See the LICENSE file. |
|
359 |
|
360 Version History |
|
361 =============== |
|
362 |
|
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. |
|
379 |
|
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. |
|
390 |
|
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. |
|
401 |
|
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. |
|
406 |
|
407 .. _`progress-bar-having, traceback-shortcutting, rootin', tootin' testrunner`: http://pypi.python.org/pypi/nose-progressive/ |
|
408 |
|
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 |