Mac Application System Event

mac にてスクリプトのみで GUI がやりたい。
つまり Linux の PyGObject のようにしたい。

AppleScript: Graphic User Interface (GUI) Scripting

やっとヒントが見つかった。
System Event で Application を作れば空のアプリになるようだ。
コレを利用して別途で GUI を作ればなんとかなりそう。

シバンで osascript を指定して実行パーミッションを付けて。
拡張子を取っ払わないとデフォルトアプリ起動になるので注意。

#!/usr/bin/osascript -l JavaScript

var app = Application("System Events");
app.includeStandardAdditions = true;
app.displayDialog("はろーわーるど");

javascript_dlg

よし、ダイアログのみを出すスクリプトはイケた!
でも Finder にて command+O では端末が開く…

Python でも試したけど拡張子が無ければシバンで開いてくれる。
けれど Windows と同様に端末が開いてしまう。
pythonw がある時点で気がつけよ俺、Linux には無いてか不要。

端末を開かずに osascript を実行する方法、あるのか?
Windows で PowerShell をブン投げた時を再現するとは。

Mac は想像していたほど Linux 的には使えないかも。

Mac gvfs-open

Mac で”デフォルトアプリにて開く”は open コマンド。
Linux の gvfs-open と同じ、説明が逆の気がするけど。

ということは Finder で /usr/bin を開くには

cd /usr/bin
open .

usr_bin

おぉ、コマンドからなら普通に開くことができるんだ。
open `pwd` でもいいけどドットのほうが簡単。

端末もいいけどたまに GUI でファイルを確認したい時があるのよ。
隠し属性ファイルを Finder に表示する必要なんて無いんだな。
finder コマンドが存在しなくて困っていたけどこんな方法が。

ドットディレクトリ内を探したい時は ls -a コマンドで。
Linux を使っている人なら常識だけど。

後はパスの通った場所にコレを用意して。

#!/bin/sh
open -a /Applications/Atom.app $@
#!/bin/sh
open -a /Applications/iHex.app $@

osx_support

よしコレでファイルの確認作業が格段に楽になった。
本当は Nautilus の拡張みたくやりたいけどまだ手段がワカラン。
iHex は無償だったので選んだけど確認用途なら十分かな。
しかしまあ、同じ UNIX というだけでありがたいYO!

Mac JavaScript

mac ではスクリプトは何を使おう?

筆者が主に Python を使っているのは Linux だったから。
書くまでもなく PyGObject という究極便利なものがあったから。
Linux なんてアップデートマネージャや dnf が Python 製。

使う言語はフレームワークやライブラリで決まる。
簡易な CMS ツールなら wordpress ベースなので PHP に。
スマホゲームなら Unity 一択に近いので C# に。

Mac で Python はどう考えたって役立たずだよなぁ。
Apple スクリプトを覚えても他で応用が効かないのが痛い。
ならば JavaScript なんてどうだ?

なんたって上記のドレも JavaScript が絡む。
今や GNOME デフォルトアプリでさえ Gjs 製がある。
Unity(mono) は JavaScript も使える、というように。
mac でも Gjs のようなものがあれば便利だけど。

知らないうちにMacがシステム標準でJavaScriptで操作できるようになってた (JXA) – Qiita

って思っていたら Yosemite なら普通に使えるんかい!

早速 .bashrc にエイリアスを用意しよう、mjs でいいかな。
どうでもいいけど mac には標準で nano が入っている。
ドットファイルの編集をする場合なんかに便利だね。

nano

PS1='[\u@\h \W]$ '

