JXA」タグアーカイブ

CRLF

何を今頃だけど JavaScript の replace について。

String.prototype.replace() – JavaScript | MDN

第一引数を正規表現にすればすべてのマッチした箇所を置換できるのか。
最初に一致した箇所だけだとずっと勘違いしていた筆者であった。

JXA: doShellScript Line feed code | Paepoi Blog

これを試しに書き換えしてみよう。

#!/usr/bin/osascript

let app = Application.currentApplication();
app.includeStandardAdditions = true;

res = app.doShellScript('ls -l');
console.log(res.replace(/\r/g, '\n'));

いけた。

ついでに。
よく考えたらコマンドの中で tr を使って変換すりゃいいじゃん。
と思ってやってみたら上手くいかなかった。

#!/usr/bin/osascript

let app = Application.currentApplication();
app.includeStandardAdditions = true;

// no...
//res = app.doShellScript('ls -l | tr "\r" "\n"');

// test
res = app.doShellScript('ls -l | tr "\n" "|"');
console.log(res);

となる。

つまりコマンド実行の時点では改行コードは LF のまま。
doShellScript が値を戻す時に CR へ変換しているようです。
LF のまま戻すオプションって無いのかな?

lf

#!/usr/bin/osascript

let app = Application.currentApplication();
app.includeStandardAdditions = true;

res = app.doShellScript('ls -l', {alteringLineEndings:false});
console.log(res);

あった、今後はコレで。

ついでに、doShellScript は bash の POSIX 互換モードです。
zsh やフル状態の bash ではないので注意、macOS って本当に色々面倒臭い。
プログラミングするならやっぱり Linux だよ、某サル専用を除く。

関係ないけど Macbook Air 2020 が出たね、かなり良さげ。
でも筆者はこんな使い方ばかりだから 2018 モデルで何の不満も無いのよね。
ペチペチキーボードにもすっかり慣れてしまったし、うるさいけど。
さて 10.15.4 にアップデートするか。

macOS Get UTI

Apple 関連で開発をしていると UTI を調べる必要がある場合が多々ある。

Uniform Type Identifier – Wikipedia

Uniform Type Identifier Concepts

検索をしていたら素敵なページを見つけた。

Mac や iOS でファイルの種類を表す識別子 Uniform Type Identifiers を拡張子から調べる(Swiftで1行で出来る) – niwatakoのはてなブログ

てゆーか JXA でも PyObjC でもできる。
しかし困ったことに JXA では CFString が NSString にキャストできない。

objective c – JXA: Accessing CFString constants from CoreServices – Stack Overflow

上記を見つけてようやく解決。
console.log って C 言語の char[] を出力できる、初めて知った。
UTF16LE に変換は不要、CJK 文字列でも問題ないようです。

#!/usr/bin/osascript -l JavaScript

let jp = $('スズキ GSX250R').UTF8String;
console.log(jp);
//=> スズキ GSX250R

// ex: ft=js.jxa

ということで JXA にて簡単に調べるコマンドを作ってみる。

#!/usr/bin/osascript -l JavaScript

ObjC.import('CoreServices');

function run(argv) {
    for (let ext of argv) {
        let uti = $.UTTypeCreatePreferredIdentifierForTag(
            $.kUTTagClassFilenameExtension, $(ext), null);
        let s = $.CFStringGetCStringPtr(uti, 0);
        console.log(`${ext}: ${s}`);
    }
}

// ex: ft=js.jxa

getuti.js

せっかくなので基底タイプも調べたいぞ。
JXA で得る方法が解らなかったので PyObjC で書いてみる。
PyObjC は CFDictionary や CFString も Python の型と等価なので超簡単。
他の言語を使うのが馬鹿馬鹿しくなってしまうので注意が必要。

#!/usr/bin/env python3

import sys, CoreServices

for ext in sys.argv[1:]:
    uti = CoreServices.UTTypeCreatePreferredIdentifierForTag(
        CoreServices.kUTTagClassFilenameExtension, ext, None)
    arr = CoreServices.UTTypeCopyDeclaration(uti)['UTTypeConformsTo']
    con = ','.join(arr)
    print(f'{ext}: {uti} [{con}]')

# ex: ft=py

@PyObjC

getuti という拡張子の無い名前で +x のパーミッションを付けパスの通った場所へ。

