Тонкая настройка .zshrc при использовании oh-my-zsh
Приветствую!

Сегодня мы рассмотрим процесс конфигурации популярной командной оболочки ZSH⚙️ через файл загрузки окружения .zshrc📝 при использовании фреймворка oh-my-zsh.

Демонстрация, приведенная в данной статье выполнялась в среде дистрибутива Linux Mint 22🌱 (Ubuntu 24🦍). Аналогичным образом все будет работать и в других популярных дистрибутивах Linux☝️.

Погнали🏎.

TLDR

BASH
# установка необходимых утилит
sudo apt update && sudo apt install -y git curl zsh

# для "красочного" терминала установка bat, exa и grc
sudo apt install -y bat exa fzf grc || sudo apt install -y bat eza fzf grc

# бэкап существующего .zshrc
[[ -f ~/.zshrc ]] && mv -v ~/.zshrc{,_backup}

# скачивание готового .zshrc
curl -fsSL --output ~/.zshrc \
    https://raw.githubusercontent.com/r4ven-me/zshrc/main/.zshrc

# смена оболочки по умолчанию
[[ $SHELL == *zsh ]] || chsh -s /usr/bin/zsh

# применение изменений для текущей сессии
exec zsh
Нажмите, чтобы развернуть и увидеть больше

Предисловие

Если вы много времени проводите в консоли/терминале Linux🧑‍💻, то вероятно, слышали про инструменты, которые облегчают взаимодействие с командной строкой и выводят «юзер экспириенс» на «новый уровень»🤔. Один из таких инструментов — оболочка ZSH и созданный умельцами фреймворк для ее простого и удобного конфигурирования — oh-my-zsh🔥.

Ранее я достаточно много времени потратил на приведение используемой мной оболочки к «идеальному», на мой взгляд или близко к тому состоянию🫠.

Ниже я приведу подробное описание своего конфига ZSH в файле .zshrc✍️, чтобы вы понимали, зачем вам это нужно.

После покажу (до безобразия простой🤷‍♂️) способ установки и применения данного конфига. Все внешние зависимости, такие как сам oh-my-zsh и дополнительные плагины, будут установлены автоматически🦾 при первом запуске ZSH.

Демо моей конфигурации

BASH
Tab
Нажмите, чтобы развернуть и увидеть больше

BASH
Ctrl+r
Нажмите, чтобы развернуть и увидеть больше

BASH
history
Нажмите, чтобы развернуть и увидеть больше

BASH
--help
Нажмите, чтобы развернуть и увидеть больше

BASH
cat
Нажмите, чтобы развернуть и увидеть больше

BASH
less
Нажмите, чтобы развернуть и увидеть больше

BASH
tail
Нажмите, чтобы развернуть и увидеть больше

BASH
tailf
Нажмите, чтобы развернуть и увидеть больше

BASH
ls
Нажмите, чтобы развернуть и увидеть больше

BASH
ss
Нажмите, чтобы развернуть и увидеть больше

BASH
ping
Нажмите, чтобы развернуть и увидеть больше

BASH
journalctl
Нажмите, чтобы развернуть и увидеть больше

BASH
docker
Нажмите, чтобы развернуть и увидеть больше

Удобный доступ к кастомным сложным командам через универсальную функцию cmd:

И многое другое. Теперь переходим к подготовке и установке.

Подготовка

Установка необходимых пакетов

Предварительно нам необходимо установить саму оболочку zsh, утилиту для взаимодействия с веб curl и систему контроля версий git:

BASH
sudo apt update && sudo apt install -y git curl zsh
Нажмите, чтобы развернуть и увидеть больше

Также (опционально) рекомендую установить утилиты для подсветки терминального вывода и удобного поиска:

BASH
sudo apt install -y bat exa fzf grc || sudo apt install -y bat eza fzf grc
Нажмите, чтобы развернуть и увидеть больше

Установка powerline шрифта для GUI сеанса

Для корректной отрисовки иконок в вашем терминале во время графической сессии — необходимо использовать специальный моноширный иконочный powerline шрифт🤯, например, из проекта Nerd fonts.

Мои читатели знают, что я предпочитаю шрифт Hack ☝️. Вот простой пример, как его можно установить:

BASH
# создаем директорию шрифта
sudo mkdir /usr/share/fonts/Hack

# скачиваем архив со шрифтами
curl -fsSLO \
    $(curl -s https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest \
    | grep browser_download_url \
    | grep 'Hack.zip' \
    | cut -d  '"' -f 4)

