| @ブログ

普段は Vim などのテキストエディターで文章を書いていて、ブログの投稿画面にはできあがった内容をコピペするだけだったので、投稿画面の使いやすさやは気にしたことがなかった。画像のドラッグ・アンド・ドロップ・アップロードや、オン・ザ・フライでプレビューをできるようにしたが、テキスト自体の書きやすさを改善しようとはしてこなかった。

大筋はテキストエディターで書いたとしても、最後に推敲したり、推敲していて気が付いたおかしなところの修正は投稿画面で行うことが多い。やっぱり投稿画面の書きやすさは重要だ。特に長大な内容を編集しているときにテキストエリアが狭いととても使いづらい。ある程度大きさがあり、画面内に大量の文字が表示されるテキストエリアが好みだ。

Lokka が開発されていた 10 年以上前は解像度の小さいディスプレイが主流で、 Lokka の管理画面は小さいサイズのウィンドウで閲覧することを想定したテキストエリアのサイズになっている。今日の高解像度ディスプレイで見ると不便なので画面一杯にテキストエリアが広がるようにした。

投稿画面のレイアウトを改善

iPad からも投稿しやすいように投稿画面のレイアウトも修正した。本文のテキストエリアが広がったためスクロールしないと「スラッグ」以降の入力欄にアクセスできなくなったので、ある程度横幅のあるウィンドウのときにはこれらを右側に配置するようにした。

加えて、フォームを書きかけで保存したかどうかがはっきりせず、未保存の内容があるのに保存せずページから離脱してしまうことがあったので、変更点があるときは背景色を変えてわかるようにした。これにより記入内容を保存せずページを離脱してしまい、内容が失われるという悲劇を回避できるようになった。やり方は適当に検索して出てきた Stack Overflow を参考に、ページを読み込んだ時点で JavaScript でフィールド内の要素を JSON.stringify して data attribute に格納し、その後各フィールドの input イベントを監視して変更があるかどうかをチェックしている。

class FormObserver {
  constructor() {
    this.initializeFields();
    this.observeFieldsChange();
  }

  initializeFields() {
    const fields = Array.from(document.querySelectorAll('div.field'));
    for (const field of fields) {
      const inputElement = field.querySelector('input[type="text"], textarea, input[type="datetime-local"], select option:checked');
      if (inputElement === null) {
        continue;
      }
      field.dataset.serialize = JSON.stringify(inputElement.value);
    }
  }

  observeFieldsChange() {
    const fields = Array.from(document.querySelectorAll('div.field'));
    for (const field of fields) {
      const inputElement = field.querySelector('input[type="text"], textarea, input[type="datetime-local"], select');
      if (inputElement === null) {
        continue;
      }
      inputElement.addEventListener('input', () => {
        if (field.dataset.serialize != JSON.stringify(inputElement.value)) {
          inputElement.dataset.changed = 'true';
          field.classList.add('edited');
        } else {
          inputElement.dataset.changed = 'false';
          field.classList.remove('edited');
        }
      })
    }
  }
}

input イベントを監視すると動作がもっさりするのではないかと心配したが、そんなことはないようだ。普通に使えている。

いまのところ管理画面の HTML レンダリングはサーバーサイドで Ruby で行っているが、これ以上凝ったことをやるなら React などを使って JavaScript で HTML を組み立てる方式にしていく方が効率が良さそうだ。

| @技術/プログラミング

最近 Vim をインストールし直したところ起動時にエラーが出るようになった。 deoplete.nvim (補完プラグイン)関係のエラーだ。

Error detected while processing VimEnter Autocommands for "*"..function deoplete#enable[9]..deoplete#initialize[1]..deoplete#init#_initialize[10]..<SNR>134_init_internal_variables[34]..VimEnter Autocommands for "*"..function deoplete#enable[9]..deoplete#initia│D, [2020-10-24T06:03:29.034369 #21401] DEBUG -- :   Option Load (1.9ms)  SELECT  `options`.* FROM `opti
lize[1]..deoplete#init#_initialize[10]..<SNR>134_init_internal_variables[28]..neovim_rpc#serveraddr

何度か python3 をインストールし直したりしてみたが直らず途方に暮れていたところ、 brew edit vim してみて理由がわかった。普通に brew install python3 すると python@3.8 がインストールされるが、 Homebrew の Vim は python@3.9 に依存してた。なので Vim 内から呼び出される python3 は python@3.9 である必要があるようだ。 python@3.9 は keg only で /usr/local/bin 以下にシンボリックリンクを張ることができないのでシェルの設定ファイルでパスを通してやる必要がある。自分は fish の設定ファイルに以下のように記載した。

set -g fish_user_paths "/usr/local/opt/python@3.9/bin" $fish_user_paths

これで起動時のエラーはおさまった。が、 Vim が依存する python3 と Homebew で入る python3 のバージョンが異なっているのはハマりポイントだと思った。

| @技術/プログラミング

Vim の設定に関してはペパボ時代に同僚のみなさん( glidenote さん、 banyan さん、 linyows さん)から色々学んでほぼほぼ不満がない状態になっている。正規表現拡張の eregex.vimrails.vimprojectionist.vimvim-surround など tpope プラグインと Shougo プラグイン( unite, vimfiler あたり)で普段のユースケースはカバーされているが、 EasyMotion というプラグインの存在と、同じ人がメンテしている incsearch.vim というものがあることを知って入れていみた。カーソル移動を楽にする Vim プラグインのようだ。これまで ⇧wf⌃d などで高速移動はできるといえばできるが、空白や単語の切れ目ではない位置を狙った移動では結局 hl を連打してしまっていた。 EasyMotion は冒頭の数文字を検索すると飛び先をアンカー表示してくれて、高速にファイル内を移動できるというもの。 Unite のファイル内ジャンプ版という感じかな。

さらに調べると incsearch.vim の方は Vim 本体に取り込まれたみたいで必要ないらしいのだが、 で検索にヒットしたカ所を移動したりする機能は incsearch.vim の機能っぽいので両方セットで使ってみることにした。 EasyMotion は incsearch と組み合わせて使うことでかなり便利になるっぽい(ブリッジに haya14busa/incsearch-easymotion.vim が必要だ)。こんな感じ↓(画像は incsearch-easymotion のリポジトリから拝借)

incsearch-easymotion demo

| @技術/プログラミング

DSC_3779.jpg

久々に開発環境をいじってて brew upgrade tmux したら色々ぶっ壊れてつらい。

具体的には以下のブログを参考に、 pane の swap を screen 風にしていた設定が効かなくなってしまった。

## paneの入れ替えをscreenっぽく
bind-key C-n swap-window -t:+ \; swap-pane -s:-
bind-key C-p swap-window -t:- \; swap-pane -s:+

こういう使い方をしていた。

# 状態 1
window 1 A|[B] <- window 1 の pane B がアクティブ
window 2 C     <- window 2 に pane C が単独で存在

C-b C-n を入力し、以下のような配置になっていた(これまで)。

# 状態 2 (tmux 2.8)
window 1 A|[C] <- window 1 の pane B があったところが pane C になる
window 2 B     <- window 2 には pane B が単独で存在

ところが tmux 2.9a 以降ではこんな風になってしまう。

# 状態 2 (tmux 2.9a)
window 1 [B]   <- window 1 pane B が単独で存在しアクティブ
window 2 A|C   <- window 2 に pane A と C 単独で存在

このほかにも tmux-powerline が綺麗に動かなくなったりして色々厳しい。 tmux は 2.8 までが安定している気がする。

仕事ではほとんどコード書かなくなってしまったのでたまの休みで時間があるときになんかやろうとするとこういうトラブルに遭遇して死んでしまう。プログラミングスキルのみならず開発環境の維持・セットアップにいたるまで、プログラミングに関連するあれこれは料理人が日々包丁の手入れをするように常日頃から磨いていないとさび付いてしまう。

追記

tmux の件は以下なんかを参考にしてみようかな。

さらに追記(2019-08-25T11:34:25)

.tmux.conf を以下のようにしたら解決した。

bind-key C-n swap-pane -t:-
bind-key C-p swap-pane -t:+

むしろ最近の変更で tmux の pane スワップの挙動が自分の好み( screen 風)に近づいたみたい😅

| @Mac/iPhone

Fire

Memolist.vim の保存先を Dropbox にする運用を長年続けてきたが、 iOS の Markdown エディターの iA Writer で編集時にファイルが無限複製されるという問題があることや、最近のポリシー変更で Dropbox を無料で使い続けるのは難しそうかつお金を払うにしてもプランが高め(最安でも ¥1,500 / 月で 2TB まで使えるプランしかない)で個人では使いづらそうなので iCloud Drive を代わりに使ってみることにした。 iCloud は今のところ無料で使ってるが 50GB 使えるプランでも月額 ¥130 なので個人で使いやすい。 iCloud Drive は Windows や Linux からは使えないが、 Linux デスクトップはもう何年も使ってないし、 Mac と iPhone にロックインされた生活に不満はないので無問題。

移行の手始めにまずは iCloud Drive にターミナルでアクセスしようとするが、 cd ~/iCloud\ Drive などではたどり着けない。以下の記事を読んで調べた。

パスは ~/Library/Mobile\ Documents/com~apple~CloudDocs で良いみたい。

