ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

fzfでChromeのtab移動をする

f:id:rasukarusan:20191103190334p:plain

VimでWeb開発してるとブラウザとTerminalを行ったり来たりすることが多い。
ブラウザのタブ切り替えをブラウザでやるのではなく、Terminalでできればノンストレスな開発ができるのではないか。そうだろう。

fzfで実現した

github.com

追記:fzf本家の方、Junegunnさんからプルリクを頂き、よりパワフルでスマートなものになった。ほんと感謝、I love fzf。

Demo.gif
fzfでchromeのTabを選択する

こんな感じでfzfで今現在開いているChromeのTab一覧を出力して、選択したらアクティブにするスクリプト。

インストール

$ brew tap Rasukarusan/tap
$ brew install Rasukarusan/tap/fzf-chrome-active-tab

使い方

$ chrome-tab-activate

ソース

シンプルにAppleScriptとShellScriptの夢のコラボレーション。
成果物がShellScript1つだけってのはミニマムで良いよね。

#!/bin/sh

function getTabs() {
osascript << EOF
    set _output to ""
    tell application "Google Chrome"
        set _window_index to 1
        repeat with w in windows
            set _tab_index to 1
            repeat with t in tabs of w
                set _title to get title of t
                set _url to get URL of t
                set _output to (_output & _window_index & "\t" & _tab_index & "\t" & _title & "\t" & _url & "\n")
                set _tab_index to _tab_index + 1
            end repeat
            set _window_index to _window_index + 1
            if _window_index > count windows then exit repeat
        end repeat
    end tell
    return _output
EOF
}

function setActiveTab() {
local _window_index=$1
local _tab_index=$2
osascript -- - "$_window_index" "$_tab_index" << EOF
on run argv
    set _window_index to item 1 of argv
    set _tab_index to item 2 of argv
    tell application "Google Chrome"
        activate
        set index of window (_window_index as number) to (_window_index as number)
        set active tab index of window (_window_index as number) to (_tab_index as number)
    end tell
end run
EOF
}

function main() {
    local tabs=$(getTabs)
    local title=$(echo "${tabs}" | awk -F '\t' '{print $3}' | fzf)
    local window_index tab_index
    read window_index tab_index <<< "$(echo "${tabs}" | grep -F "${title}" | head -n 1 | awk -F '\t' '{print $1, $2}')"
    setActiveTab $window_index $tab_index
}

main

学び

今回は結構色々学びがあった。

  • ヒアドキュメントでAppleScript書けばShellScript内に埋め込める
osascript << EOF
    tell application "Google Chrome"
    ...
EOF

みたいな形でShellScript内にAppleScriptを埋め込めるのはいい。今までAppleScriptは別のシェルファイルとして作ってたから、 1つのファイルにまとまるのは非常に良い。

  • readコマンドの変数のぶち込み方
read window_index tab_index <<< "$(echo "${tabs}" | grep -F "${title}" | head -n 1 | awk -F '\t' '{print $1, $2}')"

これも「ああなるほどなぁ...」と思うreadの使い方だった。fzfのexamplesに載っていた。
今まで複数の変数を定義する場合、

local window_index=$(echo "${tabs}" | awk -F '\t' '{print $1}')
local tab_index=$(echo "${tabs}" | awk -F '\t' '{print $2}')

こんな感じで1個ずつ定義していたが、何回も同じものをechoしていて冗長だなと感じていた。
read a1 a2 <<< awk '{print $1, $2}'ならphpのlist()みたいな形で一気に複数の変数を定義できる。これは賢い。

  • AppleScriptへのコマンドによる引数の渡し方

ヒアドキュメントでAppleScript書く場合、引数はどうやって渡すのかと悩んだが、下記でいけるらしい。

osascript -- - "$_window_index" "$_tab_index" << EOF
on run argv
    set _window_index to item 1 of argv
    set _tab_index to item 2 of argv
    ...
EOF

終わり

そもそもChromeのTabをfzfで選択したい、ってのは1年ぐらい前に思いついたが今まで手を出していなかった。
当時はAppleScriptを使うっていう脳もなかったし何から調べたら良いのかわからなかったけど、そう思うと以前よりやれること増えた。