[gjs] modules: Import a new "format" module



commit 2ef9fe8a4c31b6c66fb96a56b74394217ac4cb43
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri May 4 13:54:55 2012 -0400

    modules: Import a new "format" module
    
    Imported from gnome-shell, this provides printf-like formatting to
    JavaScript.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=675479

 Makefile-modules.am |   17 +++++++++++-
 modules/format.c    |   68 +++++++++++++++++++++++++++++++++++++++++++++++++
 modules/format.h    |   39 ++++++++++++++++++++++++++++
 modules/format.js   |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 192 insertions(+), 2 deletions(-)
---
diff --git a/Makefile-modules.am b/Makefile-modules.am
index ab8aa34..47e7a51 100644
--- a/Makefile-modules.am
+++ b/Makefile-modules.am
@@ -15,9 +15,10 @@ dist_gjsjs_DATA +=		\
 	modules/signals.js	\
 	modules/cairo.js	\
 	modules/dbus.js		\
-	modules/promise.js
+	modules/promise.js	\
+	modules/format.js
 
-gjsnative_LTLIBRARIES += console.la debugger.la langNative.la mainloop.la gettextNative.la dbusNative.la cairoNative.la system.la
+gjsnative_LTLIBRARIES += console.la debugger.la langNative.la mainloop.la gettextNative.la dbusNative.la cairoNative.la system.la formatNative.la
 
 JS_NATIVE_MODULE_CFLAGS =	\
         $(AM_CFLAGS)		\
@@ -146,3 +147,15 @@ dbusNative_la_LIBADD = \
 	$(GJS_DBUS_LIBS)
 dbusNative_la_LDFLAGS = 				\
 	$(JS_NATIVE_MODULE_LDFLAGS)
+
+formatNative_la_CFLAGS = \
+	$(JS_NATIVE_MODULE_CFLAGS)
+formatNative_la_LIBADD = \
+	libgjs.la \
+	$(JS_NATIVE_MODULE_LIBADD)
+formatNative_la_LDFLAGS = \
+	$(JS_NATIVE_MODULE_LDFLAGS)
+
+formatNative_la_SOURCES = \
+	modules/format.h \
+	modules/format.c
diff --git a/modules/format.c b/modules/format.c
new file mode 100644
index 0000000..457e349
--- /dev/null
+++ b/modules/format.c
@@ -0,0 +1,68 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2012  Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "format.h"
+#include <gjs/gjs-module.h>
+#include <gjs/compat.h>
+
+#include <glib.h>
+#include <jsapi.h>
+
+static JSBool
+gjs_format_int_alternative_output(JSContext *context,
+                                  uintN      argc,
+                                  jsval     *vp)
+{
+    jsval *argv = JS_ARGV(cx, vp);
+    char *str;
+    jsval rval;
+    int intval;
+    JSBool ret;
+
+    if (!gjs_parse_args(context, "format_int_alternative_output", "i", argc, argv,
+                        "intval", &intval))
+        return JS_FALSE;
+
+    str = g_strdup_printf("%Id", intval);
+    ret = gjs_string_from_utf8(context, str, -1, &rval);
+    if (ret)
+        JS_SET_RVAL(context, vp, rval);
+    g_free (str);
+
+    return ret;
+}
+
+JSBool
+gjs_define_format_stuff(JSContext      *context,
+                        JSObject      *module_obj)
+{
+    if (!JS_DefineFunction(context, module_obj,
+                           "format_int_alternative_output",
+                           (JSNative)gjs_format_int_alternative_output,
+                           1, GJS_MODULE_PROP_FLAGS))
+        return JS_FALSE;
+
+    return JS_TRUE;
+}
+
+GJS_REGISTER_NATIVE_MODULE("formatNative", gjs_define_format_stuff)
diff --git a/modules/format.h b/modules/format.h
new file mode 100644
index 0000000..d51419f
--- /dev/null
+++ b/modules/format.h
@@ -0,0 +1,39 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2012  Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __GJS_LANG_H__
+#define __GJS_LANG_H__
+
+#include <config.h>
+#include <glib.h>
+
+#include <jsapi.h>
+
+G_BEGIN_DECLS
+
+JSBool        gjs_define_format_stuff   (JSContext      *context,
+                                         JSObject       *in_object);
+
+G_END_DECLS
+
+#endif  /* __GJS_LANG_H__ */
diff --git a/modules/format.js b/modules/format.js
new file mode 100644
index 0000000..b903a06
--- /dev/null
+++ b/modules/format.js
@@ -0,0 +1,70 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const FormatNative = imports.formatNative;
+
+function vprintf(str, args) {
+    let i = 0;
+    return str.replace(/%(I+)?([0-9]+)?(?:\.([0-9]+))?(.)/g, function (str, flagsGroup, widthGroup, precisionGroup, genericGroup) {
+        if (precisionGroup != '' && genericGroup != 'f')
+            throw new Error("Precision can only be specified for 'f'");
+
+        let hasAlternativeIntFlag = (flagsGroup.indexOf('I') != -1);
+        if (hasAlternativeIntFlag && genericGroup != 'd')
+            throw new Error("Alternative output digits can only be specfied for 'd'");
+
+        let fillChar = (widthGroup[0] == '0') ? '0' : ' ';
+        let width = parseInt(widthGroup, 10) || 0;
+
+        function fillWidth(s, c, w) {
+            let fill = '';
+            for (let i = 0; i < w; i++)
+                fill += c;
+            return fill.substr(s.length) + s;
+        }
+
+        let s = '';
+        switch (genericGroup) {
+        case '%':
+            return '%';
+            break;
+        case 's':
+            s = args[i++].toString();
+            break;
+        case 'd':
+            let intV = parseInt(args[i++]);
+            if (hasAlternativeIntFlag)
+                s = FormatNative.format_int_alternative_output(intV);
+            else
+                s = intV.toString();
+            break;
+        case 'x':
+            s = parseInt(args[i++]).toString(16);
+            break;
+        case 'f':
+            if (precisionGroup == '')
+                s = parseFloat(args[i++]).toString();
+            else
+                s = parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
+            break;
+        default:
+            throw new Error('Unsupported conversion character %' + genericGroup);
+        }
+        return fillWidth(s, fillChar, width);
+    });
+}
+
+
+/*
+ * 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, %x and %f, for %f it also support precisions like
+ * "%.2f".format(1.526). All specifiers can be prefixed with a minimum
+ * field width, e.g. "%5s".format("foo"). Unless the width is prefixed
+ * with '0', the formatted string will be padded with spaces.
+ */
+function format() {
+    return vprintf(this, arguments);
+}



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