Вы когда-нибудь набирали:

> 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! Позвоните своей семье и расскажите им об этом!