【问题标题】:How to get the screen state as set by tput smcup/rmcup?如何获取 tput smcup/rmcup 设置的屏幕状态?
【发布时间】:2018-01-09 15:08:20
【问题描述】:

虽然我知道tput rmcup 从“备用屏幕”(man 5 terminfo 中称为“杯子模式”)返回并恢复保存的屏幕,但它确实有重新定位光标的副作用。

因此,如果调用了tput smcuptput rmcup 将恢复屏幕并重新定位光标,但如果您随后键入更多命令或按回车数次然后再次使用 tput rmcup,光标将返回到原来保存的位置。

一个用例是在 bash 脚本中重放终端记录 [使用 scriptreplay]:如果脚本提前结束而没有 [相当于] 调用 tput rmcup,那么我希望能够检测到在我的bash 脚本中并自动调用tput rmcup

简而言之,我希望能够确定当前的屏幕状态是什么;即,它是“备用屏幕”还是“正常屏幕”?

【问题讨论】:

    标签: bash terminal xterm tput


    【解决方案1】:

    如果您使用的是 xterm,那么您可以询问它使用的是什么模式。尽管备用屏幕功能是 xterm 功能而不是“DEC”,但该设置与 XTerm 控制序列中描述的 DECSET 模式组合在一起:

    CSI ? Pm h
              DEC Private Mode Set (DECSET).
    ...
                Ps = 1 0 4 7  -> Use Alternate Screen Buffer, xterm.  This
              may be disabled by the titeInhibit resource.
                Ps = 1 0 4 8  -> Save cursor as in DECSC, xterm.  This may
              be disabled by the titeInhibit resource.
                Ps = 1 0 4 9  -> Save cursor as in DECSC, xterm.  After sav-
              ing the cursor, switch to the Alternate Screen Buffer, clear-
              ing it first.  This may be disabled by the titeInhibit
    

    DECRQM控件可用于查询终端:

    CSI ? Ps$ p
              Request DEC private mode (DECRQM).  For VT300 and up, reply
              DECRPM is
                CSI ? Ps; Pm$ y
              where Ps is the mode number as in DECSET/DECSET, Pm is the
              mode value as in the ANSI DECRQM.
    

    也就是说,你的脚本可以

    printf '\033[?1049$p'
    

    然后读回结果,期待类似\033[?1049;1$y

    这是一个快速演示:

    #!/bin/sh                                                                      
    
    unexpected() {
            result=$(echo "$check"|sed -e 's/^@/\\033/')
            printf '? unexpected reply: %s\n' "$result"
            exit 1
    }
    
    exec </dev/tty
    old=`stty -g`
    stty raw -echo min 0  time 5
    printf '\033[?1049$p'
    read status
    stty $old
    
    if [ -n "$status" ]
    then
            check=$(echo "$status" |tr '\033' '@')
            if [ "$check" != "$status" ]
            then
                    case "$check" in
                    '@[?1049;1$y')
                            echo "alternate screen"
                            ;;
                    '@[?1049;2$y')
                            echo "normal screen"
                            ;;
                    *)
                            unexpected
                            ;;
                    esac
            else
                    unexpected
            fi
    else
            echo "? no reply from terminal"
    fi
    

    当然,如果您不使用 xterm,您的里程可能会有所不同...

    【讨论】:

    • 感谢您的回复。这听起来对我很有用,实际上我的$TERM 环境变量是xterm-256color,所以这可能是正确的方法。但是,我必须承认,我并没有完全按照我需要做的事情来使用它。当我执行(在bash 中)你建议的printf 时,这正是我得到的结果......这是一个惊喜还是我用错了?我也不确定$ 后跟空格的符号是什么意思:我不知道bash 中的含义。
    • 感谢您的编辑。我没有被告知它已经发生所以没有意识到你已经添加了演示代码。我刚刚在我的xterm-256color 终端上试用了它,我看到屏幕上的控制代码不到一秒钟后出现“?终端没有回复”消息。我想这意味着我的终端不兼容?
    • 听起来很像 - vttest 中有一组屏幕可以证明这一点
    • 我刚刚尝试了vttest (v2.7) 中的“屏幕功能测试”,虽然它们大部分都有效,但并不是 100%。显示“原始模式测试。此行应位于屏幕底部”的行。例如,不在屏幕底部。哦,好吧,无论如何感谢您的回答 - 希望它会帮助具有正确兼容 xterm 的人!
    • 这个特殊功能可以在菜单 11、8、2(“请求模式(DECRQM)/报告模式(DECRPM))中看到,虽然它只显示终端是否识别控件,以及它的响应是 - 不是终端在正常/备用屏幕之间切换时是否通过更改响应来正确执行。
    猜你喜欢
    • 1970-01-01
    • 2012-06-03
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多