Category Archives: 未分類

2017-03-22

新しいマウス

マウスを新調した。

ここ数年使っていたのはソニーストアのポイントで購入した(もらった?) Bluetooth光学式無線マウス(ELECOM M-XG1BB)なのだけど、 今使っているテーブルの上ではものすごく反応が悪い。

カッターマットを敷いてマウスパッドの代わりにしていたのだけど、 鍋の熱でカッターマットが変形してしまい、そしてそれを二回もやってしまいマットを撤去。 結局反応の悪い状態でしばらく使っていた。

それとマウスの形状にも少し不満があった。親指をかけるところが深く凹んでいて、それが私の親指の太さに合わないのだ。 さらにその凹んでいるところに上に前後ボタンが配置されていて、まともに指をかけると誤ってそのボタンを押してしまう。 なんでこんな所にボタンをつけたんだろう。

新しいマウスはロジクールのMX1500 MX Anywhere2にした。 少々値は張るが追跡性能は良いらしいとのこと。 実際今のテーブルの上でも全く問題なく使うことが出来た。

形状は親指のところが少し凹んでいるので心配したが、ELECOMのそれよりはずいぶんマシだ。 前後ボタンも多少指にかかるが押し込みに力がいるので誤って押すことは無い。 強いて言えばもう少し高さがある方が持ちやすいだろうか。 使う人の手の大きさにも寄るし、モバイル用マウスという点を考えると仕方ないのかもしれない。

一つ不満を挙げると重量だろうか。マウスは軽いほど良いと思うのだけど、このマウスは小ぶりな割にはかなり重い(100g超)。 カーソル移動で持ち上げるときに少し力がいる。 慣れれば気にならなくなるだろうか。

そうそう、ホイールが少し面白い。マウスのホイールと言えば回すときのクリッ ク感の有無(カリカリ引っかかりながら回るか、スムーズにサーッと回るか)が マウスによって異なるが、これはホイールを押し込むたびにその二つが切り 替わる(機械的なメカニズムによって)。作業の内容に応じて切り替えが可能だ。 そのため中ボタンはホイールの下に別に付いており、これも慣れが必要だ。 私は中ボタンをよく使うのでしばらく戸惑うと思う。

2017-01-22

2017冬の新番組

今期も一通り一話は見終わりました。

01/02(月) 21:55 TOKYO MX × 超・少年探偵団NEO
01/03(火) 12:00 ニコニコCh あいまいみー 第3期
01/04(水) 23:30 TOKYO MX AKIBA’S TRIP -THE ANIMATION-
01/05(木) 22:30 TOKYO MX ○+ 政宗くんのリベンジ
01/05(木) 25:58 TBS うらら迷路帖
01/05(木) 26:28 TBS セイレン
01/06(金) 24:30 TOKYO MX △+ スクールガールストライカーズ -Animation Channel-
01/06(金) 25:05 TOKYO MX △+ 幼女戦記
01/06(金) 25:55 TBS 青の祓魔師 京都不浄王編
01/06(金) 26:40 TBS 昭和元禄落語心中~助六再び篇~(第2期)
01/07(土) ニコニコCh ナンバカ 第2期
01/07(土) 21:00 TOKYO MX スピリットパクト
01/07(土) 22:00 TOKYO MX △- 風夏
01/07(土) 23:30 TOKYO MX △+ 亜人(デミ)ちゃんは語りたい
01/08(日) 22:00 TOKYO MX エルドライブ
01/08(日) 22:27 TOKYO MX にゃんこデイズ
01/08(日) 22:30 TOKYO MX △- チェインクロニクル ~ヘクセイタスの閃(ひかり)~
01/08(日) 23:00 TOKYO MX テイルズ オブ ゼスティリア ザ クロス 第2期
01/08(日) 23:30 TOKYO MX △- アイドル事変
01/08(日) 24:00 TOKYO MX リトルウィッチアカデミア TVシリーズ
01/08(日) 25:35 テレビ東京 銀魂 新シリーズ
01/09(月) 24:00 TOKYO MX ガヴリールドロップアウト
01/09(月) 24:30 TOKYO MX 霊剣山 叡智への資格 (第2期)
01/09(月) 25:00 TOKYO MX × ちるらん にぶんの壱
01/09(月) 25:00 TOKYO MX ワカコ酒
01/09(月) 25:35 テレビ東京 弱虫ペダル NEW GENERATION (第3期)
01/09(月) 26:05 テレビ東京 鬼平 -ONIHEI-
01/10(火) 23:00 TOKYO MX ACCA13区監察課
01/10(火) 24:30 TOKYO MX × ハンドシェイカー
01/10(火) 25:35 テレビ東京 ○+ けものフレンズ
01/11(水) 22:30 TOKYO MX ピアシェ~私のイタリアン~
01/11(水) 22:40 TOKYO MX One Room
01/11(水) 24:00 TOKYO MX 小林さんちのメイドラゴン
01/11(水) 25:05 TOKYO MX この素晴らしい世界に祝福を! 2
01/11(水) 25:35 TOKYO MX × CHAOS;CHILD
01/12(木) 23:30 TOKYO MX × MARGINAL#4 KISSから創造るBig Bang
01/12(木) 24:55 フジテレビ × クズの本懐
01/13(金) 25:40 TOKYO MX SUPER LOVERS 第2期
01/14(土) 23:30 TOKYO MX Rewrite 2ndシーズン
01/15(日) 26:05 テレビ東京 闇芝居 第4期
01/20(金) 12:00 ニコニコCh 南鎌倉高校女子自転車部
01/21(土) 22:30 TOKYO MX BanG Dream!