getuti

JXA でやりたかったけどまだまだ修行が足りない。

Catalina Atom JavaScript

おいおい、Atom の Script パッケージって…

Script はシバンを書かなければパスを通した node.js で実行するようです。
シバンを osascript に指定してもパラメーターは node.js 用のまま。
どういうことだってばよ。

右下にある言語の所をクリックし

JavaScript for Automamation (jxa)

を選択すれば osascript 用のパラメーターになるようです。

こんなのを毎回やるのなんて面倒臭いぞ。
ということで vim-modeline を使うことにする。

#!/usr/bin/osascript

console.log('Hello');

// vim:set ft=js.jxa

vim 屋は最終行に書いている場合が多いので合わせてみた。
Atom のみならこの表記でいい、本家 vim を併用している人は困るかも。
書き込んだ後に開き直すか option+control+V を押す。

問題なく JXA で起動できるようになります。
普通にシバンどおりに実行してくれたほうが嬉しいのに。

ところで node.js なんだけど。

普通にダウンロードしテキトーに置いた奴は起動できなくなっていた。
上記は以前試した graalvm に入っていた奴なんだけどね。
Gatekeeper がどんどん厳しくなるなぁ。
正式な手段でインストールしないと全部弾かれるようになったみたい。

macOS Catalinaでnode.jsをインストール – Qiita
node.jsのversionを管理するためにnodebrewを利用する – Qiita

curl -L git.io/nodebrew | perl - setup

を実行すると ~/.nodebrew が作られる。
筆者は zsh に変更したので ~/.zshrc にパスを書き込む。
しかし mac 屋は何故ドットコマンドではなく source を使うのか?

. ~/.zshrc

Node.js

コレを書いた時点の LTS は 10.16.3 である。

# ~/.nodebrew/src にバイナリでダウンロード
# ~/.nodebrew/node に展開
nodebrew install-binary v10.16.3

# ~/.nodebrew/current のリンク先を指定先に変更する
# ~/.nodebrew/current/bin に nodebrew 自体のリンクを貼る
nodebrew use v10.16.3

全部 $HOME 以下に展開されるけど問題なく使えるようになった。
Gatekeeper の仕組みがイマイチわからないな。

Catalina Scripts

zsh でプロンプトのカスタムは以前書いたのだけど。
zsh | PaePoi

~/.zshenv ではなく ~/.zshrc に書く必要があるみたい。
~/.zshenv では Mojave には無かった /etc/zshrc に上書きされてしまう。

PROMPT でもいいみたいだけど PS1 変数も使えるみたい。
RPROMPT も問題ないけど筆者は Fedora と共通にしたいので以下のようにした。
ブラケットが無いとコマンドの始まりがドコなのかワカンネーもん。

# ~/.zshrc @ User specific environment

PATH="$HOME/.local/bin:$HOME/bin:$PATH"
export PATH

# Fedora like Prompt for bash
#PS1='[\u@\h \W]\$ '
# zsh
PS1="[%n@%m %1~]%# "
#RPROMPT="[%~]"

# alias
alias ll="ls -l"
alias jxa="osascript -i -l JavaScript"
alias jsc=/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc

atom は .zshrc 等を色分けしてくれる、素敵!
スクショ間違っていたので 20 時修正。

それと。
前回クイックアクションで 72dpi 変換ができなかった理由が判明。
iPhone でお馴染み、サンドボックス機能のアクセス許可で弾かれているようだ。

Automator から「指定されたFinder項目を取得」にデスクトップの画像を一旦入れ実行。
アラートが出るので [OK] をクリック、これで Automator からはアクセス可能になる。
しかしそれをやっても「クイックアクション」からはアクセスできない、失敗作だろコレ。

クイックアクションは死にました、チーン♪
いや修正は入る、かな…

これじゃ不便なので拡張のほうに変換スクリプトを作り替え。
macOS アプリを JXA (AppleScript) で拡張

#!/usr/bin/osascript

// change72dpi.js

let app = Application.currentApplication();
app.includeStandardAdditions = true;

