AutoHotkey で指定ウィンドウでのみリマップを無効にしたい

私は「Alt + W」に「Ctrl + F4」、つまりは「タブを閉じる」を割り当てているのだが、これだとアプリ中で Alt + W にショートカットキーを割り当てても動作しない(タブが閉じられてしまう)。このアプリ中でのみ Ctrl + F4 リマップを無効にしたかったのでメモ。

元々の設定

!w::Send ^{F4}

上記のとおり、単純なリマップ構文で Alt + W → Ctrl + F4 にリマップしている。

結論

以下のように「#IfWinNotActive」を使った。

#IfWinNotActive my task-management tool
!w::Send ^{F4}
#If

これはウィンドウタイトルが "my task-management tool" の時 以外に Alt + W → Ctrl + F4 リマップをする、という命令になる。

失敗例

思考過程的なものを残しておく。

失敗1. Return

最初に考えたのは「適用したくないケースは個別に除外すればいい」「除外として Return すればいい」と考えて、以下のように書いた。

!w::Send ^{F4}
#If WinActive("my task-management tool")
!w::Return
#If

これはダメだった。

リマップで Return すると その割り当てが押された時は何もしません(その割り当て本来の機能も無効にします) という意味になる。つまり my task-management tool ウィンドウの時は、Alt + W でタブクローズは起こらなくなったが、そもそも Alt + W 自体が転送されなくなる。

失敗2. Hotkey

次に考えたのが、Return じゃなくて「その割り当て本来の働きをそのまま使う」的な構文を使えばいいんじゃないか、だったが、そんな構文はなさそう。しかし Wiki を漁っていると、いけそうな構文があった。

この Hotkey は、ホットキー設定を部分的に on/off にしたりできるようだ。

早速読んでみたのだが……よくわからん。ピンと来ない。ハマりそう。いったんスキップ。

成功

もっと楽にできないか、と粘っていると、あ、#IfWinNotActive で省けばよくない?とひらめいた。

解決。

MkDocs で何故か docs_dir の直下にある readme.md が変換されない件

MkDocs 1.0.4 の話。docs_dir で示したディレクトリに index.md と readme.md を置いていると、なぜか readme.md だけビルドの対象にならない。

原因は MkDocs のソースを見てようやくわかった。

index.md が存在する場合、readme.md のパースは無視される 仕様になっている。

該当ソース部分

from: https://github.com/mkdocs/mkdocs/blob/592e0852fe9e9c6c1316da818a8db402f73ff0c0/mkdocs/structure/files.py#L237

        for filename in _sort_files(filenames):
            path = os.path.normpath(os.path.join(relative_dir, filename))
            # Skip any excluded files
            if _filter_paths(basename=filename, path=path, is_dir=False, exclude=exclude):
                continue
            # Skip README.md is an index file also exists in dir
            if filename.lower() == 'readme.md' and 'index.md' in filenames:
                continue
            files.append(File(path, config['docs_dir'], config['site_dir'], config['use_directory_urls']))

1.0.4 後のバージョンでは log.warning が出そう

しかし現在進行のバージョンでは、log.warning による Warning メッセージが出るよう修正されている。

from: https://github.com/mkdocs/mkdocs/blob/cc03fd05876ad7ff14dfeff55832dc0dd7f0bf06/mkdocs/structure/files.py#L238

            if filename.lower() == 'readme.md' and 'index.md' in filenames:
                log.warning("Both index.md and readme.md found. Skipping readme.md from {}".format(source_dir))
continue

MkDocs で .git や node_modules など指定ディレクトリを exclude(除外) したい

MkDocs でリポジトリ中の Markdown ファイルたちを HTML に変換したいのだが、.git やら node_modules やら巨大なテンポラリフォルダが邪魔なせいで MkDocs のビルドが終わらない。

exclude できないかと思って、調べて、対処法にたどり着いたのでメモ。

対処方法

mkdocs-exclude プラグインを使う。

(設定1/2) インストール

1: MkDocs が古いならバージョンアップしておく

MkDocs が古いと mkdocs-exclude が動作しないので、先にバージョンアップしておく。

私の場合、元々こんな感じだった。

$ pip freeze | grep mkdocs
mkdocs==0.17.4
mkdocs-alabaster==0.7.4
mkdocs-material==2.9.1

これに対して mkdocs を upgrade する。

$ pip install mkdocs --upgrade
...
mkdocs-material 2.9.1 has requirement tornado<5, but you'll have tornado 5.1.1 which is incompatible.
...

エラーが一つ出ている。mkdocs-material 2.9.1が古いぞオイ(tornado ver 5 以下が必要なのに、あんた今は ver 5.1.1 になってんで) とのこと。

つまり mkdocs-material も古いので upgrade する。

$ pip install mkdocs-material  --upgrade

この時点でこうなった。

$ pip freeze | grep mkdocs
mkdocs==1.0.4             ★from 0.17.4
mkdocs-alabaster==0.7.4
mkdocs-material==4.0.1    ★from 2.9.1

もう一度 pip install mkdocs --upgrade を行って、エラーが出ないことを確認。これで upgrade はおわり

2: mkdocs-exclude をインストールする

apenwarr/mkdocs-exclude をインストールする。

$ pip install mkdocs-exclude

(設定2/2) mkdocs.yml に設定を書く

glob が使えるので楽。

