summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2011-08-31 16:12:12 +0100
committerLars Wirzenius <liw@liw.fi>2011-08-31 16:12:12 +0100
commit95da407b5e2ada81b02fe002c913904c62d7c3da (patch)
treef1e464c38f2517636dd3c10c0746f3859b9678fd
parent74988226cae019734fc114eda2a326ec298045f6 (diff)
downloadpython-ttystatus-95da407b5e2ada81b02fe002c913904c62d7c3da.tar.gz
Implement format string parsing.
-rw-r--r--ttystatus/fmt.py51
-rw-r--r--ttystatus/fmt_tests.py44
2 files changed, 90 insertions, 5 deletions
diff --git a/ttystatus/fmt.py b/ttystatus/fmt.py
index 16b2fe0..16b69de 100644
--- a/ttystatus/fmt.py
+++ b/ttystatus/fmt.py
@@ -14,10 +14,53 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import inspect
+import re
+
import ttystatus
-widgets = [getattr(ttystatus, x)
- for x in dir(ttystatus)
- if isinstance(getattr(ttystatus, x), ttystatus.Widget) and
- getattr(ttystatus, x) != ttystatus.Widget]
+def _find_widgets():
+ names = dir(ttystatus)
+ objs = [getattr(ttystatus, x) for x in names]
+ classes = [o for o in objs if inspect.isclass(o)]
+ widgets = [c for c in classes if issubclass(c, ttystatus.Widget)]
+ subclasses = [w for w in widgets if w != ttystatus.Widget]
+ return subclasses
+
+widgets = _find_widgets()
+
+
+def parse(fmt):
+ '''Parse format string.'''
+
+ names = [x.__name__ for x in widgets]
+ namespat = '|'.join(names)
+ argspat = r'[0-9a-zA-Z,_-]*'
+ pat = r'%%(?P<class>%s)\((?P<args>%s)\)' % (namespat, argspat)
+ pat = re.compile(pat)
+
+ result = []
+ prefix = ''
+ while fmt:
+ m = pat.match(fmt)
+ if m:
+ klass = getattr(ttystatus, m.group('class'))
+ argnames = m.group('args').split(',')
+ argnames = [x for x in argnames if x]
+ if prefix:
+ result.append(ttystatus.Literal(prefix))
+ prefix = ''
+ result.append(klass(*argnames))
+ fmt = fmt[m.end():]
+ elif fmt.startswith('%%'):
+ prefix += '%'
+ fmt = fmt[2:]
+ else:
+ prefix += fmt[0]
+ fmt = fmt[1:]
+
+ if prefix:
+ result.append(ttystatus.Literal(prefix))
+ return result
+
diff --git a/ttystatus/fmt_tests.py b/ttystatus/fmt_tests.py
index 1848114..af39948 100644
--- a/ttystatus/fmt_tests.py
+++ b/ttystatus/fmt_tests.py
@@ -23,7 +23,49 @@ class FormatTests(unittest.TestCase):
def test_knows_widgets(self):
self.assertEqual(type(ttystatus.fmt.widgets), list)
+ self.assert_(len(ttystatus.fmt.widgets) > 0)
for widget in ttystatus.fmt.widgets:
- self.assert_(isinstance(widget, ttystatus.Widget))
+ self.assert_(issubclass(widget, ttystatus.Widget))
self.assertNotEqual(widget, ttystatus.Widget)
+ def test_parses_string_without_widgets(self):
+ x = ttystatus.fmt.parse('hello, world')
+ self.assertEqual(len(x), 1)
+ self.assertEqual(type(x[0]), ttystatus.Literal)
+ self.assertEqual(str(x[0]), 'hello, world')
+
+ def test_parses_escaped_pecent(self):
+ x = ttystatus.fmt.parse('%%')
+ self.assertEqual(len(x), 1)
+ self.assertEqual(type(x[0]), ttystatus.Literal)
+ self.assertEqual(str(x[0]), '%')
+
+ def test_parses_parameterless_widget(self):
+ x = ttystatus.fmt.parse('%ElapsedTime()')
+
+ self.assertEqual(len(x), 1)
+ self.assertEqual(type(x[0]), ttystatus.ElapsedTime)
+
+ def test_parses_widget_with_one_parameter(self):
+ x = ttystatus.fmt.parse('%String(name)')
+
+ self.assertEqual(len(x), 1)
+
+ self.assertEqual(type(x[0]), ttystatus.String)
+ self.assertEqual(x[0]._key, 'name')
+
+ def test_parses_some_widgets(self):
+ x = ttystatus.fmt.parse('hello, %String(name): %ElapsedTime()')
+
+ self.assertEqual(len(x), 4)
+
+ self.assertEqual(type(x[0]), ttystatus.Literal)
+ self.assertEqual(str(x[0]), 'hello, ')
+
+ self.assertEqual(type(x[1]), ttystatus.String)
+
+ self.assertEqual(type(x[2]), ttystatus.Literal)
+ self.assertEqual(str(x[2]), ': ')
+
+ self.assertEqual(type(x[3]), ttystatus.ElapsedTime)
+