Gnome shell extensions: stdout from GLib.IOChannel - javascript

So I'm making a Gnome Shell extension. And I want to be able to run some command. (The command is actually "synclient -m 100", but that is off topic)
So, what I have done so far is
s=GLib.spawn_async_with_pipes(null, ["synclient","-m","100"], null, GLib.SpawnFlags.SEARCH_PATH,null)
c=GLib.IOChannel.unix_new(s[3])
The first line spawns my process. It is definitely working.
s[3] is the file descriptor for the stout of the process. (It has something to do with pipes. Not really sure about the whole pipe thing.)
Anyway, my problem is that I can't seem to read anything from the output of synclient.
This is what I'm using for reference, but it seems that not all of the functions work. For example, I want to use add_watch, but that apperently doesn't work with gnome extensions.
I've tried using a bunch or read functions and specifically read_line_string, but they all have problems. For read_line_string it seems like it should all work except I can't figure out how to create a StringBuilder object to pass as an argument.
So, does anyone know how to get the output of a command?
Edit: also I'm kind of confused about which language the extensions use. I think it's javascript, but the docs I'm using seem to make me think Vala, whatever that is (I'm guessing a variation of java?).
Edit 2:
So, what I've got now is
let [res, pid, in_fd, out_fd, err_fd] =
GLib.spawn_async_with_pipes(
null, ["synclient","-m","100"], null, GLib.SpawnFlags.SEARCH_PATH, null);
out_reader = new Gio.DataInputStream({ base_stream: new Gio.UnixInputStream({fd: out_fd}) });
And to read a line:
let [out, size] = out_reader.read_line(null);
This gives me the output of the command, but it still doesn't give me any way to get some callback whenever the DataInputStream is changed. I need to be able to do something whenever there is a new line in the stream.

Gnome Shell extensions are usually written in JavaScript. They use JavaScript bindings to libraries like GLib that are written in C. There are also Vala bindings to those libraries, and that is the documentation you are looking at. Here is the documentation for the JS bindings, unofficial as yet.
StringBuilder is a Vala language feature that corresponds to GLib.String in JS.
How do you know add_watch() doesn't work? What do you expect and what does it do instead?

Related

Writing to a .json file with node.js filesystem

As seen here: https://anidiots.guide/coding-guides/storing-data-in-a-json-file.html
It shows you how to create a point system in discord.js. But what caught my eye is how they used let points = JSON.parse(fs.readFileSync("./points.json", "utf8"));
to read the file. So i am trying to learn how to make a database where i get the points plus money that can be redeemed daily and shared. kinda like a bank. but i don't know how to do that. If anyone could help me with a hastebin link or anywhere i can learn in depth how to use the JSON.parse(fs.readFileSync("./points.json", "utf8")); thing.
and if you want to see my bot in action don't hesitate to use https://discord.me/knut
The line you're asking about is made of two call to the functions JSON.parse and fs.readFileSync.
JSON.parse. This function receives a bunch of text and transform it (parse it) into a javascript object. It can be very useful when you want to, for example, build something dynamically based on the content of a file. Maybe w3school is a good place to start looking for info about it.
Example
var string = "{id: 4, name:'Volley'}"
var parseObject = JSON.parse(string)
console.log(parseObject.id); //4
console.log(parseObject.name); //Volley
fs.readFileSync. As you probably know, most of the functions in javascript and node.js are asynchronous, that is, instead of calling and get the returned value, you have to define a callback within which you would use the value you want. fs.readFileSync is just the synchronous version of fs.readFile(callback), which returns the content of the read file. Here you have the docs about that function.
These functions are actually simple to use, you should struggle in finding some examples or trying them by yourself.
If you want to imitate what the tutorial said, then you would need to define another file, with the money of each point, or edit the first file if you can, so you could an object like
var point_and_money = {
points : [...],
money : [....]
}
or two objects with the separate information
var points = JSON.parse(fs.readFileSync("./points.json", "utf8"));
var money = JSON.parse(fs.readFileSync("./money.json", "utf8"));
Hope I gave you a hint about what you asked
not really sure what you are trying to achieve?
JSON.parse(fs.readFileSync("./points.json", "utf8"));
This line reads a json file and parse it to a Javascript-Method. Nothing less and nothing more. this can also be done in Nodejs via
var points = require('./points.json');
You mentioned something like how to do a database? Basically I am not sure if you want to develop a database or better use an existing one. Look for MongoDB, SQLLite,IndexedDB, etc. There a tons of database for almost every use case.
Remember that your line of code reads synchronous in a blocking way when the file gets large.
And when multiple users would access the file at the same time you need to handle this somehow. So definitely would suggest to look for some existing database solution and have more time to focus on your business logic.
I hope I understand your question correct and my answer helps.
Maybe this one is also a good question to start: Lightweight Javascript DB for use in Node.js

Gnome Extensions - Run shell command