以下は .git、coverage、node_modules の三つのディレクトリを弾く例。

plugins:
  - exclude:
      glob:
        - '**/.git/*'
        - '**/coverage/*'
        - '**/node_modules/*'

設定完了

これで指定ディレクトリが除外されてビルドが走るはず。

1分経っても終わらないビルドが10秒以内で終わるようになった。助かる。

(余談) あってもいい機能なのになんで MkDocs 公式はサポートしない?

MkDocs の Issues で議論されてる。

色々あるけど、一言で言うなら https://github.com/mkdocs/mkdocs/issues/1152#issuecomment-285083310 ここの

Finally, if we were to change the current behavior, it would break a lot of users existing sites. So while I can see an argument for an adjustment here, it is not likely to overcome the backward compatibility argument to leave things as-is.

これだろうか。よくわからんが今の仕組み的に、exclude 機能を入れようと思ったら後方互換性壊れちゃうみたい。

で、今年の 1 月になって、apenwarr さんという人が プラグインをつくった

I created a mkdocs-exclude plugin that uses the new plugin API to do what's requested in this bug: https://github.com/apenwarr/mkdocs-exclude

plugin API として exclude 機能が追加されたから実現できたみたい。あざっす。助かりました。

【オレオレ晒し】TIL(Today I Learned) 環境を整える

Githubのリポジトリ「TIL」を使って小さなアウトプットを習慣化する - Qiita に触発されたので、オレオレの TIL を晒してみる。

TIL とは

最初に簡単に取り上げておく。

TIL とは Today I Learned の略。

GitHub 文化の一つで、til という三文字名称のリポジトリを作って、日々学んだことを Markdown などで蓄積していくというもの。

メリット

  • 後々読み返せるので個人的に役に立つ
  • アウトプットの習慣や練習に適している
    • 自分のスペースに好き勝手に書きなぐるだけだし
    • Qiita みたいに晒されるものでもないし
  • 書きやすい
    • ローカルの使い慣れたエディタで書いて、最後に push
    • github.com の UI は使いやすいので、ブラウザでそっちで書いても良いが
  • 承認欲求を満たせる
    • GitHub の草が映える
    • 「オレ、こんなこと勉強してんだぜ?」
    • 「こんなに蓄積してるオレ、すごくない?」 etc
  • コミュニティや他ユーザーに貢献できる
  • 自分の興味や志向などを端的に表現できる

オレオレ TIL を晒す

ここからは私の TIL を晒す。コンセプトからしてかなりオレオレ。

コンセプト

  • 1: プライベート …… 自分だけが読めればそれでいい
  • 2: ローカル駆動 …… 編集、閲覧、検索などは全部ローカルでやる
  • 3: 物置 …… GitHub は物置として使うだけ

1 のプライベートは、公開だと 第三者が読んでも問題ないよう表現を考えるコスト が発生して面倒くさいから。

2 のローカル駆動は、 最も効率的に編集や閲覧ができるのは「使い慣れたテキストエディタ」 だから。

そうなると「GitHub に置く必要ある?」となるが、私は Dropbox が嫌い(常時同期が走るのが気持ち悪いうざい、gitignore がないなど)なので、普段使っている GitHub に置くことにした。ただ、そうなると git コマンドの利用が面倒くさいので、スクリで適当に端折る。

全体像

前提:

  • Windows

構造:

  • knowledge リポジトリ
    • プライベートリポジトリにする
    • リポジトリ名は何でもいい。TIL したいんだから til が無難か
    • しかし私は将来公開用の til を作るかもしれないので、あえて til は使わなかった
  • ローカルで xxxx.md や xxxx.txt に、xxxx に関するネタを書き殴り、適宜アップロード(add-commit-push)

編集時:

  • xxxx について書きたい時は、xxxx.txt や xxxx.md をつくる or 既存ならそこに書き足す
  • つくる際はスクリプトで一発で(xxxxを入力するだけで作成するとか)できるようにすると楽

検索時:

  • fenrir を使って xxxx.txt や xxxx.md にアクセス
    • いわゆるファイル名のインクリメンタルサーチ
    • Mac で言えば Spotlight や Alfred みたいな感じだろうか
  • Grep を叩くスクリプトを実行する
    • スクリ叩く → キーワード打つ → knowledge配下がgrepかけられる
    • このスクリも fenrir から呼び出す(例: _grep.bat )

同期時:

  • 適当なタイミングで _upload.bat を叩いてアップロード
    • これは add, commit -m "テキトーなメッセージ", push を行うスクリ
  • 他 PC からは git pull でダウンロード

環境のつくりかた

  • 1: til リポジトリをつくり、適当なところに clone
  • 2: fenrir をインストールして、clone した 1 をスキャンさせる
  • 3: AutoHotkeyをインストールして、2 の fenrir をキー一発で呼べるようにする
  • 4: 便利スクリプトを clone した 1 に追加する
    • xxxx.txt や xxx.md を新しくつくるやつ
    • Grep するやつ
    • アップロード(add-commit-push)するやつ
    • ダウンロード(pull)するやつ

fenrir や AutoHotkey などの詳細は割愛。

オレオレ TIL 付録

使うツールやスクリやらの中身を晒す。

fenrir の scan.ini

*.txt;*.bat;*.py;*.md;*.rst;\
D:\work\github\stakiran\knowledge
-D:\work\github\stakiran\knowledge\.git

