3

Я знаю о перехватах preexec() для zsh и о том, как этого можно добиться в bash. ( ссылка )

Но могу ли я получить текущий ввод , все еще печатая?

Идея этого вопроса заключается в следующем:

для более быстрого изучения команд, аргументов и ярлыков я хочу найти команду, набираемую в "базе данных" с подсказками «help / good-to-know / shortcut», и показать их в другом сеансе с screen / tmux при вводе текста в другом.

Можно ли проверить, набирается ли текущая команда? Если это не работает при каждом нажатии клавиши, цикл таймера может работать также.

2 ответа2

4

Я могу ответить только за zsh , где это можно сделать, да.

Во-первых, уже есть несколько виджетов для пошагового завершения. Первый, по-видимому, Ю. Фуджи. Хотя его сайт на японском языке, вы можете легко понять, не говоря на этом языке, как он работает и как его использовать. Авто-фу это расширение оригинального скрипта.

Пока что ссылки. В zsh редактор ЗШ линии zle отвечают за интерактивное использование командной строки. Помимо множества других переменных, предоставляемых виджетам (см. man zshzle), они представляют интерес для вас, так как вы хотите захватить текущую командную строку:

$ BUFFER: все содержимое буфера редактирования.

$ LBUFFER: часть буфера, которая находится слева от позиции курсора.

$ RBUFFER: часть буфера, которая находится справа от позиции курсора.

Эти переменные доступны для записи, что изменит текущую командную строку!

Чтобы захватить каждое нажатие клавиши, вы можете изменить self-insert виджета, которая выполняется (по умолчанию) для каждого нажатия клавиши, кроме LF или CR . Вот пример, который не делает ничего очень полезного, но добавляет при каждом нажатии клавиши точку к $RBUFFER - просто чтобы проиллюстрировать, как это работает:

function self-insert() {
  RBUFFER+="."
  # execute some other command, but ensure they don't produce any output.
  zle .self-insert
  }
zle -N self-insert

.self-insert является встроенным виджетом, поэтому мы не сталкиваемся с бесконечным циклом.

Таким образом, вы можете либо начать с нуля, либо начать со скрипта Fujii и изменить его. Одним из преимуществ последнего является то, что он также выполняет некоторую обработку удаления нажатий клавиш, о которой я здесь не упомянул.

2

Для Bash вы можете создать следующий скрипт test.sh :

#!/usr/bin/env bash

ARRAY=('1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '-' '=' 'BACKSPACE' ''
'q' 'w' 'e' 'r' 't' 'y' 'u' 'i' 'o' 'p' '[' ']' 'NEWLINE' '' 
'a' 's' 'd' 'f' 'g' 'h' 'j' 'k' 'l' ';' "'" '' '' '' 'z' 'x' 'c' 
'v' 'b' 'n' 'm' '0' ',' '.' '/' '' '' 'SPACE')

while read row 
do
    if [[ "$row" == *press* ]]
    then
        index=$((${row/key press   /}-10))
        if [[ "${ARRAY[$index]}" == 'NEWLINE' ]] 
        then
                printf "\n"
        elif [[ "${ARRAY[$index]}" == 'BACKSPACE' ]] 
        then
            echo  -ne "\b \b"
        elif [[ "${ARRAY[$index]}" == 'SPACE' ]] 
        then
            printf " "
        else
            printf "%s" "${ARRAY[$index]}"
        fi
    fi
done

Это простой скрипт, который получает некоторые коды клавиатуры и выводит их на экран. Теперь передайте ему коды клавиатуры:

$ stdbuf -o0 xinput test 'AT Translated Set 2 keyboard' | bash test.sh

Теперь, если вы наберете другой терминал, он должен получить значения ключей. Я не знаю, есть ли какой-нибудь умный способ сопоставить коды клавиш с их значениями ASCII, поэтому я просто делаю простое сопоставление. Вы можете улучшить этот код, чтобы реагировать и на другие ключи. Тем не менее, обратите внимание, что скрипт получит весь ввод с клавиатуры, а не только на один данный терминал.

Что касается самой задачи (проверка текущей набираемой команды), вы можете использовать compgen -c для генерации списка возможных завершений на основе переданного аргумента:

 $ compgen -c 'ls' | head -1
 ls
 $ compgen -c 'lsp' | head -1
 lspci

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .