/ 最近 .rdf 追記 設定 本棚

脳log[2016-12-21~]



2016年12月21日 (水) [正規表現]「absent operatorの挙動だが、(?~) は何にもマッチしないのが期待値なんだろうか?」■空パターンはすべての文字列に含まれている(※空文字列を含め何にでもマッチする)というのが普通なので、そういう文字列以外にマッチするパターン(※非包含オペレータが表すもの)は何にもマッチしないのだろうかってことだよね。文字の集合に対する [] (どの文字にもマッチしない)と [^] (どの文字にもマッチする) とは反対なのが面白い。■文字集合を使った初心者のよくやる間違い [^ここに文字の集合ではなく列を書いてしまう] や、お手軽だが不完全な代替 .*? を使ったパターンに対して、正しく、簡単で、理論を逸脱しない答えが用意されるのが待ち遠しい。■日本語部分だけ読んだ>「正規表現における 非包含オペレータの提案」。■いや待てよ。非包含オペレータが扱う典型的なパターンはどういうものだろう。foo だろうか .*foo.* だろうか。俺は (?~) について書いてるつもりで (?~.*) について書いていたんだろうか。二つが同じだとすると部分一致ではなく完全一致であることを明示するために (?~^foo$) みたいにアンカーを付けたくなるだろうから両者は区別されるんだろう。じゃあやっぱり勘違いしてた? s=uvw みたいな文字で構成された式を「文字列がパターンを含む? どういうこと?」と読んで疑問のままにしてるんだけど、その辺を含めて PDFを読み直したい。


2016年12月20日 (火) いやあ、履歴を読んでるだけで楽しい!「秀まるおのホームページ(サイトー企画)-秀丸エディタ改版履歴」■カラーマーカーって秀丸由来の名前と機能だったのねん。そういうのはエディタでなくワープロの機能だと思うから興味ないよ。筆箱に蛍光ペンが入っていたこともないよ(ほとんど教科書に注釈を付けるだけで済ませて読み返しもしない)。


2016年12月18日 (日) [SakuraEditor]「Request/533 正規表現検索でサブマッチにも個別の検索色を」■別件の余録だけど過去にやった>「パターン内での色分けに対応した。JavaScriptの正規表現と違ってキャプチャの位置がわかるので、SHJSの仕様に従ってかっこを /(A)(B)(C)/ というように隣接させる必要がない。入れ子にすることも許される。入れ子にしたら一番内側の色が適用されるようにしたつもり。」コードでいうとこのファイル(shjs_style_regex_keyword(trunk2@1711).patch)の 7120行目から7153行目のあいだ、JavaScriptで検索して唯一マッチする else節がそう。ただその別件っていうのが色分けのメカニズムを置き換えるものだったので、ポンと持って行くことはできない、かもしれない。知識をアップデートしないと今のサクラエディタの色分けについてはわからない。■ただねえ、マッチ全体がたとえば黄色になって、その中の一部(キャプチャ部分)が赤や青になったら、黄色は赤や青で分断されることになるんだよね。キャプチャが入れ子になってると赤の一部が青で上塗りされるということも起こる。そういう入れ子関係をただ一番内側の色で塗るということにしてわかりやすいかというと疑問。関係がわかるように(たとえば高さを変えた色つきのアンダーラインなんかで)うまく塗り分けしたくなる<もちろんそういう凝ったプレゼンテーションは管轄外なので、これはやらないフラグ。■正規表現キーワードでは使い道がないわけではない。たとえばマッチの条件が異なる複数の要素から構成されているとき、ここは記号の色、ここは文字列の色、ここはマッチの条件には必要だけど特になんでもない部分なのでテキストの色、みたいに塗り分けることができるので。もちろんそのためには正規表現キーワードの色設定の保存のしかたまで考えないといけないが。■なんといいますか、過去のパッチを読み返してみたり(あ、セミコロンダブってる>「static const Range Null;;」)、高校生のときのノートを(捨てる前に)眺めてみたりするたび思う。あの頃俺は賢かった(今はもう理解できない……)。たぶん没入することが必要なんだな。振り返ってるときにはそれがない。■パッチを読んでいて……。「-で始まる行がいっぱい」<嬉しい!やってやったぜ! 「+で始まる行が凝集している」<ファイルを移動しただけか、正しい徴候。それかなんとなく気に入らなくてイチから書き直す悪い癖の発露。「あちこちに散らばる + の行」<やり方か仕組みのどちらかが間違ってる。「交互に現れる + の行と - の行」<普通っぽい。あと手前味噌だけどコメントが丁寧だと思った。「あ、そうなんだ。勉強になります(書かれていなければわかっていなかった)」って感じ。やっぱり時間差があっても自分は自分で、阿吽の呼吸で疑問と答えが噛み合うところがある。■アクセスログの一覧を下の方まで眺めてたら、こんな名前のファイルが3ヒットしていた>subpattern_highlight.rev2.patch。え、あれ? こんなんやってたっけ。「脳log[20120517p01] サブパターンハイライト。」つい反応してしまうくらいお気に入りのネタではあるんだな。■■■漢検の対策テキストから啐啄同時(※ATOKで一発変換できない)という四字熟語を仕入れた。ここ(「阿吽の呼吸で~」)が使い所だと思うのだけど、どういう形で文に組み込めるんだろうか。


2016年12月16日 (金)

最終更新: 2018-03-14T23:15+0900

[SakuraEditor] poor-awk.js (15.8KiB, 2017-01-04)

行単位で加工するマクロのための定型。そのままで同時に標準入出力にもファイルドロップ(SendToを含む)にも対応している。Perl譲りなんだろうけど、Rubyの -p スイッチって便利だし実際のニーズに基づいてるよねって。

 @2018-03-10 使用例:大文字小文字を区別しない昇順ソート (ソート(case-insensitive).js)

マクロに登録しても良し、ソートしたいテキストファイルをドロップしても良し。

よく知らないけどプラグインだとメインメニューにコマンドを登録できたりするんだろうか。こういうものを C++で書いてエディタ本体に内蔵したくはないよね。

掲示板に貼り付けるには長いし、Wikiのマクロ投稿ページはログインを要求してきて書き込みさせてくれないしで、返信できずにここに書いてるんですよ。>「[8316] ソートの挙動の切り替えはサクラエディタ内で可能になりませんでしょうか

Meryのソートマクロを見たら実質ワンライナーだった。連打するたぐいのマクロではないとしても、自分のはゼロオーバーヘッドルールから離れすぎていた。


