ちみもの三姉妹の目の描き方が三人とも違うのが好き。
ちみもの三姉妹の目の描き方が三人とも違うのが好き。
再現コード:
(progn (require 'svg) (goto-char (point-min)) ;; (insert "\n") ;;これがあると発生しづらい(スクロールして画像を一番上にもってくれば発生する) (let ((ov (make-overlay (point) (progn (insert " ") (point)) nil t))) (overlay-put ov 'evaporate t) (overlay-put ov 'pointer 'arrow) (overlay-put ov 'line-prefix "XXX") ;;これが無ければ発生しない(実際の状況ではこれが無くてもorg-indentがテキストプロパティのline-prefixを変更するといったことでこれと同じ事になる) (overlay-put ov 'display (let ((svg (svg-create 400 300))) (svg-rectangle svg 0 0 400 300 :fill "blue") (svg-text svg "Click here" :x 200 :y 150 :text-anchor "middle" :fill "white") (svg-image svg))) (overlay-put ov 'keymap (let ((km (make-sparse-keymap))) (define-key km [mouse-1] (lambda (ev) (interactive "e") (message "xy=%s" (posn-object-x-y (event-start ev))))) km))) (insert "\n"))
上のコードをscratchバッファで実行すると画像が表示される。その画像をクリックするとミニバッファに座標が表示されるが、画像の左上からの座標になっていないことが分かる。原点は画像の左上では無く「XXX」の左上になっている。
この現象は画像がウィンドウの先頭にあり、その左にline-prefixによる文字列があるときのみ起こる。(line-prefixはテキストプロパティ、オーバーレイプロパティ、line-prefix変数のいずれで設定しても現象は起きる)
Emacs Lisp Reference Manualの22.7.4 Click Eventsには、マウスイベントのdx,dyはobjectの左上角を(0 . 0)とする相対座標と書かれている。今回の場合はobjectは画像('imageで始まるdisplayプロパティ)になるので、画像の左上からの座標になっていなければならない。しかし、画像がウィンドウの先頭にあって、かつ、line-prefixが使われている時に限り、line-prefix文字列の左上からの座標になってしまっている。画像がウィンドウの先頭に無いときや、line-prefixが使われていないときは正しく画像左上からの座標になっている。動作に一貫性が無く、文書化されている仕様と異なる結果が生じているのでEmacsの問題と言って良いのではないかと思う。
回避策としては、マウスの入力を必要とする時だけline-prefixを無効化するといったことが考えられる。
実際にel-easydrawにおいて作図エディタがウィンドウの一番上にあるときに座標がずれる問題が発生していた。org-indentを有効にすると発生する。org-indentはline-prefixやwrap-prefixを使用するので、まさに今回のケースに当てはまる。コミット701bfaaにて一時的にline-prefixを無効化することで回避した。
おそらくEmacsのバグだと思うが、この問題に気がつく人はどのくらいいるのだろうか。Emacs内に画像を表示してその中に対してマウス入力するなんてことを伊達や酔狂で無く本気でやっている人はどのくらいいるのだろうか。
(2024-02-19追記: 手っ取り早く使い方を知りたい人はMS-Windows版 Emacs 29.1への移行作業をご覧下さい)
前回の続き。
MSYS2のセットアップについては割愛します。Emacsはlibgccjitを使用してネイティブコンパイルを行うため、それに関連したファイル群をMSYS2から入手する必要があります。おそらく base-devel, mingw-w64-x86_64-toolchain, mingw-w64-x86_64-libgccjit あたりのパッケージが入っていれば良いのだと思います。
ただし実際にEmacsを使用するときにはMSYS2全体は必ずしも必要なく、少数のファイルだけコピーして他のPCに移すことも出来ます。
ここでは公式配布の emacs-28.1.zip を前提に説明しますが、自分で --with-native-compilation
を指定してビルドしたEmacsを他の環境へ移す場合にも同じ考え方が適用出来ると思います。ちなみに emacs-28.1.zip は --with-native-compilation
を指定してビルドされていますが(C-h v system-configuration-optionsで確認できる)ネイティブコンパイルに必要なDLL等が含まれていない状態です。
Emacsが起動する前に、環境変数PATHにMSYS2内の mingw64/bin
ディレクトリが含まれていればネイティブコンパイルは正常に動作します(もちろんlibgccjitパッケージがインストールされていること)。
Windowsの「システムの詳細設定」で環境変数を変更するか、次のようなbatファイルを経由するといった方法が考えられます。
set PATH=c:/hogehoge/msys/mingw64/bin;%PATH% c:/hogehoge/emacs-28.1/bin/runemacs.exe
mingw64/bin/には libgccjit-0.dll, as.exe, ld.exe が含まれている必要があります。また、 mingw64/lib/以下には必要なライブラリが含まれている必要があります。
ここで大事なのは「Emacsの起動前から」という点です。
環境変数を変更するには early-init.el や init.el 内でsetenv関数を呼び出す方法もありますが、それだと起動後すぐのネイティブコンパイルには適用されません。一番最初のネイティブコンパイルは early-init.el よりも前に起動する場合があります。なので early-init.el で (setenv "PATH" ~) しても手遅れな場合があります。
この方法は環境変数PATHを常時変更するため、人によっては許容できない場合があります。例えばCygwinやその他GNUツールを含むプロダクトに既にPATHが通っていてEmacs使用中にそのコマンドを使いたい場合です。
alpha.gnu.org has shiny new Emacs 28.0.91 Windows binaries : emacs のコメントによれば、ネイティブコンパイルに必要なファイルは次の17個だそうです。
これらをemacs-28.1.zipを展開して出来たディレクトリの適切なディレクトリへコピーするとネイティブコンパイルが条件付きで動作するようになります。libgccjit-0.dll は bin (既にrunemacs.exe等があるディレクトリ)へ、それ以外は lib (既にemacs/やsystemd/がある)の下にgccというディレクトリを作成してその中へ入れてください。
これだけである程度の割合でネイティブコンパイルが成功するようになるのですが、自動で起動する非同期コンパイルがなぜか失敗する場合があります(カレントディレクトリがbinやlib等の階層に無い場合にas.exeが無いと言われます)。
そこで early-init.el (あるいはinit.el)に次のコードを追加します。
(2022-09-23追記: Windows版Emacsを28.1に上げたのでNative Compilationフィーバーに便乗する - Qiitaにあるように native-comp-driver-options 変数に -B オプションを指定した方が良さそうです。私はearly-init.elで (setq native-comp-driver-options (list "-B" (expand-file-name (file-name-concat invocation-directory "../lib/gcc")) ))
のようにしました)
(when (and (fboundp #'native-comp-available-p) ;;emacs-28以降 (native-comp-available-p) ;;libgccjitが使える (eq system-type 'windows-nt)) ;;Windowsの場合 (他必要に応じて条件を追加すること) (defun my-comp-wrap-process-call (orig-fun &rest args) (let* (;; emacs.exeのあるディレクトリの一つ上のlib/gcc (lib-dir (expand-file-name (file-name-concat invocation-directory "../lib/gcc"))) ;; 環境変数PATHとLIBRARY_PATHを一時的に変更 (process-environment (append (list (concat "PATH=" lib-dir ";" (getenv "PATH")) (concat "LIBRARY_PATH=" lib-dir)) process-environment))) ;; 元の関数を呼び出す (apply orig-fun args))) ;; コンパイル用にemacsを起動する関数をラップする (advice-add #'comp-final :around #'my-comp-wrap-process-call) (advice-add #'comp-run-async-workers :around #'my-comp-wrap-process-call))
このコードはネイティブコンパイルのために別プロセスでemacsを起動するときにだけ環境変数PATHとLIBRARY_PATHを変更します。起動されたemacsは最初からネイティブコンパイルに必要なコマンドにPATHが通った状態になります。
つまり、early-init.elより前に起動するネイティブコンパイルについてはlib/gccに置いたas.exeやld.exeが使われることによって解決し、それ以降なぜかエラーになるケースについては環境変数の一時的な変更で解決します。
ちなみに前者はあらかじめ必要なファイルをネイティブコンパイルしておくことによって回避可能です。エラーが出るファイルを手動でネイティブコンパイルしたり、試してはいませんが NATIVE_FULL_AOT=1 でビルドすると回避できるかもしれません。
なお、既にCygwin等にPATHが通っていると、設定が間違っていてもCygwinのas.exeやld.exeが起動する場合があるので注意が必要です。
なぜか失敗するケースは、調べた限りコンパイル時のカレントディレクトリによるようなので次のようなコードでも良いかもしれません。ただ、ネイティブコンパイルがカレントディレクトリに依存している(または将来するようになる)とまずいかもしれません。
(when (and (fboundp #'native-comp-available-p) ;;emacs-28以降 (native-comp-available-p) ;;libgccjitが使える (eq system-type 'windows-nt)) ;;Windowsの場合 (他必要に応じて条件を追加すること) (defun my-comp-wrap-process-call (orig-fun &rest args) ;; 一時的にカレントディレクトリを emacs-28.1/bin にする ;; でないと emacs-28.1/lib/gcc/as.exe を見つけてくれない (let ((default-directory invocation-directory)) ;; 元の関数を呼び出す (apply orig-fun args))) ;; コンパイル用にemacsを起動する関数をラップする (advice-add #'comp-final :around #'my-comp-wrap-process-call) (advice-add #'comp-run-async-workers :around #'my-comp-wrap-process-call))
最も単純な方法は comp.el を修正することだと思います。
前述の通りネイティブコンパイルはearly-init.elよりも前に起動する場合があり、comp.elもその時にロードされます。
従ってearly-init.elやinit.elで挙動を完全に修正するのは無理なので、comp.elを直接書き替えてしまった方が素直な方法となるでしょう。(Emacsの初期化プロセスについて詳しくないので他に何か方法があったらすみません)
具体的には、前と同じようなことをcomp.elの末尾に書き加えてやれば良いでしょう。例えば:
;; share/emacs/28.1/lisp/emacs-lisp/comp.el の末尾、(provide 'comp)の前に以下を追加 (defconst my-comp-tool-path "c:/hogehoge/msys/mingw64/bin") ;;自分のmingw64/binの場所 (defun my-comp-wrap-process-call (orig-fun &rest args) (let* ((process-environment (cons (concat "PATH=" my-comp-tool-path ";" (getenv "PATH")) process-environment))) ;; 元の関数を呼び出す (apply orig-fun args))) ;; コンパイル用にemacsを起動する関数をラップする (advice-add #'comp-final :around #'my-comp-wrap-process-call) (advice-add #'comp-run-async-workers :around #'my-comp-wrap-process-call)
my-comp-tool-pathにはmingw64/binの場所を指定してください。もしくは前にやったようにemacs.exeの位置から相対的に割り出しても良いでしょう(関連ファイルのコピーが必要になりますが)。
ファイル(comp.el)の途中を書き替えるのも分かりづらいかなと思ったのでadviceのままにしてあります。make-processやcall-processの前後を直接書き替えても良いでしょう。
comp.elを書き替えたら対応する.elcや.elnを削除するのもお忘れ無く。
Emacs 28.2がリリースされてWindows版の公式ビルドも公開されました。
Index of /gnu/emacs/windows/emacs-28
emacs-28.2.zipを展開して、MSYS2のlibgccjit-0.dllとlibisl-23.dllをemacs-28.2/binへ、その他のライブラリやらas.exe、ld.exeやらをemacs-28.2/lib/gcc/へコピーし、early-init.elで (setq native-comp-driver-options (list "-B" (expand-file-name (file-name-concat invocation-directory "../lib/gcc")) ))
と指定しただけで問題なくNative Compileできるようになりました。
ちなみに、最初MSYS2最新のlibgccjit-0.dllをbinに入れてもNative Compileが有効になりませんでした((native-comp-available-p)がnil)。
それをTwitterに書いたところ、libisl-23.dllも必要になったとの情報を頂きました。
まとめ参考になりました。
libisl -23.dll も必要みたいです。— re102951 (@re102951) September 23, 2022
調べてみると確かに最新のlibgccjit-0.dll内にはlibisl-23.dllという文字列があります。libgccjitのバージョンアップに伴い依存するdllが増えたようです。libisl-23.dllもemacs-28.2/binへコピーしたところnative-comp-available-pがtになりました。
こういうことがあるからバイナリ配布するならlibgccjit(や関連ファイル)も一緒に配布してほしいものです。
MS-Windows版 Emacs 29.1へ移行に書きました。dllが二つ増えていただけです。
(2024-02-19追記: 手っ取り早く使い方を知りたい人はMS-Windows版 Emacs 29.1への移行作業をご覧下さい)
Emacs 28.1がリリースされましたね。私は少し前にpretestをいじりましたがすぐに27.2に戻ったので28系を本格的に使うのはようやくこれからです。
Windows版が見当たらないので自分でビルドしようかなーと思っていたらすぐにアップロードされたのでそれ(emacs-28.1.zip)をダウンロードして試してみました。
Emacs 28と言えば大分前からネイティブコンパイルという単語をあちこちで見かけていました。WindowsでGCCに依存した機能って大変なんじゃないの? と思っていたので期待はしていなかったのですが、一応どうなっているのか調べてみることにしました。
Native Compilation (GNU Emacs Lisp Reference Manual)
ええと何々
Emacsのカレントプロセスでネイティブコンパイル済みLispコードの生成およびロードが可能かどうか判断するには、native-comp-available-p (Native-Compilation Functionsを参照)を呼び出してください。
(native-comp-available-p)
nil
あー、やっぱり……。そもそも emacs-28.1.zip の中にGCCなんて入ってないですもんね。
ええと、ネイティブコンパイル機能はlibgccjitを利用していてビルド時に --with-native-compilation
の指定が必要。MSYS2にはlibgccjitパッケージもちゃんとあるんですね。
仕方ない、ビルドしますか。以前ビルドした時のMSYS2環境が残っていますし。MSYS2のEmacsパッケージ(mingw-w64-x86_64-emacs)もまだ27.2みたいですし。
(2022-04-07追記: 公式配布のWindows版はどうやら --with-native-compilation
付きでビルドされているようです。ただし必要なDLLが含まれていないので (native-comp-available-p)
は nil
になります。MSYS2のmingw64/bin/libgccjit-0.dllをEmacsのbinへコピーするかmingw64/binへPATHを通したら (native-comp-available-p)
は t
になりました。なので以下のビルドはしなくても行けます。ただしmingw64/binへ常にPATHを通したくない場合は色々と調整する必要があります(後述))
nt/INSTALLやnt/INSTALL.W64等を見るにビルド方法に大きな変更は無さそうです。
まずはMSYS2から既存パッケージのアップグレード(sourceforgeのミラーが廃止されたんですね。/etc/pacman.d以下を少し修正)。
その後今回追加で必要になるであろうmingw-w64-x86_64-libgccjitをインストール。
pacman -S mingw-w64-x86_64-libgccjit
次にMinGW64環境からビルド。 --without-dbus
や --with-gnutls
は前にビルドした時に付けていたので一応。今も必要なのか不明。 --with-native-compilation
は無いとダメだったので付けました。 --prefix
にはインストール先を明示的に指定します。後でMinGW64環境と分離したいので。
mkdir 20220406 && cd 20220406 wget https://ftp.gnu.org/gnu/emacs/emacs-28.1.tar.gz tar xvfz emacs-28.1.tar.gz ./configure --without-dbus --with-gnutls --with-native-compilation --prefix=/c/hogehoge/emacs-28.1 make -j4 #4はコア数 make install-strip /c/hogehoge/emacs-28.1/bin/runemacs.exe -Q # 試しに起動
(native-comp-available-p)
t
うん、大丈夫っぽい。というか裏で自動的にコンパイルが走っててキモいんですけど(笑)
次にMSYS2 MinGW環境以外からでも単独で起動できるように必要なDLL等をemacsのディレクトリへコピーします。
これで runemacs.exe をエクスプローラ等から直接実行しても起動するようになりますが……やはりネイティブコンパイルでエラーが出まくります。libgccjitがGCCを見つけられないのですから当たり前ですよね。というかCygwinのが起動されてるっぽい? ldがライブラリが見つからないとか言ってます。私はCygwinの方にはPATHを通してしまっていますからね。Cygwinのldが起動されて、それがMinGWのライブラリが見つけられないという流れになってしまっているのかもしれません。
Internals — libgccjit 12.0.1 (experimental ) documentation あたりを見ると、PATH、LIBRARY_PATHあたりの環境変数をちゃんとすれば何とかなりそう。
試しに (setenv "PATH" (concat "c:/hogehoge/msys/mingw64/bin;" (getenv "PATH")))
を評価してPATHの先頭にMinGWのbinを追加したところコンパイルが成功するようになりました。
うーん、でも常時MinGWにPATHを通したくないんだよなぁ……。
native-comp-async-env-modifier-form
という変数があったので、そこで環境変数を設定してみるもうまくいかず。
ネイティブコンパイルは外部のemacsを起動して行う(コンパイル用のelファイルを生成して、 emacs --batch -l ????.el
を起動する)みたいなので、その起動時にだけ環境変数を追加することにしました。
(when (and (fboundp #'native-comp-available-p) (native-comp-available-p)) (defun my-comp-set-env (orig-fun &rest args) (let ((process-environment (append (list (concat "PATH=c:/hogehoge/msys/mingw64/bin;" (getenv "PATH")) ;;"LIBRARY_PATH=c:/hogehoge/msys/mingw64/lib" 不要っぽい ) process-environment))) (apply orig-fun args))) (require 'comp) (advice-add #'comp-final :around #'my-comp-set-env) ;; call-processでemacsを起動している (advice-add #'comp-run-async-workers :around #'my-comp-set-env)) ;;make-processでemacsを起動している
適当ですがとりあえず。これで直接runemacs.exeを起動したとき(PATHにmingw64/binが含まれていないとき)でもネイティブコンパイルが成功するようになりました。
で、 ~/.emacs.d/eln-cache/ に色々ファイルが生成されているわけですが、これってちゃんと使われているのでしょうか。スピードも上がっているのでしょうか。後で調べてみようっと。
(2022-04-08追記:)
28.0.91(pretest)のWindows用バイナリが出たときのredditの投稿に、参考になることが色々書いてありました。
alpha.gnu.org has shiny new Emacs 28.0.91 Windows binaries : emacs
中でも、MSYS2から17ファイルほどコピーすればMSYS2無しでもネイティブコンパイルが出来るのだとか。
MSYS2の中からファイルを探してemacs-28.1.zipを展開したディレクトリ下の上記の場所にコピーして試したところ、確かに関数の同期コンパイルくらいは出来ているように見えます(私のPCはCygwinのldにPATHが通ってたりするので、他のPCで再現しない可能性あり。後でちゃんと確認します)。非同期のコンパイルはPATHを調整しないとダメだとも書いてあります。
後でもう少し詳しく調べて追記します。
(2022-04-11追記: 別の記事として書きました)
Emacs27になってからSVG画像内のimage要素が表示されなくて困ったのですが、調べたところ lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
ファイルが無いのが原因だと分かりました。
いずれも Index of /gnu/emacs/windows にある公式のWindows版ビルドでの話です。独自ビルドして必要そうなDLLファイルをMinGWから抜き出した場合も起こるかもしれません。
例えば次のようなSVGでimage要素の部分が表示されずblueのrectだけが表示されます。
<svg width="400" height="300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <rect x="10px" y="10px" width="100px" height="80px" fill="blue" /> <image xlink:href="image1.jpg" x="20px" y="20px" width="100px" height="100px" /> <image xlink:href="image2.png" x="30px" y="30px" width="100px" height="100px" /> <image xlink:href="image3.bmp" x="40px" y="40px" width="100px" height="100px" /> </svg>
image1.jpg
、 image2.png
、 image3.bmp
はSVGと同じディレクトリにあるものとします。もちろんブラウザ等、他のソフトウェアでは正しく表示されます。Emacsでの確認方法は色々ありますがdiredから開くだけでも十分です。
https://ftp.gnu.org/gnu/emacs/windows/emacs-26/emacs-26.3-x86_64.zip
問題は起きません。正しく表示されます。
https://ftp.gnu.org/gnu/emacs/windows/emacs-27/emacs-27.2-x86_64.zip
image要素が表示されません。
cmdプロンプトで emacs-27.2-x86_64/bin
ディレクトリへ移動し、次のコマンドを実行すると emacs-27.2-x86_64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
というファイルが生成されます。
gdk-pixbuf-query-loaders.exe --update-cache
Emacsを再起動して再び試してみると正しく表示されました。
https://ftp.gnu.org/gnu/emacs/windows/emacs-28/emacs-28.1.zip
image要素が表示されません。
そもそも emacs-28.1/lib/
以下に gdk-pixbuf-2.0
がありません。
Emacs27のファイル(emacs-27.2-x86_64/lib/gdk-pixbuf-2.0
以下。もちろん loaders.cache
も)をEmacs28へコピーしたところ正しく表示されました。
loaders.cache
を削除すると正しく表示されないので、Emacs28でもこのファイルは必要なようです。 emacs-28.1.zip
には gdk-pixbuf-query-loaders.exe
が含まれていないので、生成するにはEmacs 27の場合の手順を踏んでそちらからコピーしてくるのが手っ取り早いと思います。
EmacsはSVGの描画にlibrsvgを使用していますが、librsvgは画像の処理にlibgdk_pixbufを使用しています。
libgdk_pixbufで画像を読み込むには画像の形式に対応するローダーライブラリが必要で、それが lib/gdk-pixbuf-2.0/2.10.0/loaders/
以下にあるDLLファイル群です。
loaders.cache
ファイルには、DLLファイルへのパスとそれが受け付けるMIMEタイプ、拡張子、ファイル先頭のマジックナンバー等の対応表が記されているようです。詳しくは調べていませんが、このファイルが無いとlibgdk_pixbufは画像を読み込めないようです。
不思議なことにEmacs26はこのファイルが無くても正しく読み込めていました。おそらくライブラリのバージョンアップに伴って必要になったのではないでしょうか。
EmacsでSVG内のimage要素、それもWindowsで扱う必要がある人はどれだけいるのでしょうか。多分ほとんどの人が問題に気がついていないのだと思います(まさか私の環境だけ起きてる?)。
しかしsvg.elにはsvg-embedのようなimage要素を使う機能も存在します。
また、Emacs28ではSVG内のimage要素が外部ファイルを参照する時の基準ディレクトリを指定する機能も追加されました。(https://github.com/emacs-mirror/emacs/blob/78ecd67888566167fb4c881d8350f611fa039649/etc/NEWS.28#L2417 )
図形だけでも面白いのに画像を自由に配置できるとなればもっと面白いことが色々出来るはずです。皆さんも是非試してみてはいかがでしょうか。
私も試しにimage要素を沢山生成して遊んでみました。
一枚一枚の画像をtransform属性で変形し(残念ながら透視投影は無理なので正射影です)、面単位でZソートを行っています。
結構遅いです。
何となくEmacs Lisp側というよりは描画ライブラリ側が遅いような気が。
一応任意のアメダス観測所の計測データを取得できるようにしてみました。あまり使う予定はありませんが。
misohena/el-jma: Emacs Interface for Japan Meteorological Agency Data
使い方。
まずはアメダスの観測所番号を調べます。 jma-amedas-read-amedas-code
関数で補完付きの入力ができるようになっているのでそれを使います。
(require 'jma-amedas) (jma-amedas-read-amedas-code)
番号が分かったら jma-amedas-point-latest
に渡すだけです。
(jma-amedas-point-latest ;;最新のデータを取得 "44112");;八王子
結果は次のようになります。
(\20220226141000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.8 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0]))
一応アクセッサがあるのでそれを使うと楽にデータを取り出せます。
(let* ((amedas-code "44112") (sample (jma-amedas-point-latest amedas-code))) (format "%sの%sの気温は%s℃、降水量(前1時間)は%smmです" (jma-amedas-point-name (jma-amedas-point amedas-code)) (format-time-string "%Y-%m-%d %H:%M" (jma-amedas-sample-time sample)) (or (jma-amedas-sample-temp sample) "-") (or (jma-amedas-sample-precipitation1h sample) "-")))
"八王子の2022-02-26 14:10の気温は12.6℃、降水量(前1時間)は0.0mmです"
取り出せる情報は設備の種類によって異なります(気象庁 | アメダスあたりを参照のこと)。
また、計測値の品質に問題がある場合はnilを返します。生データの配列(上の例だと(temp . [12.6 0])等)の二番目の要素が品質を示す値で、0のとき正常を意味します。
期間を指定して取得することも可能です。
(let* ((max-time (jma-amedas-latest-time)) (min-time (time-add max-time (* -5 60 60)))) (jma-amedas-point-samples-between "44112" min-time max-time))
((\20220226093000 (prefNumber . 44) (observationNumber . 112) (temp . [9.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [1.0 0]) (maxTempTime (hour . 0) (minute . 27)) (maxTemp . [9.7 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 20) (minute . 31)) (gustDirection . [13 0]) (gust . [4.4 0])) (\20220226094000 (prefNumber . 44) (observationNumber . 112) (temp . [9.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [4 0]) (wind . [1.5 0]) (maxTempTime (hour . 0) (minute . 40)) (maxTemp . [9.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 20) (minute . 31)) (gustDirection . [13 0]) (gust . [4.4 0])) (\20220226095000 (prefNumber . 44) (observationNumber . 112) (temp . [10.0 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [5 0]) (wind . [2.3 0]) (maxTempTime (hour . 0) (minute . 46)) (maxTemp . [10.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 0) (minute . 50)) (gustDirection . [7 0]) (gust . [5.4 0])) (\20220226100000 (prefNumber . 44) (observationNumber . 112) (temp . [10.3 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [3.6 0]) (maxTempTime (hour . 0) (minute . 56)) (maxTemp . [10.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 0) (minute . 58)) (gustDirection . [8 0]) (gust . [5.8 0])) (\20220226101000 (prefNumber . 44) (observationNumber . 112) (temp . [10.1 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [3.1 0]) (maxTempTime (hour . 0) (minute . 56)) (maxTemp . [10.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 0) (minute . 58)) (gustDirection . [8 0]) (gust . [5.8 0])) (\20220226102000 (prefNumber . 44) (observationNumber . 112) (temp . [10.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.0 0]) (maxTempTime (hour . 1) (minute . 15)) (maxTemp . [10.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226103000 (prefNumber . 44) (observationNumber . 112) (temp . [11.2 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [3.2 0]) (maxTempTime (hour . 1) (minute . 29)) (maxTemp . [11.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226104000 (prefNumber . 44) (observationNumber . 112) (temp . [11.2 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [3.1 0]) (maxTempTime (hour . 1) (minute . 39)) (maxTemp . [11.7 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226105000 (prefNumber . 44) (observationNumber . 112) (temp . [10.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [3.0 0]) (maxTempTime (hour . 1) (minute . 39)) (maxTemp . [11.7 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226110000 (prefNumber . 44) (observationNumber . 112) (temp . [11.2 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [3.6 0]) (maxTempTime (hour . 1) (minute . 58)) (maxTemp . [11.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226111000 (prefNumber . 44) (observationNumber . 112) (temp . [11.5 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.5 0]) (maxTempTime (hour . 1) (minute . 58)) (maxTemp . [11.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226112000 (prefNumber . 44) (observationNumber . 112) (temp . [11.5 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [9 0]) (wind . [2.8 0]) (maxTempTime (hour . 2) (minute . 14)) (maxTemp . [12.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226113000 (prefNumber . 44) (observationNumber . 112) (temp . [11.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [2.6 0]) (maxTempTime (hour . 2) (minute . 14)) (maxTemp . [12.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226114000 (prefNumber . 44) (observationNumber . 112) (temp . [12.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.4 0]) (maxTempTime (hour . 2) (minute . 40)) (maxTemp . [12.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226115000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [9 0]) (wind . [3.0 0]) (maxTempTime (hour . 2) (minute . 50)) (maxTemp . [12.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226120000 (prefNumber . 44) (observationNumber . 112) (temp . [12.7 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.0 0]) (maxTempTime (hour . 2) (minute . 55)) (maxTemp . [13.0 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 0)) (gustDirection . [8 0]) (gust . [7.5 0])) (\20220226121000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [4.9 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 6)) (gustDirection . [7 0]) (gust . [8.3 0])) (\20220226122000 (prefNumber . 44) (observationNumber . 112) (temp . [12.1 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [5.1 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 6)) (gustDirection . [7 0]) (gust . [8.3 0])) (\20220226123000 (prefNumber . 44) (observationNumber . 112) (temp . [12.1 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.1 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 21)) (gustDirection . [9 0]) (gust . [9.7 0])) (\20220226124000 (prefNumber . 44) (observationNumber . 112) (temp . [12.3 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [5.5 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 21)) (gustDirection . [9 0]) (gust . [9.7 0])) (\20220226125000 (prefNumber . 44) (observationNumber . 112) (temp . [12.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.8 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 21)) (gustDirection . [9 0]) (gust . [9.7 0])) (\20220226130000 (prefNumber . 44) (observationNumber . 112) (temp . [12.5 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [7.3 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 58)) (gustDirection . [7 0]) (gust . [10.1 0])) (\20220226131000 (prefNumber . 44) (observationNumber . 112) (temp . [12.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.6 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 7)) (gustDirection . [8 0]) (gust . [10.6 0])) (\20220226132000 (prefNumber . 44) (observationNumber . 112) (temp . [12.7 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.9 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 20)) (gustDirection . [8 0]) (gust . [10.9 0])) (\20220226133000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.0 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 28)) (gustDirection . [8 0]) (gust . [12.5 0])) (\20220226134000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [7.4 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 28)) (gustDirection . [8 0]) (gust . [12.5 0])) (\20220226135000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [7.9 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 28)) (gustDirection . [8 0]) (gust . [12.5 0])) (\20220226140000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [9.3 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0])) (\20220226141000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.8 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0])) (\20220226142000 (prefNumber . 44) (observationNumber . 112) (temp . [13.0 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.0 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0])) (\20220226143000 (prefNumber . 44) (observationNumber . 112) (temp . [13.0 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [7.2 0]) (maxTempTime (hour . 5) (minute . 29)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0])))
1度のアクセスで10分毎の計測データが3時間分まとめて取得できるので、必要なだけアクセスして結果をつなぎ合わせてから不要な部分をカットしています。サーバへのアクセス頻度が高くなりがちなのでご注意ください(とは言え気象庁の観測データ一覧ページで行っていることと同じではあります)。
過去数日程度のデータしか取得できないようです。それ以前のデータは気象庁|各種データ・資料のあたりから取得しましょう。
Emacs上で気象庁の天気予報を取得するものを作りました。
misohena/el-jma: Emacs Interface for Japan Meteorological Agency Data
例によってorg-modeのagenda上にも天気を表示できます。
気象庁の提供するデータについては次のTweetを始め色々な資料がありました。
一番伸びてるのはこれかしら。仕様の継続性や運用状況のお知らせを気象庁はお約束していないという意味で、APIではないと申し上げざるを得ないのですが、一方で政府標準利用規約に準拠してご利用いただけます。 https://t.co/QLuhI4DNDv
— TOYODA Eizi (@e_toyoda) February 24, 2021
実際に天気予報を取得するにあたって、一番理解が難しかったのが予報区に関する知識でした。東京の天気を知りたかったら東京のコードを使ってデータを取得するだけなんじゃないの? と思いきや、事情はもう少し複雑でした。
天気予報のデータは概ね都道府県単位に近い区分(府県予報区)毎に取得(ダウンロード)できるのですが、そのデータの中はさらに場所が細分化されています。東京であれば、東京地方、伊豆諸島北部、伊豆諸島南部、小笠原諸島といった具合です。このサブエリアを一次細分区域と呼びます。東京都と言ってもこれらを一緒くたにはできませんから当然な話です。
それで済むかと思いきや、気温のデータだけ別のエリアコードが使われています。調べたところ、最低気温と最高気温の予報はアメダス観測所の地点のものが発表されており、そのアメダス観測所の名前とコードが使われています。東京の場合は、東京、大島、八丈島、父島といった具合です。それぞれ一次細分区域と対応していますが、一つの一次細分区域に複数のアメダス観測所がある府県もあります。
これで終わりかと思いきや、週間天気予報はまた別なエリア分けが使われています。気象庁|週間天気予報の解説には次のような記述があります。
「府県週間天気予報」は原則として府県予報区ごとに予報していますが、東京都と鹿児島県では、常に予報区内の区域を細分して予報しています(東京都は、東京地方と伊豆諸島と小笠原諸島に、鹿児島県は、鹿児島県(奄美地方除く)と奄美地方に、それぞれ細分)。また、季節を限定して区域を細分している予報区もあります。
基本的には週間予報は府県予報区単位の荒い予報ということになっているようですが、地形的・季節的な要因で多少細分化されています。
この週間天気予報で使用する区分けは府県予報区とも一次細分区域とも異なります。府県予報区や一次細分区域と同等になる区域は同じ名前やコードが使われていますが、どちらとも一致しない区域は独自の名前やコードが使われています。この区分けには明確な用語の定義が見当たらなかったので、とりあえず「週間予報区域」と呼ぶことにしました(今から思えば「府県週間予報区」くらいだったかなとも思いますが)。JSONの中ではweekと書いてあることが多いです。
一次細分区域と異なる範囲になるのでその下の選択すべきアメダス観測所も変わってきます。ただ、この週間予報区域に対応するアメダス観測所は一つのみに限定されるようです。
というわけで、場所を指定するのに五つもコードを指定しなければならなくなっていますがお許しください。一応 jma-forecast-area-read
コマンドでコードを調べられるようになってます。市区町村から調べられればより良いのですが、その辺りは今後の課題と言うことで。
天気予報の取得方法については https://github.com/misohena/el-jma/blob/main/docs/how-to-get-jma-forecast.org にもメモを残しておきました。具体的なデータ例も https://github.com/misohena/el-jma/tree/main/example-data にあります。
評 | 開始日 | タイトル | 曜 | 時刻 | 配信元 |
---|---|---|---|---|---|
× | 2022/01/04(火) | イロドリミドリ | 水 | 01:05 | dアニメ |
- | 2022/01/05(水) | テイコウペンギン | - | - | |
× | 2022/01/05(水) | ハコヅメ~交番女子の逆襲~ | 木 | 00:00 | dアニメ |
○ | 2022/01/05(水) | リアデイルの大地にて | 水 | 23:00 | dアニメ |
△ | 2022/01/05(水) | 東京24区 | 土 | 12:00 | dアニメ |
× | 2022/01/07(金) | 終末のハーレム | 土 | 01:30 | dアニメ |
○ | 2022/01/07(金) | スローループ | 金 | 22:30 | dアニメ |
- | 2022/01/07(金) | ジョジョの奇妙な冒険 第6部 ストーンオーシャン | - | - | |
× | 2022/01/07(金) | ドールズフロントライン | 土 | 12:00 | dアニメ |
- | 2022/01/07(金) | からかい上手の高木さん3 | 土 | 02:00 | dアニメ |
× | 2022/01/07(金) | CUE! | 土 | 02:55 | dアニメ |
△ | 2022/01/08(土) | その着せ替え人形は恋をする | 日 | 00:30 | dアニメ |
△ | 2022/01/08(土) | 明日ちゃんのセーラー服 | 日 | 01:00 | dアニメ |
- | 2022/01/08(土) | 現実主義勇者の王国再建記 第2期 | - | - | |
× | 2022/01/08(土) | 怪人開発部の黒井津さん | 日 | 02:30 | dアニメ |
○ | 2022/01/08(土) | 失格紋の最強賢者 | 日 | 23:30? | ABEMA |
○ | 2022/01/09(日) | 時光代理人-LINK CLICK- | 日 | 22:30 | Amazon |
× | 2022/01/09(日) | 錆色のアーマ-黎明- | 日 | 22:30 | dアニメ |
× | 2022/01/09(日) | 薔薇王の葬列 | 日 | 23:00 | dアニメ |
× | 2022/01/09(日) | フットサルボーイズ!!!!! | 日 | 23:30 | ABEMA |
- | 2022/01/09(日) | 進撃の巨人 The Final Season 第2クール | - | - | |
△ | 2022/01/09(日) | 王子の本命は悪役令嬢 | 月 | 01:00 | dアニメ |
- | 2022/01/10(月) | ガル学。Ⅱ~Lucky Stars~ | - | - | |
△ | 2022/01/10(月) | トライブナイン | 月 | 22:30 | dアニメ |
- | 2022/01/10(月) | 範馬刃牙(バキ 続編) | - | - | |
× | 2022/01/06(木) | 最遊記RELOAD -ZEROIN- | 火 | 00:00 | dアニメ |
- | 2022/01/10(月) | プリンセスコネクト!Re:Dive Season2 | - | - | |
× | 2022/01/10(月) | 幻想三國誌 天元霊心記 | 火 | 12:00 | dアニメ |
△ | 2022/01/11(火) | 賢者の弟子を名乗る賢者 | 水 | 00:00 | dアニメ |
○ | 2022/01/10(月) | 錆喰いビスコ | 水 | 00:30 | ABEMA |
△ | 2022/01/11(火) | 天才王子の赤字国家再生術 | 木 | ? | ABEMA |
△ | 2022/01/11(火) | 異世界美少女受肉おじさんと | 木 | ? | ABEMA |
△ | 2022/01/12(水) | オンエアできない! | 木 | 00:00 | dアニメ |
- | 2022/01/12(水) | BABY-HAMITANG | - | - | |
- | 2022/01/12(水) | 漢化日記 | - | - | |
△ | 2022/01/12(水) | 殺し愛 | 水 | 23:30 | dアニメ |
○ | 2022/01/12(水) | 平家物語 | 木 | 12:00 | dアニメ |
× | 2022/01/13(木) | オリエント | 木 | 01:30 | ABEMA |
- | 2022/01/13(木) | ありふれた職業で世界最強 2nd season | - | - | |
△ | 2022/01/13(木) | あたしゃ川尻こだまだよ | 金 | 01:30? | Gyao! |
- | 2022/01/14(金) | ヴァニタスの手記 第2クール | - | - | |
△ | 2022/01/14(金) | ニンジャラ | 金 | 12:00 | dアニメ |
○ | 2022/01/16(日) | 佐々木と宮野 | 月 | 00:00 | dアニメ |
- | 2022/01/20(木) | お昼のショッカーさん | |||
- | 2022/01/21(金) | テイルズ オブ ルミナリア -The Fateful Crossroad- | |||
○ | 2022/01/30(日) | リーマンズクラブ | 日 | 12:00 | dアニメ |
- | 2022/01/28(金) | 地球外少年少女 | |||
- | 2022/01/30(日) | 永遠の831 | |||
- | 2022/01/–(-) | 闇芝居 十期 | |||
△ | 2021/02/09(水) | デリシャスパーティ♡プリキュア | 水 | 00:00 | dアニメ |
次の方法があります。
必ずしもF-Droidアプリは必要なくTermuxパッケージのページから直接apkをダウンロードすることもできます。GitHubからも(Debug版ですが)apkファイルをダウンロードできます。ビルドはそれほど難しくは無いと思います。
署名の問題があるので別の供給元から入手したものは共存できません。切り替えるにはいったんアンインストールが必要です(必要に応じてバックアップすること)。
私は最終的に次の二つを自分でビルドしてインストールしました。
ソースをgit cloneで入手し、既にPCに入っていたAndroid Studioでプロジェクトを開いてRunボタンを押したらすんなり成功しました。
画面左端から右へスワイプすると、ドロワー(サイドバー)が出てきます。
KEYBOARDを 長押し すると、下部ツールバーの表示状態を切り替えられます。
下部ツールバーを左スワイプすると、Text Input Viewが出てきます。ここはInput Methodが効くので日本語を入力するのに使えます。私は上部で入力できるように改造したので今はほぼ使っていません。
色々ショートカットが割り当てられています。
先日書きました。
Termuxでハードウェアキーボードからスムーズに日本語入力したい | Misohena Blog
pkg upgrade pkg install emacs emacs
普通に起動します!
自分の設定を持ってくるためにsshとgitをインストールしました。
pkg install openssh pkg install git
鍵を作ってサーバに設定。
ssh-agentは .bashrcに . source-ssh-agent を追加するだけ。簡単!
(https://www.reddit.com/r/termux/comments/b8il5p/sshagent_want_to_start_again_when_new_terminal_is/ より)
Gitで自分の設定を持ってきて……
git clone --recursive ssh://hogehoge/my-emacs-config.git cp my-emacs-config/.emacs.el ~/.emacs.d/init.el emacs
エラー箇所を修正。最近色々判定をサボっていたので少し出ましたが、それほど多くはありませんでした。(display-graphic-p)はnilなのでそのあたりの機能はごっそり無効化。
Termux上で動いているかの判別は次のようにしました。
(setq my-termux-p (not (null (executable-find "termux-info"))))
How to detect in a BASH script that I'm in Termux? : termux によればtermux-toolsパッケージは常に存在すると考えて良いみたいです。他にもパスにcom.termuxという特徴的な文字列が含まれているのでそれをチェックするのも(コマンドを検索するより速くて)良さそうです。
パッケージのインストール。
M-x package-refresh M-x package-install-selected-packages C-x C-c emacs
TMPDIR
が "/data/data/com.termux/files/usr/tmp"
なのに server-socket-dir
のデフォルト値が "/data/data/com.termux/files/usr/var/run/<uid>"
になっているのが原因みたいです。次のようにします。
(setq server-socket-dir (and (featurep 'make-network-process '(:family local)) (format "%s/emacs%d" (or (getenv "TMPDIR") "/data/data/com.termux/files/usr/var/run") (user-uid))))
(emacsclient can not find server socket · Issue #4230 · termux/termux-packagesより)
パッチが当たらなくなったのかな?
(setq browse-url-browser-function 'browse-url-xdg-open)
browse-url-xdg-open
は xdg-open
コマンドを使います。Termuxから使えるようです。 termux-open-url
というコマンドもあります。
事前にtermux-apiアプリの導入が必要です。私はtermux-appを自分でビルドしてしまったので、こちらも自分でビルドする必要がありました。
その上でTermux内にもパッケージのインストールが必要です。
pkg install termux-api
そうすると次の二つのコマンドが使えるようになります。
termux-clipboard-set <text> termux-clipboard-get
Emacsからは xclip というパッケージを導入するとこれらのコマンドを使ってくれるようになります。
M-x package-install xclip M-x xclip-mode
(Copy/paste between apps and Emacs in Termux · Issue #6266 · termux/termux-packagesより)
termux-setup-storage
を実行し権限を許可。すると ~/storage
が追加され、 /sdcard
にもアクセスできるようになりました。
pkg install ripgrep
: Emacsから検索の際に使用pkg install wget
: ファイルをダウンロードするときに使用TermuxでのEmacs環境の整備を続けています。
Termux 上で Emacs を普段使いする為の設定 - Qiita
を読んでいて、曖昧幅なんてものもあったなぁ……と、手元のorgファイルの表の部分を見てみると……ありましたありました。メチャクチャ崩れています。○△×とか書く欄が表にあったらもうダメですね。どうしたら良いんだろう。
と、上のページをよく読むと
Termux が純粋な Linux アプリであれば、wcwidh()のハックにより解消出来ますが、Termux は Java アプリなのでハックの仕方が分かりません…。 (ソースを修正すべき箇所は多分ここです→ https://github.com/termux/termux-app/blob/master/terminal-emulator/src/main/java/com/termux/terminal/WcWidth.java)
おおお、そんな場所があるとは。幸いTermuxはビルドしたばかりですから直せるかもしれません。
hamano/locale-eaw: East Asian Ambiguous Width問題と絵文字の横幅問題の修正ロケール
ええと、このページからたどれるeaw.elをダウンロードして……ふむふむ、曖昧幅の文字と全角確定の文字を合わせて、その範囲のリストを作れば良さそうですね。
(let* ( ;; From https://github.com/hamano/locale-eaw/blob/master/eaw.el (east-asian-ambiguous '( #x00A1 ; Po INVERTED EXCLAMATION MARK #x00A4 ; Sc CURRENCY SIGN #x00A7 ; Po SECTION SIGN ;;...略... )) ;; From WIDE_EASTASIAN in termux-app/terminal-emulator/src/main/java/com/termux/terminal/WcWidth.java (east-asian-wide '( (#x01100 . #x0115f) ;; // Hangul Choseong Kiyeok ..Hangul Choseong Filler (#x0231a . #x0231b) ;; // Watch ..Hourglass ;;...略... (#x30000 . #x3fffd) ;; // (nil) ..(nil) )) (full-width-chars (sort (append (cl-loop for range in east-asian-wide nconc (cl-loop for c from (car range) to (cdr range) collect c)) east-asian-ambiguous) #'<))) (let ((p full-width-chars)) (while p (let ((first (car p)) (last (progn (while (and (cadr p) (or (= (car p) (cadr p)) ;;Omit duplication (= (1+ (car p)) (cadr p)))) (setq p (cdr p))) (car p)))) (insert (format "{0x%x, 0x%x},\n" first last)) (setq p (cdr p))))))
結果はこんな感じ。
{0xa1, 0xa1}, {0xa4, 0xa4}, {0xa7, 0xa8}, {0xaa, 0xaa}, {0xad, 0xae}, {0xb0, 0xb4}, {0xb6, 0xba}, {0xbc, 0xbf}, {0xc6, 0xc6}, {0xd0, 0xd0}, {0xd7, 0xd8}, {0xde, 0xe1}, {0xe6, 0xe6}, {0xe8, 0xea}, {0xec, 0xed}, {0xf0, 0xf0}, {0xf2, 0xf3}, {0xf7, 0xfa}, {0xfc, 0xfc}, {0xfe, 0xfe}, {0x101, 0x101}, {0x111, 0x111}, {0x113, 0x113}, {0x11b, 0x11b}, {0x126, 0x127}, {0x12b, 0x12b}, {0x131, 0x133}, {0x138, 0x138}, {0x13f, 0x142}, {0x144, 0x144}, {0x148, 0x14b}, {0x14d, 0x14d}, {0x152, 0x153}, {0x166, 0x167}, {0x16b, 0x16b}, {0x1ce, 0x1ce}, {0x1d0, 0x1d0}, {0x1d2, 0x1d2}, {0x1d4, 0x1d4}, {0x1d6, 0x1d6}, {0x1d8, 0x1d8}, {0x1da, 0x1da}, {0x1dc, 0x1dc}, {0x251, 0x251}, {0x261, 0x261}, {0x2c4, 0x2c4}, {0x2c7, 0x2c7}, {0x2c9, 0x2cb}, {0x2cd, 0x2cd}, {0x2d0, 0x2d0}, {0x2d8, 0x2db}, {0x2dd, 0x2dd}, {0x2df, 0x2df}, {0x391, 0x3a1}, {0x3a3, 0x3a9}, {0x3b1, 0x3c1}, {0x3c3, 0x3c9}, {0x401, 0x401}, {0x410, 0x44f}, {0x451, 0x451}, {0x1100, 0x115f}, {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019}, {0x201c, 0x201d}, {0x2020, 0x2022}, {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035}, {0x203b, 0x203b}, {0x203e, 0x203e}, {0x2074, 0x2074}, {0x207f, 0x207f}, {0x2081, 0x2084}, {0x20ac, 0x20ac}, {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212b, 0x212b}, {0x2153, 0x2154}, {0x215b, 0x215e}, {0x2160, 0x216b}, {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, {0x21b8, 0x21b9}, {0x21d2, 0x21d2}, {0x21d4, 0x21d4}, {0x21e7, 0x21e7}, {0x2200, 0x2200}, {0x2202, 0x2203}, {0x2207, 0x2208}, {0x220b, 0x220b}, {0x220f, 0x220f}, {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221a, 0x221a}, {0x221d, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, {0x2227, 0x222c}, {0x222e, 0x222e}, {0x2234, 0x2237}, {0x223c, 0x223d}, {0x2248, 0x2248}, {0x224c, 0x224c}, {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, {0x226a, 0x226b}, {0x226e, 0x226f}, {0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, {0x22a5, 0x22a5}, {0x22bf, 0x22bf}, {0x2312, 0x2312}, {0x231a, 0x231b}, {0x2329, 0x232a}, {0x23e9, 0x23ec}, {0x23f0, 0x23f0}, {0x23f3, 0x23f3}, {0x2460, 0x24e9}, {0x24eb, 0x254b}, {0x2550, 0x2573}, {0x2580, 0x258f}, {0x2592, 0x2595}, {0x25a0, 0x25a1}, {0x25a3, 0x25a9}, {0x25b2, 0x25b3}, {0x25b6, 0x25b7}, {0x25bc, 0x25bd}, {0x25c0, 0x25c1}, {0x25c6, 0x25c8}, {0x25cb, 0x25cb}, {0x25ce, 0x25d1}, {0x25e2, 0x25e5}, {0x25ef, 0x25ef}, {0x25fd, 0x25fe}, {0x2600, 0x27e5}, {0x27ee, 0x27ff}, {0x2b1b, 0x2b1c}, {0x2b50, 0x2b50}, {0x2b55, 0x2b59}, {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb}, {0x3000, 0x303e}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312f}, {0x3131, 0x318e}, {0x3190, 0x31e3}, {0x31f0, 0x321e}, {0x3220, 0x4dbf}, {0x4e00, 0xa48c}, {0xa490, 0xa4c6}, {0xa960, 0xa97c}, {0xac00, 0xd7a3}, {0xf900, 0xfaff}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xff01, 0xff60}, {0xffe0, 0xffe6}, {0xfffd, 0xfffd}, {0x16fe0, 0x16fe4}, {0x16ff0, 0x16ff1}, {0x17000, 0x187f7}, {0x18800, 0x18cd5}, {0x18d00, 0x18d08}, {0x1b000, 0x1b11e}, {0x1b150, 0x1b152}, {0x1b164, 0x1b167}, {0x1b170, 0x1b2fb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f1ad}, {0x1f1e6, 0x1f202}, {0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f250, 0x1f251}, {0x1f260, 0x1f265}, {0x1f300, 0x1f6d7}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6fc}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d8}, {0x1f7e0, 0x1f7eb}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f8b0, 0x1f8b1}, {0x1f900, 0x1f978}, {0x1f97a, 0x1f9cb}, {0x1f9cd, 0x1fa53}, {0x1fa60, 0x1fa6d}, {0x1fa70, 0x1fa74}, {0x1fa78, 0x1fa7a}, {0x1fa80, 0x1fa86}, {0x1fa90, 0x1faa8}, {0x1fab0, 0x1fab6}, {0x1fac0, 0x1fac2}, {0x1fad0, 0x1fad6}, {0x1fb00, 0x1fb92}, {0x1fb94, 0x1fbca}, {0x1fbf0, 0x1fbf9}, {0x20000, 0x2fffd}, {0x30000, 0x3fffd},
これを termux-app/terminal-emulator/src/main/java/com/termux/terminal/WcWidth.java の WIDE_EASTASIAN の定義と差し替えます。
そしてビルドして実行してみると……ちゃんと綺麗に揃った幅で表示されました!
Emacsの方は (set-language-environment "Japanese")
すればちゃんと幅が2になっているみたいですね。昔のEmacsは自分で設定しないといけなくて、でもいつの間にか設定しなくても良くなってた記憶があります。
フォントの方は前に作ったキメラのようなフォントを適用したところ問題なく表示されました。決して綺麗なフォントではありませんが、まぁ、ある意味カッチリしているというべきか……。ついline-spacingを指定しようとしてしまいましたが効くわけがありません(笑)
何はともあれ予想されていたもう一つの方法でも解決できたということで。