# распаковываем архив, коприруем шрифты в систем
sudo unzip ./Hack.zip -d /usr/share/fonts/Hack/ && rm -f ./Hack.zip
Нажмите, чтобы развернуть и увидеть больше

После установки шрифта, активируйте его в настройках вашего терминала🛠.

В Gnome-terminal это делается так:

Применение конфигурации .zshrc

Бэкапим текущий .zshrc, если он существует:

BASH
# бэкап текущего .zshrc
[[ -f ~/.zshrc ]] && mv -v ~/.zshrc{,_backup}
Нажмите, чтобы развернуть и увидеть больше

Создаём новый .zshrc в любом удобном редакторе:

BASH
vim ~/.zshrc
Нажмите, чтобы развернуть и увидеть больше

И наполняем:

.zshrc
#======================================================
# Описание: Конфигурация .zshrc для oh-my-zsh 
# Автор: Ivan Cherniy
# Основной сайт: https://r4ven.me
# Заметка о конфигурации: https://r4ven.me/zshrc-config
#======================================================

#============================================
#             ОБЩИЕ НАСТРОЙКИ
#============================================

# Добавляем пользовательские директории в переменную PATH
if [[ -d "$HOME/bin" ]]; then PATH="$HOME/bin:$PATH"; fi
if [[ -d "$HOME/.bin" ]]; then PATH="$HOME/.bin:$PATH"; fi
if [[ -d "$HOME/.local/bin" ]]; then PATH="$HOME/.local/bin:$PATH"; fi
export PATH

export ZSH="$HOME/.config/oh-my-zsh"       # Путь к установке Oh My Zsh
export ZSH_CUSTOM="$ZSH/custom"            # Путь к пользовательской директории Oh My Zsh
export TERM="xterm-256color"               # Устанавливаем тип терминала для лучшей поддержки цветов
# export TERM="screen-256color"             # Альтернативный тип терминала (закомментировано)

have() {
    local utils=("$@")
    for util in "${utils[@]}"; do
        if ! command -v "$util" &> /dev/null; then return 1; fi
    done
    return 0
}

cmd_alias() {
  local cmd="$1"
  shift
  local replacement=( "$@" )
  if alias "$cmd" &> /dev/null; then unalias "$cmd"; fi
  if functions "$cmd" &> /dev/null; then unset -f "$cmd"; fi
  eval "$cmd() { command ${replacement[@]} \"\$@\"; }"
}

# Автоматическая установка фреймворка oh-my-zsh
if [[  ! -d "$ZSH" ]] && have "git"; then
    git clone https://github.com/ohmyzsh/ohmyzsh.git "$ZSH"
fi

# Выбор темы Oh-my-zsh
# Больше тем можно найти здесь: https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
if [[ -n "$DISPLAY" || $(tty) == /dev/pts* ]] && have "curl"; then
    R4VEN_THEME="agnoster-r4ven.zsh-theme"
    if [[ ! -f "${ZSH_CUSTOM}/themes/${R4VEN_THEME}" ]]; then
        curl \
            --fail \
            --location \
            --show-error \
            --output "${ZSH_CUSTOM}"/themes/"${R4VEN_THEME}" \
            https://raw.githubusercontent.com/r4ven-me/zshrc/main/"${R4VEN_THEME}"
    fi
    # DASHES_COLOR=004
    DASHES_COLOR="blue"
    TIMER_FORMAT="%d"
    TIMER_THRESHOLD=0
    ZSH_THEME="${R4VEN_THEME%%.*}"         # Используем эту тему в графическом режиме
    export VIRTUAL_ENV_DISABLE_PROMPT=1    # Отключаем стандартный промпт virtualenv
else
    ZSH_THEME="dpoggi"                     # Используем тему 'noicon' в других случаях, например, в консоли (tty)
fi

# Тема Powerlevel10k (требуется установка)
# https://github.com/romkatv/powerlevel10k
# ZSH_THEME="powerlevel10k/powerlevel10k"

DISABLE_AUTO_UPDATE="true"                  # Отключаем автоматические обновления для Oh My Zsh (команда: omz update)
COMPLETION_WAITING_DOTS="true"              # Показывать точки при автодополнении команд

