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

GNU readline

前回 jxa で readline を使ったけどさ。
やっぱり C でも使いたいヤン。

GNU readline | Apribase

タブキー保管ができたり上矢印キーで履歴が辿れたり、まさに端末って感じ。
gets や scanf は非推奨なんだし、端末入力はコレに統一でいいじゃん。

Fedora では libreadline.so は最初から入っている。
でも C のヘッダは無いので以下のコマンドでヘッダを追加する必要がある。

# ncurses ヘッダも依存関係で入るけど気にしない。
sudo dnf install readline-devel

macOS では Command Line Tools の導入で readline.h も入ってくる。
GNU のものではなく互換品だったりするけど。
なので検索すると editline/readline.h と指定、なんて出てくると思う。
現在は以下にシンボリックリンクがあるので readline/readline.h のままでいい。

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/readline/readline.h

ビルドするにはどちらも -l リンカオプションは必要。

#include <stdio.h>
#include <stdlib.h> /* free() */
#include <string.h> /* strcmp() */
#include <readline/readline.h>
#include <readline/history.h>

/*
    Fedora: gcc -lreadline src.c
    macOS:  clang -lreadline src.c
*/

int main(void) {
    char *s;
    printf("usage: exit 又は Ctrl+D で終了\n");
    while (1) {
        s = readline(">> ");
        if (s == NULL) { /* Ctrl+D */
            printf("\n");
            break;
        } else if (strcmp(s, "exit") == 0) {
            free(s);
            break;
        } else if (*s == '\0')
            printf("なんか打ち込めよ!\n");
        else
            printf("%s はカッコイイ!!!\n", s);
        add_history(s);
        free(s);
    }
    return 0;
}

で。

clang_readline

Fedora, macOS 共に上矢印キーで履歴が辿れるし control+D も使える。
macOS の history.h って実は readline.h へのリンクなので不要だけど互換のために。
string.h 等の指定も省略可能だけど警告がウザいので入れたほうがいい。

JXA readline

現在本サイトの JXA Tips を書き換えしている。
以下の Objective-C Bridge の所を見ていたんだけーが。

OS?X 10.10 Release Notes

あれ、readline が import できるみたい。

GNU Readline – Wikipedia

stdio や unistd のように C と同じように使えるのかな。

#!/usr/bin/osascript

ObjC.import('readline');

console.log('May I ask your name?');
let s = $.readline('>> ');
console.log(`Hello ${s} san`);

jxa_readline

JXA の stdin ってこんなに簡単だったんだ!
世界中探しても見つからなかったのにこんちくしょう。

Gtk Next/Prev Dialog

Fedora を 32 (GNOME 3.36) にして一ヶ月たった。
今更気が付いたんだけーが GtkMessageDialog のバグが直っている。

GNOME 3.34 modal dialog bug | Paepoi Blog

この時に拙作 Comipoli は GtkInfoBar に変更した、そのまんまだ。
コレってフルスクリーンで cbz を見ていた時には解り辛いんだよね。
ダイアログのほうが視覚的に理解しやすいので元に戻すことにした。

戻すだけじゃつまらない、何か機能の追加か変更をしたい。
pixivコミックやニコニコ漫画のように「前の話」機能を追加することに。
って、GtkMessageDialog では YES/NO しか選択できないんだが。

ということで、GtkDialog を使って自作することにした。
Prev のショートカットはどうするか、Enter/Esc は勝手にやってくれるが。
ええい面倒だ、ニーモニックをそのまま描写しちゃえばいいや!

#!/usr/bin/env python3

from gi.repository import Gtk

class ComipolNextDialog(Gtk.Dialog):
    def __init__(self, text):
        Gtk.Dialog.__init__(self)
        self.set_resizable(False)
        # Buttons
        self.add_button('_Cancel (ESC)', Gtk.ResponseType.CLOSE)
        self.add_button('_Next (Enter)', Gtk.ResponseType.YES)
        self.add_button('_Prev (Alt+P)', Gtk.ResponseType.NO)
        self.set_default_response(Gtk.ResponseType.YES)
        # Message
        message = Gtk.Label(label=f'<span bgcolor="#CC0099">Next:</span> {text}', use_markup=True, visible=True)
        self.vbox.pack_start(message, False, False, 30)