2016年12月14日 (水) [SakuraEditor]「Sakura Editor / PatchUnicode / #1092 セキュリティ対策」 24ファイル版のパッチを途中まで読んだ。■bSelLock はたしかに else や default でパターンを網羅したいケース。■SetFocus は、他はなくても必ず自分自身が対象として含まれるだろうという期待があるのだろうけど、それは予断だし油断があったのだと思う。同じファイルのすぐ上にある CViewCommander::Command_CASCADE にも同じ型のコードがあるけどそれは?■クリア済みのWndProcを呼ぶことについて。呼べないから呼ばないでいいのか、呼べないから呼べるようにして呼ぶのか、判断がつかない。■パッチ部分は SendMessageToAllEditors なのだけどそのすぐ上にある Send を Post に置き換えただけの PostMessageToAllEditors については?■ここまでで触れずにとばした部分は全体に趣味的な印象を持った。delete 0 は安全らしいし、CloseHandle(0) は無害らしいし、使わない領域、範囲外とインデックスでマークされてる領域を NULL で埋めなければいけない理由はないし、変数を2つ定義して、同時に初期化した片方を条件にもう一方を直後の if-else 文で初期化(※厳密には代入)するというとき、定義部分でも初期化が必須かといえばどーでもいい。それよりも C99 より前の C言語に倣った関数冒頭にまとめた変数宣言(&定義)のほうがつらい。長大な関数のあるブロックである変数が必要になったとき、使いたい値が代入されてからそこまでのすべてのコードパスでどんな値が代入され得るのかチェックしないといけないし、反対に不要になったときは、代入をやめたことで関数の以後で問題が起こらないことを確認しなければいけないし、それを forループの変数 i についても行わなければいけないのだから。行き当たりばったりで次々変数を増やすのもどうかと思うが、適切な粒度のスコープがあると思う。env/CAppNodeManager.cppのパッチで指摘された初期化はまとまっていて問題を見出せない。■env/CAppNodeManager.cppの別の部分については、IsSakuraMainWindow でもやっていて実質的な意味を持たない NULLチェックを足して今以上にごたごたさせるより、2番目のループを取り除くぐらいの書き直しをしたらいい。「hWndLastが NULLのときに全くメッセージが送られていなかった」なんてときのコードはおそらく原型が残っていないし(そんなことを言うやつがよくわからないまま(同じ)轍を踏むのだ(自虐)。でも unicodeブランチでは遡れるログに限界が……)、その対応のせいで(たぶん昔はそうだったのだろうけど)双子のループではなくなっているのだから。こんな感じにしたい>CAppNodeGroupHandle__PostMessageToAllEditors.txt。もちろん SendMessageの方も。仕様の違いは、pWndArrに hWndLastが複数含まれていたときに複数回メッセージが送られないってことだけど、そんなこと起こらないし期待もしていないでしょう? ほぼコピペの双子関数をひとつにまとめるのは、PostMessageと SendMessageの戻り値の型が違うせいで失敗した。マクロを使うとデバッガで追いかけるのが難しくなるし、メンバ関数テンプレートはコンパイラの実装が遅かったような記憶があって積極的に使いたくないし、そもそもリンクエラーを取り除けなかった(<テンプレートの定義を.cppに書いていたから。明示的な実体化が必要だった。こんな感じ)。たぶんファイルローカルのモジュール関数テンプレートにしたら一挙両得だけど、アクセス許可を出さないとダメだよね? 代わりに staticメンバにする? そうするだけの、過剰なテクニックを駆使したりヘッダに手を入れたりするだけのメリットがないのでコピペのままでいいや。■macro/CWSH.cppについて。中断のためのスレッド関数とメインスレッドがパラメーターを通して hEventを共有していて、子スレッドの方で OpenEventDuplicateHandle みたいなものは呼んでいないんだけど、子スレッドの終了を待たずに SetEvent(hEvent);CloseHandle(hEvent); して子スレッドはイベントを受け取れる?■読んだのはここまで。趣味的(あるいは潔癖・偏執的)とは書いたけどデバッグモードのコードだと思えばそういうものかなという気がしないでもない。が、C++が初期に遅いと言われたのってコンパイラが隠れてする仕事(コンストラクタの呼び出しとか)に対する無理解が理由にあると聞くので、無駄とわかってるところに 0 を埋めて歩くことに積極的にはなれない。staticでない未初期化変数の値をそのまま使用するのは結果が予測できないバグだけど、未初期化変数(遅延初期化変数)それ自体は問題にしないよ。■自分の不見識が明らかになるだけかもしれないけど……。「スタックのドカ食い対策」<スタックで間に合ってるならスタックの方が速いんじゃないの? 「WINVERによる条件コンパイル」<ソース分裂バイナリ分裂はない方がいいし、俺プリプロセッサ嫌いなんだよね(<誰も聞いていない! 共感性・説得力皆無!)。さらに共感を得られそうにないことを書くと、namespaceが導入されたからグローバルな名前空間を明示するために :: を付けましょう、これまでただ Func(); と呼んでいたものを ::Func(); と書きましょう、なんてのはなんの冗談かと思う。譲るのは当然後から来たほうだし、衝突しないような名前を選ぶ、衝突が避けられないときにしぶしぶ :: を付けて区別する、くらいの態度でいるんだけど、みなさん積極的に :: を付けますね。それって(知らないしやったことないけど)まさに MFCプログラミングで名前のバッティングが避けられなかったからみんなそうしてただけなんじゃないかとも思ってるんだけど、SDKプログラミングでもわりと積極的だよね。自分が無知で異端なのかと不安になる。■途切れていた古いログを見つけた。「Fix: Send/PostMessageToAllEditors() don't send message when last window parameter is NULL.」この修正が不可解で、現在のソースに残ったコメントから以前のコードを想像できなかった(だから原型が残っていないのだろうとコメントした)。単純に m_hWndLast の NULLチェックを省いてこう直せば良かったじゃない?>if( phWndArr[i] != m_hWndLast ) この頃はまだ IsEditWnd(※後のIsSakuraMainWindow?)が引数の NULLチェックをしていないことから、先取りして phWndArr[i](※m_hWndLastではない)の NULLチェックを追加してもいい>if( phWndArr[i] != m_hWndLast && phWndArr[i] )。ま、済んだことはさておき、この時点ではまだ双子のループが存在していないことが興味深い。双子のループが誕生したのはこのコミット>「New: Grouping of the tab windows.」(←Firefoxだとアドレスバーで20回ぐらい Enterキーを押しているうちにページ内アンカー(#diff-24)が機能するけど、Operaだとリロードしてしまって永遠に機能しない。くそったれな遅延ロード。くそったれな S……)。グルーピング対応のためとはいえループは必要だったろうか(反語ではありません。結論保留)。


2016年12月02日 (金) おかしい。いろいろと言ってることがおかしい。「電撃 - 『サガ スカーレット グレイス』7時間プレイ後座談会。それぞれが感じた『サガ』らしさとは?」■すっごくやりたくなったけど Vitaがない。携帯ゲーム機はいらないんですよ。液晶の Vitaもいらないんですよ。うーんでも、うーん。


2016年12月01日 (木)