まずファイルタイプは txt や md など主要なものは網羅する。スクリプトも呼び出すのでバッチファイル bat や Python py なども追加している。

次に走査先だが、.git フォルダは省くこと。

fenrir.exe の設定ファイルなど

長くなるので割愛。

AutoHotkey から fenrir を呼び出す

; fenrir を Alt + 1 で呼ぶ
!1::
  run, D:\bin\fenrirs\fenrir\fenrir.exe /t /pathfile=D:\bin\fenrirs\knowledge\path /scanfile=D:\bin\fenrirs\knowledge\scan.ini /initfile=D:\bin\fenrirs\fenrir\data\fenrir.ini /instantfile=D:\bin\fenrirs\fenrir\data\instant.ini /cmddir=D:\bin\fenrirs\fenrir\cmd, D:\bin\fenrirs\fenrir
return

; fenrir の作業フォルダを Ctrl + Alt + F で呼ぶ
^!f::
  run, D:\bin\fenrirs
return

まず fenrir のディレクトリ構造を整理しておく。

  • D:\bin\fenrirs
    • fenrir …… fenrir本体フォルダ
    • knowledge …… knowdlgeリポジトリ用の設定を入れるフォルダ
    • ...

コマンドラインは煩雑だが、fenrir 本体に必要なパラメータを指定しているだけである。

あとは、おまけとして fenrir 絡みの作業フォルダを一発で開くホットキーも用意している。fenrir 自体をいじりたい時に地味に便利。

アップロードするやつ

_upload.bat

git add -A
git commit -m "update."
git push -u origin master
pause

最後の pause は、このバッチファイルを実行した時の画面を閉じずに止めるための決まり文句。

ダウンロードするやつ

_download.bat

git pull
pause

たまにアップロード忘れで衝突が発生するが、その時は手作業でテキトーに解決する。

xxxx.txt や xxx.md を新しくつくるやつ

_new_knowledge.bat

@echo off

prompt $$
pushd %0\..

set /p filename="Input the textfilename and the extension if needed. >"
copy /-Y nul %filename%
start "" "%filename%"

ファイル名 xxxx.ext を入力すると、knowledge/xxxx.ext を空ファイルで生成した後、関連付けられたエディタで開くという感じ。

※英語はたぶんおかしいけど見逃してください(普段 utf-8 で書いてるので日本語で指示させるとコマンドプロンプトが文字化けしてしまう&文字コード cp932 に直すのだるかったのであえて英語にした、のがそのまま放置されている 苦笑)

Grep するやつ

実はスクリプトとしては用意してない。

私が使っている秀丸エディタでは、knowledge/xxxx.xxx を開いている状態で F4 を押すだけで Grep 機能を呼び出せる(検索先は knowledge ディレクトリ配下がデフォ)ようになっている。ので、Grep したい時は

  • Alt + 1 で fenrir 呼び出して何か開く
  • F4 で Grep 機能呼び出す

という流れ。

Javascript ES5 などで this がおかしい時に確認すること

Javascript(ES5 など古いやつ) の this は呼び出し元次第で中身が変化するという、大変扱いづらい仕様をしている。そのせいで、なぜか TypeError が発生し、調べてみると this がなぜか別のオブジェクト(window)を指していたりする。勘弁してほしい。何度ハマったことか。

というわけで、「おかしい時に確認すること」と題して、まとめておく。次ハマったら、ここを見に来ること。

1: new してるか確かめろ

var table_xxx = VIEW_XXXX_SPACE.XXXXTableBuilder(param1, param2);
         //    A
         //    |
         //  new が足りてないぞ!

2: jQuery 等でメソッドチェーンでコールバック関数書いてると this は見えないから外から見ろ

    ...

    var p = ClassXXX.prototype;

    p._onclick = function(){
        var self = this;

        $(some_selector).click(function() {
            var result = this.calc();
                     //  ^^^^
                     // 違うぞ! this は $(some_selector) の中を指してるぞ!
                     // このクラス(もどき)の this が見たいなら
                     // 外で定義してる self を見ろ!
        });
    }

    ...

3: xxxx.func を this._func = xxxx.func みたいに持たせるのはやめて

問題となる書き方:

    ...

    var p = ClassXXX.prototype;

    p.set_update_func = function(f){
        // こんな感じで yyy の update() を保持することを想定.
        //    xxx.set_update_func = yyy.update
        this._func_update = f
    }

    p.process = function(f){
        ...

        // ここでハマる!
        // さっきセットした yyy.update を呼ぶことを想定しているのだろうが、
        // yyy.update() 側で this の中身がおかしくなる!
        // (yyy の中身じゃなくてこの ClassXXX インスタンスの中身になってる。
        this._func_update();

        ...
    }

    ...

じゃあどう書けばいいの?:

→ 関数を保持するのではなくオブジェクトを保持して Duck typing してください。

    ...

    var p = ClassXXX.prototype;

    p.set_yyy_instance = function(yyy){
        this._yyy = yyy
    }

    p.process = function(f){
        ...

        // これなら update() 中の this は yyy インスタンスの中身を指す!
        // 正しく動く!
        //
        // これはいわゆる Duck Typing。
        // 「this._yyy は yyy インスタンスであるはずだ」
        // 「yyy インスタンスであるなら update() を持っているはずだ」
        // 「私は yyy さんの update() をここで呼ぶのが仕事だから、とりあえず呼ぶ」
        // 「実際に _yyy が何を指してるかは知らん。私は呼ぶだけだ」
        // みたいな。
        this._yyy.update();

        ...
    }

    ...