let selections = Application('Finder').selection();
for (let item of selections) {
    if (item.nameExtension() === 'png') {
        let fullPath = decodeURI(item.url()).slice(7);
        let pos = fullPath.lastIndexOf('/');
        let path = fullPath.substr(0, pos);
        let name = item.name();
        app.doShellScript(`cd '${path}'
        src_width=$(sips -g pixelWidth '${name}' | cut -s -d ':' -f 2 | cut -c 2-)
        width=$(($src_width / 2))
        sips -s dpiHeight 72.0 -s dpiWidth 72.0 -Z $width '${name}' --out '72dpi-${name}'`);
	}
};

デスクトップのスクリーンショットを選択し実行。
アクセス許可アラートで [OK] を選択すると下記に表示されるようになる。

許可ばかりでサンドボックスの意味ネェ。
そもそもこんな Mac の使い方をする人は少ないだろうけど。
とりあえず当面はこの方法で 72dpi 変換するとしよう。

zsh も bash と同じく $((formula)) 計算できるのね。
てかバッククォートを JXA で使うのでシェル部分で使えないのは難しかった。
NSRect が使えればもっと簡単な手段があるのになぁ。

ところで Python3 なんだが。

macOS 10.15 Catalina 19A583にはPython 2.7.16、Ruby 2.6.3p62、Perl 5.18.4が同梱されるも、Python 2.7の使用は非推奨で”python3″を推奨。 | AAPL Ch.

元々インストールしていたマシンならそのまま使える、ってことか。
ただ筆者は 3.7.4 に更新していたのに 3.7.3 に巻き戻されてしまった。
多分今後も勝手にそうされるだろうからこのままにするけどさ。

今日はここまで。

macOS 10.15 Catalina

macOS 10.15 Catalina を導入しました。
Macbook Air 2018 の Mojave からのアップグレードです。
さて、一番気になる所をチェック。

デフォルトシェルは初期状態では bash のまま。
ただし [zsh に自分で変更しろ] というメッセージが毎回出る。
.bashrc でカスタムしていた所は .zshenv に変換コピペ等の猶予がある。
一通り調べた後で筆者も zsh に変更します。

Python2 も実は残っている、同様なメッセージが出る。
でも Python3 ってあれ?

筆者は自分で Python3 を入れたけど、それは /usr/local/bin にある。
デフォルトで /usr/bin に入るようになったみたい、情報が無かったけど。
シンボリックリンク先は同じなので残しても問題ないけど local のは消すかな。

PyObjC は pip3 で自分で入れたのだけどコレも最初からあるのかいな?
他人の情報を待とう。

筆者自作の Comipoli はソースもビルド済みも問題なく動いた。
ただソースのまま起動するのが異様に遅くなったような気が。
macOS アプリケーション

何より気になる JXA での NSRect のバグ。

そのまんまヤン!
もう JXA はダメだ、GUI は PyObjC に完全移行しよう。

httpd.conf はやはりリセットされた。
変更点は特に無いようだ、とっとと元に戻す。
macOS httpd.conf | PaePoi
んで

sudo apachectl restart

そんなことより。
sips を使ったスクリーンショットの 72dpi 変換ができない!
macOS をクイックアクションで拡張 – L’Isola di Niente
シェル変更の影響か?

#!/usr/bin/env python3

# change72dpi *.png

import sys, os
from AppKit import *
from Quartz.CoreGraphics import *

args = sys.argv[1:]

for s in args:
    name = os.path.basename(s)
    src_image = NSImage.alloc().initWithContentsOfFile_(name)
    img = NSBitmapImageRep.imageRepWithData_(src_image.TIFFRepresentation()).CGImage()
    h = CGImageGetHeight(img) // 2
    w = CGImageGetWidth(img) // 2
    ctx = CGBitmapContextCreate(None, w, h, 8, 4 * w, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast)
    CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), img)
    imgref = CGBitmapContextCreateImage(ctx)
    out_image = NSImage.alloc().initWithCGImage_size_(imgref, (w, h))
    bmp = NSBitmapImageRep.imageRepWithData_(out_image.TIFFRepresentation())
    data = bmp.representationUsingType_properties_(NSBitmapImageFileTypePNG, {})
    data.writeToFile_atomically_(f'72dpi-{name}', True)

以前書いた使い捨てスクリプトでなんとか 72dpi 変換した。
しかし端末でこんなの出ていたっけ?

とりあえず気がついたのはそんなところ。
相変わらず mac らしい使い方をしていないなぁ。