[gnome-shell] Add String formatting



commit 64cd51667dc498412cbaeb53cd92cc6de7a04e23
Author: Adel Gadllah <adel gadllah gmail com>
Date:   Sun Oct 4 23:30:18 2009 +0200

    Add String formatting
    
    Add String formatting by extending the String object with a
    format method.
    
    Now we can do stuff like "Text: %s, %d".format(somevar, 5)
    
    This is required for proper translation of some strings.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=595661

 js/misc/Makefile.am  |    3 ++-
 js/misc/format.js    |   44 ++++++++++++++++++++++++++++++++++++++++++++
 js/ui/environment.js |    3 +++
 tests/Makefile.am    |    3 ++-
 tests/unit/format.js |   29 +++++++++++++++++++++++++++++
 5 files changed, 80 insertions(+), 2 deletions(-)
---
diff --git a/js/misc/Makefile.am b/js/misc/Makefile.am
index a278812..084a45c 100644
--- a/js/misc/Makefile.am
+++ b/js/misc/Makefile.am
@@ -1,4 +1,5 @@
 jsmiscdir = $(pkgdatadir)/js/misc
 
 dist_jsmisc_DATA =		\
-	docInfo.js
+	docInfo.js		\
+	format.js
diff --git a/js/misc/format.js b/js/misc/format.js
new file mode 100644
index 0000000..e6848b5
--- /dev/null
+++ b/js/misc/format.js
@@ -0,0 +1,44 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+/*
+ * This function is intended to extend the String object and provide
+ * an String.format API for string formatting.
+ * It has to be set up using String.prototype.format = Format.format;
+ * Usage:
+ * "somestring %s %d".format('hello', 5);
+ * It supports %s, %d and %f, for %f it also support precisions like
+ * "%.2f".format(1.526)
+ */
+
+function format() {
+    let str = this;
+    let i = 0;
+    let args = arguments;
+
+    return str.replace(/%(?:\.([0-9]+))?(.)/g, function (str, precisionGroup, genericGroup) {
+
+                    if (precisionGroup != '' && genericGroup != 'f')
+                        throw new Error("Precision can only be specified for 'f'");
+
+                    switch (genericGroup) {
+                        case '%':
+                            return '%';
+                            break;
+                        case 's':
+                            return args[i++].toString();
+                            break;
+                        case 'd':
+                            return parseInt(args[i++]);
+                            break;
+                        case 'f':
+                            if (precisionGroup == '')
+                                return parseFloat(args[i++]);
+                            else
+                                return parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
+                            break;
+                        default:
+                            throw new Error('Unsupported conversion character %' + genericGroup);
+                    }
+
+                });
+}
diff --git a/js/ui/environment.js b/js/ui/environment.js
index 718b1f1..6d0bb48 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -4,6 +4,8 @@ const St = imports.gi.St;
 
 const Tweener = imports.ui.tweener;
 
+const Format = imports.misc.format;
+
 // "monkey patch" in some varargs ClutterContainer methods; we need
 // to do this per-container class since there is no representation
 // of interfaces in Javascript
@@ -30,4 +32,5 @@ _patchContainerClass(St.Table);
 
 function init() {
     Tweener.init();
+    String.prototype.format = Format.format;
 }
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0803394..ebe65fc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -10,7 +10,8 @@ TEST_JS =					\
 	interactive/scrolling.js		\
 	interactive/table.js			\
 	testcommon/border-image.png		\
-	testcommon/ui.js
+	testcommon/ui.js                        \
+	unit/format.js
 EXTRA_DIST += $(TEST_JS)
 
 TEST_MISC =					\
diff --git a/tests/unit/format.js b/tests/unit/format.js
new file mode 100644
index 0000000..9e618c2
--- /dev/null
+++ b/tests/unit/format.js
@@ -0,0 +1,29 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+/*
+ * Test cases for the Format module
+ */
+
+const JsUnit = imports.jsUnit;
+const assertEquals = JsUnit.assertEquals;
+const assertRaises = JsUnit.assertRaises;
+
+// We can't depend on environment.js to set up the String.prototype.format,
+// because the tests  run in one JS context, and the imports run in the GJS
+// "load context" which has its own copy of the String class
+const Format = imports.misc.format;
+String.prototype.format = Format.format;
+
+// Test common usage and %% handling
+assertEquals("foo", "%s".format('foo'));
+assertEquals("%s", "%%s".format('foo'));
+assertEquals("%%s", "%%%%s".format('foo'));
+assertEquals("foo 5", "%s %d".format('foo', 5));
+assertEquals("8", "%d".format(8));
+assertEquals("2.58 6.96", "%f %.2f".format(2.58, 6.958));
+
+// Precision is only allowed for %f
+assertRaises(function() { "%.2d".format(5.21) });
+
+// Wrong conversion character ' '
+assertRaises( function() { "%s is 50% done".format('foo') });



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]