Dropbox サポート終了のため MacBook Air を 10.9(Mavericks) から 10.14(Mojave) にアップデートした

執筆マシン&ネットサーフィンマシンとして使っている MacBook Air だが、Dropbox が「10.9 以前は 2019 年 4 月で使えなくなります」と仰る。MacOS をアップデートせなばならない。調べてみると、10.14 の Mojave にアップデートできる模様。一連の作業内容についてメモ。

1. MacOS を Mojave にアップグレード

まずは OS のアップグレードが必要。

  • 作業時間: 10分
  • 所要時間: 一晩丸々かかる

手順としては、以下公式サイトを辿る。

すると最終的には App Store で Mojave をインストールする形になるはず。

時間がかかるのはここから。何しろ 6.1GB もあるブツだから。ダウンロードはすぐ終わる(オンライン型のインストーラなのだろう)が、続くインストールがとにかく長い。私は WiFi をつないだまま一晩放置した(朝起きたら完了していた)。

2. Git コマンドが動かないので対処する

GitHub を物置として使っているので、git が使えないと死ぬ。今は git を実行しただけで「pxcrun: error: invalid active developer path...」などと怒られる。対処したい。

  • 作業時間: 1分
  • 所要時間: 20分

以下コマンドを実行するだけで良い。ただし XCode をインストールする形になるらしく、この XCode が中々に大きいブツなので結構時間かかる。気長に待つ。

$ xcode-select --install

3. 日本語入力システムが使いづらいので対処する

日本語入力システムがなんかおかしい。日本語が打ちづらい。対処する。

(余談) ちなみに Google 日本語入力など他の IME を使うつもりはない。バッテリー消費が激しいから。

3-1. ライブ変換を無効にする

なんか勝手に変換が走る?感じの、よくわからない使いづらい挙動をしている。これは「ライブ変換」という機能らしいので無効にする。

  • 作業時間: 1分
  • 所要時間: 1分

手順は、右上の IME アイコンをクリックしてメニューを開いて、「ライブ変換」を無効にすればいい。

3-2. 常に半角スペースで入力する

Mojave の日本語入力システムは「ことえり」ではなく JapaneseIM というそうだが、コイツが常に半角スペースで入力するオプションを用意してないポンコツである。

設定変更は結構めんどうくさかった。

  • 作業時間: 10分
  • 所要時間: 10分

i. まず全体像をおさらい

  • 「常に半角スペース」の実現は、KeySetting_Default.plist というファイルをいじる
  • でもこれ、システムファイルで、簡単にはいじれない
  • いじるには...
    • csrutil とかいうセキュリティツールでセキュリティを落とす
    • KeySetting_Default.plist をいじる
    • csrutil とかいうセキュリティツールでセキュリティを戻す

ii. 作業手順

※本手順では、macOS の再起動と(Windows でいうセーフモードみたいな)モードを使う(つまり 作業中の mac でブラウザ等で手順見ながら、なんてことができない )ので、別途本手順を読める手段を用意しておくと良い。

  • (1) macOS 復元システムを起動する
  • (2) ユーティリティ > ターミナルからターミナルを開いて、セキュリティを落とす
$ csrutil disable

ちなみに csrutil disable 実行時点で、既に disable になっている。csrutil status を見ると enabled のままだが、これは再起動してなくて反映されてないだけ。

  • (3) reboot コマンド等で再起動し、普通にログインして、ターミナルを開いて、以下のように plist ファイルをいじる
$ cd /System/Library/Input\ Methods/JapaneseIM.app/Contents/PlugIns/JapaneseIM.appex/Contents/Resources/
$ sudo vi KeySetting_Default.plist

いじり方だが、 macOS High Sierra / Mojave で 日本語モード時に スペース <-> 半角 入れ替え - Qiita がわかりやすいので抜粋

--- /System/Library/Input Methods/JapaneseIM.app/Contents/PlugIns/JapaneseIM.appex/Contents/Resources/KeySetting_Default.plist.orig 2017-09-26 10:34:40.000000000 +0900
+++ /System/Library/Input Methods/JapaneseIM.app/Contents/PlugIns/JapaneseIM.appex/Contents/Resources/KeySetting_Default.plist  2017-09-26 10:38:30.000000000 +0900
@@ -11,12 +11,16 @@
            <key>&apos; &apos;</key>
            <dict>
                <key>command</key>
-               <string>contextual_space</string>
+               <string>direct_input</string>
+               <key>character</key>
+               <string> </string>
            </dict>
            <key>shift+&apos; &apos;</key>
            <dict>
                <key>command</key>
-               <string>contextual_space_reverse</string>
+               <string>direct_input</string>
+               <key>character</key>
+               <string> </string>
            </dict>
            <key>delete:</key>
            <dict>

コピペ用文字列も置いとく。

                <string>direct_input</string>
                <key>character</key>
                <string> </string>

                <string>direct_input</string>
                <key>character</key>
                <string> </string>
  • (4) 日本語入力システムを再起動して反映させる
$ killall JapaneseIM

ここまでで「常に半角スペース」は実現できているはず。

