作业暂停时,Bash函数压缩“作业”的输出

时间:2019-05-01 19:58:22

标签: linux bash unix vim command-line

TSOSCType

我正在使用上述shell函数来临时更改stty选项,以便CTRL-Q和CTRL-S可以充当vim中的键绑定。

这很好用,但是作为副作用,当我用CTRL-Z暂停vim时,我不再看到哪个文件对应于后台作业。我经常在后台进行多个会话,因此能够再次查看哪个工作确实非常方便。

具有后台任务的作业的当前输出:

# allow CTRL-Q and CTRL-S keybindings
vim() {
  (
    # No ttyctl, so we need to save and then restore terminal settings
    # osx users, use stty -g
    local STTYOPTS="$(stty --save 2> /dev/null)"
    trap "stty $STTYOPTS" EXIT
    stty stop '' start '' -ixoff
    command vim "$@"
  )
}

这样的解包输出将是理想的:

root@rock64:~# jobs
[1]+  Stopped                 ( local STTYOPTS="$(stty --save 2> /dev/null)"; trap "stty $STTYOPTS" EXIT; stty stop '' start '' -ixoff; command vim "$@" )
root@rock64:~#

是否有其他方法可以实现相同的效果(临时更改STTY选项,并在完成工作后恢复)而不会压缩后台工作列表?

目前我正在运行Bash 4.4.x,但是如果需要,我可以轻松地编译新版本。

2 个答案:

答案 0 :(得分:1)

因此,如果没有更好的代码格式,很难传达我在评论中建议的内容。我只是建议删除周围的dialog (Result)(。另外,需要删除RETURN陷阱,所以我刚刚创建了第二个函数,当调用)时,我们跳回到原始函数并删除陷阱。

return

替代

您可以将其放在runvim() { local STTYOPTS="$(stty --save 2> /dev/null)" trap "stty $STTYOPTS" RETURN # This may need to be changed to RETURN stty stop '' start '' -ixoff command vim "$@" } # allow CTRL-Q and CTRL-S keybindings vim() { # No ttyctl, so we need to save and then restore terminal settings # osx users, use stty -g runvim "$@" trap - RETURN } 中名为vim的脚本中:

$HOME/bin

然后通过将#!/bin/bash STTYOPTS="$(stty --save 2> /dev/null)" trap "stty $STTYOPTS" EXIT stty stop '' start '' -ixoff #/usr/bin/vim "$@" # or where ever your vim is $( whereis vim | cut -d\ -f3) "$@" # Here is a more generic version. 添加到您喜欢的点文件中,将该目录添加到PATH变量的前面。

答案 1 :(得分:1)

编辑:

我继续进行了改进,改进了包装器,以在路径中查找下一个真正的vim(如果它在用户路径中作为名为“ vim”的符号链接运行)。这样可以避免在vimwrapper.sh上使用指向“ vim”的别名,并将“ vim”调用透明地转发到实际的vim二进制文件。我认为现在已经基本完成。

#!/usr/bin/env bash
#
# vimwrapper.sh:  Wrapper script to enable use of CTRL-Q/S keybinds in Vim
#
# Using a wrapper script avoids clobbering the editor command line with an
# anonymous subshell that's hard to read when vim is suspended with ^Z. We need
# the scope of the subshell to trap our trap (aaayyyyy) and keep the stty magic
# out of our interactive environment's namespace.  The wrapper script just
# makes background jobs look sane if you interrupt vim with CTRL-Z.

# set -x

case $(basename "$0") in
  "vim")
    # Check if we're shadowing real vim by existing earlier in the path as a
    # symlink and call it directly if so. This lets us symlink vimwrapper.sh to
    # "$HOME/bin/vim", munge "$HOME:/bin" onto the beginning of the path and
    # transparently wrap calls to 'vim' without our script going recursive.

    for _v in $(which -a "vim"); do
      # I refuse to fork myself. You know what, fork you too.
      [[ $(realpath "$_v") == $(realpath "$0") ]] && continue
      #printf "found real vim in path at '%s'\n" "$(realpath $_v)"
      cmd="$_v" && break
    done

    if [[ -z "$cmd" ]]; then
      echo "$(basename $0): Unable to find real vim in path"
      exit 1
    fi
    ;;
  *)
    cmd="vim"
    ;;
esac

STTYOPTS="$(stty --save 2> /dev/null)"
trap "stty $STTYOPTS" EXIT
stty stop '' start '' -ixoff
command "$cmd" "$@"

原始帖子:

今天玩了一段时间后,我认为我有一个不错的解决方案。需要一个子shell来限定/包含stty参数更改以及我们希望它们所影响的vim进程,但在主shell环境中不必一定是一个匿名函数。

#!/usr/bin/env bash
#
# vimwrapper.sh:  Wrapper script to enable use of CTRL-Q/S keybinds in Vim
#                 For best results bind 'alias vim="/path/to/vimwrapper.sh"
#
# Using a wrapper and alias avoids clobbering the editor command line with an
# anonymous subshell that's hard to read when vim is suspended with ^Z. We need
# the scope of the subshell to trap our trap (aaayyyyy) and keep the stty magic
# out of our interactive environment's namespace.  The wrapper script just
# makes background jobs look sane if you interrupt vim with CTRL-Z.

# We'll be paranoid and make sure our wrapper script isn't the target of the
# 'command vim' call that comes next.
if [[ $(realpath $(basename "$0")) == $(realpath $(which vim)) ]]; then
  echo "$0: I refuse to fork myself. You know what, fork you too."
else
  # Save stty state and restore on exit.
  STTYOPTS="$(stty --save 2> /dev/null)"
  trap "stty $STTYOPTS" EXIT
  stty stop '' start '' -ixoff

  command vim "$*"
fi

exit 0

alias vim="~/foo/vimwrapper.sh"将调用绑定到包装脚本可以很好地处理所有事情:

root@rock64:~/bin# vim vim.sh 


[1]+  Stopped                 ~/bin/vim.sh vim.sh

可以将vimwrapper.sh符号链接为路径中某处的'vim',前提是其位置的优先级也低于真实vim。我为此添加了一个检查,因此它不会偶然递归。我可能会稍微扩展一点,以便脚本可以隐藏路径中的实际vim,并通过查看which -a vim并选择下一个本身不是的条目来找出哪个是正确的命令。 / p>

感谢@Jason为我指出了正确的方向,