# Конфигурация истории команд
HIST_STAMPS="yyyy-mm-dd"                    # Добавлять метку времени к истории команд
HISTFILE=~/.zsh_history                     # Файл для сохранения истории
HISTSIZE=10000                              # Максимальное количество записей в истории в памяти
SAVEHIST=10000                              # Максимальное количество записей истории для сохранения в файл
setopt hist_ignore_all_dups                 # Игнорировать дублирующиеся записи в истории
setopt share_history                        # Делиться историей между сессиями
setopt histignorespace                      # Игнорировать команды, начинающиеся с пробела

# Включить режим vi для командной строки (по умолчанию - режим emacs)
# set -o vi

#============================================
#                  ПЛАГИНЫ
#============================================

plugins=(
    fzf                        # Интеграция с Fuzzy finder (Ctrl+r)
    git                        # Алиасы и функции Git
    sudo                       # Запуск/повтор последней команды с sudo (двойной Esc)
    docker                     # Помощник командной строки Docker
    kubectl                    # Помощник командной строки Kubernetes
    # zsh-autopair               # Автоматическое закрытие скобок и кавычек
    zsh-completions            # Дополнительные скрипты автодополнения (Tab)
    zsh-autosuggestions        # Предложения команд на основе истории
    fast-syntax-highlighting   # Подсветка синтаксиса для команд
    history-substring-search   # Поиск в истории по подстроке (стрелки вверх/вниз)
)

# zsh-autopair: отключить этот плагин в MidnightCommander
# if ! [[ $(ps -o comm -h $PPID) =~ "^mc" ]]; then
#     plugins+=(zsh-autopair)
# fi

# Автоматическая установка выбранных плагинов
if [[ -d "$ZSH_CUSTOM" ]] && have "git"; then
    if [[ ! -d "${ZSH_CUSTOM}"/plugins/zsh-autopair ]]; then
        git clone https://github.com/hlissner/zsh-autopair \
            "${ZSH_CUSTOM}"/plugins/zsh-autopair
    fi
    
    if [[ ! -d "${ZSH_CUSTOM}"/plugins/zsh-completions ]]; then
        git clone https://github.com/zsh-users/zsh-completions \
            "${ZSH_CUSTOM}"/plugins/zsh-completions
    fi
    
    if [[ ! -d "${ZSH_CUSTOM}"/plugins/zsh-autosuggestions ]]; then
        git clone https://github.com/zsh-users/zsh-autosuggestions \
            "${ZSH_CUSTOM}"/plugins/zsh-autosuggestions
    fi
    
    if [[ ! -d "${ZSH_CUSTOM}"/plugins/fast-syntax-highlighting ]]; then
        git clone https://github.com/zdharma-continuum/fast-syntax-highlighting \
            "${ZSH_CUSTOM}"/plugins/fast-syntax-highlighting
        
        reset
    fi
fi

#============================================
#              ИНИЦИАЛИЗАЦИЯ OH-MY-ZSH
#============================================

source "${ZSH}"/oh-my-zsh.sh                # Инициализация фреймворка Oh My Zsh

autoload -Uz compinit && compinit           # Инициализация и включение системы автодополнения

if [[ -r "${HOME}"/.profile ]]; then
    source "${HOME}"/.profile               # Загрузить '.profile', если он существует
fi

#============================================
#              ПРИЛОЖЕНИЯ И УТИЛИТЫ
#============================================

# Python
cmd_alias "python" "python3"

# Сеть
cmd_alias "p8" "ping" "-c3" "8.8.8.8"
cmd_alias "ip" "ip" "--color"

# Настройка текстового редактора
if have "nvim"; then
    export EDITOR="$(command -v nvim)"
    export VISUAL="$(command -v nvim)"
    alias vim="nvim"
    alias n="nvim"
    alias N="sudo nvim"
elif have "vim"; then
    export EDITOR="$(command -v vim)"
    export VISUAL="$(command -v vim)"
    alias v="vim"
    alias V="sudo vim"
fi

# Настройка FZF с цветами темы Nord
if have "fzf"; then
    export FZF_DEFAULT_OPTS="--exact"
    export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS'
        --color=fg:#e5e9f0,bg:#2e3440,hl:#81a1c1
        --color=fg+:#e5e9f0,bg+:#2e3440,hl+:#81a1c1
        --color=info:#eacb8a,prompt:#bf6069,pointer:#b48dac
        --color=marker:#a3be8b,spinner:#b48dac,header:#a3be8b
        --color=border:#5e81ac
        --border=rounded
    '
fi