あとは、落としたセキュリティをもとに戻しておく。

  • (5) (1) と同じ要領で macOS 復元システムを起動し、ユーティリティ > ターミナルから以下を実行
$ csrutil enable

もう一度再起動。これで一段落。

4. 使っているアプリに許可を与える

私の場合、BetterTouchTool や ClipMenu を使っているのだが、これらが動かなかった。権限付与されていないせい。付与していく。

  • 作業時間: 3分
  • 所要時間: 3分

設定は 2 箇所必要。

設定手順(全体的な設定):

  • システム環境設定 > セキュリティとプライバシー > 一般
  • ダウンロードしたアプリケーションの実行許可を「App Store と確認済みの開発元からのアプリケーションを許可」にする

設定手順(個別の許可):

  • システム環境設定 > セキュリティとプライバシー > プライバシー
  • 左ペインからアクセシビリティを選ぶ
  • 右ペインに、実行を許可するアプリを追加

5. システム環境設定は全部眺めてみる

他にもシステム環境設定は一通り眺めてみて、要らないものや気に入らないものは適宜変えると良い。なんかちょろちょろ変わってたりするので。

  • 作業時間: 10分
  • 所要時間: 10分

6. キーボードのバックライトを消す

バッテリーを食うし目障りなので、キーボードのバックライトは無効にしていたのだが、勝手に有効になっていた。

  • 作業時間: 1分
  • 所要時間: 1分

Fn + F5 キーで明かりを 1 段落とせるので、一番左まで落とす。

※Mission Control の設定次第では F5 キーだけで作用するかも

7. ファイルの関連付けがリセットされているので適宜直す

私の場合、.txt と .dry は mi に関連付けしていたが、これら関連付け設定がリセットされてやがるので再設定が必要。

  • 作業時間: 1分
  • 所要時間: 5分

作業手順は以下のとおり。

  • 1: Finder で関連付けを変えたいファイルのあるフォルダを開く
  • 2: 当該ファイルを選択して、ファイル > 情報を見る
  • 3: このアプリケーションを開く、から関連付けしたいアプリを設定し、すべて変更ボタンを押す

8. bin/ 配下のエイリアスが死んでいるので .bash_profile などに書き直す

  • 作業時間: 1分
  • 所要時間: 5分

私は Sublime Text のエイリアス subl を以下のようにしてつくっていた。

sudo ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" /usr/bin/subl

しかし Mojave ではセキュリティが強化されて bin/ 配下に書き込めないからか、パーミッションエラーが出る。

仕方ないので、.bash_profile などに以下を書くことで対処。

alias subl="/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl $1"

ひとまずここまで

とりあえずここまで。

他に設定を直したことがあったら、気が向いたら追記する (2019/02/14 追記) 7と8を追記した。

Mavericks と比べて Mojave はどう?

一言で言うと なんか動作が重たいのでイライラする

私にとって MacBook Air は「軽快な執筆マシーン&ネットサーフィンマシーン」でしかなく、アプリの充実やら画面がキレイになりましたとか、そういうのはどうでもいい。iTunes も消してるくらいだし。

Mojave になってから露骨に動作が重たくなった。

どれくらいかというと、Alfred2 でキーワード検索した時の動きがもっさり(反映が遅い)していて「ん?バックで何か慌ただしいプロセスでも動いてるんか?」と疑うレベル。まるで Windows Update が走っている Windows みたいなもっさりさだ。

常にここまで重たいわけではないが、少なくとも Mavericks の時よりは明らかに重い。やらなくていいならアップグレードしたくなかったなぁ。

……他の使い心地については、これからわかることだろう。

はてなブログ内の全記事を効率良く修正するためにインポートが使えるかを実験してみた

つまり、エクスポートしたテキストファイルをローカルで修正した後、これをインポートすることで、実質ローカルで全記事を修正したかのような行動を実現できるかどうか。

結論

無理です。

頑張ってやるとしたら、こうなる

  • (1) エクスポートする
  • (2) エクスポートしたファイルを編集・修正
  • (3) ブログ中の記事をすべて削除する
    • ただし 管理画面からは一度に 20 件ずつしか削除できない
  • (4) 2 のデータをインポートする
    • インポートは結構時間かかる
    • 1記事1秒くらいは見た方がいいかも
    • 内部的には他ドメインの画像を全部解析して、あとでフォトライフにインポートできるようにしている

20件削除縛りと、インポートに時間がかかるのがネックか。

本手順実行時に想定される懸念

  • 削除中にアクセスしに来た人がこんがらがる
  • 削除中にクロールに来た Google が「このブログなんかおかしくね?」と否定的な判断をする可能性

スパム扱いされることはないと信じたいが……。それまで記事がたっぷりあったブログが、いきなりすっからかんになる(なり始める)と、Google さんはどう解釈するのだろうか。

(余談) インポートの仕様

  • インポートは常に 新規追加 の挙動になる
    • たとえば全く同じファイルを n 回インポートしたら、各記事は n 個重複して存在することになる
  • インポートは、インポート後に取り消すことができる
  • 取り消しを行うと、当該インポートの対象だった記事を書き換えていた場合でも、当該記事は消える

はてなブログを新規作成する時に「使用できない文字」が含まれていないのに「使用できない文字が含まれています」と怒られる件

はてなブログ新規作成時に少しハマったのでメモ。

新規作成時に、使用できない文字を使っていないのに