最終更新: 2016-12-02T23:22+0900

目があった。鹿。このあとどんどん近づいていって見つめ合ったまますれ違った。体当たりされなくてよかった。 シシトビバシっていうのは名前だけではなかったのだ。


2016年11月29日 (火)

最終更新: 2017-11-01T20:40+0900

[SakuraEditor] TSV

ただの表データを扱うのに Excelを起動したくはなくて、エディタの TSVモードを使った(※世の中には関連づけのままにフォトショップを使って画像をプレビューする人もいますがね<鷹揚な人だ見習おう)。タブ文字って、列の幅がタブの幅の倍数をまたぐたびに上下で列がずれるのが微妙で、タブを複数連続で使って揃えたとしても、列を編集して長さが変わったら限界まで圧縮されていたタブがぴょっこり復元して後ろの列を押し出したりするし、1タブでなんとかしようとタブの幅を想定最大列幅まで大きくするなら3つか4つの列しか画面に収まらないしで、どうやっても手間がかかる。タブ文字の拡張として TSVモードは良い。

 ここが気になる

TSVモードとは関係なく、いつもと違う使い方をしたのでこれまで気付かなかったことに気がついたり、新バージョンのバグに当たったりした。

  1. タブの幅を大きくするとあるレベル以上で幅が固定されて大きくならない
  2. 拡張子 .tsvで TSVファイル設定を作成したのに .tsvファイルを開いたときに TSVファイルタイプにならない
  3. (その状態で)タイプ別設定の内容を変更して決定しても反映されない
  4. (TSVモード) 列の余白が広すぎて収まるものまで画面の右にはみ出る
  5. (TSVモード) タブストップの再計算はいつ? (Alt、F、W、W で再読み込みするしかないの?<頻繁なので覚えた)

 1. タブの幅を大きくするとあるレベル以上で幅が固定されて大きくならない

文字の大きさや折り返し幅が関係してる。原因をつきとめてさあ報告しようかと既存のバグ報告を漁ろうとしたら、いきなり掲示板の3スレッド目がそれだった>開発掲示板(Unicode)[2370]。おまけ付きのパッチもある。脱力。

 2. 拡張子 .tsvで TSVファイル設定を作成したのに、.tsvファイルを開いたときに TSVファイルタイプにならない

MRUに前回の適用ファイルタイプが記録されていたせいだった。けっこう昔からある機能で、Ver.2系の最初のリリースぐらいからある。要望も昔からあるみたいで「Request/111 手動で変更したタイプを記憶 - SakuraEditorWiki」の投稿者は request.txtとなっている。

いらない機能です。「一時適用」したファイルタイプを一時でなく覚えておいた結果、ユーザー(俺)を欺いてしまっているのだから。先にばらしてしまうと、次に挙げる問題もこの機能に起因して引き起こされていたし、せめて、拡張子というルールに基づくファイルタイプ判別に引っかからなかった場合に限り、アドホックな一時適用ファイルタイプを採用するなどしてほしかった。

どちらを優先するのか一概に決められないところはある。アドホックな選択を記憶・復元するのがユーザーの意思を尊重した結果なら、ルールを新設して適用したいというのもユーザーの意思なのだから。お天気屋の原理主義者の今日の言い分は「ルールはルール(なので絶対)、一時は一時」ですがね。

※お天気屋たる所以は、かっこ書きの中身が普段は「(所詮はルール。人の作ったもの。文言の枝葉末節や不備に盲従せずその精神を忖度した運用でカバーし必要なら変えるべし)」だから。どちらへ転んでも自分に都合のいい主張になるという。

 3. タイプ別設定の内容を変更して決定しても反映されない

タイプ別設定一覧から選んで一時適用ボタンを押したときと、ファイルを開くときに MRUから記憶していたファイルタイプを復元したときでは、状態が違う。ついでにいうとコマンドラインの -TYPEスイッチでファイルタイプを任意に設定したときは、MRUから復元したときと同じ挙動を示す。

どういう挙動か。ファイルタイプの選択結果がロックされていないので、設定を変更したときに、拡張子に基づくルールベースの選択に上書きされる。

この結果どういうイライラ状況が発生したか。

  1. TSVファイル設定を作って拡張子 .tsvを登録(※「「ドット省略必須」「スペースorカンマorセミコロン区切り」のリスト(20100915p01)」であることはソースコードから既知)したのにテキストモードになる。なんで? 開き直してもエディタを再起動してもダメ。なんで?
  2. じゃあテキストモードでいいよ。テキストファイルの設定を TSVファイルの設定として使ってやる。設定変更、完了。全然反映されてないんだけど、なんで? (実はさっき複製して新設したばかりで未設定の TSVファイルタイプが拡張子に基づいて適用されていた)

適用されているファイルタイプってタイプ別設定一覧を表示するまでわからないんだよね。ちょっと覚えがあってヘルプを調べたらタイトルバーには表示できるみたいだけど(「$B タイプ別設定の名前 (sakura:2.0.7.0以降)」)、初期設定ではない。

ファイルタイプが見えないしすり替わってるしルールを無視するしで、気がつくまで(つまりソースコードを読むまで) 1と 2のあいだをぐるぐるぐるぐるしていたのだった。

 4. (TSVモード) 列の余白が広すぎて収まるものまで画面の右にはみ出る

どうも W の幅をひとつの基準にしているらしい(※高さの基準に x が、ハイフンの長さの基準に n や m が使われるように(<果たしてそれを聞き分けて区別できるだろうか)、もっとも幅広な文字として W が挙がるのかもしれない)。そして列の幅計算にはフォントを使わず、全角半角単位で数えてるっぽい。

たとえば最近愛用してる HG正楷書体-PRO フォントの場合、W の文字は全角半角で字形にゆらぎ程度の違いしかなく、基準に使う W は半角文字ながら全角の幅を持っている。その結果、列幅の想定と実際におよそ2倍の開きが生じた結果、ほぼ列の内容と同じ幅の余白が隣の列との間に確保されることになった。

そういうアルゴリズムで(=列幅の2倍の)タブストップを計算してるのだと思ったから、よーし好きに書き直しちゃうぞー、と CTsvModeInfo::CalcTabLength を頭から書き下していって途中で首を傾げてしまった(あれ? これ、俺が書こうとしてるそのまんまやん)。実際、列の内容が W のみだった場合は想定とのあいだに誤差はなく、計算された余白は適正と思えるものだった。

 5. (TSVモード) タブストップの再計算はいつ? (Alt、F、W、W で再読み込みするしかないの?)

実際どうなのだろう。閲覧を主に想定してるのだろうか。

 雑に解決します>TSVモードを富豪的に使いやすく。以前のファイルタイプを記憶しない。コマンドラインで指定されたファイルタイプをロックする。.rev2.patch

ファイル名の通り……ではないな。細かいけど「記憶しない」ではなく復元しないだし、一定以上のタブ幅が4に切り詰められることの修正も入ってる。

