L'Isola di Niente
L'Isola di Niente » JavaScript Tips » Gjs, jjs, JXA, Node.js

Gjs, jjs, JXA, Node.js

# 最終更新日 2017.08.18

スタンドアロン(単独で利用できる)の JavaScript 実行環境での基本機能の覚書
Gjs (GNOME) SpiderMonkey
jjs (JVM) Nashorn
JXA (macOS) JavaScriptCore
Node.js (多分 macOS ユーザーしか使っていない) V8

※ 未対応の jjs を除いて ES6 を使っています
※ jjs, Node.js はサードパーティなので env に渡しています。
※ Windows での動作は考慮するだけ無駄なので無視しています

標準入出力
echo ほげ | jjs test.js
のようなパイプ入力も考慮しました
/**
 * Gjs
 */
#!/usr/bin/gjs

const GLib = imports.gi.GLib;
 
// stdin=0 stdout=1 
let channel = GLib.IOChannel.unix_new(0);
 
if (channel.get_flags() == GLib.IOFlags.IS_READABLE) {
    let [status, str_return] = channel.read_to_end();
    // toString が必要、\n を取り除く
    let line = str_return.toString().trim();
    print(`${line} がパイプから渡されました`);
} else {
    channel.write_chars("何か入力して Enter : ", -1);
    let [status, str_return] = channel.read_line();
    let line = str_return.toString().trim();
    print(`${line} が入力されました`);
}

/* Gio での面倒な方法
const Gio  = imports.gi.Gio;

let uostream = new Gio.UnixOutputStream({fd: 0});
let dostream = new Gio.DataOutputStream({base_stream: uostream});
dostream.put_string("何か入力して Enter :", null);

let uistream = new Gio.UnixInputStream({fd: 1});
let distream = new Gio.DataInputStream({base_stream: uistream});
let [txt, len] = distream.read_line_utf8(null);
print(txt + " が入力されました");
*/

/**
 * jjs
 */
#!/usr/bin/env jjs

var System  = java.lang.System;
var BufferedReader = java.io.BufferedReader;
var InputStreamReader = java.io.InputStreamReader;

var console = System.console();
if (console == null) {
    var r = new BufferedReader(new InputStreamReader(System.in));
    var line = r.readLine();
    System.out.println(line + " がパイプから渡されました");
} else {
    var line = console.readLine("何か入力して Enter : ");
    System.out.println(line + " が入力されました");
}

/* こんな手段もある、-scripting option 必須
#!/usr/bin/env jjs -scripting
  
var jjs_str = readLine("何か入力して Enter :");
print(jjs_str + " が入力されました");
*/

/**
 * JXA
 */
#!/usr/bin/osascript

ObjC.import("Cocoa");
ObjC.import("unistd");

let text = "がパイプから渡されました";
if ($.isatty(0)) {
    let fho = $.NSFileHandle.fileHandleWithStandardOutput;
    let prp = $("何か入力して Enter :").dataUsingEncoding($.NSUTF8StringEncoding)
    fho.writeData(prp);
    text = "が入力されました";
}

let fhi = $.NSFileHandle.fileHandleWithStandardInput;
let data = fhi.availableData;
let res = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding).js.trim();
console.log(`${res} ${text}`);

/**
 * Node.js
 */
#!/usr/bin/env node

const ReadLine = require('readline');
const Tty = require('tty');

let readline = ReadLine.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: false
});

if (Tty.isatty(0)) {
    readline.question("何か入力して Enter : ", function(line) {
        console.log(`${line} が入力されました`);
        readline.close();
    });
} else {
    readline.question("", function(line) {
        console.log(`${line} がパイプから渡されました`);
        readline.close();
    });
}

ファイルの読み書き
Gjs は Gio を使ったほうがいいけどそれは別の機会に
jjs は上記で JAVA 同様と解るだろうから以下簡単版のみに
/**
 * Gjs
 */
#!/usr/bin/gjs

const GLib  = imports.gi.GLib;

const TEXT = "書き込み及び読み込みができない場合は例外が発生します";
const FILE = "gjs_write.txt";