使用できない文字が含まれています。英数字で始まり、ハイフンと英数字が続く必要があります。

とエラーが出て作成できない、という問題に出くわした。

原因

使用禁止キーワードが含まれているせい

たとえば hatena とか。

f:id:stakiran:20190209202032j:plain

対処

使用禁止になっていないキーワードがないかを確認し、削除してから試してみる。

固有名詞系は疑った方が良い

とはいえ非常にレアっぽいので、普通は遭遇しないと思う。

どんなキーワードが禁止されている?

発見したもののみ記載する。

含まれている時点でアウトなキーワード:

  • hatena
  • nintendo

完全一致でアウトなキーワード

  • jkondo
  • staff

私はこれだけしか見つけられなかった。nintendo がダメなのに他の社名は問題ないとか、staff はダメなのに contact や help は問題ない(既に取られてるけど)など、いまいちよくわからない。ちなみに jkondo ははてなの生みの親。

Visual Studio Code でメニューバーとタイトルバーが一緒になっているのを別々に分ける

v1.30.1 の話。

  • ファイル > 基本設定 > 設定
  • 「title bar」で検索する
  • Title Bar Style を native にする
  • VSCode を再起動したら反映される

ちゃんと native 派の利用者の存在を考えてくれているのが素晴らしい。

あと余談だが、1.30 からなのか知らないが 設定を(設定ファイルではなく)インクリメンタルサーチと GUI でいじれるようになっているのがとても便利

OS、言語、フレームワークなどのログレベル名称をまとめてみた

ログレベルを設計するためのインプットとして、OS/言語/フレームワークなどからログレベルがどう定義されているかを調べて、まとめてみた。意外と色んな名称が使われていて、まとめるの大変だった。

前提

注意事項

  • ログレベル名の記述は Camel Case で統一する
  • 言語のログは言語というより標準ライブラリの機能だが、言語のものとして取り上げる
  • 今回選んだ OS、言語、フレームワークなどの選定基準は「テキトー」

情報源

ログレベル(まとめ)

  • Emergency/Severe/Fault/Assert/Unknown
  • Alert/Fatal
  • Critical/Critical Error
  • Error
  • Warning/Warn/Default
  • Notice
  • Info/Information
  • Debug
  • Verbose/Trace
  • Config/Fine/Finer/Finest

ログレベル: ガチでやばい

ログレベル全体を通して一番上にあったやつ。

Emergency

  • syslog

Severe

  • Java

Fault

  • iOS

Assert

  • android

assert というと条件式が偽だったら Abort する命令を思い出すけども。

Unknown

  • Rails

要するに「よーわからん」ってことでしょ。ちょっといいかげんやない?

ログレベル: 割とやばい

ログレベル全体を通して大体一番上(か二番目くらい)にあるやつ。

Alert

  • syslog

Fatal

  • log4j, Rails
  • Ruby

ログレベル: まあまあやばい

いわゆる「エラー」よりもやばい位置づけのやつ。

Critical

  • syslog
  • Erlang, Python

Critical Error

  • Windows

二単語やめてー。

ログレベル: やばい

いわゆるエラー。

Error

  • syslog, Windows, android, iOS
  • log4j, rails
  • Erlang, Python, Ruby, Go, PHP

ログレベル: やばいかも

いわゆる警告。

Warning

  • syslog, Windows
  • Java, Python, PHP, Erlang

Warn

  • android
  • log4j, rails
  • Ruby, Go

おしゃれなのは Warn ってイメージ?

Default

  • iOS

Readable じゃないのでダメだと思う。

ログレベル: お知らせ

警告と情報の間くらいのやつ。

Notice

  • syslog
  • Erlang, PHP

ログレベル: 情報

その名のとおり情報。

Info

  • syslog, android, iOS
  • log4j, rails
  • Java, Python, Ruby, Go, Erlang

Information

  • Windows

Windows さん空気読んで。

ログレベル: 細かい

開発者向けの細かい世界。

Debug

  • syslog, android, iOS
  • log4j, rails
  • Python, Ruby, Go, Erlang

ログレベル: めっちゃ細かい

さらに細かい。

Verbose

  • Windows, android

Trace

  • log4j

ログレベル: ばちくそ細かい

Java「どや?親切やろ?」

Config

  • Java

Fine

  • Java

Finer

  • Java

Finest

  • Java

秀丸エディタでファイルマネージャ枠を自動で同期する

秀丸エディタのファイルマネージャ枠(エクスプローラ枠)は便利だが、表示内容が自動で同期されないのが不便だった。自動で同期する方法を見つけたのでまとめる。

方法

  • [マクロ] > [マクロ登録] > [自動起動] > [自動起動マクロを有効にする]
  • [アクティブ切り替え後] を有効にして、以下マクロを指定
loaddll "HmExplorerPane.dll";
#get_1_if_pain_opened = dllfunc("GetMode",hidemaruhandle(0));
if(#get_1_if_pain_opened!=1){
    endmacro;
}

#h = dllfunc("GetWindowHandle", hidemaruhandle(0) );
// 252 同期
#ret = sendmessage(#h, 0x111, 252, 0);

解説

自動同期は以下の二段階で実現する。

  • (1) ファイルマネージャ枠の同期処理を行うマクロをつくる
  • (2) 秀丸エディタに「タブが切り替わる度に指定マクロを実行する」的な仕組みがあるので、ここに 1 を指定する

