# ~/.zshrc
# ...
HISTFILE="$HOME/.zsh_history"
HISTSIZE=10000000
SAVEHIST=10000000
HISTORY_IGNORE="(ls|cd|pwd|exit|cd)*"
Мы не можем эффективно искать и использовать историю, если не сохраняем данные. Конфигурация выше делает так, чтобы мы хранили практически бесконечное количество команд в истории. Она также использует HISTORY_IGNORE, чтобы указать команды вроде ls, cd и другие, которые не будут сохраняться в истории. Вы можете настроить этот список игнорирования по своему усмотрению.
Чтобы еще больше оптимизировать конфигурацию, можем добавить следующие опции ZSH:
# ~/.zshrc
# https://zsh.sourceforge.io/Doc/Release/Options.html (16.2.4 History)
setopt EXTENDED_HISTORY # Write the history file in the ':start:elapsed;command' format.
setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits.
setopt SHARE_HISTORY # Share history between all sessions.
setopt HIST_IGNORE_DUPS # Do not record an event that was just recorded again.
setopt HIST_IGNORE_ALL_DUPS # Delete an old recorded event if a new event is a duplicate.
setopt HIST_IGNORE_SPACE # Do not record an event starting with a space.
setopt HIST_SAVE_NO_DUPS # Do not write a duplicate event to the history file.
setopt HIST_VERIFY # Do not execute immediately upon history expansion.
setopt APPEND_HISTORY # append to history file (Default)
setopt HIST_NO_STORE # Don't store history commands
setopt HIST_REDUCE_BLANKS # Remove superfluous blanks from each command line being added to the history.
Настройки выше в основном конфигурируют ZSH, чтобы игнорировать определенные команды и избегать засорения истории, например, дубликатами или командами истории. Они также добавляют временные метки к каждой команде, что будет полезно при поиске (см. следующий раздел).
Одна особая опция, на которую стоит обратить внимание, — это HIST_IGNORE_SPACE, которая может быть полезна, если вы хотите избежать хранения секретов в истории. Просто добавьте пробел перед любой командой, которая включает в себя секрет/пароль, например, export AWS_ACCESS_KEY_ID=... (обратите внимание на пробел перед export), и она не появится в истории.
Теперь расскажем о том, как настроить поиск и отображение истории.
По умолчанию вы можете искать только по точному совпадению, но в ZSH есть плагин, который позволяет использовать нечеткий поиск. Чтобы включить его, нам просто нужно добавить плагин:
# ~/.zshrc
# ...
plugins=(git fzf)
ZSH автоматически будет использовать FZF для нечеткого поиска. Однако, возможно, команда find будет использоваться в фоновом режиме, что не очень быстро. Чтобы улучшить производительность (для очень больших файлов истории), рекомендуем использовать ag:
sudo apt-get install silversearcher-ag
# add to # ~/.zshrc
export FZF_DEFAULT_COMMAND='ag --hidden -g ""'
И последняя опция конфигурации, о которой стоит упомянуть, — форматирование временных меток истории. По умолчанию, когда вы просматриваете историю, вы получите вывод вида:
10206 echo hello
10207 head some-file.txt
10208 curl google.com
10209 cat some-file.txt
Это — номер строки из файла истории и сама команда. Однако, добавив HIST_STAMPS="yyyy-mm-dd" в ~/.zshrc, мы можем получить следующее:
10206 2024-03-30 12:29 echo hello
10207 2024-03-30 12:51 head some-file.txt
10208 2024-03-30 13:21 curl google.com
10209 2024-03-30 14:15 cat some-file.txt
Теперь, когда мы всё настроили, давайте посмотрим, как эффективно искать по всей истории.
Самый простой способ — без горячих клавиш — это использовать команду history. Однако, это означает вывод всей истории, что непрактично, вместо этого мы можем сделать так:
\history -E -10
10206 30.3.2024 12:29 echo hello
10207 30.3.2024 12:51 head some-file.txt
10208 30.3.2024 13:21 curl google.com
10209 30.3.2024 14:15 cat some-file.txt
...
\history -i
10206 2024-03-30 12:29 echo hello
10207 2024-03-30 12:51 head some-file.txt
10208 2024-03-30 13:21 curl google.com
10209 2024-03-30 14:15 cat some-file.txt
...
fc -E -l -10
10206 30.3.2024 12:29 echo hello
10207 30.3.2024 12:51 head some-file.txt
10208 30.3.2024 13:21 curl google.com
10209 30.3.2024 14:15 cat some-file.txt
...
Используем флаг -<N>, чтобы указать количество строк как для команды history, так и для fc. Дополнительно, флаги -E и -i предоставят различные форматы дат.
fc — без аргументов — также можно использовать, если вы хотите отредактировать и повторно выполнить последнюю команду: она откроется в текстовом редакторе по умолчанию, и после закрытия редактора команда будет выполнена.
Ещё одна полезная команда — r, которая выполняет последнюю команду без редактирования (как !!), и r <WORD>, которая выполняет последнюю команду, содержащую строку WORD.
Однако чаще всего мы хотим искать историю с помощью горячих клавиш — в ZSH сочетание CTRL+R по умолчанию предоставляет прокручивание истории на основе контекста (виджет истории).
Как видите, это также включает нечеткий поиск FZF.
Если по какой-то причине это не работает на вашей машине, проверьте привязки клавиш:
bindkey | grep fzf-history-widget
"^R" fzf-history-widget # ^R is CTRL+R
Если вы предпочитаете классический обратный поиск вместо прокрутки истории на основе контекста, тогда вы можете привязать события history-incremental-search-backward и history-incremental-search-forward:
# Add to ~/.zshrc
bindkey "^E" history-incremental-search-backward # CTRL+E
bindkey "^S" history-incremental-search-forward # CTRL+S
Вы также можете просто начать вводить команду и нажимать стрелки вверх/вниз для поиска по истории, учитывая то, что уже введено в командной строке.
bindkey "^[[A" up-line-or-beginning-search # Arrow up
bindkey "^[[B" down-line-or-beginning-search # Arrow down
В документации также есть другие варианты, например:
history-beginning-search-backward
history-beginning-search-backward-end
history-search-backward
...
Учтите, что коды клавиш могут отличаться в зависимости от вашей операционной системы. Например, стрелка вверх может быть \e[A, ^[OA или ^[[A на разных системах.
Как вы, вероятно, заметили из приведенного выше GIF, вы можете включить синтаксическую подсветку для классического обратного поиска. Просто установите zsh-syntax-highlighting с помощью:
sudo apt-get install zsh-syntax-highlighting
echo "source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc
Чтобы перейти на следующий уровень и всегда иметь историю командной строки на разных рабочих станциях, вы можете дополнительно использовать плагин ZSH history-sync, который использует Git для синхронизации истории между рабочими станциями — смотрите документацию плагина, чтобы понять, как он работает и как его настроить.
Более современная альтернатива вышеуказанной функции синхронизации — atuin.sh, который использует SQLite в качестве хранилища и поддерживает ZSH.
Надеемся, что с вышеприведёнными советами и конфигурациями ваша история командной строки станет личным хранилищем знаний и поможет немного эффективнее работать в терминале.
Примечание: Полный ~/.zshrc (без комментариев) можно найти здесь.