Author Archives: AKIYAMA

2024-09-16 ,

org-modeでエクスポート時の翻訳をバッファ内オプションで変更する

「エクスポート時の翻訳ってなんじゃ?」とお思いの方もいると思いますが、org-modeには人間が読むための短い文字列を英語以外の言語へ翻訳するための仕組みがあります。詳しくはorg-export-dictionary変数を見るのが手っ取り早いと思います。 "Author""著者""Date""日付""Figure %d:""図%d: ""Listing""ソースコード" 等々、色々定義されています。そしてそういった訳がイマイチしっくりこないという事はありませんか? それも文書によって適したものは変わってくることもあります。そこで今回はこの翻訳をバッファ内のオプションでカスタマイズする方法を用意してみました。

前準備:

  1. 末尾掲載のorg-custom-translation.elをload-pathが通っているところに配置。
  2. init.elに次のコードを追加。
(with-eval-after-load "ox"
  (require 'org-custom-translation))

使い方:

単純に置き換える例。

#+TITLE: むかしのはなし
#+AUTHOR: おおむかしのかたりべ
#+CUSTOM_TRANSLATION: ja Author さくしゃ
#+CUSTOM_TRANSLATION: ja Created つくったにちじ

むかしむかしあるところにおじいさんとおばあさんがいました。

めでたしめでたし。

図番を消す例。次のようにすれば「図1:」のような番号を消すことも出来ます。

#+CUSTOM_TRANSLATION: "Figure %d:" ""

これは何かの写真です。

#+CAPTION: 何かの写真
[[file:example-1.jpg]]

これは別の写真です。

#+CAPTION: 別の写真
[[file:example-2.jpg]]

いや、本当はこの図番を消すために作ったのですが、いざ作り終えてみると正直この方法で消すのはイマイチかなぁ、と。もしorg-modeの更新で "Figure %d:" の部分が変わってしまったら効果が無くなってしまいますからね。例えば ":" の部分は別途付け加えるようになるとか。

なので後でもうちょっと違うやり方を考えてみようと思いますが、せっかく作ったのでここに残しておきます。

;;; org-custom-translation.el --- Customize export translations -*- lexical-binding: t; -*-

;; Copyright (C) 2024 AKIYAMA Kouhei

;; Author: AKIYAMA Kouhei <misohena@gmail.com>
;; Keywords: 

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Change the translation dictionary used during export from the
;; in-buffer options.

;; Add the export option "#+CUSTOM_TRANSLATION:" to temporarily change
;; org-export-dictionary during export.

;; * Preparation
;; Put the following in your init.el.
;;   (with-eval-after-load "ox"
;;     (require 'org-custom-translation))

;; * Option Syntax
;; #+CUSTOM_TRANSLATION: [<language>] <src> <dst>

;; * Examples
;; Translate to Japanese romanization.
;; #+CUSTOM_TRANSLATION: ja Author Sakusha
;; #+CUSTOM_TRANSLATION: ja Date Hizuke

;; Remove figure number.
;; #+CUSTOM_TRANSLATION: "Figure %d:" ""

;;; Code:

(require 'cl-lib)
(require 'ox)

(defun org-custom-translation-split-option-value (str)
  (cl-loop with index = 0
           while (progn
                   (string-match
                    " *\\(\\(\"\\([^\"]*\\)\"\\)\\|\\([^ \t\"]+\\)\\)\\|"
                    str index)
                   (match-beginning 1))
           collect (or (match-string 3 str)
                       (match-string 4 str))
           do (setq index (match-end 0))))

(defun org-custom-translation-make-dictionary (lines current-language)
  (cl-loop for line in lines
           for values = (org-custom-translation-split-option-value line)
           when (>= (length values) 2)
           collect (let ((lang (if (>= (length values) 3)
                                   (pop values)
                                 current-language))
                         (src (car values))
                         (dst (cadr values)))
                     (list src (list lang :default dst)))))

(defun org-custom-translation-override-dictionary (options)
  (setq-local
   org-export-dictionary
   (append
    (org-custom-translation-make-dictionary
     ;;(cdar (org-collect-keywords '("CUSTOM_TRANSLATION")))
     (when-let ((lines-str (plist-get options :custom-translation)))
       (split-string lines-str "\n"))
     (or (plist-get options :language) org-export-default-language))
    org-export-dictionary)))

(defun org-custom-translation-filter-options (options _backend &rest _rest)
  (org-custom-translation-override-dictionary options)
  options)

(defun org-custom-translation-add-export-option ()
  (setf (alist-get :custom-translation org-export-options-alist)
        '("CUSTOM_TRANSLATION" nil nil newline)))

(defun org-custom-translation-setup ()
  (org-custom-translation-add-export-option)
  (add-to-list 'org-export-filter-options-functions
               'org-custom-translation-filter-options))

(org-custom-translation-setup)

(provide 'org-custom-translation)
;;; org-custom-translation.el ends here

基本的な処理は全て org-export-filter-options-functions を経由して呼び出される org-custom-translation-filter-options で行っています。

org-export-filter-options-functions は本来オプションをフィルタするためのものですが、ここで CUSTOM_TRANSLATION オプションの値に応じて org-export-dictionary を変更してしまいます。ここが呼ばれる時のカレントバッファは元のorg-modeバッファをコピーした一時的なバッファのようなので、ローカル変数として設定してしまいます。後は自然に新しい訳が使われるようになります。

2024-09-13

Emacs 30.0.91を試す(MS-Windows)

たまにはpretestの段階で触ってみる。

Windows版のバイナリは既にある。仕事が速い。

https://alpha.gnu.org/gnu/emacs/pretest/windows/emacs-30/

ネイティブコンパイルの設定は以前と同じでOKだった(一部のdllファイルはすでに含まれていた)。MSYS2は最近pacman -Suyしたので最新のはず(国内のミラーって無くなってたのね)。

lib/gdk-pixbuf-2.0(画像ローダーdll)はコピーしなくてもSVG内のimage要素が表示されるみたい。環境変数PATHをSystem32だけにしたりmsys64ディレクトリを一時的にリネームしたりしても表示されるので、密かに画像ローダーが見つけられてしまっているわけでも無さそう。喜ばしいことではあるけど何でだろう。「librsvg decode image」でGoogle検索したらLibrsvg will use Rust-only image decoders starting on 2.58.0 - Federico's Blogというのが出てきた。ひょっとしてこれのおかげ? 去年の12月の記事だし、emacs-30.0.91.zipに入っているlibrsvgのバージョンも2.58.0になっている。bmpも表示できなくなっているので多分間違いない(対応しているのはJPEG、PNG、GIF、WebPのみ:Do not load images with gdk-pixbuf; use Rust loaders instead (!904) · マージリクエスト · GNOME / librsvg · GitLab)。

.emacs.dを29と分けるため、runemacs.exeへのショートカットに --init-directory= オプションを含めて ~/.emacs.d.30 を指すようにした(私はいつもrunemacs.exeへのショートカットをスタートメニューにemacs-xx.xという名前で入れていて、「Ctrl+ESC em RET」でEmacsを起動している。バージョンアップするときはいつもこのショートカットを入れ替える作業をしている)。29と一緒だとやはりバイトコンパイル済みのelispに問題が生じる。

ソースコード(https://alpha.gnu.org/gnu/emacs/pretest/emacs-30.0.91.tar.xz)をダウンロードしてfind-function-C-source-directoryがそれのsrcディレクトリを指すようにする。

image-diredが色々変更されているのでそれに追従する。私のカスタマイズと衝突しているので修正。まずは29から30へのlisp/imageディレクトリのdiffを取って変更点を理解する。image-dired-insert-thumbnail関数の引数が一つ減っているので、とりあえずそこだけ対応したらエラーは出なくなった。他にも何かあるかもしれない。

w32image-create-thumbnailという関数が追加された。image-diredはサムネイル作成用のプログラム(ImageMagickやGraphicsMagick)が存在しない場合はこの関数を使うようになった。パフォーマンスはどちらが良いのか分からない。0.05秒のタイマーで繰り返しているのは気になる。試しに (setq image-dired-cmd-create-thumbnail-program "hoge") などと存在しないプログラムを指定することで使ってみた。縦横比を無視して正方形のサムネイルが生成されてしまう。ExifのOrientationも考慮されなかった。パフォーマンスはそう大きく変わらないように感じたが、多分サムネイル生成部分以外が遅そうなので後で調べてみる。

(追記:パフォーマンス以前にw32image-create-thumbnailを使ってサムネイルを生成するimage-dired-thumb-queue-run関数の後半はタイマーの使い方が間違っていてサムネイルが全部出来るまで操作不能になってしまう。直るまで使わない方が良い)

Windowsでは、convert.exeがImageMagickのものかSystem32のものかを /? オプションを付けて実際に実行して判別するコードが追加された。これがqueue-runで呼び出されているのはパフォーマンス的に良くないと思う。というかいい加減convertなんてやめてmagickコマンドを使えば良いのに。

サムネイルのファイル名をファイル内容の先頭4096バイトのSHA-1にできる設定が追加されているが、これはどうなんだろう。どうもファイルを移動してもサムネイルが使い回せることが狙いのようだが、先頭4096バイトがたまたま同一な別の画像というのは普通にあり得るのではないだろうか。特にbmpのような圧縮しない形式においては。

2024-09-12

最近Emacs関連でやったカスタマイズ

tramp-default-methodをplinkにする

久しぶりにMSYS2をアップグレードしたせいか分からないけれど、なぜか突然trampがscpxで繋がらなくなった。少しだけ原因を調べてみたけどよく分からなかったので諦めてplinkを使うことに。これまで頑なにplinkを使うことを避けていたのだけど、使ってみたら超快適! なぜいままで使っていなかったのかと。パスフレーズの記憶がssh-agentと一緒にならないのは良くないところだけど。

暇があったらなぜ動かなくなったのか調べてみたい。そもそもtrampはどうやって動いているのかよく知らない。

Emacsの標準機能でメールを送れるようにする

これまでメールと言えばWanderlustばっかり使っていたんだけど、Emacsの標準機能だけでメールを送れるようにしてみた(Sending Mail (GNU Emacs Manual (Japanese Translation)))。

(setq smtpmail-default-smtp-server "smtp.gmail.com"
      smtpmail-smtp-server "smtp.gmail.com"
      smtpmail-smtp-service 587
      smtpmail-stream-type 'starttls
      smtpmail-local-domain nil
      smtpmail-smtp-user "<username>")

後は.authinfoにごにょごにょと。面倒だからアプリパスワードも使っちゃう。この辺りは人によってセキュリティ的に許容できないだろう。

ちなみにEmacsに標準で組み込まれているメール作成のためのパッケージ(MUA)には次のものがある(define-mail-user-agentで検索):

また、メールを送信する方法には次のものがある:

上の設定はsmtpmailで送るためのもの。

image-diredでサムネイルが横になるのを直す

ExifのOrientationで回転させている写真が回転していないので直した。

image-dired-cmd-create-thumbnail-options に "-auto-orient" オプションを追加しただけ。

image-diredのサムネイルサイズを変更

前々からどのくらいのサムネイルサイズが最適なんだろうかと疑問に思っていた。小さすぎると内容が分からないし、大きすぎると一度に沢山の画像を並べられない。私が普段使っているテキスト領域の幅は640pxなので、横に3つ並ぶサイズということで image-dired-thumb-size を 196 にした。サムネイル毎の余白に案外スペースを取られる。

縦画像のサムネイルが左寄せで表示されるので、そのうち中央寄せされるように直したい。

image-diredのキー割り当てを変更

サムネイルを表示するバッファ( *image-dired* バッファ)のキーマップがdiredと違っていて戸惑うことがよくあるので、できるだけdiredに近づけるようにした。特に外部ビューアで開くキー。

次表示(SPC)、前表示(DEL)は良くある操作方法だけど、DEL(私はC-hをDELにしている)が押しづらいのでnとpに割り当ててしまった。fとbの方が良いのかもしれないけれど、dired上でファイルを移動するのがnとpだし、next-lineではなくnext-imageだと考えればそこまでおかしくもない気がする。いや、やっぱりfとbの方が使いやすいだろうか。そもそもC-f C-m、C-b C-mと押すのがそんなに面倒だろうか。SPCはそれほど苦では無いのだから、bだけ割り当てれば良いのかもしれない。

image-diredは使えば使うほど直したいところが出てくるのでまたそのうち。