こうなった。
YES/NO は最適なものが無いので簡易利用しただけ。
ボタン自体にショートカットが書いてある親切な仕様になってしまった。

んで呼び出し。
一つ前が存在しない時はボタンを無効にする必要があるなと。

dlg = ComipolNextDialog(html.escape(cbzs[next_index]))
dlg.set_transient_for(self)
if next_index < 2:
    dlg.set_response_sensitive(Gtk.ResponseType.NO, False)
res = dlg.run() 
if res == Gtk.ResponseType.YES:
    uri = GLib.filename_to_uri(GLib.build_filenamev([path, cbzs[next_index]]), None)
    self.set_uri(uri)
elif res == Gtk.ResponseType.NO:
    uri = GLib.filename_to_uri(GLib.build_filenamev([path, cbzs[next_index - 2]]), None)
    self.set_uri(uri)
dlg.destroy()

コレでイケた。
どんな感じに表示されるか。

dlg

うーん、GtkMessageDialog よりボタンの大きさが小さいなぁ。
勝手に等間隔にはなるけど長いファイル名だと右に寄ってしまうし。
アクションエリアにアクセスが非推奨ではどうにもできない。
タイトルバーも出るんだね、無しにしたいけど手段が解らない。
iPhone を考えるとあのスタイルが普通になるのよね今後は。

とはいえ動作は問題無しなのでコレでいこう。

bash Color 256

前々回、tree コマンドを Python で自作したんだけど。
「ディレクトリを青色にしたけど tree コマンドとなんか色が違う」
の本家 tree コマンドの色を出力したい。

bash:tip_colors_and_formatting – FLOZz’ MISC

こんなページを発見。
bash ってここまで高機能だったのか、マジで知らなかった!
というか \033 だけじゃなく \e とか \x18 でも良かったのか。
アンダーラインも点滅も反転も、256 色で色指定さえも思いのまま。

しかし文句の付けようがない完璧で解りやすいまとめだなぁ。
こんな有用なページを筆者も作りたい、それは別の話で。

とにかく 256 色に指定するには以下にすればいいのね。

echo -e "\e[38;5;numm***string***\e[0m"

色見本ではドレが tree コマンドの青なのかよくわからない。
自前でソレっぽいのをいくつか選んで出力して確かめてみよう。

#!/bin/bash

for cl in {31..33} {37..39} {73..75} ; do
	echo -e "\e[38;5;${cl}m_texts\e[0m"
done

sh_color

どうやら 33 で正解のようだ。

ところで下方に対応ターミナルの表がありますが。
macOS の Terminal.app でも printf にすればイケます。
おまけに指定は sh でも bash でも zsh でもオケ。

mac_sh

Fedora 32 JavaScript

Fedora 32 は Gjs が ES2019 にフル対応した。
いや、フル対応した SpiderMonkey にアップデートというべきか。
JavaScriptの ES2019で追加された新機能まとめ – Qiita

更に BigInt にも対応、素晴らしい。
Python 屋としては Number の拡張はできなかったのかと言いたい所だけど。

bigint

プライベートフィールド等は駄目でした。
そんなことより Gjs の開発者はかなりがんばったようだ。

ClutterImage PyGObject/Gjs | Paepoi Blog

gjs_speedup

まさかの PyGObject より速くなるとは、誤差の範囲とはいえ。
何をやったか解らないけどコレで Gjs を諦める理由が減った。

Gjs: GdkPixbuf Memory leak | Paepoi Blog

この意味不明メモリリークもやっと起こらなくなった。
やはりメンテを続けていると良くなっていくんだよね。
ただこの実験は Python のガベージコレクションの凄さを思い知るだけだが。
メンテを続けた年期の差ってことで。

ところで JavaScript といえば。
/usr/libexec/webkit2gtk-4.0/jsc
が無くなった、Nautilus の検索機能でも見つからない。
けれど gir に JavaScriptCore-4.0.typelib は残っている。

#!/usr/bin/python

import gi
gi.require_version('JavaScriptCore', '4.0')
from gi.repository import JavaScriptCore

context = JavaScriptCore.Context()
out = context.evaluate('3 + "あ" + 4', -1)
print(out.to_string())

//=> '3あ4'

これは動く。

SpyderMonkey, V8 同様に実体が無くライブラリだけになったみたい。
実験にしか使っていなかったし mac も持っているから別にイイか。