一番気になるのが「けものフレンズ」というのがなんとも今期は不作なのか何なのか。

けものフレンズはほのめかしが凄い。 それが生きてくるかは最後まで見なければ分かりませんが、1話2話を見たところではなかなか興味をくすぐられますね。

  • 声が棒 → いや、あれは動物が元気で頭悪いということを表現する演技でしょう
  • 5分で十分 → 5分じゃ出会う場面だけで終わってしまうけど……
  • 絵が汚い → アニメは絵の綺麗さは必ずしも重要じゃ無くて、動く絵によって話が伝われば十分なのです
  • 子供向け → 明らかに可愛いものを愛でたい大きなお友達向けでしょう

動物の生態を再現しようと努力している点は好感が持てますし教育的でもあります。とはいえそんなに重視はしていないのでしょうね。教育を重視するなら動物園スタッフによる解説コーナーで実写を映しても良さそうなものです。

2016-10-27 ,

org2blogでpublish時に固まる(Emacs25.1, xml-rpc 20160430.1458)

Emacs25.1にしたせい(?)か org2blog でpublish時に "error in process sentinel: url-http-create-request: Multibyte text in HTTP request: POST /????/xmlrpc.php HTTP/1.1 …" とか言われて困ったのだけど xml-rpc-request の encode-coding-region の部分がダメっぽい。 xml-rpc-allow-unicode-string が t の時は encode-coding-string を使うようにしたらうまく行った。

xml-rpc.el:

                                         " encoding=\"UTF-8\"?>\n"
                                         (with-temp-buffer
                                           (xml-print xml)
-                                          (when xml-rpc-allow-unicode-string
-                                            (encode-coding-region
-                                             (point-min) (point-max) 'utf-8))
-                                          (buffer-string))
+                                          (if xml-rpc-allow-unicode-string
+                                              (encode-coding-string (buffer-string) 'utf-8)
+                                            (buffer-string)))
                                         "\n"))
               (url-mime-charset-string "utf-8;q=1, iso-8859-1;q=0.5")
               (url-request-coding-system xml-rpc-use-coding-system)

