Programming」カテゴリーアーカイブ

Gjs setInterval

先日 Gjs で TextDecoder が使えると書きましたが。

for (let s in this) print(s);

this

グローバル関数だったんですね、無理やりな実装だなって。
てか setTimeout や setInterval も追加されているじゃないの。
console.log も使えるようになったし、Web に合わせてきたのね。
Web や Node.js と同じなのかな、チト試してみよう。

#!/usr/bin/gjs -m

import GLib from 'gi://GLib';

const mainloop = new GLib.MainLoop(null, false);

let count = 1;
let id = setInterval(()=> {
    if (count == 5) {
        clearInterval(id);
        mainloop.quit();
    }
    console.log(count);
    count++;
}, 1000);

print('__do__');

mainloop.run();

print('__done__');

log

基本 Web と同じですけど、やっぱりメインループが必要ですね。
Web の場合はブラウザがメインループを回しているから不要なだけで。
Node.js が不要だからややこしい、繰り返し処理にはループが必要。
GtkApplication から使う等の場合は当然別途のループはいりません。

console.log は print と同じでいいのに、スタンドアロンでこの表示いる?
とにかく Web 標準と同様に使えます、ということで。

というか、Gjs って三年前とは全然変わってしまったなと。
tips ページはそろそろ丸ごと書き換えしなきゃ、面倒くさいなぁ。。。。。

Javascript TextDecoder

知らぬ間に Gjs の挙動が変わっていた。
普段は Python ばかりなのでいつからかは解らない。

#!/usr/bin/gjs -m

import GLib from 'gi://GLib';

/**
 * res is Uint8Array
 */
let res =  GLib.spawn_command_line_sync('pwd')[1];
print(res.toString()); //=> Warning

warn

よく見ると実行はされているので警告されているだけですね。
今まで普通に動いた、なんなら toString さえ暗黙実行されていた。

Google translate 等を使えば解るけど TextDecoder 使えってさ。
互換性のために残しているけどはよ移行しろということらしい。
警告メッセージも親切になったもんだ、ということで。

TextDecoder – Web API | MDN

主要ブラウザは全部が既に実装済みなんですね。
Web API なんだが Gjs や JXA でも使えるのだろうか?

#!/usr/bin/gjs -m

import GLib from 'gi://GLib';

let res =  GLib.spawn_command_line_sync('pwd')[1];
// TextDecoder
let dec = new TextDecoder();
let text = dec.decode(res);
print(text.trim());

動くじゃん、Spider Monkey 自体に実装されているのだろうか。
import 何も無しで使えるのって筆者は正直気持ち悪いんですけど。
string に変換されたので trim メソッドで改行を削除しています。
ちなみに。

#!/usr/bin/gjs

/**
 * old gjs
 */

const GLib = imports.gi.GLib;
const ByteArray = imports.byteArray;

let res =  GLib.spawn_command_line_sync('pwd')[1];
let text = ByteArray.toString(res);
print(text.trim());

byteArray モジュールを使う以前の正規な手段もまだ使えます。
というか、imports でのインポートもまだ普通に使えるんだよね。
byteArray も imports も Gjs 独自実装だから排除したかったのだろうけど。
Gjs で新しい手段の import では -m オプションを忘れずに。

jxa

JXA では TextDecoder 等は使えない、やはり実装はバラバラ。
というか JXA の UTF8String って正体は string じゃないか。
普通に string のメソッドが使えるし、まあ Cocoa がそうなのね。
Uint8Array は JXA ではほぼ扱われることが無いということだろう。
Node.js やその他は知らないしどうでもいい。

非推奨の機能、廃止された機能 – JavaScript | MDN

てか escape や unescape は非推奨になっていたのか。
Tips ページをいくつか書き換えなきゃなぁ面倒だなぁ。
え?今日は公園には行きましたよ、察して。

Bookmarklet

ブログに他サイトのリンクを貼る用のブックマークレット。
長年どこかのサイトで見つけた以下の奴をずっと使っていた。

javascript:var url=location.href;var title=document.title;var link ='<a href="'+url+'" target="_blank">'+title+'</a>';var x = prompt('',link);

これ骨董品の ES5 ではないですか。
2023 年な現在でも問題なく動くけれど、流石に書き換えたいぞ。

それと、この手段では一度プロンプトを出すと二度目が出せないのがたまに困る。
今までページの読み直しで対処していたけどせっかくなのでソレもなんとかしたい。
ということで色々探してみる。

【必見】ブックマークレットの使い方・作り方と便利なおすすめ13選を解説 – WEBCAMP MEDIA

