Bash 脚本:使用 Watch 分别更新屏幕的上半部分

Bash Script: Updating Top Half Of The Screen Separately Using Watch

我正在编写一个 bash 脚本,该脚本在屏幕的前 16 行显示一个随机的 ANSI 艺术横幅,然后在其余行显示我的 todo.txt 列表的项目视图.这旨在存在于我的 tmux window 的一个窗格中,以便我屏幕的右三分之一(大约 80x48 个字符)始终显示我的待办事项列表。

现在我的横幅在加载时随机化,然后每当我添加或删除某些内容时通过 fswatch 更新待办事项列表。我还想每 15 分钟左右更新一次横幅,所以我想使用 watch 之类的东西来 运行 命令以 15 分钟的间隔随机生成一个 ANSI 横幅,但是当使用 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 ""

看起来 cat 不会以 watch 可以接受的格式生成彩色输出,因为 watch ls 或其他一些彩色输出工作正常,但涉及 cat 和彩色输出的任何内容除了使屏幕空白外不会做任何事情.

我的回答是放弃 watch,只结合脚本,运行 后台有一个 bash 循环,每 60 秒更新一次横幅。不幸的是,对于这个循环或待办事项列表,对 STDOUT 的写入不是原子的,所以我不得不简单地更新包含横幅和列表的变量,并在每次列表文件更改时更新整个屏幕 现在是 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