static const Range Null;;」)、高校生のときのノートを(捨てる前に)眺めてみたりするたび思う。あの頃俺は賢かった(今はもう理解できない……)。たぶん没入することが必要なんだな。振り返ってるときにはそれがない。■パッチを読んでいて……。「-で始まる行がいっぱい」<嬉しい!やってやったぜ! 「+で始まる行が凝集している」<ファイルを移動しただけか、正しい徴候。それかなんとなく気に入らなくてイチから書き直す悪い癖の発露。「あちこちに散らばる + の行」<やり方か仕組みのどちらかが間違ってる。「交互に現れる + の行と - の行」<普通っぽい。あと手前味噌だけどコメントが丁寧だと思った。「あ、そうなんだ。勉強になります(書かれていなければわかっていなかった)」って感じ。やっぱり時間差があっても自分は自分で、阿吽の呼吸で疑問と答えが噛み合うところがある。■アクセスログの一覧を下の方まで眺めてたら、こんな名前のファイルが3ヒットしていた>subpattern_highlight.rev2.patch。え、あれ? こんなんやってたっけ。「脳log[20120517p01] サブパターンハイライト。」つい反応してしまうくらいお気に入りのネタではあるんだな。■■■漢検の対策テキストから啐啄同時(※ATOKで一発変換できない)という四字熟語を仕入れた。ここ(「阿吽の呼吸で~」)が使い所だと思うのだけど、どういう形で文に組み込めるんだろうか。
最終更新: 2018-03-14T23:15+0900
行単位で加工するマクロのための定型。そのままで同時に標準入出力にもファイルドロップ(SendToを含む)にも対応している。Perl譲りなんだろうけど、Rubyの -p スイッチって便利だし実際のニーズに基づいてるよねって。
マクロに登録しても良し、ソートしたいテキストファイルをドロップしても良し。
よく知らないけどプラグインだとメインメニューにコマンドを登録できたりするんだろうか。こういうものを C++で書いてエディタ本体に内蔵したくはないよね。
掲示板に貼り付けるには長いし、Wikiのマクロ投稿ページはログインを要求してきて書き込みさせてくれないしで、返信できずにここに書いてるんですよ。>「[8316] ソートの挙動の切り替えはサクラエディタ内で可能になりませんでしょうか」
Meryのソートマクロを見たら実質ワンライナーだった。連打するたぐいのマクロではないとしても、自分のはゼロオーバーヘッドルールから離れすぎていた。
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を共有していて、子スレッドの方で
OpenEvent
や DuplicateHandle
みたいなものは呼んでいないんだけど、子スレッドの終了を待たずに 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-02T23:22+0900
♪ 目があった。鹿。このあとどんどん近づいていって見つめ合ったまますれ違った。体当たりされなくてよかった。 シシトビバシっていうのは名前だけではなかったのだ。
最終更新: 2017-11-01T20:40+0900
ただの表データを扱うのに Excelを起動したくはなくて、エディタの TSVモードを使った(※世の中には関連づけのままにフォトショップを使って画像をプレビューする人もいますがね<鷹揚な人だ見習おう)。タブ文字って、列の幅がタブの幅の倍数をまたぐたびに上下で列がずれるのが微妙で、タブを複数連続で使って揃えたとしても、列を編集して長さが変わったら限界まで圧縮されていたタブがぴょっこり復元して後ろの列を押し出したりするし、1タブでなんとかしようとタブの幅を想定最大列幅まで大きくするなら3つか4つの列しか画面に収まらないしで、どうやっても手間がかかる。タブ文字の拡張として TSVモードは良い。
TSVモードとは関係なく、いつもと違う使い方をしたのでこれまで気付かなかったことに気がついたり、新バージョンのバグに当たったりした。
文字の大きさや折り返し幅が関係してる。原因をつきとめてさあ報告しようかと既存のバグ報告を漁ろうとしたら、いきなり掲示板の3スレッド目がそれだった>開発掲示板(Unicode)[2370]。おまけ付きのパッチもある。脱力。
MRUに前回の適用ファイルタイプが記録されていたせいだった。けっこう昔からある機能で、Ver.2系の最初のリリースぐらいからある。要望も昔からあるみたいで「Request/111 手動で変更したタイプを記憶 - SakuraEditorWiki」の投稿者は request.txtとなっている。
いらない機能です。「一時適用」したファイルタイプを一時でなく覚えておいた結果、ユーザー(俺)を欺いてしまっているのだから。先にばらしてしまうと、次に挙げる問題もこの機能に起因して引き起こされていたし、せめて、拡張子というルールに基づくファイルタイプ判別に引っかからなかった場合に限り、アドホックな一時適用ファイルタイプを採用するなどしてほしかった。
どちらを優先するのか一概に決められないところはある。アドホックな選択を記憶・復元するのがユーザーの意思を尊重した結果なら、ルールを新設して適用したいというのもユーザーの意思なのだから。お天気屋の原理主義者の今日の言い分は「ルールはルール(なので絶対)、一時は一時」ですがね。
※お天気屋たる所以は、かっこ書きの中身が普段は「(所詮はルール。人の作ったもの。文言の枝葉末節や不備に盲従せずその精神を忖度した運用でカバーし必要なら変えるべし)」だから。どちらへ転んでも自分に都合のいい主張になるという。
タイプ別設定一覧から選んで一時適用ボタンを押したときと、ファイルを開くときに MRUから記憶していたファイルタイプを復元したときでは、状態が違う。ついでにいうとコマンドラインの -TYPEスイッチでファイルタイプを任意に設定したときは、MRUから復元したときと同じ挙動を示す。
どういう挙動か。ファイルタイプの選択結果がロックされていないので、設定を変更したときに、拡張子に基づくルールベースの選択に上書きされる。
この結果どういうイライラ状況が発生したか。
適用されているファイルタイプってタイプ別設定一覧を表示するまでわからないんだよね。ちょっと覚えがあってヘルプを調べたらタイトルバーには表示できるみたいだけど(「$B タイプ別設定の名前 (sakura:2.0.7.0以降)」)、初期設定ではない。
ファイルタイプが見えないしすり替わってるしルールを無視するしで、気がつくまで(つまりソースコードを読むまで) 1と 2のあいだをぐるぐるぐるぐるしていたのだった。
どうも W の幅をひとつの基準にしているらしい(※高さの基準に x が、ハイフンの長さの基準に n や m が使われるように(<果たしてそれを聞き分けて区別できるだろうか)、もっとも幅広な文字として W が挙がるのかもしれない)。そして列の幅計算にはフォントを使わず、全角半角単位で数えてるっぽい。
たとえば最近愛用してる HG正楷書体-PRO フォントの場合、W の文字は全角半角で字形にゆらぎ程度の違いしかなく、基準に使う W は半角文字ながら全角の幅を持っている。その結果、列幅の想定と実際におよそ2倍の開きが生じた結果、ほぼ列の内容と同じ幅の余白が隣の列との間に確保されることになった。
そういうアルゴリズムで(=列幅の2倍の)タブストップを計算してるのだと思ったから、よーし好きに書き直しちゃうぞー、と CTsvModeInfo::CalcTabLength を頭から書き下していって途中で首を傾げてしまった(あれ? これ、俺が書こうとしてるそのまんまやん)。実際、列の内容が W のみだった場合は想定とのあいだに誤差はなく、計算された余白は適正と思えるものだった。
実際どうなのだろう。閲覧を主に想定してるのだろうか。
ファイル名の通り……ではないな。細かいけど「記憶しない」ではなく復元しないだし、一定以上のタブ幅が4に切り詰められることの修正も入ってる。
雑なパッチとは「Viewが前の行にさかのぼって再描画してくれない? 全部書き換えたらいいじゃない」の精神で。「Viewが持ってるフォント情報は古い、しょうがないので自分で作る
」みたいなコメントがソースのどこかにはあって、フォントを利用した列幅計算はある状況では問題があるのかもしれないけど、「こまけぇこたぁ(略)」の精神で。
あと、TSVモードで現在無視されてるタブ幅の設定を、余白の量として扱った。タブ幅8なら隣の列とのあいだに最小の行で全角4個分の余白。
我慢して使うよ。
下に書いた悪魔合体を進めると、横スクロール対応を雑でなくできる
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)」のときから変わらない悩み。マクロ実行の前後でフォーカスを見失うのは我慢できない。
たしか秀丸にあったことで知った機能。今はソートの前に列を並び替えてるんだけど、ドロップをミスってデータを壊さないかはらはらしてる。気がつけばアンドゥできるけど、気がつかなかったときが怖い。
何度も[End]キーを押しては間違って行末へ飛んだ。どうやら TSVファイルの列を編集しているとき、無意識の[End]キーで飛んで行きたい末尾とは列の末尾だったらしい。
あと Tabキーで次の列へ移動するとか、Enterキーで下の行へ移動するとかしたい気がするけど、違和感なく適応できるかはわからない。試してみようにもマクロから CSV/TSVモードのオンオフを知る方法がないので。
できると思うんだけど。つまり、タブストップの随時再計算をそれなりの規模の 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のコードに、自分で使うわけではないレイアウトのためのメンバーが出てくる。よくあるらしい。レイアウトは親が子のサイズを知りたがり子が親のサイズを知りたがるので、すぱっと割り切れないし決めきれない。それを解決する方法も入り組んでいて難しい。</追記>
当然の利用法として、特定の列を矩形選択で一括削除したくなったりするだろう。ダメ。削除し過ぎたり削除し足りなかったりする。なんだろう。削除の途中でタブストップの再計算が走るのだろうか。
すぐ上で
タブストップの随時再計算をそれなりの規模の CSVファイル(※ウチのPCだと富豪パッチバージョンで1MB・1万行ならもたつくけど現実的なレベルなので、それより大きいファイル)でやろうとして時間を空間で購った場合、横スクロールバーをドキュメントの最長行に対応させるためにやっていることっていうのはその一部になる。でもコストが整数2個から配列の配列と段違いに大きくなるので、CSVモードではない場合のコスト増を避けなければいけない。(折り返しモード)×(CSVモード)=4通りのコード分裂……
と書いたけど、別に配列1個でもよさそう。その場合「横スクロールバーをドキュメントの最長行に対応させるためにやっていること」とは独立したデータになるのでコード分裂もない。どういうデータを持つか。
スキャンの発生頻度はそこそこ低いのではないか。ネックは N番目の列の幅を網羅的にスキャンするときに、行の頭からスキャンして列番号をカウントしていくのでは後ろの方の列がつらいってこと。このへんはダブルクォーテーションの解釈と連携してさらなる補助データを用意することも考えられる。まあ、考えるだけで書かないんだけど……。
最終更新: 2017-01-25T00:05+0900
耳がね、レーダーよろしく周囲を警戒してるんですよ。目を閉じて横になっていても、耳だけが寝ていない。たぬき寝入りはばれているぞ、この耳が証拠だ、と、つんとするとピクピク、つんとするとピクピク、と律儀に反応が返ってくる。ひとしきりあそんだら、ふぅと息を吹きかけておしまい。どれだけかすかな風であっても、ナニゴト!と寝耳に水のいきおいで首から上がとびおきる(やっとこっち向いてくれた)。
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だとか、そんな感じ。疑いを持ってるという点ではどちらも同じ。スクショ画像の名前はあれでよかったんだろうか。最終更新: 2017-09-06T19:57+0900
写真も動画もとってない(追加予定)。
場所は左のフロントフォーク。フォークがねじれたときに緩めて締める下の方のブラケットに、元からあったブレーキホースのガイド共々共締めした。おもちゃを構造部にってどうよとは思ったが、ここがベストポジションだと思ったんだよねえ。次点はウィンカーの上、ヘッドライトの上部を固定するボルトに共締めして。次次点はハンドルバー。どんどん上方に移動して目立ってくるのが嫌。目立てば盗難を警戒しないといけなくなる。安くなっても 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"; } } }
カウルが写ってるのは昼の動画よりポイントが高いが、空の狭さが大きなマイナス。マウント位置を下げてやや上向けるか?
だいたい4分の1のサイズに圧縮してる。ナンバーは元から読めません。止め絵の画質的にもスピード感的にも品質設定をフルHD/30fpsの方にしようかな(<画質は良くならないわりに動きの滑らかさは低下するので、やっぱり 720/60fpsがいい)。DSC-HX30Vで以前撮ったフルHD/60fpsの動画もあるんだけど、音が全然違うよね。低音があるおかげであちらは聞きやすい。NECKERのも YouTube動画から予想してたよりはましな音で、ミュートするまでではなかったが。
画面の一部に夕焼け空が写ってる場面では肝心の前方が暗くつぶれてしまってた。旧機種ではホワイトバランスをはじめ細かくセッティングをしていたらしいが、自動調整で面倒を解決とはいかなかったか。
右下のカメラ名と時刻表示は消せない。DSC-HX30Vがするように字幕扱いでもなく、画面に埋め込まれてる。
最終更新: 2017-05-16T22:39+0900
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関数の乗っ取りをやっています)とその他エラーメッセージに出ていたいくつかのプラグインに原因があると疑って試行錯誤していたので、もはやなにが原因でなにが奏功したのかは藪の中といってよいでしょう。
コメントするために GitHubのアカウントを取った。デフォルトのプロフィールアイコンがあまりにもクソ雑魚ナメクジだったので、あわててペンタブ付属のフォトショップエレメンツ9を起動した(初回起動だった)。スカートの中に光源を配置したり、円形のグラデーションをアルファチャネルに設定したり、フォトショップはやりたいことが探せばちゃんとできるようになっている優秀なプログラムだった。自分の想像の及ばないすごいこともできるのだろう。でも Windowsネイティブではないから、数字入力フォームで[End]キーを押してもカーソルが末尾に移動しなかったり、リストで先頭の文字をタイプしても項目が選択できなかったり、戸惑うけど我慢するしかないね。使いたいもんね。
正直なところリンクを張るにあたってどれを指せばいいのかよくわからなかった。ブランチ作成、コミット、マージ、ブランチ作成、リバート、マージ、ブランチ作成、コミット、コミット、マージ、の最後のマージを指すつもりで #596のプルリクエストにリンク(※2番目の方)を張ったんだけど、これでいいの? ていうか活動の流れと全貌がさっぱりわからん。
昨日「もうGitは怖くない: 自信を持って使いたいあなたへ - 檜山正幸のキマイラ飼育記」を読んで理解したにわか知識によると、コミット(リバートももちろんコミット)とマージは同じ種類の実体(コミットオブジェクト)によって表されるらしい。ただし、コミットは親が1つでマージは親が2つ。親というのは変更の元にしたコミットオブジェクトのこと。親子それぞれがファイルシステムのスナップショットとでもいうものを保持しており、その差分を求めることで変更の内容がわかる。ブランチはコミットを継ぎ足す先を指し示す先導役で(実体は refs/heads/の中)、先導役が異なればコミットの列は別方向に伸びていく(枝分かれしていく)。枝分かれして以後の変更の蓄積としてのブランチは、たとえば masterブランチを構成するコミット集合との差集合を求めれば出るとか。
とりあえず4章でストップしてた『[単行本] 濱野 純(Junio C Hamano)【入門Git】 秀和システム』をまた読んでるけど、もう7年も前の本ですよ、これ。いやぁ(略)。アマゾンのカスタマーレビューを読むと gitが幅広い人に使われてるのが想像できるんじゃないかな。
- シンタックスエラーをうまく回避して日記サービスの利用者が信頼済みコードのコンテキストに這い出ることができるのかはよくわかりません
たとえばこういう日記を書く(※アンダースコアは例によってスペースに読み替える。日記サーバーが Windowsでないなら cmd /C dir
は ls
にするとか)。
! [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)スクリプトに変換されたものがそっくり <<BODY
~BODY
で囲まれて apply_pluginへ引き渡され、セキュアモードなら $SAFE=4
で実行される。
上の例ではユーザーの入力した日記がほぼそのまま(※リダイレクト記号(<>)は <>に変換されたりする)、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
最終更新: 2017-05-16T22:48+0900
NECKER V1 Plus アクションカム/バイク用ドライブレコーダー 日本正規版
DST
¥ 15,980
USB給電を受けると自動で録画を開始する
PCの USBポートに接続したときは、充電はされるけどマスストレージモードになるだけで録画は開始されなかった。アダプタを通してコンセントにつなぐと録画がスタートした。賢いね。
USB給電中でも防水状態が保たれる
防水キャップ一体型の USBケーブルが付属してくる
低画質長時間モードがない
とはいえメモリーカード容量は倍増する一方だし、60fpsは絶対にほしいし、今のところ一番画質とファイルサイズのバランスがとれてると考える 1280x720/60fpsモードはちゃんと用意されてるので、ないものねだりの感はある。32GBのメモリーカードに無限録画するとして、常時ラスト5時間分の動画が残っているか10時間20時間分の動画が残っているかという程度の違い(※目安は1分あたり100MB)。
コマ撮り動画(タイムラプス)モードの最短撮影間隔が8秒
あんまり搭載されていない機能なので用意されてること自体は嬉しいのだけど……。
時速60kmで移動することを考えたら1秒間隔がいいところ。8秒はおろか3秒間隔でもちょっと長い。
NECKER V1Pは SDXCに対応していないので、64GBの microSDXCカードを FAT32でフォーマットした、microSDHCカードもどきを使用する。
落とし穴があって、NECKER V1Pを PCにつないでカードリーダーとして使用した場合、Windows(Vista)はカードが読めないからフォーマットをしろと要求してくる。ここで言われるままフォーマットすると FAT32 32GBのメモリーカードになってしまう。
SDXCに対応したデジカメである DSC-HX30Vをカードリーダーに使って Windowsでフォーマットしようとすると、正当な SDXCカードである exFAT 64GBになってしまう。
DSC-HX30Vを通してカードを PCに接続し、以前(20130917p01)にも使った HP USB Disk Storage Format Toolを起動すると、FAT32 64GBでフォーマットできた。
この 64GBの microSDHCカードもどきに関して
撮影して保存 | USBケーブルで接続して Windowsから読み書き | |
---|---|---|
NECKER V1P | できる | できない |
DSC-HX30V | できる | できる |
カードリーダーとしての NECKER V1Pにはフォーマットや読み書きに際して 32GBより大きい FAT32を取り扱えない制限がある様子。
LEDインジケーターが電源・録画兼用ボタンの前後に1つずつ付いてる。前が青色で、後ろが赤(緑)色。
点灯は定常状態。青点灯で電源がオン。赤点灯で Wi-Fiがオン。緑点灯で充電中。点滅は異常状態。青点滅でバッテリー切れ。赤点滅でメモリーカード異常(不在・満杯)。点滅より間隔の長い間欠点灯は過渡・持続状態。青間欠は録画中。赤間欠は Wi-Fi有効化中。
ここまでは説明書に書かれた表の通り。では緑と
2つしかないインジケーターをフルに使ってながら、色や点灯パターンがだいたい慣例や感覚にそっていてわかりにくくなってない。
UPDATE:N WIFI=0 VCT=2 PDD=0 ;; ----------------------------------------------- ; ;(WIFI) WIFI Turn ON/OFF: 0~1 (0):ON (1):OFF ;(VCT) Video Clip Time: 0~3 (0):Off (1):1min (2):3min (3):5min ;(PDD) Power Down Delay: 0~6 (0):0 S (1):10S (2):30S (3):1min (4):2min (5):3min (6):Disable Power Down
現在のファームウェアは「幸滔數位科技有限公司 - タイムライン」から拾ってきた最新 V15715版(NECKERV1P_FW_0715_1839.zip)。他に 7月 3日の V15316版とか 3月 3日の V150203版を拾ってきた。
アップデート前にはあった Gセンサーだとかタイムラプスモードの設定がなくなってダウングレードしてるみたいな。V150203版に戻すとネットや説明書通りの内容の設定ファイル(SportDV.txt)がカードのルートに作成された。もう一度最新 V15715にアップデートして、ルートにある SportDV.txtを削除したり変更したりすると、上の状態に戻る。アプリで設定しろってことなのかな。以前の設定項目を勝手に SportDV.txtに書き戻すとだいたいは反映されてるんだけど、撮影したタイムラプス動画(TLP_*.MOV)が有効なファイルではない(5MBくらいの固定サイズで真っ暗の映像。撮影ボタンを押したときの反応は一度だけ振動して青色LEDが点灯したままだった)。
たぶん緊急保存ファイル(SOS_*.MOV)を記録してるあいだじゃないかなあ。画面右下の日時表示によると空白の時間帯がある。
もしかしたら本気でしばきすぎて一時的な録画エラーが発生してたということも? でも本当にこけたときよりは弱いだろう。
余計なことはせずに録画を継続してくれた方がちゃんと撮れてる期待が高そうだし、最長でも5分区切りの細切れ録画ファイル(といっても 500MBある。そして FAT32の 1ファイル上限は 4GB)の命名規則が乱れなくて管理がしやすい。
付属していた三脚用の 1/4インチネジと GoPro互換のマウントのネジの両方がコインで回せるようになっていた。
これねえ、苦労するんだよ。ささやかでもあるとないとで大違い。どうしてネジの頭をそのごついつまみに貫通させておかないんだって、以前買った GoPro互換ネジに対して思ったもん。その代わりに栓抜き(The Tool (Thumb Screw Wrench + Bottle Opener))を持ち歩けって?(揶揄するつもりで栓抜きって書いたのに、最初からそういう商品名だったよ。チッ)
USB給電がストップして NECKERがシャットダウンをしてる最中に再度給電を開始してしまうと、そのままでは NECKERが起きてこないとはネットの誰か(といっても日本語では全部で4、5人ぐらいしかブログで取り上げてないんだよね……)が報告していた。その逆に、NECKERが起動してる最中に(これが10秒20秒かかるんだ)給電が切れた場合には、NECKERが起きたままになる(たしか LEDが青点灯だったので録画はスタートしていない)とは今日(11日)確認した。メインスイッチをオンにするのもオフにするのもゆっくり時間をかけるようにしないと、期待通り動いてないことがあるってことだ。信号待ちでキルスイッチをパチパチしてエンジンを切って、結構待ちそうだなとメインスイッチをオフオンしてヘッドライトを切ることがよくあるんだけど、それをすると録画が終了したままになるってことだ。
<追記@2017-05-16>例えば給電停止から電源オフまでの待ち時間を10秒に設定しておいて、メインスイッチをパチパチと短時間でオフオンした場合は録画が継続する。</追記>
初期設定で Wi-Fiの自動起動が有効になっており、赤色LEDが点灯しているとき NECKERは無線LANのアクセスポイントになっている。初期SSIDは NECKER_V1_Plusで、暗号化方式は WPA2-PSK。キーの初期値はネットで下載できる產品說明書に書かれている通り。そうすると、Android/iOSアプリを通してカメラの設定を変更したり、記録されてる動画を再生したり、いままさにカメラが写してる映像を見たりができる。できた。
押しにくいけど一応 Wi-Fiのスイッチ(1-2mmのでっぱり)がカメラ後部に付いてるし実際のところ Wi-Fiを使う予定はないので、自動起動をオフにして
半日走り続けた場合、例えば3時間目4時間目以降の動画が全くなかったりする。そういう走り方を2回して、2回ともそうだった。シュラウドの前っていう走行風に恵まれた設置場所なんだけど、風が当たるのはレンズばかりで筒の後端に位置するメモリーカードや USB端子部分が熱くなりすぎるんだろうか。