雑なパッチとは「Viewが前の行にさかのぼって再描画してくれない? 全部書き換えたらいいじゃない」の精神で。「Viewが持ってるフォント情報は古い、しょうがないので自分で作る」みたいなコメントがソースのどこかにはあって、フォントを利用した列幅計算はある状況では問題があるのかもしれないけど、「こまけぇこたぁ(略)」の精神で。

あと、TSVモードで現在無視されてるタブ幅の設定を、余白の量として扱った。タブ幅8なら隣の列とのあいだに最小の行で全角4個分の余白。

 @2016-12-09 やはり……雑!
  • 切り取ったときにゴミが残る
  • 横スクロールがときどき狂って右端が見えなくなる

我慢して使うよ。

 @2016-12-11 パッチを .rev2.patchに差し替えた
  • 雑な全体再描画誘導をアップデート(0を -1に置換しただけ)
  • 雑に折り返さないときの横スクロールに対応(常に最長行をフルスキャン)

下に書いた悪魔合体を進めると、横スクロール対応を雑でなくできる


P.S. histという用語は MoveHistPrev/MoveHistNext という前例に基づいたものだったらしい。マクロを書いていて気がついた。だからどうということではないが。

そして、マクロを書いていてアンドゥ履歴をまとめたいなとか、カーソルをコマンド連打以外の方法で操作したいなとか思って調べたら、そういう機能は 2.0.4.0とか 2.1.0.0で入っていたらしい。マクロ強化の動きは見ていたけど、これはたしかに必要だわ。理想的にはコマンド列挙の VBスタイルではなく JScript式のオブジェクトモデルが欲しいという考えは変わらないけど。コマンド群が不足なく整備されさえすれば、マクロの先頭で JScriptで書いたラッパーライブラリを読み込んで evalするという方法もありそうだけど。『C++のためのAPIデザイン』を読んだところでは、関数群を整備するのに比べてオブジェクトライブラリを用意することには特有の問題(依存とか修正とかに関してだっけ?)があって難易度が上がるとかなんとか(つまり最初は関数列挙で正解)。

書いていたマクロっていうのがカーソル行をファイル末尾に飛ばすものなんだけど、Ruby風に書くと File.lines.partition{...} というのをそのマクロを使ってやろうとしていたんだけど、どうしてもできないのがスクロール位置(縦と横)を動かさずにそれをすること。Jumpダメ。GoFileEndダメ。MoveHistPrevダメ。AddTailダメ。LineCutToStartダメ。DeleteLineは対象が折り返し行でダメ。使えるコマンドがなかった。「行削除って便利。(20100620p01)」のときから変わらない悩み。マクロ実行の前後でフォーカスを見失うのは我慢できない。

 PLAN TODO: 列を指定してソート

たしか秀丸にあったことで知った機能。今はソートの前に列を並び替えてるんだけど、ドロップをミスってデータを壊さないかはらはらしてる。気がつけばアンドゥできるけど、気がつかなかったときが怖い。

 PLAN TODO: 次のタブ(の前か後ろ)へ移動するコマンド

何度も[End]キーを押しては間違って行末へ飛んだ。どうやら TSVファイルの列を編集しているとき、無意識の[End]キーで飛んで行きたい末尾とは列の末尾だったらしい。

あと Tabキーで次の列へ移動するとか、Enterキーで下の行へ移動するとかしたい気がするけど、違和感なく適応できるかはわからない。試してみようにもマクロから CSV/TSVモードのオンオフを知る方法がないので。

 悪魔合体:CSVモードのための列幅キャッシュ + テキストを折り返さないときの最大行長キャッシュ (@2016-12-07)

できると思うんだけど。つまり、タブストップの随時再計算をそれなりの規模の CSVファイル(※ウチのPCだと富豪パッチバージョンで1MB・1万行ならもたつくけど現実的なレベルなので、それより大きいファイル)でやろうとして時間を空間で購った場合、横スクロールバーをドキュメントの最長行に対応させるためにやっていることっていうのはその一部になる。でもコストが整数2個から配列の配列と段違いに大きくなるので、CSVモードではない場合のコスト増を避けなければいけない。(折り返しモード)×(CSVモード)=4通りのコード分裂……。

レイアウトマネージャーの仕事の一部(※折り返さないときのための再計算を適宜実行すること)が外に漏れた結果あちこちにコピペコードが散らばってるなーとか、レイアウトはレイアウトマネージャーの持つパラメーターがないと幅計算できないしレイアウトマネージャーからは独立してる(参照を持っていない)んだから、レイアウトに計算結果を持たせるのは間違いだし値が意味を持たないよなーとか、レイアウトマネージャーからレイアウトを受けとってそのレイアウトにレイアウトマネージャーを引数として渡して幅計算をさせるっていうのは、直接レイアウトマネージャーに指定レイアウトの幅を聞けばいいし(※)、そうするならレイアウトマネージャーにはゲートウェイとして値をキャッシュして返す役割が期待できて、その値っていうのがつまり折り返さないときのために計算してレイアウトにこっそり(レイアウトの与り知らないところで)埋め込んだレイアウト幅のことなのだから、やっぱりレイアウトに値を埋め込むのは間違いだよなーとか、if (bFastMode) {...} で囲まれた複数の部分が幅計算の適宜実行だけじゃなく、CLayoutMgr::_DoLayout なんてアンダースコア付きで見るからにやばいメンバ関数を呼んでいて、レイアウトマネージャーの内臓に手を突っ込むがごとき癒着ぶりだなーとか、うーん、すでに悪魔の脳みそが必要な状態なんじゃないのこれ。

※こうなっていないのはレイアウトマネージャーが束ねるレイアウトっていうのがリンクリストになっていて、添え字で任意のレイアウトにランダムアクセスできないからだろうっていうのは想像できる。でも……。

落し所はレイアウトを必要なときに必要な分だけ作成して返すプロキシクラスに位置づけて、内部的にはレイアウトマネージャーの持つ情報に自由にアクセスすることだろうか。これだとレイアウトにレイアウトマネージャーへのポインタを持たせるオーバーヘッドを正当化できる、というか、それがレイアウトの持つ一番大事な情報ということになる。プロキシが自身が古くて無効だと知る方法はなんなのだろう。レイアウトマネージャーとレイアウトにバージョン番号を持たせて突き合わせるのだろうか。C++のイテレータはどうしてるかな……って考えると、俺だ! 俺が無効化されたイテレータを管理してた。デバッグモードでは違うけど。

でも……、レイアウトマネージャーの持つ情報のうち、レイアウト行ごとに分割できるものをまとめてレイアウトクラスとし、情報だけでなく行ごとに独立した機能もレイアウトのメンバーとしてレイアウトマネージャーからオフロードしたら、それって現状? プロキシクラスだなんだと言ってレイアウトマネージャーへのポインタを持たせる理屈をこねて、現状のレイアウトにポインタメンバを一個追加する言い訳を考えてただけ?

