Ubuntu…

第418回 Ubuntu GNOME 16.04 LTSの変更点:Ubuntu Weekly Recipe|gihyo.jp … 技術評論社

何コレ、標準 Ubuntu って Gedit 3.18 にメニューバーを付けたの?
プラグインはどうすんのよ、メニューバーが無い前提で作っているのに。

筆者は公開プラグインや作り方ページは Ubuntu 未サポートって追記した。
標準の奴はなんとかしているだろうけど、多分。

動作確認するためだけに ISO を落とすなんて絶対にやらないyo。
変えるかフォークでもして別名にしてくれないとマジで困るんだが。

ついでに少し古いけど。

“Ubuntu on Windows”搭載の「Windows 10 Insider Preview」Build 14316が登場 – 窓の杜

ココで言う bash って、いわゆるシェルではなくアプリケーションのようです。
実行パーミッションという概念が無いので shebang も使えないですし。
ls -a は Windows の隠しファイルでなくドットファイルのままだったりして。

せめて Mac の open -a コマンドみたいな、、、
何をやるにもフルパスが必要な OS 仕様ではそれも無理だよなぁ。
使い道がまったく思いつかない。

Canonical は何がしたいのだろう?

Gjs Desktop Mascot

近頃は小ネタばかりでまともなサンプルコードを書いていないと気が付いた。
このブログらしくないので久々に小物アプリ作ってみます。

もちろん JavaScript(Gjs) で。
基本は大分やったと思うので実際に何か作ってみるとどうかを試したい。
経験で実際にアプリを作ってみないと気が付かないことが多いと知っている。

とりあえず今回はデスクトップマスコットを。
背景が透過されている PNG 画像をデスクトップに表示というありがちなもので。

常にすべての GUI アプリの再背面に表示とかイベントの処理とかのサンプルにも。
それなら応用範囲も広がるだろう、と勝手に考える。
何より重要なのが GtkApplication を必ず使う。
でないと後々で困ることになりそうな謎の雰囲気があるのですよ。
GNOME 公式サンプルからして。

ということで。
背景透過画像は以下からカワイイ苗ちゃんを拾って使う。

【ウチ姫】UR++「小粒姫 優木 苗」ステータス・評価まとめ – お姫さま図鑑|ウチ姫公式攻略Wiki – GAMY(ゲーミー)

んで、こんなコードになりました。

#!/usr/bin/gjs

const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Lang = imports.lang;

const NaeWindow = new Lang.Class({
    Name: 'NaeWindow',
    Extends: Gtk.ApplicationWindow,

    _init: function(app) {
        this.parent({
            application: app
        });
        // GdkColormap to GdkVisual
        let screen = this.get_screen();
        let visual = screen.get_rgba_visual();
        if (visual != null && screen.is_composited()) {
            this.set_visual(visual);
        } else {
            print("no Composited...");
        }
        this.set_app_paintable(true);
        // Transparent background image
        this.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size("nae_ur++.png", 300, 300);
        // Event Mouse
        //this.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
        this.connect("button-press-event", Lang.bind(this, function(widget, event) {
            /* NG
            https://people.gnome.org/~gcampagna/docs/Gdk-3.0/Gdk.Event.html
            
            if (event.type === Gdk.EventType.BUTTON_PRESS) {
                this.begin_move_drag(event.button, event.x_root, event.y_root, event.time);
            */
            if (event.get_event_type() === Gdk.EventType.BUTTON_PRESS) {
                let [res, x_root, y_root] = event.get_root_coords();
                this.begin_move_drag(
                    event.get_button()[1],
                    x_root,
                    y_root,
                    event.get_time()
                );
            } else if (event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS) {
                this.close();
            }
        }));
        // Event Draw
        this.connect("draw", Lang.bind(this, function(widget, cr) {
            Gdk.cairo_set_source_pixbuf(cr, this.pixbuf, 0, 0);
            cr.paint();
        }));
        // z-order
        this.set_keep_below(true);
        // etc
        this.set_decorated(false);
        this.resize(300, 300);
        this.show_all();
    }
});

const Application = new Lang.Class({
    Name: 'Application',
    Extends: Gtk.Application,

    _init: function() {
        // TaskBar Title
        GLib.set_prgname("Nae Chan !");
        // property
        this.parent({
            application_id: 'apps.test.NaeChan',
            flags: Gio.ApplicationFlags.FLAGS_NONE
        });
    },
    // override activate signal
    vfunc_activate: function() {
        new NaeWindow(this);
    }
});
let application = new Application();
application.run(ARGV);

