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

Finder の名前順ソート再現 (JXA)

本日も朝からドン曇り、でも天気予報は昼には晴れると。
嘘つき!ドン曇りのまま、野鳥もサッパリで散々だ。
正午過ぎに少し晴れてきたけどもうヤル気ない、ボウズです。

ということで久々にプログラミングネタ。
macOS で Finder と同じ名前順でファイル名をソート。

「自然順ソート」あれこれ | 電書魂

こんなの見つけた、localizedStandardCompare を使うのね。

localizedStandardCompare: | Apple Developer Documentation

AppleScript は面倒だし PyObjC は変換作業と初期化に問題が。
Objective-c はコンパイルが、Swift は SUZUKI しか知らない。
ということで JXA の出番です。

#!/usr/bin/osascript -l Javascript

let strings = ['2.jpg', '10.jpg', '1024.jpg', '44.jpg', '321.jpg'];

strings.sort((a, b)=> {
    return $(a).localizedStandardCompare($(b));
});

for (let s of strings) {
    console.log(s);
}

jxa

これだけか、なんだ簡単だった。
コレさえ解れば macOS に mpv を入れても自前拡張できる。

Fedora Tips | MPV をスクリプトで拡張 – Paepoi

と思ったけど調べると Homebrew 必須かよ、IINA でいいや。
mpv ベースみたいだから同じ拡張が使えるはず。

IINA – The modern media player for macOS

1.4.1 を落としてみた、Tahoe 26.3 で動くじゃん。
早速 macOS 向けスクリプトを作って、と思ったけど。

iina

ディレクトリ内の次を再生する機能はデフォルトであったわ。
意味なかった、まあ macOS プログラミングの勉強にはなった。

Gtk.Window.get_toplevels

Vala については Valadoc.org しか知らなかったけど。
GTK4 になって使わない間に Documentation サイトができていたのね。

Vala Documentation

で、よく考えたら筆者は自作した Vala Tips ページがある。
これも GTK3 のまま放置している、そろそろ書き換えしないと。

Vala (C Generator) – Paepoi

Vala 自体も C# の進化に合わせて細かく変わっていると思うけど。
筆者は 3.5 以降の C# を知らない、7 以降の Windows 買っていないし。
まあ後方互換のはずだし細かい違いは勘でなんとかなると読んでみる。
そんなことより下記のサンプルコードが気になってしまった。

Minimal App – Vala Documentation

GtkApplication や GMainLoop を使わずシグナル処理できるの?
ということで試しに PyGObject で書き換えしてみることにした。
書くまでもなく Gjs のほうが文法が近いけど独自機能が多いし。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, GLib

window = Gtk.Window (title = 'Minimal GTK4 App')

button = Gtk.Button(label='Click me!')
button.connect('clicked', lambda b: b.set_label('Thank you'))

window.props.child = button
window.present()

while (Gtk.Window.get_toplevels().get_n_items() > 0):
    GLib.MainContext.default().iteration (True)

vala

普通に動くんですけど、こんな手段があったのか。
閉じると終了する仕組みがある無限ループならなんでもいいのか。
まあどう考えても GApplication のほうが便利なんですけどね。
WPF なんかもそうでしょ、いや 3.5 以降はマジで知らないけど。

default の前にある @ は何だ?と思ったけど。
キーワードの default と誤認識を防止しビルド時は読み飛ばす仕組みらしい。
知らなかったわい、てか C# にこんな機能あったっけか?

Gjs: runAsync

世間は三連休です、筆者は明日休日出勤ですけど。
ということで久々に Gjs ネタでも。

import GLib from 'gi://GLib';

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

GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT_IDLE, 1, () => {
    console.log('アイドリングで実行');
    loop.quit(); // 必ずこちらが後で実行されるので
    return false;
});

GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => {
    console.log('EOF の後に実行');
    return false;
});

//await loop.runAsync();
loop.runAsync().then( ()=> {
    console.log('__END__');
});
console.log('__EOF__');

gjs

await も当然使える、GLib の関数が非同期な Promise になっている。
なんですかコレ、g_main_loop にこんな関数あったか?

GLib.MainLoop

やっぱり無いよな。
そもそも GLib の関数は Python と同じく全部小文字でスネークケース。
つまり Gjs 独自機能、PyGObject からは当然使えない。

#!/usr/bin/env python3

from gi.repository import GLib

loop = GLib.MainLoop.new(None, False)
loop.runAsync() #=> Error

then の所でメインループを quit できそうだと思ったけど。
メインループを抜けないと then に辿り着けないようで、うーん。
使い道がありそうで無さそうな Gjs 独自機能でした。

で、本日はホトトギスを発見したのにカメラを出している間に逃げられて。
超望遠を持たずに出かけた昨日は沢山見たホオジロも本日は全然見つからず。
野鳥は収穫ゼロ、でもオイラにはプログラミングがあるんだーい!

Clang++ がヘッダを参照できない件