それもこれもレイアウトマネージャーを引数に取るレイアウトの一部のメンバ関数(CalcLayoutWidth, CalcLayoutOffset)と、レイアウトが自身で一切触れずにレイアウトマネージャーが操作するメンバ(m_nLayoutWidthとそのアクセサ)が気に入らないからだ。どちらもオフロード対象ではないということだから、レイアウトがレイアウトマネージャーへのポインタを持つか、レイアウトを通さず直接レイアウトマネージャーに尋ねて解決すべき問題。そもそも後者はメンバがメンバではないという一見してあり得ない状態。パブリックなメンバ変数しか持たない構造体ならそういう使われ方はあるが、じゃあお飾りでお為ごかしのアクセサを捨てよ。<こういうのって性格の反映なのかな。引きこもって外からの干渉を拒絶する姿勢、線を引いて私の仕事あなたの仕事と分ける姿勢って。人格のコアというか凝り固まってこじらせてるからこういう語調になるんだろうって。

……とまあこんな感じで脱線するから CSVモード(富豪パッチ版)の脱富豪化は進まないのだった。それにこういうのは実装前が一番楽しい段階だから。

<追記@2017-11-01>『[単行本(ソフトカバー)] 有野 和真【Androidを支える技術〈I〉──60fpsを達成するモダンなGUIシステム (WEB+DB PRESS plus)】 技術評論社』で解説される Androidのコードに、自分で使うわけではないレイアウトのためのメンバーが出てくる。よくあるらしい。レイアウトは親が子のサイズを知りたがり子が親のサイズを知りたがるので、すぱっと割り切れないし決めきれない。それを解決する方法も入り組んでいて難しい。</追記>

 @2017-08-18 矩形選択削除に問題

当然の利用法として、特定の列を矩形選択で一括削除したくなったりするだろう。ダメ。削除し過ぎたり削除し足りなかったりする。なんだろう。削除の途中でタブストップの再計算が走るのだろうか。

 @2017-08-28 TSV補助データのコスト

すぐ上で

タブストップの随時再計算をそれなりの規模の CSVファイル(※ウチのPCだと富豪パッチバージョンで1MB・1万行ならもたつくけど現実的なレベルなので、それより大きいファイル)でやろうとして時間を空間で購った場合、横スクロールバーをドキュメントの最長行に対応させるためにやっていることっていうのはその一部になる。でもコストが整数2個から配列の配列と段違いに大きくなるので、CSVモードではない場合のコスト増を避けなければいけない。(折り返しモード)×(CSVモード)=4通りのコード分裂……

と書いたけど、別に配列1個でもよさそう。その場合「横スクロールバーをドキュメントの最長行に対応させるためにやっていること」とは独立したデータになるのでコード分裂もない。どういうデータを持つか。

  • 1列目からN列目までのそれぞれで、最長の幅を持つのは何行目でその幅はなんぼか、というのを配列に記録する。
  • その記録された(列,行)の幅が縮んだときは、すべての行でその列の幅をスキャンして記録を更新する。
  • 列の編集によってある行が記録されている最長の幅を超えた場合は、その行と列の幅で上書きする。

スキャンの発生頻度はそこそこ低いのではないか。ネックは N番目の列の幅を網羅的にスキャンするときに、行の頭からスキャンして列番号をカウントしていくのでは後ろの方の列がつらいってこと。このへんはダブルクォーテーションの解釈と連携してさらなる補助データを用意することも考えられる。まあ、考えるだけで書かないんだけど……。


2016年11月27日 (日)

最終更新: 2017-01-25T00:05+0900

にゃーん (約1MiB)

耳がね、レーダーよろしく周囲を警戒してるんですよ。目を閉じて横になっていても、耳だけが寝ていない。たぬき寝入りはばれているぞ、この耳が証拠だ、と、つんとするとピクピク、つんとするとピクピク、と律儀に反応が返ってくる。ひとしきりあそんだら、ふぅと息を吹きかけておしまい。どれだけかすかな風であっても、ナニゴト!と寝耳に水のいきおいで首から上がとびおきる(やっとこっち向いてくれた)。


2016年11月17日 (木) いやあ、どうでしょうね。「和英混在の日本語にはinter-ideographがベストと思っていたが、どうもinter-clusterが一番うまくいくようだ。」■inter-clusterの説明は、「単語間に調整字間を分配するよ(=inter-word)、スペースが1個もないような文章でもなんとかするよ。」と言っているように読める。それに、(IE9で)実験してみたけどあまりなんとかする気がないように見える。ragged rightを許容してるし、それは日本語だけの段落でも同じ。■長い英単語に相当するものとして分離分割禁止文字であるダッシュの連続を挿入してみた>suspicion_about_inter-cluster.png. 英単語間だけでなくすべてのスペースが対象であることを確かめるために漢字(「独自実装」)の間にもスペースを挿入している。■これは過去の Safariと同じ状況ではないかな。「Safari(5.1.7)は……スペースだけを使って両端揃えをしようとして英字混じり文が不自然に分断される」「全角文字だけで文章を書くならスペースに頼らない字間調整が行われるとの報告もある」(20131101p01.10)。このやり方はスペースが1個でも入ると、その1個だけが引き伸ばされるがゆえにたちまち問題を引き起こす。■どこを重視してどこを妥協するかは好みの問題かもしれないけど、text-justify: distribute(=inter-ideographの対象に加えて英単語内にも調整字間を分配する)を指定するのが、日本語がメインの和欧混交文の一番無難な表示方法だと思ってる。条件が悪ければ英単語が不格好に間延びするけれど、大体においては広く薄くさりげなく調整が行われる。それに、distributeは "Handles spacing much like the newspaper value." であり、newspaperは "the most sophisticated form of justification for Latin alphabets." らしいのだから、向こうの人も条件によっては間延びするのも致し方なしと受けとってくれるのではないだろうか。■■■suspectと doubtの違いについて学校で聞いた記憶が……。……ではないか、が suspectで、……ではないのではないか、が doubtだとか、そんな感じ。疑いを持ってるという点ではどちらも同じ。スクショ画像の名前はあれでよかったんだろうか。


