summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Rose <grinch@grinchcentral.com>2012-10-28 17:56:08 -0700
committerErik Rose <grinch@grinchcentral.com>2012-10-28 17:56:08 -0700
commit9e22f5ab78107280df7ab973e4b7349516cd1479 (patch)
tree0a50569d804749aadcd2accfa576709f76f1bd86
parentb781239e850ec8e1947c4951576879dbcea27319 (diff)
downloadblessings-window-title.tar.gz
-rw-r--r--README.rst15
-rw-r--r--blessings/__init__.py47
2 files changed, 51 insertions, 11 deletions
diff --git a/README.rst b/README.rst
index 5bfeb87..67a7aad 100644
--- a/README.rst
+++ b/README.rst
@@ -20,6 +20,8 @@ capabilities::
print '{t.bold}All your {t.red}bold and red base{t.normal}'.format(t=t)
print t.wingo(2)
+Add links to example apps somewhere, like mkelly's mp3 player or conway or (eek) nose-progressive.
+
The Pitch
=========
@@ -107,7 +109,7 @@ you don't have to say ``normal`` afterward::
print 'I am', term.bold('bold') + '!'
Or, if you want fine-grained control while maintaining some semblance of
-brevity, you can combine it with Python's string formatting, which makes
+brevity, you can combine them with Python's string formatting, which makes
attributes easy to access::
print 'All your {t.red}base {t.underline}are belong to us{t.normal}'.format(t=term)
@@ -283,7 +285,7 @@ give them nicer names. The added wrinkle--that they take parameters--is also
given a pleasant treatment: rather than making you dig up ``tparm()`` all the
time, we simply make these capabilities into callable strings. You'd get the
raw capability strings if you were to just print them, but they're fully
-parametrized if you pass params to them as if they were functions.
+parametrized if you pass arguments to them as if they were functions.
Consequently, you can also reference any other string-returning capability
listed on the `terminfo man page`_ by its name under the "Cap-name" column.
@@ -404,9 +406,9 @@ Blessings has your back:
* Works great with standard Python string templating
* Provides convenient access to all terminal capabilities, not just a sugared
few
-* Outputs to any file-like object, not just stdout
-* Keeps a minimum of internal state, so you can feel free to mix and match with
- calls to curses or whatever other terminal libraries you like
+* Lets you put the output anywhere, not just on stdout
+* Keeps a minimum of internal state, so you can mix and match with calls to
+ curses or whatever other terminal libraries you like
Blessings does not provide...
@@ -433,6 +435,9 @@ Blessings is under the MIT License. See the LICENSE file.
Version History
===============
+1.6
+ * Add the ability to set the window title on most terminal emulators.
+
1.5
* Add syntactic sugar and documentation for ``enter_fullscreen`` and
``exit_fullscreen``.
diff --git a/blessings/__init__.py b/blessings/__init__.py
index 68212c2..122f609 100644
--- a/blessings/__init__.py
+++ b/blessings/__init__.py
@@ -92,14 +92,14 @@ class Terminal(object):
self._init_descriptor = (sys.__stdout__.fileno()
if stream_descriptor is None
else stream_descriptor)
+ self._kind = kind or environ.get('TERM', 'unknown')
if self._does_styling:
# Make things like tigetstr() work. Explicit args make setupterm()
# work even when -s is passed to nosetests. Lean toward sending
# init sequences to the stream if it has a file descriptor, and
# send them to stdout as a fallback, since they have to go
# somewhere.
- setupterm(kind or environ.get('TERM', 'unknown'),
- self._init_descriptor)
+ setupterm(self._kind, self._init_descriptor)
self.stream = stream
@@ -202,7 +202,8 @@ class Terminal(object):
# setupterm() again.
for descriptor in self._init_descriptor, sys.__stdout__:
try:
- return struct.unpack('hhhh', ioctl(descriptor, TIOCGWINSZ, '\000' * 8))[0:2]
+ return struct.unpack(
+ 'hhhh', ioctl(descriptor, TIOCGWINSZ, '\000' * 8))[0:2]
except IOError:
pass
return None, None # Should never get here
@@ -301,6 +302,41 @@ class Terminal(object):
#self.__dict__['colors'] = ret # Cache it. It's not changing. (Doesn't work.)
return colors if colors >= 0 else 0
+ def set_title(self, title):
+ """Set the title of the terminal window, and return whether it worked.
+
+ "It worked" includes the case where this Terminal doesn't do any
+ styling at all. If you want to distinguish that case, check the
+ ``is_a_tty`` attribute, and take into account the value you passed to
+ ``force_styling``.
+
+ Supports xterm- and rxvt-like terminals, OS X, and everything else
+ listed in http://www.ibiblio.org/pub/Linux/docs/HOWTO/Xterm-Title.
+
+ """
+ # TODO: I don't know if I like this as a special-purpose method. Why shouldn't we have to print() it like everything else? True, the special method makes it easy to support Windows, but whatever we would do to make "bold" work would also apply to this. OTOH, it's a pretty safe bet that you would never want to actually output something that you meant to go in the title bar, unlike bold. OTOOH, some status lines (different from title bars but often coincident) sometimes support doing bold and such within them. Doing this as a special method rules doing that nicely out. So what if we exposed the titlebar entry and exit codes as pseudo-caps, used them here, but still made them available for those who want to do crazy things within the titlebar? We kinda leapfrog ncurses' current support, codifying years of case statements in people's prompt-setting scripts.
+ # I kinda like shippng this first as a special-purpose method, and then we can add pseudo-caps later if somebody wants them.
+ # TODO: Shouldn't the tsl and fsl caps work for this, after checking that the hs cap is true? http://blog.hashpling.org/every-tried-too-hard-to-solve-something/ But they're blank on OS X. And https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man5/terminfo.5.html says ncurses doesn't "use any of these caps", whatever that means. Okay, I guess some terminal emulators map tsl and fsl to window title, but it's not a standard thing: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634956.
+ # TODO: On Windows, os.system('title Whatever') works.
+ if self._does_styling:
+ if (self._kind.startswith('xterm') or
+ self._kind.startswith('rxvt') or
+ self._kind.startswith('aixterm') or
+ self._kind.startswith('dtterm')):
+ out = '\x1b]2;' + title + '\x07'
+ elif self._kind.startswith('screen'):
+ out = '\x1bk' + title + '\x1b\\' # Does this work?
+ elif self._kind.startswith('iris.ansi'):
+ out = '\x1bP1.y' + title + '\x1b\\'
+ elif self._kind.startswith('sun-cmd'):
+ out = '\x1b]l' + title + '\x1b\\'
+ elif self._kind.startswith('hpterm'):
+ out = '\x1b&f0k' + len(title) + 'D' + title
+ else:
+ return False
+ self.stream.write(out)
+ return True
+
def _resolve_formatter(self, attr):
"""Resolve a sugary or plain capability name, color, or compound formatting function name into a callable capability."""
if attr in COLORS:
@@ -330,7 +366,7 @@ class Terminal(object):
if code:
# We can encode escape sequences as UTF-8 because they never
# contain chars > 127, and UTF-8 never changes anything within that
- # range..
+ # range.
return code.decode('utf-8')
return u''
@@ -445,8 +481,7 @@ class NullCallableString(unicode):
"""
def __new__(cls):
- new = unicode.__new__(cls, u'')
- return new
+ return unicode.__new__(cls, u'')
def __call__(self, arg):
if isinstance(arg, int):