マクロ解説

loaddll "HmExplorerPane.dll";

これはファイルマネージャ枠を使う際の決まり文句。

#get_1_if_pain_opened = dllfunc("GetMode",hidemaruhandle(0));
if(#get_1_if_pain_opened!=1){
    endmacro;
}

これはファイルマネージャ枠が表示されているかどうかを調べ、されていないならその場で終了する処理。

このような判定を行っておくと、ファイルマネージャ枠を使っていない時に同期処理が走らず無駄がない。

#h = dllfunc("GetWindowHandle", hidemaruhandle(0) );
// 252 同期
#ret = sendmessage(#h, 0x111, 252, 0);

これはファイルマネージャ枠の同期処理を行う。DLL に実装された機能を呼び出す、という使い方になるので表記が多少煩雑。値 252 の部分など、詳細はマクロヘルプを調べたら載ってある。

使い心地

秀丸エディタにこもっている間は使いやすい。自動で同期されるから。

別のウィンドウと切り替えながらだと使いづらいかも。秀丸エディタをアクティブにする度に自動同期が走るので、ファイルマネージャ枠中で別フォルダを開いていた場合も(自動同期されてしまい)カレントディレクトリに戻されてしまう

ホワイトボードみたいな「白紙の好きな位置に書く」をテキストエディタ上で実現する『Freetext』

freetext_demo_1

Freetext とは

ホワイトボードみたいな「白紙の好きな位置に書く」をテキストエディタ上で実現すること。

実現アイデアの肝は以下 4 つ。

  • (1) テキストエディタの フリーカーソル を有効にする
  • (2) 行番号、ルーラー、空白文字表記などをなくして 表示を白紙に近づける
  • (3) 直線をいかに簡単に書くか、など マクロスクリプトで手作業を省力化 する
  • (4) Freetext を実現する専用拡張子を設ける(そうすれば「拡張子別の設定」として Freetext 用の設定を集中的に組み込める)

フリーカーソルとは?

一部のテキストエディタ(特に国産テキストエディタ)には フリーカーソル という機能がある。(この呼び名の)元は一太郎など国産ワードプロセッサから始まった機能っぽい。海外では Virtual Space と呼ぶことが多い。 昔の Visual Studio にはある みたいだが、 VSCode ではまだ実装されていない ようだ。

フリーカーソルを使うと、以下のようなことができる。

    test
              ^^^^^^
            たとえばこのあたりにカーソルを移動させることができる

つまり 行末の先にカーソルを移動させることができる。そこで入力を行うと、間には自動的に半角スペースが挿入されるという仕組み。

サンプル

秀丸エディタで実現した hidemaru_freetext。GitHub に置いた。

以下は画像例。hidemaru_freetext 開発時の思考こねこねを Freetext でやってみた例である。

hidemaru_freetext_image

使い心地

(Good) 好きな位置から書き始められるのは気持ちいい

ホワイトボードに書くみたいに、空間を自由に使って書けるのはとても気持ちが良い。

最大化して、文字サイズも小さくすれば、領域としてはかなり広い。

(Good) アナログよりも速く、キレイ

アナログで手書きだと字を書くのがどうしても遅いし、また汚い(人によるだろうが少なくとも私は苦手だ)。

デジタルだとタイピングによる断然速くキレイに書ける。が、アナログみたいな空間的自由が無く、特にブレストのような発想重視ではやりづらい。

しかし Freetext なら、自由配置については解決しているため、いわば両者のいいとこどりのような手段を実現できる(というと言い過ぎだが、近い操作感を実現できる)

(Bad) 線で結ぶ、線で囲むなどは苦手

容易に想像できるが、線で結んだり線で囲んだりといったことは苦手である。

テキストエディタの限界ではなかろうか。あるいはエディタのマクロやスクリプトによる自動化処理を工夫しまくれば実現できるのかもしれないが、現状の私の実力では皆目検討もつかない。

ただし、悪あがきとして一部は実現している。

(Bad) カーソル移動の癖が強い

(Vimmer などがどうかは知らないが秀丸エディタマンの私は)カーソルキー/Home/End キーを多用してカーソルを移動させる。ここには「行末で→を押すと次行の行頭に行く」「行頭で←を押すと前行の行末に行く」といった前提も含んでいる。

しかし、フリーカーソルモードだと、この前提が効かなくなるため、「あれ?行頭に移動しねぇぞ」なんてことが起こり、違和感が満載なのである。

フリーカーソル時はフリーカーソルの挙動・癖というものがある。私は Freetext を使いはじめて数日だが、まだ慣れていない。そのうち慣れるだろうが。

「指定フォルダ内の画像ファイルをサムネイルで一覧表示する HTML」をつくる Python スクリプト

ローカルに保存している画像ファイルたちを簡単に俯瞰する手段が欲しいと思っていたが、良い方法が見当たらなかったのでつくることにした。

成果物

GitHub に置いた

github.com

サンプル

指定フォルダ内の全画像を、こんな感じでズラリと並べる。

f:id:stakiran:20190126155213j:plain

クリックすると画像本体を開く。

表示サイズと一行分の画像枚数はスクリプト側でいじる。

# ★ここ
conf_image_x = 150
conf_image_y = 150
conf_image_count_per_line = 6

スクリプト

# encoding: utf-8