2016年11月16日 (水) 筆ペン。■ちょっと前にボールペンをやめて筆ペンで字を書こうと思い立った。最初は万年筆がかっこいいと思って、アルファベットではなく漢字を書くための日本製のペン先があることもわかったんだけど、どれもこれも判で押したような樽型ボディなせいでこれという1本を決められなかった(見た目だけならこれは合格だった>『DAKS ハウスチェック クロスリング万年筆』)。俺ドクターグリップが触りたくもないくらい嫌いだったんだよね。トレパンマンを見るような目?■同じサイト内で横にスライドして筆ペンを見つけた。ボールペンでもきれいな字を書く人は書くけども、筆の不自由さはへたくそに、丁寧な線を引くことを強制して矯正してくれるのではないか。紙を押さえつけることができないので距離を保ってインクが乗るのを待つ時間が必要だし、折れ曲がった穂先がねじれたりつっかえたりするので縦横にチャキチャキ走らせることができないし、臆病にぷるぷるしてると線の太さが一定しないしで、緩急のリズムが必要。生きた線を引くのにリズムが必要なのはボールペンも変わらないのではと思うのだけど、それを強制してくるのが筆(ペン)なのではないか。それとも幼時の手習いを思い出しただけか。■オールドタイプな人間なので漢検(20161101)の漢字練習には筆ペンとノートを使ってる。そういう気分にさせるものがあるね。ここまで能書きを垂れておきながら現実には筆ペンはお蔵入り寸前だったし(ボールペンの代わりにはなりませんよ)、紙のノートは一度整理したので1冊も残っていなかった。まさか使う当てができるとは。ノートがない間はお蔵入りしていたペンタブレット(20121216)と水彩LITEを使って書き取りをしていた。■漢字に対する意識がちょっと変わって、書けなくてもいい漢字があるとは考えなくなった。目にした漢字はすべて書けるようになろう、現実に使われている漢字は書けて当たり前だと考えるようになった結果、ちょっとだけ脳みそと時間を割いて字の構成を脳と手に焼き付けるようになった。このときネックになるのが簡略化される前の形と学校でひとつも出てこなかった形。常用漢字?から外れると簡略化は定義されていないし、見たことのない形は書き順すら想像するしかなくて、覚えるためのデータ量が整数の文字コードというよりベクタ画像級になる。線が何本……どちらが長い……止める……払う……くっつける……離す……突き出る……出ない……どちらでもいい(※巳と己の両方が許容されていたりする)……知ってる形に見えるけど線が1本少ない……などなど、ちょっとでも少ないデータ量でコードしようと努力しながら手と口を動かしてる。そうこうするうちに符号化文字集合が拡大していって、文字コードひとつで引き出せるようになるんじゃないですか。


2016年11月15日 (火) AI研究者が問う ロボットは文章を読めない では子どもたちは「読めて」いるのか?(湯浅誠) - 個人 - Yahoo!ニュース」■過去に読めてなかったことを書いた>20100401p01。小学5年のときにも割合の計算で小さい数を大きい数で割るというのが感覚的に受け入れられなくて、必ず一度1より大きい答えを出してしまってから数字を入れ替えてもう一度割り算するという手順を踏んでいた。■ぶつかってそれではダメだと気がついたら定義に立ち返ってひとつひとつの手順を確かめながらたどるのが方法。ここでは注意が必要だと学習したから立ち止まって確かめることができるというだけで、失敗しないうちや失敗を回避できるようになれば、やっぱり中間を飛躍して答えに飛びつく高速のパターンマッチングの出番だと思う。それが人間の基本で、トライ&エラーで最適化を重ねた結果が思慮や洗練として見えているという気がする。■最近は物を見る訓練も必要だったなと、今でもまるで見えていないなと感じている。脳の自動処理を迂回してあるがままに物を見る訓練を通して、対象を「見る」ことができるようになるんじゃないかと期待してる。


2016年11月11日 (金) Facebookのうんこぶりがすげー。画面を覆い隠して「ログインしろ」。コメントを読もうとしてポインタがどこかに触れたら「続きはログインしてから」。20件のコメントを読もうとしてクリックしたら 2件のコメントと「残りの18件のコメントを表示」するリンク。それもクリックしたらたくさんのコメントとたくさんの「他の返信を表示」するリンク。何回クリックさせようって? こんな苦労は俺が個別ページを見つけられなくてタイムラインを見てるせいかもしれないね。個別ページの URLを探す一環で「シェアする」リンクをクリックしたら、それも「続きはログインしてから」。ネットに Facebook以外のメディアが存在しないかのようではないか。内輪のなかよしクラブぶりがすげー(そういう出自ですからね)。囲って排除してその結果できあがった輪っかのどちらがウチでどちらがソトか、Facebookの方が隅っこに消えてしまえばいいのに。■好き好んで近寄ったわけではなくて、ファームウェアが Facebookでだけ公開されてるのでそうせざるを得なかったっていう残念な事情があります>20161110p01。自分とこの商品ページとかサポートページとかを使ってくださいよ。

最終更新: 2017-09-06T19:57+0900

[WR250R][NECKER V1P] バイク用ドライブレコーダーをインストールした

写真も動画もとってない(追加予定)。

場所は左のフロントフォーク。フォークがねじれたときに緩めて締める下の方のブラケットに、元からあったブレーキホースのガイド共々共締めした。おもちゃを構造部にってどうよとは思ったが、ここがベストポジションだと思ったんだよねえ。次点はウィンカーの上、ヘッドライトの上部を固定するボルトに共締めして。次次点はハンドルバー。どんどん上方に移動して目立ってくるのが嫌。目立てば盗難を警戒しないといけなくなる。安くなっても 16000円はしたのだから。というか、カメラを構えるとか撮影するとかいう行為がひどくプライベートで恥ずかしいことに感じられるので(鏡を見るとか食事もそう)、他人に気取られたくないというのが第一。その点 lowerブラケットの横だと、正面からはヘッドライトの右、ウィンカーの下、シュラウド内側の黒プラスチックを背景にして収まることになる。ハンドルをロックした状態ではシュラウドに包み込まれて手をつっこむ隙間もない。シュラウドとカメラがぎりぎり接触するので半センチほどブレーキホースガイドを押しのけたくらいのぴったりさ。

ホームセンターで L字の短いステーを1つと M10のキャップボルト(アーレンキーで回せるやつ。携帯ツールで一番太い、自転車のクランクを外すときに使うのが合う太さだった)・ナットを1組買ってきて、あとは NECKER付属のマウントを使った。プラスチックがしなるとかすぐ割れたとか聞くけどもとりあえずは。付属してきたティーメジャーのような形のステーに開いてる、三脚穴ではない方の穴は 1cm。買ってきた L字ステーに2個開いてる穴も 1cm。だからステーとステーの連結は M10のキャップボルトにしたんだけど、共締めさせてもらうフォークのロアーブラケットピンチボルトは M8。穴が大きすぎるので M8のワッシャー(9円)だけまた買いに行ったさ。

ステー単体だと素手で曲げるのは難しいんだけど、2個を連結してその先に重いカメラ(※)が乗っていれば結構しなる(それは 3Mの VHB(=付属品画像に見える赤いシールのやつ)をそのまま間に挟んでるのも理由だろうけど)。明日の録画がどれだけひどいか、ましてカメラが脱落しないかが心配だ。USBケーブルを既設のケーブル類と一緒にハンドルに固定したので、NECKERの特長のひとつである USBケーブル一体型の防水キャップが一体のままである限りは、スポークに届く位置までは落ちなさそう。ストラップホールはケーブル一体でないキャップには付いてた。直径方向に 2mmの穴が貫通してるだけなのでケータイストラップみたいなのは使えないけど。

