Функция Bash, выводящая данные из «заданий», когда задание приостановлено - PullRequest
1 голос
/ 01 мая 2019
# 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 "$@"
  )
}

Я использую вышеупомянутую функцию оболочки для временного изменения параметров stty, чтобы CTRL-Q и CTRL-S могли функционировать как привязки клавиш в vim.

Это работает хорошо, но как побочныйэффект Я больше не вижу, какой файл соответствует фоновому заданию, когда я приостанавливаю vim с помощью CTRL-Z.Я часто работаю с несколькими сессиями в фоновом режиме, и было бы очень удобно видеть, какое задание снова и снова.

Текущий вывод заданий в фоновом режиме:

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

Развернутый вывод, подобный этому, был бы идеальным:

root@rock64:~# jobs
[1]+  Stopped                 vim .bashrc
root@rock64:~#  

Есть ли другой способ достижения того же эффекта (временное изменение параметров STTY с восстановлением после завершения задания) без сжатия списка фоновых заданий?

Я сейчас использую Bash 4.4.x, но при необходимости могу скомпилировать более новую версию.

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Редактировать:

Я пошел дальше и улучшил обертку, чтобы искать следующий реальный vim в пути, если он запускается как символическая ссылка с именем 'vim' в пути пользователя.Это позволяет избежать необходимости использовать псевдоним, указывающий «vim» на vimwrapper.sh, и прозрачно перенаправляет вызовы «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" "$@"

Оригинальный пост:

Поработав сегодня с этим, я думаю, у меня есть достойное решение.Подоболочка необходима для охвата / хранения изменений параметров stty и процесса vim, который мы хотим осуществить, но это не обязательно должна быть анонимная функция в основной среде оболочки.

#!/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 и выбрав следующую запись, которая не является самой.

Спасибо, @ Джейсон, за то, что указал мне правильное направление, я действительно ценю это.

1 голос
/ 01 мая 2019

Так что то, что я предлагаю в комментарии, трудно передать без лучшего форматирования кода. Я просто предлагаю удалить окружающие ( и ). Кроме того, ловушка 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, добавив export PATH="$HOME/bin:$PATH" в ваш любимый точечный файл.

...