Vimプラグインをインストールするための基本的なbashスクリプトがあるとしましょう。
#!/usr/bin/env bash
plugins=(
tpope/vim-endwise
tpope/vim-fugitive
tpope/vim-surround
tpope/vim-unimpaired
)
rm -rf $HOME/.vim/pack/bundle/*
mkdir $HOME/.vim/pack/bundle/start
installplugin() {
plugin=”$(echo “$1" | sed -e ‘s/.*[\/]//’)”
git clone –depth=1 -q https://github.com/$1.git \
$HOME/.vim/pack/bundle/start/$plugin
rm -rf $HOME/.vim/pack/bundle/start/$plugin/.git*
echo $plugin installed!
}
for repo in ${plugins[@]}; do
installplugin “$repo” &
done
wait
これは配列内の各ストレージをplugins
複製し、~/.vim/pack/bundle/start
それを非同期で実行します。
今はスクリプトの非同期要素(&
の末尾に位置)を無視します。installplugin “$repo” &
.
Installing $plugin
スタート特定のプラグインのインストールプロセス) 毎秒進行状況バーでDone.
そのプラグインを終了した後、同じ行に出力して次のプラグインを続行できますか?
この問題に関する私の見解は次のとおりです。
#!/usr/bin/env bash
plugins=(
tpope/vim-endwise
tpope/vim-fugitive
tpope/vim-surround
tpope/vim-unimpaired
)
rm -rf $HOME/.vim/pack/bundle/*
mkdir $HOME/.vim/pack/bundle/start
progressbar() {
until [ $installed -eq 1 ]; do
sleep 0.1
echo -n '.'
done
}
installplugin() {
installed=0
echo -n "Installing $plugin"
progressbar &
plugin=”$(echo “$1" | sed -e ‘s/.*[\/]//’)”
git clone –depth=1 -q https://github.com/$1.git \
$HOME/.vim/pack/bundle/start/$plugin
rm -rf $HOME/.vim/pack/bundle/start/$plugin/.git*
installed=1
echo ' Done.'
}
for repo in ${plugins[@]}; do
installplugin “$repo”
done
wait
動作しませんが、理由を理解していません。
解決が簡単だと思います。元のスクリプトが非同期であることを覚えておくと、Installing
各メッセージの出力が一番下から数行であることを覚えてから、インストールされるまでドットで行を更新する必要があるため、解決がより複雑になります。対応するプラグイン。前述の進行状況バーの基本形式を表示するには、元のスクリプトを変更する必要がありますか?
答え1
シェル変数は、関数installed
内(サブシェル環境で)と関数内で2つの異なる変数なので、機能しません。バックグラウンドジョブから始まるため、関数はサブシェルで実行されます。関数が起動すると、親環境から値を継承しますが、親は子環境(subshell)で新しい値を設定できません。progressbar
installplugin
progressbar
progressbar
これはまだprogressbar
バックグラウンドタスクとして機能しますが、無限ループを終了するようにトラップを設定できます。メイン関数はfoo
適切な信号を送信してトラップを完了してトリガします。
progressbar () {
trap 'break' USR1
while printf '.' >&2; do
sleep 0.25
done
}
foo () {
progressbar & pid="$!"
echo 'working...'
sleep 5
echo 'done.'
kill -s USR1 "$pid"
}
foo