# Определение переменной с именем утилиты: bat или batcat
if have "batcat"; then bat="batcat"; else bat="bat" fi

# Использование bat вместо cat, less, man, --help, tail -f
# Подробнее: https://r4ven.me/bat-exa-config
if have "$bat"; then
    export COLORTERM="truecolor"
    export BAT_THEME="Nord"
    export MANPAGER="sh -c 'col -bx | "$bat" --language=man --style=plain'"  # Команда для просмотра man-страниц
    export MANROFFOPT="-c"  # Отключение переноса строк в man
    cmd_alias "cat" "$bat" "--style=plain" "--paging=never"
    cmd_alias "less" "$bat" "--paging=always"
    if [[ $SHELL == *zsh ]]; then # глобальный алиас "--help" если zsh
        alias -g -- --help='--help 2>&1 | "$bat" --language=help --style=plain'
    fi
    help() { "$@" --help 2>&1 | "$bat" --language=help --style=plain; }
    tailf() { tail -f "$@" | "$bat" --paging=never --language=log; }
    batdiff() { git diff --name-only --relative --diff-filter=d | xargs "$bat" --diff; }
fi

# Использование exa вместо ls
# Подробнее: https://r4ven.me/bat-exa-config
if have "exa"; then
    if [[ -n "$DISPLAY" || $(tty) == /dev/pts* ]]; then # отображать иконки, если псевдотерминал
        cmd_alias "ls" "exa" "--group" "--header" "--icons" "--time-style=long-iso"
    else
        cmd_alias "ls" "exa" "--group" "--header" "--time-style=long-iso"
    fi
    alias l="ls"
    alias ll="ls --long"
    alias lll="ls --long --all"
    alias llll="ls -lbHigUmuSa --sort=modified --time-style=long-iso"
    alias lm="ls --long --all --sort=modified"
    alias lt="ls --tree"
    alias lr="ls --recurse"
    alias lg="ls --long --git --sort=modified"
fi

# Подсветка вывода различных команд
if have "grc" && tty -s && [[ -n "$TERM" && "$TERM" != dumb ]]; then
    GRC_UTILS=(
        configure ping traceroute gcc make netstat stat ss diff
        wdiff last who cvs mount findmnt mtr ps dig ifconfig
        df du env systemctl iptables lspci lsblk lsof blkid
        id iostat sar fdisk free docker journalctl kubectl
        sensors sysctl tail head tcpdump tune2fs lsmod lsattr
        semanage getsebool ulimit vmstat dnf nmap uptime w
        getfacl ntpdate showmount apache iwconfig lolcat whois
        go sockstat
        #ls ip
    )
    for cmd in "${GRC_UTILS[@]}"; do
        if have "$cmd"; then
            cmd_alias "$cmd" "grc" "--stderr" "--stdout" "$cmd"
        fi
    done
fi

# APT
if have "apt"; then
    alias AU="sudo apt update"
    alias AUP="sudo apt upgrade"
    alias AR="sudo apt autoremove"
    alias AI="sudo apt install"
    alias AUI="sudo apt update && sudo apt install"
fi

# Ansible
if have "ansible"; then
    AP() { ansible-playbook ~/ansible/playbooks/"$@"; }
    alias AC="ansible-console"
fi

# Tmux
if have "tmux"; then
    alias T="tmux attach -t Work || tmux new -s Work"
    alias TT="sudo tmux attach -t Work! || sudo tmux new -s Work!"
fi

# ShellGPT 
if have "sgpt"; then
    export LITELLM_LOG="ERROR"
    G() { sgpt --chat temp "$*"; }
    GS() { sgpt --shell "$*"; }
    GC() { 
        echo ""
        sgpt --code --no-md "$*" | "$bat" --language=sh --paging=never --style=plain
        echo ""
    }
    alias GG="sgpt --repl temp"
fi

