GNOME Bugzilla – Bug 584558
Need print() function
Last modified: 2009-12-10 17:30:54 UTC
Seed has a print() function. It would be very useful to have the same in gjs; right now the only way I can get debug output via gjs-console(1) is to use log("foo") and run my program with GJS_DEBUG_OUTPUT=stderr.
The complete adjustment discussed earlier was something like: * log() is changed to be log4j-ish or something, taking a log level or topic * debug() or trace() output to stderr by default by invoking log() * print() and printerr() always write to stdout/stderr * all of the above are "varargs" and concatenate all their args into one string Maybe useful to get seed input on what the whole API should look like.
Created attachment 135778 [details] [review] Add print() and printerr() functions Here's a patch to add print() and printerr() function. Maybe it would be nicer to use println() but that would give up compat with Seed so not sure it's worth the effort...
Comment on attachment 135778 [details] [review] Add print() and printerr() functions It would be really nice if print() and others would accept printf-style format modifiers. Maybe not necessary for the C-function as one could maybe use sprintf js implementation around it, but IMO the global function should be printf-like for convenience.
Created attachment 135898 [details] [review] Updated patch Updated function that concatenates arguments; here's an example of how to use it #!/usr/bin/env gjs-console const Gio = imports.gi.Gio; let icon = new Gio.ThemedIcon ({name : "drive-cdrom-writer", use_default_fallbacks : true}); // this prints out the following line // // Hello world foobar 42 '. GThemedIcon drive-cdrom-writer drive-cdrom drive' 8 // print ("Hello world" + " foobar ", 42, " '", icon.to_string (), "' ", Gio.FileCopyFlags.ALL_METADATA);
(In reply to comment #3) > (From update of attachment 135778 [details] [review] [edit]) > It would be really nice if print() and others would accept printf-style format > modifiers. Maybe not necessary for the C-function as one could maybe use > sprintf js implementation around it, but IMO the global function should be > printf-like for convenience. Wouldn't you rather use GLib.print() for that? I don't know.
Also, any thoughts about newline? I think it's a bit broken that we append the newline automatically, it's typically not what you want, e.g. sometimes you want to be able to do things like this print ("foo ") if (frob.should_do_bar ()) { print ("bar"); } else { print ("baz"); } print ("\n"); although I suppose that could be done through just building a string. I don't know.
could have println() that tacks on newline and print() that does not maybe. log() I believe appends newline only if there isn't one already, which is sort of convenient for a true debug log function. I wouldn't mind just a half-page quick spec for the whole plan around printing and logging, maybe my bullet points above are good enough, and be sure everyone who cares has a chance to comment.
Hmm: print ("Hello world" + " foobar ", 42, " '", icon.to_string (), "' ", Gio.FileCopyFlags.ALL_METADATA); Doesn't delight. I think either: - You want to do somethin sophisticated like the above, and for that you really want string formatting of some type - You want to do a quick: print (x, y); Debug print, and for that, having to write: print (x, ",", y); To avoid an unparsable 12345 always makes me want to cry. So, I'd be in favor of adding spaces between arguments, along the lines of: http://docs.python.org/reference/simple_stmts.html#the-print-statement String formatting seems best to me done at the JS level and operating on strings, rather than built into print/log - sprintf() not printf(). [ Though the advantage of building formatting into log() is efficency when not logging, as always ] But there are numerous questions there: e.g. you go with {0} in the style of log4j, C#, and python 3, or do you go with %s in the style of C, Java's formatter, python 2, etc. What's the API look like? etc. A couple of comments on the patch: 1) The duplicated code between gjs_print and gjs_printerr is ugly, they could easily be written in terms of a common function, it seems. 2) + } else { + gjs_debug(GJS_DEBUG_LOG, "<cannot convert argument %d to string>", n); + g_string_free (str, TRUE); + return JS_TRUE; + } I cant' believe that the right behavior for hitting an exception is to debug and print nothing and not throw an error (especally since gjs_debug() goes to /dev/null by default now.)
FWIW, my vote's with print() and println() and space-separating the arguments. It's javascript, you can always do: print = imports.gi.GLib.print if you want something different. For true logging, you probably want the option to pass a function to the logger, so that you don't pay for formatting when you're not logging. Something like: log("Unexpected input:", function() { return obj.toString(); }) or, in JavaScript 1.8 syntax: log("Unexpected input:", function() obj.toString());
Someone has tested GLib.print ? It does appear to work.
GLib.print might work with no args, but something like this will not: GLib.print("%d %d %d %d", 1, 2, 3, 4) h
Ok, testing const GLib = imports.gi.GLib; GLib.print("test"); gjs testeprint.js JS ERROR: !!! Exception was: Error: No symbol 'print' in namespace 'GLib' JS ERROR: !!! lineNumber = '0' JS ERROR: !!! fileName = 'gjs_throw' JS ERROR: !!! stack = 'Error("No symbol 'print' in namespace 'GLib'")@:0 ("No symbol 'print' in namespace 'GLib'")@gjs_throw:0 @testeprint.js:3 ' JS ERROR: !!! message = 'No symbol 'print' in namespace 'GLib'' Besides a print function something like readline/scanf would be useful too.
Created attachment 149492 [details] [review] Bug 584558 – Need print() function Updated patch, this changes: - Reduces the duplication between print/printerr - Adds a space between the arguments - Always adds a newline For the space between the arguments discussion, yes it's the right thing to do and if you want another behavior you can easily write your own string formatting function on top and send it out. For the newline discussion. You almost always want to add a space in the end, it's most certainly the best thing to do. For other use cases, build a string and send it to print. We shouldn't let this get bike shredded by the formatting discussion, which is a separate bug. We have a sprintf javascript implementation in litl which we should probably open source for that.
Review of attachment 149492 [details] [review]: Big picture...this is OK, but I'd like to have https://bugzilla.gnome.org/show_bug.cgi?id=588828 too. ::: gjs/context.c @@ +183,3 @@ + uintN argc, +gjs_print_parse_args(JSContext *context, +static JSBool NULL sets the string up to be binary; I'd use "" here. @@ +194,3 @@ + jstr = JS_ValueToString(context, argv[n]); + if (jstr != NULL) + argv[n] = STRING_TO_JSVAL(jstr); // GC root Hmm...how does that work? Is the whole argv array guaranteed to be rooted? Now there is a hack in spidermonkey where one new object of each type (e.g. String) is automatically rooted, but here we're creating many strings. Anyways it'd feel cleaner to me if we used JS_EnterLocalRootScope then JS_LeaveLocalRootScope.
I addressed the Colin mentioned and pushed this, thanks!