Вы когда-нибудь набирали:
> make run.deplo[TAB]
И надеялся, что Bash просто автозаполнит эту чертову вещь?
Этот рефлекс привел меня к созданию удобного скрипта для автозаполнения целей Makefile. Мы используем множество Makefile для управления общими командами bash на уровне репозитория, поэтому он отлично подходит в качестве локальной утилиты оболочки.
В Bash есть утилита для добавления списков слов в автозаполнение и привязки их к вызову функции. Например:
Это означает:
С этого момента в этом сеансе оболочки, когда я нажимаю [TAB] после
caught-in-the-rain
, я хочу, чтобы автозаполнение учитывало слова 'if you like pina coladas"
как мой словарь для автозаполнения.
Итак, для Makefile имеет смысл начать с чего-то вроде этой команды:
Это гипотетически связывает список всех доступных целей Makefile в текущем каталоге с командой make. К сожалению, make не имеет встроенной утилиты list-target. Итак, нам придется создать свою собственную!
Теперь мы в деле. Это запускает каждую строку Makefile в текущем каталоге через grep
, ищет строки с определенными шаблонами, совпадающими перед двоеточием (специальный символ для целей Makefile), удаляет все содержимое после двоеточия с помощью sed
, а затем удаляет повторяющиеся цели. (Он также пропускает цели с префиксом точки, такие как .PHONY
). Результат передается в виде списка слов для автозаполнения при каждом вызове make
.
Но Джон! Разве это не привязывает один и тот же список слов к каждому вызову в текущем сеансе bash, независимо от Makefile? Что делать, если у меня есть несколько каталогов с Makefile?
Да друг! Это не совсем то, что нам нужно. Нам необходимо динамически идентифицировать текущий Makefile, где бы мы ни находились. Это подводит нас к добавлению хуков к нашим командам автозаполнения, что привело меня к этой фантастической записи в блоге о скриптах автозаполнения. Используя эту информацию, я двинулся вперед:
Здесь есть что распаковать. COMP_WORDS
- это специальная переменная в этой функции. Это список всех слов, введенных пользователем на данный момент, используемых, чтобы мы могли определить, какие слова уже были использованы, а какое в настоящее время набирается. COMP_CWORD
- это индекс текущего слова в COMP_WORDS
, здесь не используется, потому что нас интересует только одна цель для завершения.
compgen
является сестринской утилитой для complete
. Учитывая список слов и набор слов, введенных пользователем, он возвращает ответ автозаполнения , как если бы пользователь ввел эти слова. Это позволяет нам динамически обновлять список слов во время выполнения, а не заранее при запуске complete
. Таким образом, автозаполнение будет учитывать только Makefile в текущем каталоге.
У нас все еще есть проблемы. Вы можете продолжать нажимать [TAB] до тошноты, и он продолжит автозаполнение, и он выдаст ошибку, если нет Makefile. Более того, он будет считать действительным только один аргумент Makefile, но не учитывает возможность флаговых аргументов. Все это смягчается следующим окончательным черновиком:
Добавьте это в свой .bashrc
, чтобы немного повеселиться с Makefile! Позвоните своей семье и расскажите им об этом!