~/Dropbox/memolist ディレクトリを ~/Library/Mobile\ Documents/com~apple~CloudDocs/Documents/ ディレクトリに移し、 .vimrc を以下のように書き換えた。

diff --git .vimrc .vimrc
index 6c4987e..56882b2 100644
--- .vimrc
+++ .vimrc
@@ -568,7 +568,7 @@

     " memolist.vim {{{

-      let g:memolist_path = "~/Dropbox/memolist"
+      let g:memolist_path = "~/Library/Mobile Documents/com~apple~CloudDocs/Documents/memolist"
       let g:memolist_unite = 1
       let g:memolist_unite_source = "file"
       let g:memolist_unite_option = "-auto-preview -start-insert"

これで Memolist.vim の Markdown ファイル保存先を iCloud Drive に移行できた。

| @技術/プログラミング

ヒトデさんの以下のツイートを目にして便利そうだと思ったので fish + peco + vim でやってみることにした。

以下のような fish 関数を追加した上でショートカットキーを bind しておいた。

function peco_gitlsfiles_vim
  git ls-files | peco --query "$LBUFFER" | read selected
  if [ $selected ]
    vim $selected
  end
end
function fish_user_key_bindings
  fish_vi_key_bindings
  bind \cg\cv peco_gitlsfiles_vim
  bind -M insert \cg\cv peco_gitlsfiles_vim
end

これまで一旦 vim を閉じてしまうとファイルを開きたいときには vim . して Unite で調べててたけど、いきなり git ls-files して peco して絞り込めるようになってとても便利になった。

2018-06-20 16.48.40.gif

| @技術/プログラミング

fish-shell に移行 してこれで .zshrc のお守り業から解放されたと思ってたが、最近異常にシェルの新規セッションの開始が遅くて死にそうになってた。特にやばいのが git mergetool したときで、これは内部的には沢山の fish のプロセスが起動して diff を調べて最終的に vimdiff で表示しているように見えた(僕は git config editor=vim です)。下手するとちょっとしたコンフリクトを修正するために vimdiff が起動するまで 15 分くらい待たないといけないことがあって、 20 年くらい前の Photoshop 作業の現場[1]みたいな感じになってた。これはかなりやばくて、生産性ががた落ちになる。 vimdiff が開くまでに待っている間に他のことやり始めて、気がつくと平気で夕方になってたりする。

fish-shell のバージョンを 2.7.0 に上げたことが原因かと思って、かつて快適に使えていた fish のバージョンに下げたりしてみたが解決しなかったが、以下の記事にたどり着いて $fish_user_paths への値の push をやめたところ解決した。

fish-shell での PATH の通し方として以下のようなのがよく出てくる。 Homebrew で keg only なやつを入れたときにも表示される。

set -U fish_user_paths $HOME/Library/Python/2.7/bin $fish_user_paths

しかしこれをやると $fish_user_paths にどんどんパスが積まれていってしまう。どうもこれが原因で遅くなるようだった。自分の環境でも echo $fish_user_paths してみたところかなり酷いことになっていた…。

↑の Qiita 記事では set -U fish_user_paths するときに第三引数を消せとあったが、それでは根本的な問題の解決にならない( Python やら Ruby やらいろんなものの実行ファイルを PATH に通したいはず)。自分は以下の方法で解決した。

set -x PATH /usr/local/bin $PATH

bash や zsh で export PATH=/usr/local/bin:$PATH とやるのと同じオーソドックスなやり方だと思う。

これだけではこれまでに散々肥えた $fish_user_paths は残ったままなので適当に set -U fish_user_paths '' とかやってあげると空になって起動が速くなる。

fish-shell の set -U はセッションをまたいでグローバルかつ永続的に設定される変数定義の方法っぽいので下手するとその環境で fish を使い始めてからずーっと残ってしまう可能性がある(端末を再起動したらリセットされるかも知れないけど)。

まとめ

  • set -U は基本的にしない
  • $fish_user_paths は設定ファイルの中では使わない
  • PATH を通したいときは set -x PATH を使う

[1]: 何らかの処理を実行して処理が完了されるまでにめっちゃ時間がかかるのでその間にたばこを吸いに行くことが可能だったらしい

追記 2020-05-23

set -x PATH /usr/local/bin $PATH がよいと書いていたが、 tmux を起動すると $PATH に重複してパスが登録されてしまう。ファイナルアンサーとしては以下。

$ set -g fish_user_paths /usr/local/bin $fish_user_paths
  • set -U は使わないではなく set -g する
  • $fish_user_paths は設定ファイルの中でも使ってオッケー
    • パスを通したいときは set -g fish_user_paths /usr/local/bin $fish_user_paths とやる
      set -x PATH /usr/loca/bin $PATH をやると tmux のセッションの中でパスがダブるため