Emacs25からurl-http-系でリクエストを送るときはユニバイト文字列でないとエラーになるようになった(https://github.com/emacs-mirror/emacs/blob/master/etc/NEWS.25#L1306)。 RC1のときはユニバイト文字列を指定してもエラーになるバグがあったようなのだけど、今回のはそれではないようだ。

原因は以下の挙動の違いらしい。

(multibyte-string-p
 (with-temp-buffer
  (insert "こんにちは")
  (encode-coding-region (point-min) (point-max) 'utf-8)
  (buffer-string))) ;; => t
(multibyte-string-p (encode-coding-string "こんにちは" 'utf-8)) ;; => nil

encode-coding-regionの説明には「符号化結果は『生のバイト』であるが、 マルチバイトであったバッファはマルチバイトのままである。」とあるので、それが関係しているのかもしれない。

2016-10-26

2016秋の新番組

最近は最初から見ないものや1話即切りが増えてきましたね。まぁ仕方なし。

09/01(木) 22:30 TOKYO MX レガリア The Three Sacred Stars
09/03(土) 19:00 TOKYO MX PERSONA5 the Animation -THE DAY BREAKERS-
09/18(日) 07:00 テレビ朝日系 ヘボット!
09/18(日) 09:00 フジテレビ系 こちら葛飾区亀有公園前派出所 新作テレビスペシャル
09/27(火) 06:40 NHK Eテレ にゃんぼー!
09/27(火) 18:00 dアニメストア 怪獣娘(かいじゅうがーるず) ~ウルトラ怪獣擬人化計画~
10/01(土) 07:00 TOKYO MX 猫のダヤン ふしぎ劇場(第3期)
10/01(土) 07:00 TOKYO MX タマ&フレンズ ~うちのタマ知りませんか?~
10/01(土) 07:00 テレビ東京系 デジモンユニバース アプリモンスターズ
× 10/01(土) 17:30 日本テレビ系 タイムボカン24
× 10/01(土) 21:00 TOKYO MX Bloodivores(ブラッディヴォーレス)
△- 10/01(土) 22:00 TOKYO MX ブブキ・ブランキ 星の巨人 (第2期)
△- 10/01(土) 23:30 TOKYO MX WWW.WORKING!!
10/01(土) 24:00 TOKYO MX デュラララ!!×2 結 外伝!? 第19.5話「デュフフフ!!」
△- 10/01(土) 24:30 TOKYO MX ViVid Strike!
10/01(土) 25:00 TOKYO MX うたの☆プリンスさまっ♪マジLOVEレジェンドスター (第4期)
10/01(土) 25:30 TOKYO MX 終末のイゼッタ
× 10/01(土) 26:45 テレビ朝日 タイガーマスクW
10/02(日) 07:00 テレビ東京系 チーズスイートホーム こねこのチー
10/02(日) 08:30 フジテレビ モンスターハンター ストーリーズ RIDE ON
10/02(日) 10:00 テレビ東京系 カードファイト!! ヴァンガードG NEXT (第8期)
10/02(日) 17:00 TBS系 機動戦士ガンダム 鉄血のオルフェンズ 第2期
10/02(日) 22:00 TOKYO MX SHOW BY ROCK!!# 第2期
10/02(日) 22:28 TOKYO MX 雨色ココア 第3期
10/02(日) 22:30 TOKYO MX マジきゅんっ!ルネッサンス
10/02(日) 24:00 TOKYO MX 刀剣乱舞-花丸-
× 10/02(日) 24:30 TOKYO MX アイドルメモリーズ
△- 10/02(日) 27:05 テレビ東京 あおおに ~じ・あにめぇしょん~
10/03(月) 19:00 TOKYO MX 怪盗ジョーカー シーズン4
10/03(月) 19:30 TOKYO MX 12歳。~ちっちゃなムネのトキメキ~ 2ndシーズン
10/03(月) 21:55 TOKYO MX 3ねんDぐみガラスの仮面
× 10/03(月) 24:00 TOKYO MX 魔法少女育成計画
10/03(月) 24:30 TOKYO MX 聖闘士星矢 黄金魂 -soul of gold-
10/03(月) 25:00 TOKYO MX 学園ハンサム
10/03(月) 25:05 TOKYO MX TRICKSTER -江戸川乱歩「少年探偵団」より-
10/03(月) 25:35 テレビ東京 灼熱の卓球娘
× 10/04(火) 18:30 TOKYO MX 侍霊演武(ソウルバスター)
10/04(火) 21:55 TOKYO MX 信長の忍び
○- 10/04(火) 23:00 TOKYO MX 装神少女まとい
△- 10/04(火) 24:30 TOKYO MX ステラのまほう
○+ 10/04(火) 25:35 テレビ東京 夏目友人帳 伍 (第5期)
× 10/05(水) 18:30 TOKYO MX CHEATING CRAFT(チーティングクラフト)
× 10/05(水) 18:40 TOKYO MX TO BE HERO(トゥ ビー ヒーロー)
× 10/05(水) 22:00 TOKYO MX 美少女遊戯ユニット クレーンゲールギャラクシー (第2期)
10/05(水) 22:20 TOKYO MX ナゾトキネ -NAZOTOKINE-
10/05(水) 22:30 TOKYO MX てーきゅう 第8期
△- 10/05(水) 22:33 TOKYO MX 奇異太郎少年の妖怪絵日記
10/05(水) 22:38 TOKYO MX 魔法少女なんてもういいですから。 セカンドシーズン
× 10/05(水) 22:43 TOKYO MX あにトレ!XX -ひとつ屋根の下で-(第2期)
× 10/05(水) 23:30 TOKYO MX ナンバカ
10/05(水) 24:00 TOKYO MX 響け!ユーフォニアム 第2期
○+ 10/05(水) 24:21 テレビ朝日 ユーリ!!! on ICE
10/05(水) 25:05 TOKYO MX 文豪ストレイドッグス 第2クール
× 10/05(水) 25:35 TOKYO MX ブレイブウィッチーズ
△- 10/06(木) 22:00 TOKYO MX フリップフラッパーズ
10/06(木) 23:30 TOKYO MX 競女!!!!!!!!
× 10/06(木) 24:00 TOKYO MX ALL OUT!! (オールアウト!!)
○+ 10/06(木) 25:58 TBS 私がモテてどうすんだ
△+ 10/06(木) 26:28 TBS ガーリッシュ ナンバー
× 10/07(金) 22:30 TOKYO MX ドリフェス!
× 10/07(金) 23:00 TOKYO MX ドリフターズ
× 10/07(金) 25:05 TOKYO MX Lostorage incited WIXOSS
× 10/07(金) 25:55 TBS ハイキュー!! -烏野高校 VS 白鳥沢学園高校- (第3期)
10/07(金) 26:25 TBS 亜人 第2クール
× 10/08(土) 17:30 NHK Eテレ クラシカロイド
10/08(土) 22:30 TOKYO MX ろんぐらいだぁす!
10/08(土) 23:00 NHK総合 3月のライオン
10/08(土) 24:00 TOKYO MX Occultic;Nine -オカルティック・ナイン-
10/08(土) 25:55 日本テレビ うどんの国の金色毛鞠
× 10/09(日) 25:00 TOKYO MX はがねオーケストラ
△- 10/10(月) 00:00 ニコニコCh 戦国鳥獣戯画
10/11(火) 12:00 ニコニコチャンネル バーナード嬢曰く。
10/13(木) 12:00 ニコニコCh おくさまが生徒会長!+! (第2期)
10/13(木) 24:55 フジテレビ 舟を編む
10/15(土) –:-- YouTube 100%パスカル先生
10/22(土) 20:00 ANIMAX ルガーコード 1951
10/22(土) 22:00 YouTube ガールフレンド(♪) WEBアニメ
11/–(木) 18:55 テレビ東京系 ポケットモンスター サン&ムーン
10/–(-) –:-- ニコニコ動画 拡張少女系トライナリー
10/–(木) –:-- フジテレビ PJベリーのもぐもぐむにゃむにゃ -パラッパラッパー新シリーズ-

今期は何だろうなぁ。

第一話では「ユーリ!!! on ICE」なんかが目を惹きましたよね。

「舟を編む」はゆっくりした滑り出しですが案外悪くないかもしれない。

「競女!!!!!!!!」は思わず女性蔑視という単語が浮かんで心配になってしまうほどでしたが、ここまでやられるとさすがに笑ってしまう。

「ガーリッシュ ナンバー」この手のものは嫌いだと思っていたのですが案外見られます。主人公の率直な性格が魅力的だからでしょうか。

2016-07-23

2016夏の新番組

第一印象では「甘々と稲妻」「orange」が良かったですが、さてさて、今期はどうなることやら。

06/06(月) 23:50 NHK Eテレ オトナの一休さん
06/06(月) 24:08 NHK総合 ほのぼのログ
06/11(土) 09:30 テレビ東京系 レゴ ネックスナイツ
06/18(土) 07:00 TOKYO MX ネコこのゴロ
06/19(日) 26:35 フジテレビ ワンピース キャラクターズLog
06/25(土) 26:20 フジテレビ RS計画 -Rebirth Storage-
07/01(金) 21:55 TOKYO MX ぐらP&ろで夫 第2Season
07/01(金) 22:30 TOKYO MX ももくり
07/01(金) 24:00 TOKYO MX ReLIFE(リライフ)
07/02(土) 22:00 TOKYO MX 食戟のソーマ 弍ノ皿 (第2期)
× 07/02(土) 22:30 TOKYO MX ラブライブ!サンシャイン!!
× 07/02(土) 23:30 TOKYO MX Rewrite(リライト)
× 07/02(土) 24:30 TOKYO MX B-PROJECT~鼓動*アンビシャス~
07/02(土) 25:00 TOKYO MX 初恋モンスター
07/03(日) 17:00 TBS系 アルスラーン戦記 風塵乱舞 (第2期)
07/03(日) 22:00 TOKYO MX 不機嫌なモノノケ庵
07/03(日) 23:00 TOKYO MX テイルズ オブ ゼスティリア ザ クロス
07/03(日) 23:30 TOKYO MX DAYS
07/03(日) 24:00 TOKYO MX orange-オレンジ-
07/04(月) 18:25 テレビ東京系 パズドラクロス
× 07/04(月) 25:00 TOKYO MX SHOW BY ROCK!! しょ~と!!
07/04(月) 25:05 TOKYO MX 甘々と稲妻
× 07/04(月) 25:35 テレビ東京 D.Gray-man HALLOW
07/04(月) 26:05 テレビ東京 TABOO-TATTOO(タブー・タトゥー)
× 07/05(火) 23:00 TOKYO MX チア男子!!
07/05(火) 24:30 TOKYO MX NEW GAME!
× 07/05(火) 25:35 テレビ東京 スカーレッドライダーゼクス
07/06(水) 22:00 TOKYO MX SERVAMP -サーヴァンプ-
07/06(水) 23:00 TOKYO MX ツキウタ。 THE ANIMATION
× 07/06(水) 24:00 TOKYO MX OZMAFIA!!
07/06(水) 24:00 ニコニコ動画 planetarian(プラネタリアン)
07/06(水) 24:05 TOKYO MX 魔法少女?なりあ☆がーるず
07/06(水) 25:05 TOKYO MX プリズマ☆イリヤ ドライ!! (第4期)
× 07/06(水) 25:35 TOKYO MX 魔装学園H×H
× 07/07(木) 21:55 TOKYO MX ちょびっとづかん
07/07(木) 22:00 ニコニコ生放送 銀河機攻隊 マジェスティックプリンス
07/07(木) 22:30 TOKYO MX レガリア The Three Sacred Stars
07/07(木) 25:58 TBS はんだくん
07/07(木) 26:28 TBS この美術部には問題がある!
07/07(木) 27:05 テレビ東京 美男高校地球防衛部LOVE!LOVE! (第2期)
07/08(金) 23:00 TOKYO MX Thunderbolt Fantasy 東離劍遊紀
07/08(金) 25:05 TOKYO MX ねじ巻き精霊戦記 天鏡のアルデラミン
07/08(金) 25:55 TBS 91Days
07/08(金) 26:25 TBS ベルセルク 新作
07/09(土) 07:00 テレビ東京系 タイムトラベル少女 ~マリ・ワカと8人の科学者たち~
07/09(土) 21:00 TOKYO MX 一人之下 the outcast
07/09(土) 24:00 TOKYO MX クオリディア・コード
07/09(土) 24:00 バンダイCh ばなにゃ
× 07/09(土) 25:30 TOKYO MX アンジュ・ヴィエルジュ
07/10(日) 24:30 TOKYO MX あまんちゅ!
07/10(日) 25:35 テレビ東京 斉木楠雄のΨ難
07/11(月) 23:00 TOKYO MX ダンガンロンパ3 -The End of 希望ケ峰学園- 未来編
07/11(月) 24:00 TOKYO MX モブサイコ100
07/11(月) 24:30 TOKYO MX アクティヴレイド 機動強襲室第八係 第二期
07/12(火) 21:00 ニコニコ動画 腐男子高校生活
07/14(木) 23:30 TOKYO MX ダンガンロンパ3 -The End of 希望ケ峰学園- 絶望編
07/14(木) 24:55 フジテレビ バッテリー
07/16(土) 21:00 フジテレビ系 ワンピース ~ハートオブ ゴールド~
08/28(日) 17:00 TBS系 七つの大罪 聖戦の予兆
2016-06-14

過去の紙資料やメモ書きをスキャン中

ここ数日過去の紙資料をスキャンして処分しています。部屋の空きスペースを増やしたかったので。

手帳、仕事の印刷資料、手書きのメモなんかが主ですが、これが意外と量があって百科事典何冊分かにはなりそうです。紙を閉じているファイルなんかは無駄にかさばりますしね。

手帳は大学生くらいから2010年くらいまでありました。2009年くらいからあまり書かなくなっていて、2010年はほとんど書いてません。TODO管理用テキストの最初の項目が2010年から始まっているので、あまり必要なくなったのかもしれません。Android端末(HT-03AやSO-01B Xperia)を使い始めたのもこのあたりなので、それも関係しているかもしれません。まぁ、色々と行き詰まっていたというのもあるのかもしれません。

いつの頃からかA4コピー用紙でメモを書く習性がつきました。職場の机の右の引き出しには常に白紙のコピー用紙が大量に入っていて、何か考えるときはサッと取り出して考えをまとめながら書き、上にタイトルと日付を書いてパンチで穴を開けてファイルに閉じていました。そういうのがプロジェクト毎に沢山あります。最近は出来るだけデジタルだけで済ますようにしていますし、紙に書いたときでも最後はScanSnapでスキャンして紙の方は速やかに処分するようにしています。

そんなことで昔書いたものを見るわけですが、色々感じるところがありますね。なんだか切なくなったり、色々考えてるんだぁと感心したり、脳の中の忘れていた部分が刺激されてなんだか可能性が広がったような錯覚があったり。

まぁ、部屋は広くなるので新しいものが置けるようにはなるでしょう。

こういう日記もそうなのですが、基本的に自分が興味があることを書いているので後で読み返しても(自分にとっては)面白いんですよね。

2016-06-05 ,

Google Calendarで過ぎた日の色を変える

カレンダーの過ぎた日に斜線を引くのが好きな私としては、過ぎた日が一目で分かるようにして欲しいのです。

例えば次のようなユーザースクリプトを作ってGreasemonkeyなりTampermonkey使えば出来るわけですが、まぁ、やりたいことの些細さに比べて面倒ですね。

(追記2018-11-14: デザインが変わって動かなくなっていたので Google Calendarで過ぎた日の色を変える(2018) を書きました)

(function(){
    var PAST_COLOR = "#e0e0e0";
    var PAST_BORDER_LEFT = "1px solid #d0d0d0";
    var TODAY_COLOR = "#ffa";

    var timer = null;
    function schedule(){
        if(timer){
            clearTimeout(timer);
        }
        timer = setTimeout(update, 100);
    }

    function update(){
        if(document.getElementsByClassName("st-bg-today").length === 0){
            return;
        }

        var bgs = Array.prototype.slice.call(document.getElementsByClassName("st-bg"));
        bgs.find(function(e,i,a){
            if(e.className.match("st-bg-today")){
                e.style.backgroundColor = TODAY_COLOR;
                return true;
            }
            else {
                //e.className += " st-bg-past";
                e.style.backgroundColor = PAST_COLOR;
                e.style.borderLeft = PAST_BORDER_LEFT;
                return false;
            }
        });
        var dtitles = Array.prototype.slice.call(document.getElementsByClassName("st-dtitle"));
        dtitles.find(function(e,i,a){
            if(e.className.match("st-dtitle-today")){
                e.style.backgroundColor = TODAY_COLOR;
                return true;
            }
            else {
                //e.className += " st-dtitle-past";
                e.style.backgroundColor = PAST_COLOR;
                e.style.borderLeft = PAST_BORDER_LEFT;
                return false;
            }
        });
    }

    var observer = new MutationObserver(schedule);
    observer.observe(document.body, {childList:true, subtree:true});

    update();
})();

月表示や4週間表示の時、各日付の枠(td)には st-bg というクラスが付いています。 今日の日付をグレーにするためか、 st-bg-today というクラスも用意されていて、 今日の日付の枠は st-bg st-bg-today というクラスが付きます。

なので、クラスst-bgが付いている要素をgetElementsByClassNameで列挙して、 先頭からst-bg-todayが付いている要素に到達するまで背景色を変えることにしました。

今日の日付(st-bg-today)がカレンダー内にない場合もあります。 本来なら、過去のカレンダーか未来のカレンダーかを判別して、 全部色を変えるか全く色を変えないか判断しなければなりません。 面倒なので、st-bg-todayが無ければ何もしないようにしました。

日付の数字部分(td.st-dtitle)の背景には不透明な白が指定されています。 そのままだとせっかく背景の色を変えても数字部分だけ白くなってしまいます。 transparentを指定したら良いのかと思ったのですが、 カレンダーの1行がわずかに次の行と重なっているため、 数字部分の上の方が前の行の背景色になってしまいます。 div.month-rowのheightが4行の時は26%、5行の時は21%となっていて、 これを25%や20%にするとぴったり収まります。 なぜ1%余計に大きくしているのでしょうか。 無理矢理1%小さくする方法も考えたのですが、 Googleは今日の日付の色を変えるために.st-bg-todayと.st-dtitle-todayの両方の backgroundを指定していますので、それにならって.st-dtitleの色も.st-bg と同様に変更することで解決しました。

最初はst-bg-pastとst-dtitle-pastというクラスを付加するようにしたのですが、 別途Stylish等でユーザースタイルを指定するのが面倒だったので 直接ユーザースクリプトで色を変えるようにしてしまいました。

MutationObserverのコールバック頻度はどのように決まっているのでしょうか。 今ひとつ分からなかったので、タイマーを併用して最後の更新から100ms後に 色替えを実行することにしました。

Googleのプロダクトはかゆいところに全く手が届かないのが困りものですよね。 あまり細かいカスタマイズが必要ならGoogle Calendar APIを使用して 自分でカレンダーを作るなり、他の既成のカレンダーを探すなりした方が良いかも しれません。

FullCalendar - JavaScript Event Calendar (jQuery plugin)

2016-05-29 ,

org-mode文書中の予定(タイムスタンプ)をGoogle Calendarへ登録する

Google Calendarとやりとり出来るようになったので、org-modeとGoogle Calendarとの間で必要となる道具立てを作成しています。

色々作成中ですがとりあえず。

misohena/gcal: Google Calendar Utilities for Emacs

gcal-org.el というのが中心になるのですが、その中のgcal-oeventオブジェクトがGoogle Calendarへ登録される予定を表します。

gcal-oeventオブジェクト

gcal-oevent(以下単にoevent)は、org文書を解析して得られた1つの予定(event)を表現するオブジェクトです。

オブジェクトの作成

オブジェクトは、例えば以下のようなコードで作成できます。

(setq oe
  (make-gcal-oevent
    :id "a84717b2-7c0b-4549-80f4-9477d14f975f"
    :ord 0
    :summary "田中さんと打ち合わせ"
    :ts-prefix "DEADLINE"
    :ts-start '(2016 2 3 nil nil)
    :ts-end '(2016 2 4 nil nil)
    :location "東京駅"))

また、org文書を解析して(そのリストが)得られたり、

(gcal-org-parse-file "~/my-schedule.org") ;;指定ファイルから
(gcal-org-parse-buffer) ;;現在のバッファから

オブジェクトをファイルへ保存して、それを読み込んで得られたり、

;; my-schedule.orgを解析したものをmy-schedule.gcal-cacheへ保存
(gcal-oevents-save "~/my-schedule.gcal-cache" (gcal-org-parse-file "~/my-schedule.org"))

;; my-schedule.gcal-cacheからoeventのリストを読み込み
(gcal-oevents-load "~/my-schedule.gcal-cache")

Google Calendar上のカレンダーから読み込んで得られたりします。

;; カレンダー(ID:example@gmail.com)から予定を読み込んでoeventのリストとして返す
(gcal-org-pull-oevents "example@gmail.com")

プロパティの取得

プロパティの取得は (gcal-oevent-プロパティ名) で行えます。

(gcal-oevent-id oe) ;;=> "a84717b2-7c0b-4549-80f4-9477d14f975f"
(gcal-oevent-summary oe) ;;=> "田中さんと打ち合わせ"

1オブジェクト=1タイムスタンプ

このオブジェクトはorg文書中の一つの(アクティブ)タイムスタンプに対応します。一つのヘッドラインに対応するのでは ありません 。 org-agendaが行うように、SCHEDULED、DEADLINE、その他記事中のアクティブタイムスタンプ一つにつき一つの予定をGoogle Calendarへ登録したかったからです。

そのため :id の他に :ord というプロパティを持っています。このプロパティは一つのエントリー中に現れたアクティブタイムスタンプの順番を表します。

IDの変換

Google Calendarの予定のIDはbase32hexで使う範囲の文字(0-9a-v)しか受け付けません(ハイフンが入っているとダメです)。 また、デフォルトではUUIDをbase32hexでエンコードしたものをIDとしています。

従って、oeventをGoogle Calendarへ登録するときは:idをbase32hexでエンコードしたものへ変換することにしました。

(downcase (gcal-uuid-to-base32hex "a84717b2-7c0b-4549-80f4-9477d14f975f"))
;; => "l13hfcjs1d2kj07kihrt2jsnbs"

(gcal-uuid-from-base32hex "l13hfcjs1d2kj07kihrt2jsnbs")
;; => "a84717b2-7c0b-4549-80f4-9477d14f975f"

しかしこれだけだと1エントリー中に複数のタイムスタンプがある場合にIDが重複してしまいます。

それを避けるために :ord が1以上の時は、その数をIDの後ろに付加することにしました。幸い文字数の制限は緩いので。

(gcal-oevent-gevent-id
  (make-gcal-oevent
    :id "a84717b2-7c0b-4549-80f4-9477d14f975f"
    :ord 1
    ... )) ;;=> "l13hfcjs1d2kj07kihrt2jsnbs00001"

(gcal-oevent-id-ord-from-gevent-id "l13hfcjs1d2kj07kihrt2jsnbs00001")
;; => ("a84717b2-7c0b-4549-80f4-9477d14f975f" . 1)

:ord が0のときは付加しません。Google Calendar上で作成した予定を取り込むときはその方が都合が良いからです。取り込んだイベントをorg文書中にインポートした後、元のGoogle Calendar上のイベントのIDを番号付きに修正する必要が出てしまいますので。

タイムスタンプの扱い

:ts-start や :ts-end は ( ) というリストで表現します。このリストは gcal-ts- で始まる関数で色々な処理が出来るようになっています。

はnilの場合があります。時間の入っていないタイムスタンプに対応します。

(gcal-ts-date-only '(2016 5 29 nil nil)) ;;=> t <2016-05-29 Sun>
(gcal-ts-date-only '(2016 5 29 12 34)) ;;=> nil <2016-05-29 Sun 12:34>

ややこしいのはts-endの扱いで、Google Calendar側では終了時刻はその時刻自身を含まない(exclusive)とされていますが、org-mode側では曖昧であることです。 org-modeは日付のみの場合はinclusive、時刻を含む場合はexclusiveなのだと思うので、それを前提に変換しています。

(gcal-ts-end-exclusive '(2016 5 1 nil nil) '(2016 5 1 nil nil)) ;; => '(2016 5 2 nil nil) 1day <2016-05-01 Sun>
(gcal-ts-end-exclusive '(2016 5 1 nil nil) '(2016 5 2 nil nil)) ;; => '(2016 5 3 nil nil) 2days <2016-05-01 Sun>--<2016-05-02 Mon>
(gcal-ts-end-exclusive '(2016 5 1 10 00) '(2016 5 1 10 00)) ;; => '(2016 5 1 10 0) 0hour <2016-05-01 Sun 10:00>
(gcal-ts-end-exclusive '(2016 5 1 10 00) '(2016 5 1 12 00)) ;; => '(2016 5 1 12 0) 2hours <2016-05-01 Sun 10:00-12:00>
(gcal-ts-end-exclusive '(2016 5 1 10 00) '(2016 5 2 10 00)) ;; => '(2016 5 2 10 0) 24hours <2016-05-01 Sun 10:00>--<2016-05-02 Mon 10:00>
;;逆は gcal-ts-end-inclusive

oeventとGoogle Calendarとのやりとり

oeventをGoogle Calendar APIへ送る(gcal-events-insertへ渡す)ための形式へ変換するには gcal-oevent-to-gevent を、その逆は gcal-oevent-from-gevent を使用します。

;; Send a oevent
(gcal-events-insert "example@gmail.com" (gcal-oevent-to-gevent oevent))

;; Receive a event as oevent
(gcal-oevent-from-gevent (gcal-events-get "example@gmail.com" "l13hfcjs1d2kj07kihrt2jsnbs"))

oeventのリストは gcal-org-push-oevents と gcal-org-pull-oevents で送受信できます。

;; Send all active timestamps in my-schedule.org
(gcal-org-push-oevents "example@gmail.com" (gcal-org-parse-file "~/my-schedule.org") nil)

;; Receive
(gcal-org-pull-oevents "example@gmail.com")

gcal-org-push-oeventsは差分抽出機能を備えており、旧リストから新リストへの差分(追加、削除、更新)のみをGoogle Calendarへ送ることが出来ます。

;; my-schedule.orgだけにあるものを追加し、.oldだけにあるものを削除し、内容が変わったものをパッチする。
(setq result-events
  (gcal-org-push-oevents
    "example@gmail.com"
    (gcal-org-parse-file "~/my-schedule.org") ;;new-events
    (gcal-org-parse-file "~/my-schedule.org.old");;old-events
))
;; result-eventsはサーバ上に残った予定のリスト。
;; エラーが無ければnew-eventsと同じ。
;; 追加に失敗すればその予定を載らないし、更新に失敗すればその予定は旧状態、削除に失敗すればその予定は残る。

;; my-schedule.orgにある予定を全て削除する。
;; new-eventsがnil(空リスト)なので、old-events内の予定に対応するものは一つもないので。
(gcal-org-push-oevents
  "example@gmail.com"
  nil
  (gcal-org-parse-file "~/my-schedule.org"))

oeventとOrg文書とのやりとり

org文書からoeventのリストを得る(解析する)には次のようにします。

(gcal-org-parse-file "~/my-schedule.org")
(gcal-org-parse-buffer)

逆にoeventを文字列化してorg文書へ挿入するには次のようにします。 (※ただし、:ordのことを考慮していないので注意が必要です)

;; 挿入先のorg文書を開いた状態で実行すること
(gcal-org-insert-string-after-headline
  (gcal-oevent-format oevent)
  "Inbox")

gcal-oevent-format は何も引数を指定しなければ gcal-org-oevent-template 変数に書いてあるテンプレートを使ってoeventを文字列化します。

gcal-org-oevent-template
"** %{summary}\nSCHEDULED: %{timestamp}\n:PROPERTIES:\n :ID: %{id}\n :LOCATION: %{location}\n:END:\n"
  "org-mode text representation of oevent."

Org文書とGoogle Calendarとのやりとり

oeventオブジェクトを介さずに直接やりとりする関数も作っています。

;; キャッシュ~/my-schedule.gcal-cacheから~/my-schedule.orgへの差分を
;; カレンダーexample@gmail.comへ適用します。
;; 成功した更新はキャッシュへ反映されます。
(gcal-org-push-file "example@gmail.com" "~/my-schedule.org" "~/my-schedule.gcal-cache")

;; キャッシュmy-schedule.gcal-cacheからカレンダーexample@gmail.comへの差分を
;; ~/my-schedule.orgへ適用します。
;; 新しく追加された予定はヘッドライン"Inbox"の下に挿入します。
;; 成功した更新はキャッシュへ反映されます。
(gcal-org-pull-to-file "example@gmail.com" "~/my-schedule.org" "Inbox" "~/my-schedule.gcal-cache")

pullは作り途中で、更新に対応していません(2016-05-29現在)。org文書中の一部の場所だけ書き換えないといけないので。

oeventsリストの差分抽出

gcal-oevents-diffを使用すると二つのoeventリストを比較できます。

それぞれの予定を :id と :ord をキーにマッチングを行い、変化(追加、削除、変更、そのまま)を見つけ出し、それに対応する関数を呼び出します。

(gcal-oevents-diff
 (gcal-oevents-load "~/my-schedule.org") ;;old-events
 (gcal-org-pull-oevents "example@gmail.com") ;;new-events
 (lambda (old-oe new-oe) (insert (format "mod %s => %s\n" old-oe  new-oe)))
 (lambda (new-oe) (insert (format "add %s\n" (gcal-oevent-summary new-oe))))
 (lambda (old-oe) (insert (format "del %s\n" (gcal-oevent-summary old-oe))))
 (lambda (oe) (insert (format "not change %s\n" (gcal-oevent-summary oe)))))