そうか、即時関数にしてしまえばいいんだ!
ということでこう書き換えてみました。

javascript:(()=> {prompt('',`<a href="${location.href}" target="_blank">${document.title}</a>`);})();

テンプレートリテラルなら普通に一行で終わるんだよね。
同一ページで何度でも出せるようになったし、狙いどおり。
まあ、使い勝手は何も変わらないんですけど。

ところで、上記リンク先なように replace で URL を書き換えるのって使えそう。
localhost で編集した自サイトをアップロードしてお知らせをブログでって時。
今まで手書きで URL を書き換えしていたけれど、たまに忘れて再編集とかやったけど。

javascript:(()=> {prompt('',`<a href="${location.href.replace('http://localhost', 'https://palepoli.skr.jp')}">${document.title}</a>`);})();

そんなことまで自動化できるじゃん。
プログラミングとは定形作業の自動化が主体ですからね。

JavaScript Object for-in

つい最近知ったのですが。
JavaScript のオブジェクトで for-in は順序固定になっていた。

#!/usr/bin/gjs

let text = 'あいうえおかきくけこ';
let ls = {};

for (let s of text) ls[s] = s+s+s;

for (let key in ls) print(`Key=${key} Value=${ls[key]}`);

gjs

マジだ、ES2020 かららしい。

これができないのが主な理由で ES6(ES2015) で Map が追加された。
Map なんて誰も使わなかったということなのだろうか。

JavaScript その他 – Paepoi
書き換えしなきゃなぁ、どんどん情報が古くなる。

そういえば Python の連想配列も 3.7 から順序固定になっていたんだっけ。
collections.OrderedDict は存在すら知らない人も多いし。

#!/usr/bin/env python3

text = 'あいうえおかきくけこ'
ls = {}

for s in text: ls[s] = s+s+s

for key in ls: print(f'Key={key} Value={ls[key]}')

まったく同じですね、流行なのかな。
まてよ、もしかして GLib なんかも。

#include <glib.h>
#include <glib/gprintf.h>

void
printfunc(gpointer key, gpointer value, gpointer user_data) {
    g_printf("key=%s value=%s\n", key, value);
}

int
main (int argc, char *argv[]) {

    GHashTable *table;

    table = g_hash_table_new(g_str_hash, g_str_equal);
    g_hash_table_insert(table, "あ", "あああ");
    g_hash_table_insert(table, "い", "いいい");
    g_hash_table_insert(table, "う", "ううう");
    g_hash_table_insert(table, "え", "えええ");
    g_hash_table_insert(table, "お", "おおお");
    g_hash_table_insert(table, "こ", "こここ");
    g_hash_table_insert(table, "け", "けけけ");
    g_hash_table_insert(table, "く", "くくく");
    g_hash_table_insert(table, "き", "ききき");
    g_hash_table_insert(table, "か", "かかか");
    //
    g_hash_table_foreach(table, printfunc, NULL);
    return 0;
}

glib

やっぱり駄目でした、普通はこうなるし。
C を久々に書いてみたけどメンドクセー!

JavaScript filter

最近 JavaScript をまったくやっていないことに気がついた。
ES2023 とかどうなっているんだろう、全然知らないので検索。

JavaScriptのES2023・ES2022の新機能まとめ – ICS MEDIA

jxa

JXA てか JavaScriptCore は ES2023 対応だ、まあ Safari が対応済ですし。
Gjs は駄目だった、おいおい Spider Monkey さん。
ECMA Script を定義しているのって Mozilla さんなのに。

しかし配列の非破壊操作か、Tips を書くときに短くできるメリットはあるけど。
いや大規模な Web アプリとかなら必要になるのかもな。

配列を征する者はJSを制す。JavaScriptのスマートな配列操作テクニック – ICS MEDIA

filter は便利そうですね。
というか Python の内包表記みたいに使えるんでないの。

#!/usr/bin/env python3

ls = ['aa.js', 'bb.py', 'cc.js', 'dd.png', 'ee.js', 'ff.json']

# *.js を抜き出す
jss = [s for s in ls if s.endswith('.js')]
print(jss)

python

#!/usr/bin/gjs

let ls = ['aa.js', 'bb.py', 'cc.js', 'dd.png', 'ee.js', 'ff.json'];

// *.js を抜き出す
let jss = ls.filter(s => s.endsWith('.js'))
console.log(jss)

JavaScript

なんだ便利じゃん、今度からコレ使おう。
あと関係ないかもだけど。

log

Gjs でも console.log が使えるようになっていた、知らなかった!
以前から使えた log とは少し出力が違うのね、いや基本 print を使うけど。