2025.05 現在、Clang++ が iostream を見つけられない。
iostream だけではなく C++ 標準ヘッダが参照できないようで。

まあバグだろうからすぐ修正されるだろう。
で、先日 CommandLineTools の更新通知がきた。
これで修正されて、って同じヤン。

15.4 から 15.5 にアップデートされてはいる。
小数点の無い MacOSX15.sdk は小数点付きへのリンクなのか。
アップデートに追従するみたいだから今後はこっち指定に。

ちなみにルートを Finder で開くには、端末を起動して。

open /

でイケます、GNOME の Linux なら gio open / ですね。
別にホームから command+up してもいいですけど、脱線でした。

そんなこんなで、ビルド毎に -I オプションなんてメンドイぞ。
なのでエイリアスを作ることに、修正されたら消せばいいだけだ。
~/.zshrc を開いて、作ってない人は作成して。

alias clang2="clang++ -I /Library/Developer/CommandLineTools/SDKs/MacOSX15.sdk/usr/include/c++/v1"

名前は各自適当に、筆者は clang2 にしました。

普通にビルドできるようになりました。
ヘッダの場所は環境によって違うかもなので各自調べてね。

ついでに、clang 17 や gcc 15 は C++23 もいくつか対応なのね。

#include <print>

/**
 * clang2 -std=c++23 cc23.cpp
 * g++ -std=c++23 cc23.cpp
 */

int main (int argc, char const* argv[]) {
    /**
     * println なら改行付き、いらないなら print
     */
    std::println("最高な{0}は{1}です", "カメラレンズ", "パナライカ");
    return 0;
}

Java と C# のいいとこどりみたいなことしやがって。
でも思うんだ、名前空間の区切りはドットでよくね?

コンパイラの実装状況 – cpprefjp C++日本語リファレンス

凄いサイトがあるもんだ。

C/C++ auto

gcc や Clang でのビルド方法ページを作っている筆者ですが。
ちょっと、いや数年サボっていたら C 23 や C++ 20 が出ていた。
流石に情報が古いので書き換えしようかと、てか調べないと。

C23 (C言語) – Wikipedia

ついに C 言語にも auto キーワードが、今頃知った。
いや C++ の柔軟な奴と違って変数宣言にしか使えないっぽい。
やってみないと断言できないので少し使ってみる。

#include <stdio.h>
#include <stdlib.h> // free
#include <string.h> // strdup

/**
 * gcc -std=c23 c23.c
 * clang -std=c23 c23.c
 */
int calc(int n) {
    return n * n;
}

int
main (int argc, char *argv[]) {
  
    // 静的文字列はイケる
    auto om = "OLYMPUS"  " " "Workspace";
    printf ("%s\n", om);
    // ポインタもイケる
    auto heap = strdup("おならプー");
    printf ("%s\n", heap);
    free(heap);
    // 計算値もイケる
    auto num = 3*5;
    printf ("%d\n", num);
    // 再代入も普通に可能
    num = 30;
    printf ("%d\n", num);
    // 関数の戻り値dでも可能
    auto num2 = calc(8);
    printf ("%d\n", num2);
    // ループがちょっとだけ簡易にできる
    char *l_mount[] = {"Leica", "Panasonic", "SIGMA"};
    auto count = sizeof (l_mount) / sizeof (l_mount[0]);
    for (auto i=0; i<count; i++) {
        printf ("%s\n", l_mount[i]);
    }
    // 配列自体は無理
    //auto num_array = {1, 2, 3};
    return 0;
}

gcc

配列もダメか、あんまり便利じゃないてかコレ意味あるの?
とにかく -std=c23 又は -std=c2x 指定はどちらでも使えました。

#include <iostream>

/**
 * Fedora 42 は普通にイケました
 * g++ -std=c++20 c23.cc
 * 
 * macOS ではエラーになったので、場所指定は人によって違うと思う
 * clang++ -I /Library/Developer/CommandLineTools/SDKs/MacOSX15.4.sdk/usr/include/c++/v1 -std=c++20 c23.cc
 */

auto
get_half(auto num) {
    return num / 2;
}
 
int
main (int argc, char *argv[]) {
  
    //char *l_mount[] = {"Leica", "Panasonic", "SIGMA"};
    auto l_mount = {"Leica", "Panasonic", "SIGMA"};

    for (auto obj : l_mount) {
        std::cout << obj << std::endl;
    }
    // 簡易オーバーロード
    std::cout << get_half(3) << std::endl;
    std::cout << get_half(3.0) << std::endl;

    return 0;
}

clang

C++ の auto はまさかのこんなことまで可能なのにね。
おまえは Python か、偽オーバーロードの中身はどうなっているのやら。
C++ でも stdio な某クソ OS はどうでもいいよね。

それより Clang が iostream を見つけてくれないんですけど。
macOS だけでなく Linux 版も同じみたいだけどバグなのか?
-I で場所指定すれば通るけどもっといい方法がありそうな。