mjs()
{
        if [ $# -eq 0 ]; then
                osascript -l JavaScript -i
        else
                osascript -l JavaScript $@
        fi
}

普通にエイリアスを登録でもいいけど筆者は関数にした。
これなら Gjs や Python 同様に引数の有無でインタラクティブシェルに。
同じようにしたい人は関数名をお好みで変更してね。

再ログインで使えるようになったのを確認してと。
control+D で終了できるけど終了時に改行はしてくれないようだ。
さて、Gjs 並には使えるのかな?

mac_js

let は無理か、まあ Safari でも使えないからね。
JavaScript エンジンは Safari と同じ Nitro だろうし。
でも Gjs のようにタプルは問題なく使えるようです。
SpiderMonky に統一ってわけにはいかないよな。

標準出力は console.log() を使えば可能。
print() を用意してほしいな、手段を知らないだけかもだが。

さて言語は使えることが解ったので GUI を作る方法でも。

OS X YosemiteからJSでMacアプリを作れるようになったって!?と聞いてみたものの | mah365

こんなのを見つけたけど osascript では動かないや。
スクリプトエディタ.app で command+R の必要がある。
うーん、これじゃたいして役に立たないぞ。

何か手段があるのだろうけど検索しても出てこない。
そりゃこんな Mac らしくないことがしたい人は少ないよNE。
もう少し調べる。

Atom(TextEditor)

GitHub、オープンソースのテキストエディター「Atom」の正式版v1.0.0をリリース – 窓の杜
MS、Win/Linux/Mac対応のコードエディター「Visual Studio Code」をプレビュー公開 – 窓の杜

こんなのあるんだね。
Mac と Fedora で共通のテキストエディタが欲しかった自分にピッタリかな。

Electronでアプリケーションを作ってみよう – Qiita

Electron というクロスプラットホームライブラリで GUI 構築らしい。
ゴミ糞(mono+WindowsForm)よりは圧倒的にまともなクロスプラットホームになりそう。
いや、ウチ姫で mono(Unity) にはお世話になっているけど。

ということで。
Visual Studio Code は大きなお世話なので Atom だけ試す。

Atom

Linux rpm で 56.8MB
Mac は Atom.app のまま配布で 203.5MB

やはり Mac のアプリってやたらとデカいよ…
/Applications ディレクトリに移動するだけで動くのね。

両方起動すると唖然とするほど共通な GUI に感心する。
メニューや設定は英語だけど Linux, Mac 使いなら普通のこと。

Fedora では日本語が豆腐になるが Font Family を変更すれば即時解決。
Mac はそのまま日本語表示できる。

vlgothic

mac_atom

起動時間もキー入力の反応速度もまったく問題無し。
使い勝手は Mac では Ctrl が command になるだけで基本同じ。
保存ダイアログ等は OS 標準のものが出る。

肝心のエディタ部分もかなり優秀。
拡張子で色分けは常識、HTML 中の StyleSeet, JavaScript も認識。
Gedit と比較しても同等かそれ以上。

atom_highlight

設定の Soft Tabs で Tab キーを半角スペースにできる。
BackSpace(Mac は Delete) でインデント分を削除。
Shift+Tab も使えた、マジで Gedit の代わりになる。

閉括弧自動補完は大きなお世話だが人によるだろう。
設定は最小限、でも不満は特にない。
Line Height は 1.35 にすると Gedit とほぼ同じになるね。

Home(command+←) キーでインデントの先頭にカーソル移動する。
Xcode や TextEdit.app の不満点だったのでコレは嬉しい。

面白いのは Ctrl+マウスホイールでズームできる。
Mac はタッチパッドでズームできる、使い道はともかく。
Web ブラウザと同じ、なるほど HTML5 ベースだなと納得する所。

一つだけ気になるのがアプリ再起動で前回開いていたファイルを開くこと。
Mac やスマホアプリのデフォルト動作がコレだし時代なんだろうね。
Ctrl+W(command+W) で全部閉じてから終了すればいいだけ。

試すだけのつもりが基本機能には文句のつけようがない。
私的に Mac 用はコレに決まり、Gedit みたく使えればいいんだよ。
検索するとメニューの日本語化もできるようだけど筆者は別にいいかな。

後は自作 Gedit プラグインと同等な拡張を作ればもっと便利に。
いやコードスニペット機能は必須だぞ、既に拡張があるかな?

というか Electron ってスゲェな。
クロスプラットホームアプリはゴミ糞という常識が通じない。
今後はデスクトップもコレがデファクトになる可能性すら感じる。

GtkPopoverMenu

Fedora 22 にしてから一ヶ月近いが GTK3 関連でヤル気が出ない。
新規 Widget が GtkPopoverMenu くらいしかないので。
GtkPopover とたいして違わなそうだし。

多分 Nautilus のメニューがコレだと思うけど。
GTK+ Inspector で確認してみるか。

nautilus316menu

やはりっっってあれ、GtkModelButton って何?
devhelp で確認するとコレも 3.16 からの新規 Widget のようだ。
何故こんなにヒッソリと追加なのよ、よし調べて使ってみよう。

gtk3-demo には無い、海外を検索してもまだ誰もやっていない。
また devhelp のみが頼りか、いつものことだ。

GtkPopoverMenu: GTK+ 3 Reference Manual

GtkPopover のサブクラスなのでやはり GtkBox に積み重ねる必要あり。
action-name プロパティに GAction のアクション名指定だけでイケるっぽい。
今回は devhelp のように GtkBuilder でやってみました。

#!/usr/bin/env python3
 
from gi.repository import Gtk, Gio

POPOVER = '''<interface>
<object class="GtkPopoverMenu" id="menu">
  <child>
    <object class="GtkBox">
      <property name="visible">True</property>
      <property name="margin">10</property>
      <property name="orientation">vertical</property>
      <child>
        <object class="GtkModelButton">
          <property name="visible">True</property>
          <property name="active">True</property>
          <property name="action-name">win.hello</property>
          <property name="text" translatable="yes">Hello</property>
        </object>
      </child>
      <child>
        <object class="GtkModelButton">
          <property name="visible">True</property>
          <property name="action-name">win.world</property>
          <property name="text" translatable="yes">World</property>
        </object>
      </child>
    </object>
  </child>
</object>
</interface>'''
 
class PopoverMenu(Gtk.ApplicationWindow):
    """
        GtkPopoverMenu Test
    """
    def __init__(self):
        Gtk.ApplicationWindow.__init__(self)
        # DrawingAre
        area = Gtk.DrawingArea.new()
        # Popup Button
        button = Gtk.Button.new_with_label("Option")
        button.connect("clicked", self.on_option_button_clicked)
        # ActionBar
        bar = Gtk.ActionBar.new()
        bar.pack_end(button)
        #
        # Popup Contents
        builder = Gtk.Builder.new_from_string(POPOVER, -1)
        self.menu = builder.get_object("menu")
        self.menu.set_relative_to(button)
        action = Gio.SimpleAction.new("hello", None)
        action.connect("activate", self.hello_cb)
        self.add_action(action)
        action2 = Gio.SimpleAction.new("world", None)
        action2.connect("activate", self.world_cb)
        self.add_action(action2)
        #
        # pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(area, True, True, 0)
        vbox.pack_start(bar, False, False, 0)
        # self
        self.add(vbox)
        self.connect("delete-event", Gtk.main_quit)
        self.set_title("PopUp")
        self.resize(300, 200)
        self.show_all()

    def hello_cb(self, action, parameter):
        self.set_title("Hello")

    def world_cb(self, action, parameter):
        self.set_title("World")

    def on_option_button_clicked(self, widget):
        """
            Show Menu
        """
        self.menu.show_all()
 
PopoverMenu()
Gtk.main()

gtkpopovermenu

Gedit や eog のプラグインを作っておいて良かった。
多分やっていなければ action-name property でドンズマリしていた。

つまり action-name プロパティには win のプリフィクスが必要。
win なんて自分ではどこにも定義していないけど固定値みたい。
GtkApplication を使わなくてもいるのね、なんでだろう。

margin は 10 にすると Nautilus のメニューとほぼ一致する。
妙にデカい気がするけど多分タッチパネル化の準備だろう。

GtkBuilder の XML で vertical と書くことができるのか。
あまり使わないから知らなかった、整数や文字列だけかと思っていた。
つか devhelp のサンプルコードにコレ入れてくれよ。

この程度なら GtkBuilder よりコードで作ったほうが簡単そう。
他人が読むことを考えると XML のほうが理解しやすいだろうけどNE。