※三脚穴に対応したネジはカメラのアクセサリだろうと、ビックもヨドバシも近くにはないし、カメラを売ってるなら電気屋も同じだろうと2件寄ってみたんだけど、つまんないね。何を売ってるんだろう。高すぎるメモリーカードをずらずら並べて、プリンターのカートリッジを一面に並べて、(パッケージ版の!)ゲームソフトを扱う一角があって、それってこち亀を全巻陳列するくらいの場所の無駄だし、客にそこから選ばせるのもまた無駄だし。ソニーのアクションカムの実物(※コードにつながれていたので本物だろう)が画像で見るよりひとまわり小さかったのと、持ったときに中身の詰まった重さを感じるのが全体のごく一部で、全体としてものすごく軽い(でもたぶんバッテリーは入ってなかったんだろうな。バッテリーは中身詰まってるし、総重量のおよそ 1/5を占めるみたいですよ)というのが発見できただけ。欲しいものは置いてないし見逃せないものもないし、ホームセンターの目移りするわくわく感との落差よ。昔は電気屋のチラシって眺めてるだけで楽しめたのにね。

マイクは電源ボタンの反対側。数少ない YouTube動画では高音が反響したような耳障りな音ばっかり聞こえてくるので、素の状態からどうにかしてましにしなければいけない。参考にできる NECKERの成功例は?

「共締め」ってどう読むのか正しい言葉なのか検索したときにヒットしたたいそうなお役立ちサイト>「ねじ」のゆるみ ねじのことならコムウエル・フジサワ。勉強になります。

 @翌日| スクリプトを書いた

連番だと PCにコピーしたときに名前がかぶる可能性が高いし、動画の撮影開始時刻、終了時刻という重要な情報がファイルの作成日時、更新日時という失われやすい場所にだけ(※)保存されてるというのも不安なので。※映像から読み取れればいいんだけどね。

/* [NECKER V1P] renamer.js

	NECKER V1 Plusが保存する動画ファイル
	CAR_XXXX.MOV, SOS_XXXX.MOV, TLP_XXXX.MOV
	の連番部分(XXXX)をファイル作成日時(YYYYMMDDHHMMSS)で置き換える。

	CAR_XXXX.MOVで確かめた限りは、ファイルの作成日時と更新日時は
	動画の撮影開始時刻と終了時刻と一致するようですよ。
	SOS_XXXX.MOVはちょっと特殊かもしれないけど。

	メモリーカードから PCにコピーした場合、ファイルの更新日時は維持されるけど
	作成日時はコピーした日時(コピーファイルの作成日時)で上書きされるみたいですよ。
	だからこのスクリプトはメモリーカード内の \DCIM\100__DSC フォルダで実行しないとダメですよ。
*/

var FSO = new ActiveXObject("Scripting.FileSystemObject");
var Dir = FSO.GetFolder(".");
var FAC = {Normal:0, ReadOnly:1, Hidden:2, System:4, Volume:8,
           Directory:16, Archive:32, Alias:64, Compressed:128};
var Reg = /^(CAR|SOS|TLP)_[0-9]{4}\.MOV$/;
for (var it = new Enumerator(Dir.Files); ! it.atEnd(); it.moveNext()) {
	var file = it.item();
	if (file.Attributes & (FAC.ReadOnly+FAC.Hidden+FAC.System+FAC.Volume+FAC.Directory+FAC.Alias)) {
		continue; // 属性持ちには触らない。非ファイルには用がない。
	}
	var m = Reg.exec(file.Name);
	if (! m) {
		continue; // NECKERの動画ではない。
	}
	var t = new Date(file.DateCreated);
	var time = ("000"+t.getFullYear()).slice(-4)
	         + ("0"+(1+t.getMonth())).slice(-2)
	         + ("0"+t.getDate()).slice(-2)
	         + ("0"+t.getHours()).slice(-2)
	         + ("0"+t.getMinutes()).slice(-2)
	         + ("0"+t.getSeconds()).slice(-2);
	var newname = m[1]+"_"+time+".MOV";
	for (var i = 1; i < 10; ++i) { // 無印と(2)から(9)までリネームを試します。
		try {
			file.Name = newname;
			break;
		} catch(e) {
			newname = m[1]+"_"+time+" ("+(i+1)+").MOV";
		}
	}
}

 @翌日| 夜の画像

NECKER V1 Plusで撮った動画の再生画面キャプチャ。(1280×720 66KiB)

カウルが写ってるのは昼の動画よりポイントが高いが、空の狭さが大きなマイナス。マウント位置を下げてやや上向けるか?

 @翌日| 昼の動画

NECKER V1 Plusで撮ったバイク車載動画。(1280×720 5分 120MiB)

だいたい4分の1のサイズに圧縮してる。ナンバーは元から読めません。止め絵の画質的にもスピード感的にも品質設定をフルHD/30fpsの方にしようかな(<画質は良くならないわりに動きの滑らかさは低下するので、やっぱり 720/60fpsがいい)。DSC-HX30Vで以前撮ったフルHD/60fpsの動画もあるんだけど、音が全然違うよね。低音があるおかげであちらは聞きやすい。NECKERのも YouTube動画から予想してたよりはましな音で、ミュートするまでではなかったが。

画面の一部に夕焼け空が写ってる場面では肝心の前方が暗くつぶれてしまってた。旧機種ではホワイトバランスをはじめ細かくセッティングをしていたらしいが、自動調整で面倒を解決とはいかなかったか。

右下のカメラ名と時刻表示は消せない。DSC-HX30Vがするように字幕扱いでもなく、画面に埋め込まれてる。

最終更新: 2017-05-16T22:39+0900

[tDiary] サクラインターネットに index.rbの実行を止められたよ。(その節はご迷惑をおかけしました)

index.rbのパーミッションをすべて落としたんだって。そうやるんだ。

日記を書くと長々待たされたあげくエラーになって、どうも category.rbに原因がありそうだとキャッシュを削除したり再作成しようとしたらそれも長々待たされる理由になって、parserキャッシュを含めて cacheフォルダをあらかた掃除したらとうとう更新(update.rb)だけでなく参照(index.rb)も終わらなくなっていたらしく、index.rbが夜の間に止められていました。

詳細はここに書いた>http://tdiary-users.osdn.jp/cgi-bin/wforum/wforum.cgi?mode=allread&no=6793&page=0