desktop_naechan

あぁ、苗ちゃんがいつもデスクトップにいる。
カワイイよぉ、剥製にして飾…(嘘です

最近気が付いた、g_set_prgname でアクティビティ横の文字列を決められる。
たしか Ubuntu は違ったような、まあ猿専用ディストリなんてガン無視でいい。

そんなことより。
button-press-event ハンドラの仕様は何なんだよ!

Gdk.Event

UNION だとこういうバインドしか手段が無いのか、それとも別の理由か。
現状 Python, C のようにメソッドは使えず関数で取得しか手が無い。

ぶっちゃけ。
コレで混乱しなかったらこんな素敵なサイトなんて見つけられなかったぞ!
やはり何か具体的にアプリを作ってみないと解らない事って多い。

Gjs resource

Gjs のサンプルコードはほとんど以下が書いてある。

const Lang = imports.lang;

この lang.js って今はドコにあるの?
以前は /usr/share/gjs-1.0 以下にあったのに。

Gjs は gir 以外のモジュールをどこから探しているのだろう。
以下のコードで調べることができるようだ。

#!/usr/bin/gjs

let list = imports.searchPath;
for (let s of list) {
    print(s);
}
/* output @ 3.18
resource:///org/gnome/gjs/modules/
/usr/local/share/gjs-1.0
/usr/share/gjs-1.0
/usr/share/gjs-1.0
*/

こんなディレクトリは 3.18 では存在しない。
どうやら現行版はリソース化されてソレを参照しているようだ。

ちなみにこの resource:///org/gnome/* は Gvfs の URI でして。
たとえば Nautilus にて Ctrl+L して resource:/// と打ち込むと。

resource1

と Nautilus が参照しているリソースにアクセスできます。
ファイルに見えるけど拡張子が無いものはディレクトリ。
Gedit の FileChooserDialog で Ctrl+L しても同じようにできます。

resource2

各アプリが参照しているリソースにしかアクセスできませんので注意。
ということで、Gjs のリソースの中身を探してみる。

gjs/modules at master ? GNOME/gjs ? GitHub

上記がリソースの中身らしい、lang.js もしっかりあります。
以前書いた format.js もこの中にある。
Here Document | PaePoi

色々まとめようと思ったけどバージョンでコロコロ変わりそう。
もしかしたら Gjs も PyGObject 同様にバージョン指定が必要になるかも。
Fedora 24 が出てからもう少し確認しよう。

GNOME 開発センター

もはや GNOME 公式の overview が Gjs なんだよな。
vfunc_* のオーバーライドを使っていないのは何故だ?

GitHub – gcampax/gtk-js-app: A template for a standard Gtk/GNOME JS application

コッチのほうが解りやすい、メモメモ。

PyGObject and Gjs API Reference

PyGObject の API Reference を見つけた。
GLib, Gtk だけでなく GObject introspection 全部。

Python GI API Reference

正直かなり見難いけど。
使い道がイマイチ解からなかったライブラリもコレでバッチリ。

実は Gjs も同じライブラリなのでそのまんま適用できます。
とりあえず Xkl で試してみましょう。

#!/usr/bin/env python3

from gi.repository import Xkl

s = Xkl.get_country_name("DE")
print(s)
#=> Germany

s = Xkl.get_language_name("jpn")
print(s)
#=> Japanese

Gjs

#!/usr/bin/gjs

const Xkl = imports.gi.Xkl;

let s = Xkl.get_country_name("DE");
print(s);
//=> ドイツ

s = Xkl.get_language_name("jpn");
print(s);
//=> 日本語

コメントに解答してますが、動かしてみます。

python_setlocale

忘れていた、3.18 から require_version 必須だった!
Gjs は不要なのに、今後は解らないけど。
それより Gjs だと日本語になるんだが何が違うのだ?

#!/usr/bin/env python3

import locale
locale.setlocale(locale.LC_ALL, '')

import gi
gi.require_version('Xkl', '1.0')

from gi.repository import Xkl

s = Xkl.get_country_name("DE")
print(s)
#=> ドイツ

s = Xkl.get_language_name("jpn")
print(s)
#=> 日本語

これで Gjs と同じ結果になった。
Gjs は locale 設定を自動的にやっているってことなのね。
PyGObject しかやっていなかったら英語でしか取得できないと勘違いしていたかも。
やっててよかった JavaScript!

それより、Gjs のほうが簡単になる場合なんてあったのか。
そろそろ本格的に移行かな、Y901x を作り替えするだけだが。

Visual Studio Code (Mac, Linux)

Linux で Windows アプリを使おうとする人が理解できない。
郷に入れば郷に従え、せっかく海外に留学したのに日本語しか話さないようなものだ。

なので筆者の愛用テキストエディタは Linux では Gedit。
Mac では Mac ユーザーに人気の高い Atom を。

だったけど Atom に色々不満が。
なんたって今では標準プラグインをこうしているし。

atom_setting

補完機能は全て無効、だって中途半端で邪魔なだけなんだもん。
自動補完は Visual Studio レベルでないとイライラするだけ。
これじゃ単なる色分けできるテキストエディタだ。

再起動で前回開いていたファイルを開き直しするのがウザい。
スマートフォンだとありがたいこの動作がパソコンではイライラ。

Alt(option)+上下矢印キーで行の入れ替えができないとか。
ドラッグアンドドロップ編集ができないとか。

筆者的には拡張子が無いファイルを見分けてくれないのが地味に痛い。
それをなんとかする modeline プラグインを入れたが効果無し。
Fedora で多用していた emacs 形式 modeline のプラグインも見当たらない。
自分で作れって?他の不満がこんなに多いのに嫌だよ。

そんなこんなで、今回は Visual Studio Code を試す。
こんな名前だ、どのくらい本家 Visual Studio のレベルなんだろう?

レビューを探すと仕事でバリバリ使っている凄い人ばかり…
以下はサンデープログラマーのレビューということで。

まず、JavaScript の保管機能は文句のつけようが無い。

array

配列の後にドットを打つと配列のメソッドのみが候補窓に現れる。
選択状態になった時点で return(Enter) で確定。
括弧を打つとパラメーターの解説窓が出る。

括弧関連の自動保管が神がかっている。
自動保管なのに勢いで閉じ括弧をタイプしてしまう場合が多々ある。
すると何事もなかったように保管された閉じ括弧の後ろにカーソルが移動する。
ブレースの後に改行すると当然のようにインデント。

Visual Studio C# での鬼補正や全自動整形はさすがにできない。
しかし Visual Studio C++ と同じレベル、いやもっと凄いかも。

さすが Visual Studio という名前にしただけはある。
これなら補完機能を無効にするほうが馬鹿だと断言できる。

コードスニペットも使えます。
for とか forin とか打ち込んで tab キーを叩いてみてください。

文字列を選択状態にしなくても shift+tab でインデント戻し。
option(Alt)+上下矢印キーで行の入れ替え。
よしよしできる。

文字列を選択状態にしなくても command(Ctrl)+C でカーソル行のコピー。
Visual Studio 以外で見たことがないこの機能もまさか使えるとは。

何故か初期状態では C# 関連は無効になっている。
extension で入れられるみたい、筆者はいらないけど。
Mac で Unity プログラマーも多いだろうけど Unity 関連の保管は無いかと。

さて肝心の modeline は emacs 形式も使えるものが extensions にあった。
あれ、tab 関連は普通に指定できるけど Mode: がスルーされるんですけど。
ソースコードを覗いてみよう、~/.vscode 以下にあるよ。

modeline

editor.language なんて設定は無いよ!
README.md に書いてあったけど現在は不可能らしい、気長に待つか。

褒めてばかりでなく欠点もいくつか。

この文書みたいなのの下書きに使うと保管でウザすぎるwww
ドラッグアンドドロップ編集はできない、残念。
OLE DnD も、筆者はよく使うのになぁ。
TextEdit.app で文字列選択して Safari のアドレスバーにドロップして検索とかで。

結論、Atom ヤメてしばらくコイツを使ってみる。

Fedora にも入れた、ただ Makefile も install.sh も無かった。
~/app に全部放り込んで ~/bin に vscode というファイル名で。
パスは変えてね。

#!/bin/sh

/home/sasakima-nao/app/VSCode-linux-x64/code $@

vscode.desktop を ~/.local/share/applications に。

[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=vscode %U
Name=Visual Studio Code
Comment=Visual Studio Code
Icon=/home/sasakima-nao/app/VSCode-linux-x64/resources/app/resources/linux/code.png
StartupNotify=true
Categories=Education;Languages;
MimeType=application/javascript;text/plain;

linux_vscode

最初に書いたことと矛盾しているようでしていない。
本家 Visual Studio がある Windows でコレ使う人いるの?