fishでprevious commandしたときに前方一致で絞り込みたい

fishで history-search-backward する話 config.fishに以下を追加すると、↑矢印やCtrl+Pで以前使ったコマンドを遡るときに、前方一致が一致するもので絞り込むことができます。

※fish3.1〜

# down-or-search    
bind -k down history-prefix-search-forward
bind \e\[B history-prefix-search-forward
bind \cn history-prefix-search-forward
# up-or-search  
bind -k up history-prefix-search-backward
bind \e\[A history-prefix-search-backward
bind \cp history-prefix-search-backward

Vue RouterでURL変更後になにかしたいときは Vue.nextTick() を使うといいという話

Vue Routerのrouter.afterEachでwindow.locationを使う場合は Vue.nextTick() を使わないと期待した結果が返ってこないかもよという話。

確認手順

1. 下のようなrouterを定義して、 /?foo/?bar のAnchorリンクをHTMLに書いておく

import Vue from "vue";
import Router from "vue-router";
import Home from "../components/Home";

Vue.use(Router);

const router = new Router({
  mode: "history",

  routes: [
    {
      path: "/",
      component: Home,
      props: (route) => ({ name: route.query.name })
    }
  ]
});

router.afterEach(() => {
  console.log("A", window.location.href);
  Vue.nextTick(() => console.log("B", window.location.href));
});

export default router;

できあがったものがこれ https://jnjjv.csb.app

2. ブラウザのConsoleを確認する

f:id:mii288:20200929155805p:plain

AとBで結果が違うのがおわかりいただけるだろうか。


router.afterEachで toと一致する window.locationを確実に取得したくて MatteoGabriele/vue-analytics の中身を覗いて知ったissueでした。 簡易的にGAのpageviewを送るときなんかは気をつけたほうが良さそう。

github.com

jest.useFakeTimers()を使ってテスト時間を短縮する

ある外部SDKをラップしたものをjestでテストしたい。 外部のSDKの仕様も相まって、ちょっとややこしかった。

jest.useFakeTimers() を使ったテストが初めてだったのもあってメモ。

※以下サンプルソースですが、雰囲気コードなので動作しないかも。

SampleSdkという外部のモジュールがあるとする。

// SampleSdk.d.ts

interface initContext {
  type: 'init',
  body: { isMobile: boolean }
}

interface getSessionContext {
  type: 'getSession',
  body: {
    token: string
  }
}

type Context = initContext | getSessionContext

interface Window {
  // Windowオブジェクトの中にSampleSDKオブジェクトが入っている。
  SampleSDK:  {
    dispatch: (context: Context) => void
    emit: (type: 'init' | 'getSession') => void
  }
}

それをこんな感じでラップする。

// sample.ts

class SampleSdk {
  window: Window
  emitter: EventTarget
  promise: null | Promise<initContext['body']> = null

  constructor(window: Window) {
    this.window = window
    // emitterはmittでもなんでもよい、雰囲気で。
    this.emitter = window.EventTarget

    this.init()
  }

  async init():  Promise<initContext['body']> {
    if (this.promise) {
      return this.promise
    }

    const initEvent = new Event('init'),
    this.window.SampleSDK.dispatch = (context) => {
      if (context.type === 'init') {
        this.emitter.dispatchEvent(events[context.type], context.body)
      }
    })

    this.promise = new Promise(resolve => 
      this.emitter.addEventListener('init', resolve)
    )

    this.window.SampleSDK.emit('init')

    return this.promise
  }
}

// 実際に使うときは
// const sdk = new SampleSdk(window)
// const body = await sdk.init()
// console.log(body) // { isMobile: false }

await SampleSdk.init()で isMobile が取得できるかテストする

// sampleSdk.spec.ts

import SampleSdk from './sampleSdk'

describe('SampleSDK', () => {
  it('初期化完了後デバイス情報が返却されること', () => {
    const mockWindow = {
        SampleSdk: {
            dispatch: () => jest.fn(),
            emit() {
              window.setTimeout(
                  () => this.SampleSdk.dispatch({ type: 'init', body: {isMobile: false}}),
                  1000
              );
            }
        };
    }

    new SampleSDk(mockWindow);
    expect(await this.init()).toEqual({ isMobile: false })
  })
})

このままでも一応動くんだけど、テストが完了するまでに絶対1秒かかる。 ので、 jest.useFakeTimers()jest.runAllTimers(); を組み合わせることで、 テスト時間を短縮できる。

 // sampleSdk.spec.ts
 
 import SampleSdk from './sampleSdk'
 
 describe('SampleSDK', () => {
   it('初期化完了後デバイス情報が返却されること', () => {
+    jest.useFakeTimers();
     const mockWindow = {
         SampleSdk: {
             dispatch: () => jest.fn(),
             emit() {
               window.setTimeout(
                   () => this.SampleSdk.dispatch({ type: 'init', body: {isMobile: false}}),
                   1000
               );
             }
         };
     }

     new SampleSDk(mockWindow);
+    jest.runAllTimers();
     expect(await this.init()).toEqual({ isMobile: false })
   })
 })

Automatorを使って動画ファイルを右クリックでGifに変換できるようにする

準備

FFmpegのインストール

$ brew install ffmpeg

Automator

クイックアクションとして以下の内容のものを作成する。 シェルスクリプトのコードは、

for f in "$@"
do
 echo "${f}"
 /usr/local/bin/ffmpeg -i "$f" -r 24 "${f%.*}.gif"
done

f:id:mii288:20200401172827p:plain

iPhoneで動画キャプチャ→AirDropMacに送信→Gif変換→issueへアップロードみたいなのがスムーズにできて便利

vim8 in macにdeoplete.vimをインストール

.vimrcの整理をしていたら、起動時に [vim-hug-neovim-rpc] Vim(pythonx):Traceback (most recent call last): がエラーとして出ていたので対処した。

neovimというPython 3のパッケージがシステムに導入されてる必要があります

とのことなので、もろもろインストール方法の備忘録。

続きを読む

CentOS 6.7にtmux2.2をインストールする方法

can't create socket: Permission denied が出たので入れなおした。

$ cat /etc/redhat-release
CentOS release 6.7 (Final)
$ arch
x86_64

公式の手順で導入

$ git clone https://github.com/tmux/tmux.git
$ ./configure && make
$ sudo make install

参考