import os
import sys

def str2file(filepath, s):
    with open(filepath, encoding='utf8', mode='w') as f:
        f.write(s)

def get_filelist(basedir):
    ret = []
    for path, dirnames, filenames in os.walk(basedir):
        for filename in filenames:
            fullpath = os.path.join(path, filename)
            ret.append(fullpath)
    return ret

MYFULLPATH = os.path.abspath(sys.argv[0])
MYDIR = os.path.dirname(MYFULLPATH)

filenames_all = get_filelist(MYDIR)
filenames_jpg = [filename for filename in filenames_all if filename.lower()[-4:]=='.jpg']
filenames_curdir_removed = [filename.replace('{:}\\'.format(MYDIR), '') for filename in filenames_jpg]
filenames_slash_delim = [filename.replace('\\', '/') for filename in filenames_curdir_removed]

print(filenames_slash_delim)
print('{:} items.'.format(len(filenames_jpg)))

outfilename = 'image_gallery.html'
outstrs = ''

conf_image_x = 150
conf_image_y = 150
conf_image_count_per_line = 6

for i,image_filepath in enumerate(filenames_slash_delim):
    url = image_filepath
    alttext = url

    image_html_template = '<a href="{href}" target="_blank"><img src="{src}" width="{width}px" height="{height}px"></a>'
    image_kwargs = {
        'href'   : url,
        'src'    : url,
        'width'  : conf_image_x,
        'height' : conf_image_y,
    }

    image_html = image_html_template.format(**image_kwargs)

    outstrs += image_html
    outstrs += '\n'
    if i%conf_image_count_per_line==(conf_image_count_per_line-1):
        outstrs += '<br>\n'

html_template = """<html>
<head>
    <title>Image Gallery</title>
    <meta charset="UTF-8">
</head>
<body>
{:}
</body>
</html>"""

html = html_template.format(outstrs)
str2file(outfilename, html)

使い方

  • image_gallery.py など適当なファイル名で保存
  • HTML を生成したいフォルダに、このファイルを配置する
  • python image_gallery.py
  • HTML ファイルが生成されるはず

FAQ

追々使いやすく改造するかもしれないが、とりあえず FAQ の形で書いとく。

Q. ライセンスは?

Ans: MIT

Q. PNG画像は対応してない?

Ans: してない。

適当にスクリをいじって改造してちょ。

Q. 画像ファイルの表示順序はどうなっている?

Ans: よくわからん。

たぶんファイル名と階層がからんだ昇順降順みたいな感じだと思う。

秀丸エディタで単語補完を用いてタグを実現する

ブログにせよタスク管理にせよ「タグ」を付けるというシステムは整理や抽出の観点で重宝するが、テキストに対してこれを行うのは(自力でタグ文字列を書かないといけないので)しんどい。なんとかしたかったが、単語補完を使って少しだけ楽できることがわかった。

方法

  • タグを tag.txt などに一行一タグで書いておく
  • その他 > ファイルタイプ別の設定 > その他 > 単語補完にて以下設定を行う
    • 単語補完の自動表示はオンに
    • 表示形式はリストに
    • 単語補完の検索対象は辞書ファイルにして、上記 tag.txt を指定

運用例

私は GTD をテキスト(Markdown)ベースで構築しているが、いつかやるリスト(いつかやりたいことが何百と並ぶ)にタグを付けたかった。

なので以下のような構成にした上で、単語補完によりタグ名を(自分で覚えて打つことなく)補完で打てるようにした。

--[gtd]
    |
    +---inbox.gtdlist
    |
    +---someday.gtdlist
    |
    +---context.txt
    |
    ...

context.txt は以下を書いている。

ccblog        ブログネタ
ccbook        書籍ネタ
ccbusiness    ビジネスアイデアネタ
ccbuy         買う
ccdev         開発
ccfuture      将来に備える
ccnovel       小説ネタ
ccwanttobe    こうなりたい、こうありたい

そして GTD 用のファイルタイプ .gtdlist の設定として、単語補完は context.txt から行うようにしている。

結果として、ccと入力するだけでタグが補完される。いちいち「ブログネタは ccblog で、将来備えネタは cc、えっとなんだっけ……」なんてことにならない。ただ補完された選択肢から選べばいい。

単語補完でタグを運用する際の TIPS

専用のファイルタイプをつくる

私は GTD 用のファイルタイプとして .gtdlist をつくったが、これを安易に「.txt や .md で書けばいいか」と考えて運用すると、txt ファイルや md ファイルならなんでも単語補完が発動してしまう。

タグを自動補完させたいケースは、普通なら限定されるはずだ(私の例でいうと GTD 用のリストを扱う時のみ)。なので、その限定用途用のファイルタイプを、別につくってしまえばよい。

prefix(接頭辞)を設ける

単語補完という性質上、接頭辞は何かしらの文字で統一することになる。

私としては「@」が良かったのだが、秀丸エディタは記号だと単語補完の対象にならない。

仕方なく私は「c」を二つ重ねた。二つ重ねれば他の言葉とバッティングすることはほとんどない。ちなみに c は Context の C である(GTD ではタグのことをコンテキストと呼ぶ)。

補完用のファイル(tag.txt)は txt ファイルにする

秀丸エディタが .txt ファイルにしか対応していないため、Markdown ファイルを使っているからと .md を使うと動作しない。