evalの第3引数を "category.rb:619:#{ymd}p#{idx}" (619は #{__LINE__} とかが使える?)にしてシンタックスエラーを引き起こすもとを探ったら、5年前のこの日(20111209)の日記が原因だったとかね。実はときどき日記の更新がエラーを起こすのは経験してたんだけど、変更自体は反映されてたし、裏で延々実行が続いてるということもなかったので知らんぷりしてたんだ。それが5年?

 誤解のないように

この日記はいろいろ魔改造が施されてるので CPU酷使の原因が category.rb にあるとは限らないし、そうであると考える理由も今のところ持っていません。実際5年間深刻な問題は起こっていなかったわけで。ただ、index.rbを止められたのをきっかけに category.rbを修正したら昨日からの問題が解消したので 、index.rbのパーミッションを怖々元に戻してみて今のところ過負荷は生じていないみたいだってことです。最初は x-math.rb(これは evalよりも大胆かもしれない print関数の乗っ取りをやっています)とその他エラーメッセージに出ていたいくつかのプラグインに原因があると疑って試行錯誤していたので、もはやなにが原因でなにが奏功したのかは藪の中といってよいでしょう。

 その後

  1. fix error about here document in category plugins by tdtds · Pull Request #593 · tdiary/tdiary-core
  2. fix error about here document in category plugins by tdtds · Pull Request #596 · tdiary/tdiary-core

コメントするために GitHubのアカウントを取った。デフォルトのプロフィールアイコンがあまりにもクソ雑魚ナメクジだったので、あわててペンタブ付属のフォトショップエレメンツ9を起動した(初回起動だった)。スカートの中に光源を配置したり、円形のグラデーションをアルファチャネルに設定したり、フォトショップはやりたいことが探せばちゃんとできるようになっている優秀なプログラムだった。自分の想像の及ばないすごいこともできるのだろう。でも Windowsネイティブではないから、数字入力フォームで[End]キーを押してもカーソルが末尾に移動しなかったり、リストで先頭の文字をタイプしても項目が選択できなかったり、戸惑うけど我慢するしかないね。使いたいもんね。

正直なところリンクを張るにあたってどれを指せばいいのかよくわからなかった。ブランチ作成、コミット、マージ、ブランチ作成、リバート、マージ、ブランチ作成、コミット、コミット、マージ、の最後のマージを指すつもりで #596のプルリクエストにリンク(※2番目の方)を張ったんだけど、これでいいの? ていうか活動の流れと全貌がさっぱりわからん。

昨日「もうGitは怖くない: 自信を持って使いたいあなたへ - 檜山正幸のキマイラ飼育記」を読んで理解したにわか知識によると、コミット(リバートももちろんコミット)とマージは同じ種類の実体(コミットオブジェクト)によって表されるらしい。ただし、コミットは親が1つでマージは親が2つ。親というのは変更の元にしたコミットオブジェクトのこと。親子それぞれがファイルシステムのスナップショットとでもいうものを保持しており、その差分を求めることで変更の内容がわかる。ブランチはコミットを継ぎ足す先を指し示す先導役で(実体は refs/heads/の中)、先導役が異なればコミットの列は別方向に伸びていく(枝分かれしていく)。枝分かれして以後の変更の蓄積としてのブランチは、たとえば masterブランチを構成するコミット集合との差集合を求めれば出るとか。

とりあえず4章でストップしてた『[単行本] 濱野 純(Junio C Hamano)【入門Git】 秀和システム』をまた読んでるけど、もう7年も前の本ですよ、これ。いやぁ(略)。アマゾンのカスタマーレビューを読むと gitが幅広い人に使われてるのが想像できるんじゃないかな。

 掲示板に書いたリストの4番目の補足(追加実験) @2016-11-22

  • シンタックスエラーをうまく回避して日記サービスの利用者が信頼済みコードのコンテキストに這い出ることができるのかはよくわかりません

たとえばこういう日記を書く(※アンダースコアは例によってスペースに読み替える。日記サーバーが Windowsでないなら cmd /C dirls にするとか)。

! [cat] title
_
_BODY
_BODY=File.new("./zzz.txt","w").write(`cmd /C dir`)#

古い category.rbは以下のように保存しておいたプラグインロード時のバインディングで evalをする。

@conf.shorten(eval(body.untaint, @binding))

evalされる bodyの中身はこうなっている。

text = apply_plugin(<<'BODY', true)
<pre>
BODY
BODY=File.new("./zzz.txt","w").write(`cmd /C dir`)#</pre>
BODY

通常はユーザー入力たる日記のソースは ERB(eRuby)スクリプトに変換されたものがそっくり <<BODYBODY で囲まれて apply_pluginへ引き渡され、セキュアモードなら $SAFE=4 で実行される。

上の例ではユーザーの入力した日記がほぼそのまま(※リダイレクト記号(<>)は &lt;&gt;に変換されたりする)、3ステップある(3ステップに分断された) Rubyスクリプト(1.apply_plugin, 2.定数(BODY)代入, 3.定数(BODY)参照)の2ステップ目を構成している。apply_pluginの文字列引数ではなく、apply_pluginと同列の Rubyスクリプトである。

index.rbのディレクトリに zzz.txtファイルが作成されたりしてませんか? ウチだけですか? シンボリックリンクがどうとかパーミッションがどうとかでも結果は変わりそうだけど……。そもそもセキュアモードでないならこれができても良かったんだっけ?

うーん、どうなんでしょうね。日記ホスティングサービスの制限っていうのがわからないんだよね。たとえば(tDiaryをベースにしてる?) Hikiだと単独のプラグインメソッド呼び出ししか許さないように独自にプラグイン記法をパースしていて、ただの文字列埋め込み({{"ここにタグなりなんなりを自由に書く"}})すらできなかったりする。もちろんそれができるとなんの工夫も必要のない XSS脆弱性が悪意ある不特定の書き手に晒されるわけで、今思うと当然なのだけど。

最近は(といって一年半前の日付だ)「[第一] クラウドへの移行を始めます」というアナウンスがあったりもして、クラウドなんてさっぱりですよ。ユーザー単位で仮想化されていて(※)、悪さをしても損をするのは自分ばかりなりけりってことになってんだろうか。

※「仮想化する」って意味を十分に説明していない気がする。何を仮想化したの? 仮想化されたそれがどうしたの? 「仮想マシンを専有していて」と書くとどうだろう。実態にあっているだろうか。

参考@2016-12-24>「原理原則で理解するDocker - Qiita」 例えば Dockerなら、プロセス毎の名前空間という、仮想化よりはゆるい仕組みによっている。

悪さの想定内容がそもそも古いんだよなー。能力の誇示や破壊なんてのは昔の話で、いまどきはみーんなお金だもんなー。お金になるから、お金になることを、する。


ぼそり。typo? >refeter

	class FakeCGI < CGI
		def refeter; nil end
		def user_agent; nil; end
		def mobile_agent?; nil; end
		def request_method; 'GET'; end
	end