let result = GLib.file_set_contents(FILE, TEXT); // Write
if (result) {
    print("Write Success");
}
let [result, contents] = GLib.file_get_contents(FILE); // Read
if (result) {
    print(contents.toString());
}

/**
 * jjs (readFully は -scripting option 必須)
 */
#!/usr/bin/env jjs -scripting
 
var FileWriter  = java.io.FileWriter;
 
var FILENAME = "jjs_write.txt";
 
var fw = new FileWriter(FILENAME); // Write
fw.write("jjs で書き込み\nもちろん改行も");
fw.close();
 
var s = readFully(FILENAME); // Read
print(s);

/**
 * JXA
 */
#!/usr/bin/osascript

ObjC.import("Cocoa");

let nil = $();
let newFile = $("新規テキストファイル.txt");
let text = $("UTF-8 で書き出します\n\tエスケープシーケンスも使えます");

// Write
let res = text.writeToFileAtomicallyEncodingError(newFile, true, $.NSUTF8StringEncoding, nil);
if (res) {
    console.log("Write Success!");
}

// Read
let s = $.NSString.alloc.initWithContentsOfFileEncodingError(newFile, $.NSUTF8StringEncoding, nil);
console.log(s.js);

/**
 * Node.js
 */
#!/usr/bin/env node

let fs = require('fs');
let text = "日本語を書き込むよ\n改行もしてみるよ";

fs.writeFile("node_write.txt", text, function (err) {
    if (err != null) console.log(err);
});

fs.readFile("node_write.txt", "utf8", function(err, content) {
    if (err != null)
        console.log(err);
    else
        console.log(content.trim());
});

起動パラメータ
Gjs は UTF-8 のまま渡ってくるので注意、toString では変換できない
Node.js は Python と同様なパラメータになる、他は全部パラメータのみの配列
/**
 * Gjs (UNICODE 化しないとバケる)
 */
#!/usr/bin/gjs

let argv = ARGV;

if (argv.length == 0) {
    print("No argv");
} else {
    argv.forEach(function(element) {
        print(decodeURIComponent(escape(element)));
    });
}

/**
 * jjs
 */
#!/usr/bin/env jjs

var argv = $ARG;

if (argv.length == 0) {
    print("No argv");
} else {
    argv.forEach(function(element) {
        print(element);
    });
}

/**
 * JXA
 */
#!/usr/bin/osascript

function run(argv) {
    if (argv.length == 0) {
        console.log("No argv");
    } else {
        argv.forEach(function(element) {
            console.log(element);
        });
    }
}

/**
 * Node.js (実行ファイル名, スクリプトファイル名, argv[0], argv[1], ...)
 */
#!/usr/bin/env node

if (process.argv.length == 0) {
    console.log("No argv");
} else {
    process.argv.forEach(function(element) {
        console.log(element);
    });
}

環境変数
$HOME を表示する例
/**
 * Gjs
 */
#!/usr/bin/gjs

const GLib = imports.gi.GLib;
print(GLib.getenv("HOME"));

/**
 * jjs
 */
#!/usr/bin/env jjs

print(java.lang.System.getenv("HOME"));

/**
 * JXA
 */
#!/usr/bin/osascript

ObjC.import("stdlib");
console.log($.getenv("HOME"));

/**
 * Node.js
 */
#!/usr/bin/env node

console.log(process.env.HOME);

シェルコマンドの実行
ls -l の結果を表示する例
/**
 * Gjs
 */
#!/usr/bin/gjs

const GLib = imports.gi.GLib;

let output = GLib.spawn_command_line_sync("ls -l")[1];
print(output);

/**
 * jjs($OUT に標準出力が入る)
 */
#!/usr/bin/env jjs

$EXEC("ls -l");
print($OUT);

/**
 * JXA
 */
#!/usr/bin/osascript

let app = Application.currentApplication();
app.includeStandardAdditions = true;
let res = app.doShellScript("ls -l");
console.log(res);

/**
 * Node.js
 */
#!/usr/bin/env node

const exec = require("child_process").exec;
exec("ls -l", function(err, stdout, stderr) {
    console.log(stdout);
});
Copyright(C) sasakima-nao All rights reserved 2002 --- 2017.