Bash スクリプト: Watch を使用して画面の上半分を個別に更新する

okwaves2024-01-25  8

画面の上部 16 行にランダムな ANSI アート バナーを表示し、残りの行に todo.txt リストのプロジェクト ビューを表示する bash スクリプトを作成しています。これは、tmux ウィンドウの 1 つのペインに常駐し、画面の右 3 分の 1 (約 80x48 文字) に常に ToDo リストが表示されるようにすることを目的としています。

現在、読み込み時にバナーがランダム化されており、何かを追加または削除するたびに fswatch を介して todo リストが更新されます。また、バナーを 15 分ごとに更新したいので、watch などを使用して、ランダムな ANSI バナーを 15 分間隔で cat するコマンドを実行したいのですが、watch を使用すると、スクリプトは画面全体を空白にするだけです。 (以下のコードは 10 秒間隔ですテストに使用されます)

これを行うより良い方法、または Watch にバナーの出力を正しく開始させる方法はありますか?

スクリプトは次のとおりです:

#!/bin/bash
clear
banner.sh
/usr/local/bin/todo.sh projectview | fold -w 80 -s

watch -t -c -n 10 banner.sh # this just gives me a blank screen and hangs

fswatch -l 1 -o --event=Updated -e "~/.todo/.*" -i "todo.txt" ~/.todo | while read;
        do
                tput cup 18 0 && tput ed && /usr/local/bin/todo.sh projectview | fold -w 80 -s # draw the todo list starting on the 18th line.
        done

そして、banner.sh は次のとおりです。

#!/bin/bash

filename=`ls -d ~/banners/* | shuf -n 1`
tput cup 0 0 && cat $filename && echo ""

1

tmux を使用しています。アートと Todo を別々のペインに分割してみてはいかがでしょうか?

– ジェレミーのプロフィール

2020 年 9 月 4 日 22:34

"スクリプトのバナー部分は画面全体を空白にするだけです。」 …でもクリアの機能はないんですか?画面の 2 分の 1 でしか機能しないことを自分で証明できましたか?また、「usr」local「bin」todo.sh を使用しますが、banner.sh のみを使用します。 Banner.sh は本当に実行されていますか? Banner.sh に「完全に」入力するだけで効果があるでしょうか?頑張ってください。

– シェルター

2020 年 9 月 5 日 1:39

@Shellter はい、banner.sh を実行しています。単独で、または watch コマンドを単独で実行しても、空白の画面がハングします。

– トニー・シャーウッド

2020 年 9 月 5 日 23:52

@jeremysprofile: これを 1 つのスクリプトとして実行したいと考えています。現在 tput について学習していて、画面の後半のみを置き換えることができるためです。 watch コマンドが期待どおりに動作する場合は、前半部分のみを置き換えることも可能です。 bash スクリプトのレベルアップを目指しています。

– トニー・シャーウッド

Sエピソード 5、2020 23:55



------------------------

cat は、watch が受け入れる形式でカラー出力を生成しないように見えます。ls またはその他のカラー出力の監視は正常に機能しますが、cat とカラー出力が関与するものは、画面を空白にする以外の効果はありません。

私の答えは、watch を無視してスクリプトを結合するだけで、60 秒ごとにバナーを更新する bash ループをバックグラウンドで実行することでした。残念ながら、STDOUT への書き込みはこのループでも todo リストでもアトミックではないため、バナーとリストを含む変数を単純に更新し、毎回画面全体を更新する必要がありました。リスト ファイルが変更されるまでの時間、または 60 秒経過したら新しいバナーを作成する時間です。

再描画する必要のないものを大量に再描画しているため、これは理想的ではありませんが、書き込みを行う方法が見つからないという事実を回避する唯一の方法です。 STDOUT アトミック。

#!/bin/bash
clear
# choose a random banner and initialize variables
filename=`ls -d ~/banners/*.ans | shuf -n 1`
banner=$(head -c -1 $filename)

function todo {
        # move to the top left of the screen but don't clear
        tput cup 0 0
        # display the banner
        echo "${banner}"
        # make sure we're on line 16
        tput cup 16 0
        # update the todo list, so that it will clear each line to the end
        todolist=$(/usr/local/bin/todo.sh today | fold -w 80 -s | sed -r 's/$/\033\[K/g')
        # display the todo list
        echo -e "${todolist}"
        # clear the rest of the screen
        tput ed
}

# CTRL-C exits cleanly, killing the banner process that was running in the background
trap 'trap - SIGTERM && tput cnorm && clear && kill 0' SIGINT SIGTERM EXIT

while true; do
        # choose a new banner
        filename=`ls -d ~/banners/*.ans | shuf -n 1`
        banner=$(head -c -1 $filename)
        # redraw the screen
        todo
        # do this every 60 seconds
        sleep 60
done &

# make the cursor invisible for now
tput civis

fswatch -l 1 -o --event=Updated -e "~/.todo/.*" -i "todo.txt" ~/.todo | while read;
        do
                # redraw the screen
                todo
        done

# make the cursor visible again
tput cnorm
exit

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。