# Определяет функцию 'cmd', которая выполняет пользовательские команды из списка
# Она принимает один аргумент - имя команды и вставляет её в командную строку
# Используйте клавишу TAB для подсказки
cmd() {
    local cmd_name="${1}"
    typeset -A cmd_list

    # Ассоциативный массив для хранения списка команд
    # Ключи — это имена команд, значения — сами команды
    cmd_list=(
        ps_top5_cpu "ps --sort=-%cpu -eo user,pid,ppid,state,comm | head -n6"
        ps_top5_mem "ps --sort=-%mem -eo user,pid,ppid,state,comm | head -n6"
        ps_zombie "ps -eo user,pid,ppid,state,comm | awk '\$4=="Z" {print \$3}'"
        cron_add_task '{ crontab -l; echo "0 3 * * 0 ls -l &> dirs.txt"; } | crontab -'
        du_top20 'du -x -h / 2> /dev/null | sort -rh | head -n 20'
        df_80 "df -h | awk '\$5 ~ /^8[0-9]%/ {print $6}'"
        git_init 'git init --initial-branch=main && git remote add origin ssh://git@github.com/r4ven-me/reponame.git'
        journal_vacuum 'journalctl --vacuum-size=800M'
        lsof_opened 'lsof +D /opt'
    )

    # Проверяем, существует ли команда в массиве, или если запрошена помощь
    if [[ -z ${cmd_list[$cmd_name]} || -z "$cmd_name" || "$cmd_name" == "-h" ]]; then
        # Отображаем список доступных команд
        echo "ДОСТУПНЫЕ КОМАНДЫ:\n"
        printf "%-20s %s\n" "Ключ" "Команда"
        echo "----------------------------"
        # Перебираем все ключи в массиве и отображаем их
        for key in "${(@k)cmd_list}"; do
            printf "%-20s %s\n" "$key" "${cmd_list[$key]}"
            # echo "------------------"
        done | sort
        return 0
    else
        # Если команда найдена, вставляем её в командную строку
        print -zr "${cmd_list[$cmd_name]}"
        return 0
    fi
}

# Функция для автодополнения команды
_cmd_completion() {
    local -a keys
    keys=($(cmd -h | awk 'NR>4 {print $1}'))  # Извлекаем ключи из вывода справки
    compadd "$@" -- "${keys[@]}"
}

# Регистрируем функцию автодополнения для команды `cmd`
compdef _cmd_completion cmd

#============================================
#                  ПРОМПТ
#============================================

# Удаляем контекст user@host из промпта, когда установлен DISPLAY
if [[ -n "$DISPLAY" && -z "$SSH_CONNECTION" ]]; then
    prompt_context() { }                    # Пустая функция для отключения контекста
fi
Нажмите, чтобы развернуть и увидеть больше

Закрываем/сохраняем и запускаем zsh в текущем сеансе:

PLAINTEXT
exec zsh
Нажмите, чтобы развернуть и увидеть больше

Начнётся процесс скачивания недостающих компонентов в директорию ~/.config/oh-my-zsh:

Если вы в графическом сеансе, у вас будет минималистичный prompt:

В ином случае он будет таким:

Консольный же сеанс будет с использованием темы без иконок:

На данный момент мы просто запустили оболочку zsh в текущем сеансе☝️. Чтобы сделать zsh вашей оболочкой по умолчанию (если это не так) выполните команду:

BASH
[[ $SHELL == *zsh ]] || chsh -s /usr/bin/zsh
Нажмите, чтобы развернуть и увидеть больше

Готово. Для корректного применения изменений рекомендуется выйти из текущего сеанса и зайти заново🚶‍➡️.

Послесловие

В этот раз мы детально рассмотрели, как настроить поведение оболочки ZSH в файле .zshrc при использовании популярного фреймворка oh-my-zsh😌.

На мой взгляд, кастомизация своего рабочего пространства (в т.ч. оболочки) значительно увеличивает эффективность🧑‍💻. Если, конечно, не заниматься этим фанатично😉. Многие игнорируют данный момент, предпочитая дефолтные настройки. Не могу сказать, что это плохо, просто, имея некоторый опыт уяснил для себя: лучше потратить немного (или много) времени на настройку👨‍🔧 и просто пользоваться полученным конфигом везде, где возможно, тем самым решая различные задачи с большим удобством и меньшим количеством нервов😎.

Например, при вводе команды в терминале постоянно забываешь (или не знаешь🤷‍♂️), какие ключи у нее есть и что они делают. Приходится прерывать ввод, чтобы посмотреть справку. В случае моей конфигурации для большинства популярных команд достаточно просто нажать Tab, чтобы увидеть подсказку по ключам, которые еще и можно «протабать»👌. Сюда же относится удобство работы с историей команд и так далее😏.

Полезные материалы

Авторские права

Автор: Иван Чёрный

Ссылка: https://r4ven.me/dots/tonkaya-nastrojka-zshrc-pri-ispolzovanii-oh-my-zsh/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша