- Вопрос или проблема
- Общий обзор
- Текущий код автозаполнения (тот, который работает)
- Текущее поведение автозаполнения
- Какой цели я хочу достичь
- Что я уже пробовал
- Попробованный код (тот, который не работает)
- Поведение попробованного кода
- Что я также сделал
- Ближайшее решение, которое я нашел
- Вопрос
- Ответ или решение
- Общее представление
- Цель
- Попытки решения
- Лучше всего предложенное решение
- Практическая реализация
- Выводы
Вопрос или проблема
Общий обзор
Мне нужно настроить автозаполнение значений в zsh для команды (в следующем минимальном примере я покажу это с помощью testcmd
).
Так что мой текущий код работает довольно хорошо с жестко закодированными значениями:
Текущий код автозаполнения (тот, который работает)
function testcmd()
{
echo "Нечего делать, просто тестовая команда"
}
_test_complete() {
_values \
"Возможные значения" \
foo'[Foo]' \
bar'[Bar baz]' \
}
compdef _test_complete testcmd
Текущее поведение автозаполнения
Когда я набираю testcmd <tab>
, я правильно получаю следующее ожидаемое отображение:
$ testcmd
Возможные значения
bar -- Bar baz
foo -- Foo
Какой цели я хочу достичь
Но, как вы видите, значения жестко закодированы внутри функции, в идеале функция должна их получать из переменной.
Что я уже пробовал
Поэтому естественно, я поместил значения в переменную values_variable
следующим образом:
Попробованный код (тот, который не работает)
function testcmd()
{
echo "Нечего делать, просто тестовая команда"
}
_test_complete() {
local values_variable
values_variable="foo'[Foo]' \
bar'[Bar baz]' \ "
_values \
"Возможные значения" \
${values_variable}
}
compdef _test_complete testcmd
Поведение попробованного кода
Но затем, когда я пытаюсь testcmd <tab>
, это полностью проваливается:
$ testcmd
_values:compvalues:11: неверное определение значения: foo'[Foo]' \t\tbar'[Bar baz]' \
_values:compvalues:11: неверное определение значения: foo'[Foo]' \t\tbar'[Bar baz]' \
_values:compvalues:11: неверное определение значения: foo'[Foo]' \t\tbar'[Bar baz]' \
$ testcmd
Что я также сделал
- Я пытался экранировать пробелы с помощью
echo ${values_variable} | sed "s/ /\\ /g"
; - Я пытался использовать
$values_variable
с командойeval
, чтобы имитировать, как будто его содержимое было напрямую набрано внутри определения_values
; - Я пытался использовать как
eval
, так и экранирование с помощьюeval $(echo ${values_variable} | sed "s/ /\\ /g")
; - Я пытался прочитать строку за строкой с помощью цикла:
echo "$values_variable" | while read -r line; do
eval "$line"
done
- Расширение с
${(@f)values_variable}̀
; - Множество других идей. Но это тоже не сработало.
Ближайшее решение, которое я нашел
В Как передать содержимое файла с использованием cat
в _values
(zsh completion) ветке я нашел решение для значений, импортированных из внешнего файла, но пользователь кажется столкнулся с той же проблемой экранирования пробелов. Однако я не могу адаптировать его к случаю с внутренней переменной $values_variables
.
Я естественно попробовал это, что тоже не работает:
_test_complete() {
local values_variable
values_variable="foo'[Foo]' \
bar'[Bar baz]' \ "
OLD_IFS=$IFS
IFS=$'\n'
_values \
"Возможные значения" \
${values_variable}
IFS=$OLD_IFS
}
Вопрос
Как я могу загрузить значения для передачи в _values
внутри функции автозаполнения из переменной?
Вы можете использовать переменную массив:
_test_complete() {
local -a values_variable=(
'foo[Foo]'
'bar[Bar baz]'
)
_values 'Возможные значения' "${values_variable[@]}"
}
compdef _test_complete testcmd
Тогда testcmd
TAB покажет:
bar -- Bar baz
foo -- Foo
Ответ или решение
Значительная часть работы системного администратора или специалиста в области информационных технологий — это настройка окружения так, чтобы с ним было легко и удобно взаимодействовать. Одной из таких важных частей удобства работы в командной строке является автодополнение. Оно позволяет значительно сократить время ввода команд и снижает вероятность ошибок. В данной статье будет рассмотрен пример настроек автодополнения для Zsh (Z shell), который является одной из самых популярных оболочек для UNIX-подобных операционных систем.
Общее представление
Перед нами стоит задача настроить автодополнение в Zsh для команды testcmd
, используя значения, заданные в переменной. Ранее использованная настройка работает, но имеет значительное ограничение: значения жестко зашиты в код функции. Это создает неудобства, если понадобится изменить или расширить перечень значений, поскольку для этого придется вносить изменения непосредственно в код функции автодополнения.
Текущая работающая конфигурация:
function testcmd() {
echo "Nothing to do, just a test command"
}
_test_complete() {
_values \
"Possible values" \
foo'[Foo]' \
bar'[Bar baz]'
}
compdef _test_complete testcmd
При вводе testcmd
и нажатии клавиши TAB пользователю предлагаются варианты:
$ testcmd
Possible values
bar -- Bar baz
foo -- Foo
Цель
Основная цель заключается в том, чтобы заменить жестко прописанные внутри функции _test_complete
значения на использование переменной. Это бы упростило процесс обновления и поддержки автодополнения, позволяя вынести значения в более доступную для редактирования область. В идеале, значения должны извлекаться из переменной values_variable
.
Попытки решения
Было предпринято несколько попыток:
- Использование переменной
values_variable
строкового типа, содержащей значения:
_test_complete() {
local values_variable
values_variable="foo'[Foo]' \
bar'[Bar baz]'"
_values \
"Possible values" \
${values_variable}
}
compdef _test_complete testcmd
Этот метод не сработал, выдав ошибку: _values:compvalues:11: invalid value definition
.
- Проводились разные методы для манипуляции строками, такие как использование
eval
, попытка экранирования пробелов сsed
, разбор строки по частям с помощью циклов. Однако все эти методики не привели к положительному результату.
Лучше всего предложенное решение
В итоге наилучший результат был получен при использовании массива. Массивы в Zsh являются гибким и мощным инструментом, позволяющим хранить и работать с множеством отдельных строк, что отлично подходит для нашего случая.
_test_complete() {
local -a values_variable=(
'foo[Foo]'
'bar[Bar baz]'
)
_values 'Possible values' "${values_variable[@]}"
}
compdef _test_complete testcmd
Практическая реализация
С использованием массивов, автодополнение работает так же, как и с жестко зашитыми значениями, но теперь мы можем легко добавлять или изменять значения в массиве без необходимости изменения основной логики функции _test_complete
.
При использовании testcmd
с нажатием TAB пользователь увидит тот же список:
bar -- Bar baz
foo -- Foo
Выводы
Настройка автодополнения в оболочке Zsh с помощью массивов — это удобный и гибкий способ упростить взаимодействие пользователя с командной строкой. Массивы позволяют абстрагировать значения от основной логики, повышая ее гибкость и удобство поддержки, что особенно полезно в корпоративной среде, где изменения могут требоваться часто или неожиданно.