I am writing a simple extension to open browser by clicking the extension button. I would like to know if there is a function which can execute passed shell command as argument. Also, it'd be really helpful if anyone can suggest a good simple reference for extension development.
From https://github.com/GNOME/gnome-shell/blob/master/js/misc/util.js:
// Runs #command_line in the background, handling any errors that
// occur when trying to parse or start the program.
function spawnCommandLine(command_line) {
try {
let [success, argv] = GLib.shell_parse_argv(command_line);
trySpawn(argv);
} catch (err) {
_handleSpawnError(command_line, err);
}
}
There are a few variations on that method in there. Save yourself mountains of headaches and just bookmark the GitHub repository.
Some quick links:
popupMenu.js: working with popup menus
panel.js: a good read for implementing "tray" icons
modalDialog.js: some UI elements were made to be reused, runDialog.js uses this for example
mpris.js: there are also good examples of using frameworks like DBus in gjs
I can't stress enough how much you'll get out of reading the gnome-shell source. Unfortunately, it's compiled into a resource file now so we don't have local copies to stumble upon.
UPDATE (2021)
If you're reading this, please instead see the documentation available on gjs.guide. Specifically the documentation on Spawning Subprocesses, which covers why this is a bad idea in extensions and how to do it slightly less bad.
If you're not interested in the result - i.e. when you want to open a browser window - you can just use GLib.spawn_command_line_async like so:
const GLib = imports.gi.GLib;
...
(this._menuEntries[i]).connect('activate', () => {
GLib.spawn_command_line_async('firefox http://example.com?p='+ my_params[i]);
});
If you need a synchronous result, read https://gjs.guide/guides/gio/subprocesses.html

How to develop a javascript library from an already existing npm module (codius)

never done this before.
I'm using https://github.com/codius/codius-host. CodiuĀ§ development has been abandoned, but I want to salvage part of it to use for my own project. I really need to be able to run codius commands from browser, so I need to develop a library or what you call it.
var codius = require('codius')
codius.upload({host: http://contract.host}
codius-host comes packed with command-line integration,
$ CODIUS_HOST=https://codius.host codius upload
How do I make a .js script do what the command-line command does ?
also posted on https://stackoverflow.com/questions/31126511/if-i-have-a-npm-tool-that-uses-comman-line-commands-how-can-i-create-a-javascri
hard time asking this questions since don't know where to start. help.
Assuming that you have access to the codius-host source code you should find the piece of code which manages the command line arguments. I am sure that they do handle the command and the command line arguments from an entry module/function and than later delegate the real job to a different module/function. What you need to do is to provide correct parameters to the functions which the function/module that handles command line argument calls with command line parameters.
In addition to that there are some nodejs libraries that might imitate a command line call from the program itself. One of those I know is shelljs:
https://www.npmjs.com/package/shelljs
You might want to check this out as well. With this one without bothering with the source code you might be able to imitate command line behaviour.

Emscripten exported function oddities in Visual Studio

I'm just starting to play around with Emscripten, but I've run into something odd, when trying to export functions, for use in JavaScript. The test project has to do with libsquish, but it's not really relevant for the question, other than the header/code filenames.
So - anyway, simple test.
c/c++
//squish.h
extern "C" int main();
int main();
extern "C" int gsr();
int gsr();
//squish.cpp
int main()
{
return 99;
}
int gsr()
{
//return squish::GetStorageRequirements(width,height,flags);
return 8675309;
}
Additional Options/Command Line
-s EXPORTED_FUNCTIONS="['_gsr','_main']"
Javascript
main=Module.cwrap('main','number',null);
console.log(main());
GetStorageRequirements = Module.cwrap('gsr', 'number',null);
console.log(GetStorageRequirements());
Javascript Console (Chrome)
99
Assertion failed: Cannot call unknown function gsr (perhaps LLVM optimizations or closure removed it?)
Assertion failed: Cannot call unknown function gsr (perhaps LLVM optimizations or closure removed it?)
And on top of everything else, optimization is disabled (O0).
So, what's the deal here? Same return types, same number of parameters, defined in exactly the same way, with the only difference being the name of the function. Yet one works, and the other is "unknown".
The only possible, logical cause is that it's automatically exporting main, and ignoring the EXPORTED_FUNCTIONS all together. But if that's the case, I have no idea why.
Thanks to Charles Ofria's work in narrowing down the issue, the only real oddity ended up being with the Emscripten Visual Studio plugin. I was on the right track, when I thought that it might just be automatically exporting main - which was correct. The reason it wasn't exporting the other function, was because I put it in the Additional Options, for the Clang/C++ section, instead of the Emcc Linker.
The trouble was, and this is where the "oddity" comes in, the Emcc Linker section doesn't appear when you choose Console Application (.js) as the Configuration Type. So, after changing the Target Extension to .html and the Configuration Type to Browser Application (.html) - the Linker section re-appeared, and I was able to put the EXPORTED_FUNCTIONS option, in the correct location.
After building, and copying the output over, both functions were defined, and returned the proper values in the Javascript console.
Probably the issue here is C++ name mangling. That's a C++ filename, so "gsr" turns into something like "_Z3gsr". You can avoid that by making it a C file, or using extern "C" around that method.
For more see http://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process

How to run jslint on the client?

For testing purposes, obviously not for production. What is the best way to do this?
Googling I found this tutorial, and of course the project on github.
For starters which files do I need to run:
// removed
and is there an API reference. I see there is a large comment block in jslint.js that seems to server this purpose but was wondering if there is something easier to read.
Because the client has no file access, I was planning on ajaxing the code in to get its contents.
Please never the mind, on why I want to do this on the client.
If you include the JSLint script you will have access to a single global variable, JSLINT. You can invoke it with a string and an optional map of options:
var valid = JSLINT(code, options);
The result will be true or false, depending on whether the code passed the check based on the provided options.
After this call you can inspect the JSLINT.errors property for an array of warnings, if any.
This is precisely what I have done to build JSLint integration into the editor in the articles on http://jslinterrors.com.
Have you looked at http://jshint.com/ ? Source is available here: https://github.com/jshint/jshint/
The browser bundle is available here: http://jshint.com/get/jshint-2.1.10.js and the docs describe how to call it (http://jshint.com/docs/)

Categories

Resources