arcanis.me/ru/_posts/2014-01-14-about-zshrc.html
2015-10-12 03:13:25 +03:00

560 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
category: ru
type: paper
hastr: true
layout: paper
tags: zshrc, настройка, linux
title: О zshrc
short: about-zshrc
description: Это моя первая статья в блоге (я думаю, мне нужно что-нибудь для тестов =)). Существует множество похожих статей и, я думаю, не буду отличаться от большинства. Я просто хочу показать мой <code>.zshrc</code> и объяснить, что в нем есть и зачем оно нужно. Также, любые комментарии или дополнения приветствуются. <a href="//archlinux.org.ru/forum/topic/12752/" title="Тема на форуме">Оригинал</a> статьи.
---
<h2><a href="#prepare" class="anchor" id="prepare"><span class="octicon octicon-link"></span></a>Подготовка</h2>
<p>Сначала установите необходимый минимум:</p>
{% highlight bash %}
pacman -Sy pkgfile zsh zsh-completions zsh-syntax-highlighting
{% endhighlight %}
<p><a href="//www.archlinux.org/packages/pkgfile/" title="Пакет Archlinux">pkgfile</a> очень полезная утилита. Данная команда также установит шелл, дополнения к нему и подсветку синтаксиса.</p>
<h2><a href="#configuration" class="anchor" id="configuration"><span class="octicon octicon-link"></span></a>Настройка шелла</h2>
<p>Все доступные опции приведены <a href="//zsh.sourceforge.net/Doc/Release/Options.html" title="Документация zsh">здесь</a>.</p>
<p>Указываем файл с историей, число команд хранящихся в кэше текущего сеанса и число команд, хранящихся в файле:</p>
{% highlight bash %}
# history
HISTFILE=~/.zsh_history
HISTSIZE=500000
SAVEHIST=500000
{% endhighlight %}
<p>Я не могу запомнить все комбинации <code>Ctrl+</code>, поэтому я назначаю клавиши на их стандартное использование:</p>
{% highlight bash %}
# bindkeys
bindkey '^[[A' up-line-or-search # up arrow for back-history-search
bindkey '^[[B' down-line-or-search # down arrow for fwd-history-search
bindkey '\e[1~' beginning-of-line # home
bindkey '\e[2~' overwrite-mode # insert
bindkey '\e[3~' delete-char # del
bindkey '\e[4~' end-of-line # end
bindkey '\e[5~' up-line-or-history # page-up
bindkey '\e[6~' down-line-or-history # page-down
{% endhighlight %}
<p>Но здесь важно, что стрелки <code>вверх</code>/<code>вниз</code> служат для навигации по истории с учетом <b>уже введенной части</b> команды. А <code>PgUp</code>/<code>PgDown</code> <b>проигнорируют</b> уже введенную часть команды.</p>
<p>Автодополнение команд:</p>
{% highlight bash %}
# autocomplete
autoload -U compinit
compinit
zstyle ':completion:*' insert-tab false
zstyle ':completion:*' max-errors 2
{% endhighlight %}
<p>Подключается полное автодополнение команд. <code>insert-tab false</code> включит автодополнение для <b>невведенной</b> команды (не знаю, зачем). <code>max-errors</code> устанавливает максимальное число опечаток, которые могут быть исправлены.</p>
<p>Приглашение:</p>
{% highlight bash %}
# promptinit
autoload -U promptinit
promptinit
{% endhighlight %}
<p>Включим цвета:</p>
{% highlight bash %}
# colors
autoload -U colors
colors
{% endhighlight %}
<p>Различные опции.</p>
<p>Смена директории без ввода <code>cd</code>:</p>
{% highlight bash %}
# autocd
setopt autocd
{% endhighlight %}
<p>Корректировка опечаток (и шаблон вопроса):</p>
{% highlight bash %}
# correct
setopt CORRECT_ALL
SPROMPT="Correct '%R' to '%r' ? ([Y]es/[N]o/[E]dit/[A]bort) "
{% endhighlight %}
<p>Отключаем е#$%ую пищалку:</p>
{% highlight bash %}
# disable beeps
unsetopt beep
{% endhighlight %}
<p>Включаем калькулятор:</p>
{% highlight bash %}
# calc
autoload zcalc
{% endhighlight %}
<p>Дополнение истории (<b>а не перезапись</b> файла):</p>
{% highlight bash %}
# append history
setopt APPEND_HISTORY
{% endhighlight %}
<p>Не сохранять дубликаты в историю:</p>
{% highlight bash %}
# ignore dups in history
setopt HIST_IGNORE_ALL_DUPS
{% endhighlight %}
<p>...и дополнительные пробелы:</p>
{% highlight bash %}
# ignore spaces in history
setopt HIST_IGNORE_SPACE
{% endhighlight %}
<p>...и пустые линии тоже:</p>
{% highlight bash %}
# reduce blanks in history
setopt HIST_REDUCE_BLANKS
{% endhighlight %}
<p>Включаем <code>pkgfile</code>:</p>
{% highlight bash %}
# pkgfile
source /usr/share/doc/pkgfile/command-not-found.zsh
{% endhighlight %}
<h2><a href="#highlighting" class="anchor" id="highlighting"><span class="octicon octicon-link"></span></a>Подсветка синтаксиса</h2>
{% highlight bash %}
# highlighting
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern)
# brackets
ZSH_HIGHLIGHT_STYLES[bracket-level-1]='fg=blue,bold'
ZSH_HIGHLIGHT_STYLES[bracket-level-2]='fg=red,bold'
ZSH_HIGHLIGHT_STYLES[bracket-level-3]='fg=yellow,bold'
ZSH_HIGHLIGHT_STYLES[bracket-level-4]='fg=magenta,bold'
# cursor
#ZSH_HIGHLIGHT_STYLES[cursor]='bg=blue'
# main
# default
ZSH_HIGHLIGHT_STYLES[default]='none' # стандартный цвет
# unknown
ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=red' # неизвестная команда
# command
ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=magenta,bold' # зарезервированное слово
ZSH_HIGHLIGHT_STYLES[alias]='fg=yellow,bold' # алиас
ZSH_HIGHLIGHT_STYLES[builtin]='fg=green,bold' # built-in функция (например, echo)
ZSH_HIGHLIGHT_STYLES[function]='fg=green,bold' # функция, определенная в шелле
ZSH_HIGHLIGHT_STYLES[command]='fg=green' # обычная команда
ZSH_HIGHLIGHT_STYLES[precommand]='fg=blue,bold' # пре-команда (например, sudo в sudo cp ...)
ZSH_HIGHLIGHT_STYLES[commandseparator]='fg=yellow' # разделитель команд, && || ;
ZSH_HIGHLIGHT_STYLES[hashed-command]='fg=green' # команда, найденная в путях (hashed)
ZSH_HIGHLIGHT_STYLES[single-hyphen-option]='fg=blue,bold' # флаги типа -*
ZSH_HIGHLIGHT_STYLES[double-hyphen-option]='fg=blue,bold' # флаги типа --*
# path
ZSH_HIGHLIGHT_STYLES[path]='fg=cyan,bold' # станлартный путь
ZSH_HIGHLIGHT_STYLES[path_prefix]='fg=cyan' # префикс пути
ZSH_HIGHLIGHT_STYLES[path_approx]='fg=cyan' # примерный путь
# shell
ZSH_HIGHLIGHT_STYLES[globbing]='fg=cyan' # шаблон (например, /dev/sda*)
ZSH_HIGHLIGHT_STYLES[history-expansion]='fg=blue' # подстановка из истории (команда, начинающаяся с !)
ZSH_HIGHLIGHT_STYLES[assign]='fg=magenta' # присвоение
ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]='fg=cyan' # конструкции типа "$VARIABLE"
ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]='fg=cyan' # конструкции типа \"
ZSH_HIGHLIGHT_STYLES[back-quoted-argument]='fg=blue' # конструкции типа `command`
# quotes
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=yellow,underline' # конструкции типа 'text'
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=yellow' # конструкции типа "text"
# pattern
#ZSH_HIGHLIGHT_PATTERNS+=('rm -rf *' 'fg=white,bold,bg=red')
# root
#ZSH_HIGHLIGHT_STYLES[root]='bg=red'
{% endhighlight %}
<p>В первой строке включаем подсветку. Затем включаем основную подсветку, а также подсветку скобок и шаблонов. Шаблоны указываются ниже (<code>rm -rf *</code> в примере). Также может быть включена подсветка команд от <code>root</code> и курсора <code>cursor</code>. Синтаксис настроек понятен, <code>fg</code> цвет шрифта, <code>bg</code> цвет фона.</p>
<h2><a href="#prompt" class="anchor" id="prompt"><span class="octicon octicon-link"></span></a>$PROMPT и $RPROMPT</h2>
<p>Я хочу использовать один файл <code>.zshrc</code> для рута и обычного пользователя:</p>
{% highlight bash %}
# PROMPT && RPROMPT
if [[ $EUID == 0 ]]; then
# [root@host dir]#
PROMPT="%{$fg_bold[white]%}[%{$reset_color%}\
%{$fg_bold[red]%}%n%{$reset_color%}\
%{$fg_bold[white]%}@%{$reset_color%}\
%{$fg_no_bold[red]%}%m %{$reset_color%}\
%{$fg_bold[yellow]%}%1/%{$reset_color%}\
%{$fg_bold[white]%}]# %{$reset_color%}"
else
# [user@host dir]$
PROMPT="%{$fg_bold[white]%}[%{$reset_color%}\
%{$fg_bold[green]%}%n%{$reset_color%}\
%{$fg_bold[white]%}@%{$reset_color%}\
%{$fg_no_bold[green]%}%m %{$reset_color%}\
%{$fg_bold[yellow]%}%1/%{$reset_color%}\
%{$fg_bold[white]%}]$ %{$reset_color%}"
fi
{% endhighlight %}
<p><code>fg</code> цвет шрифта, <code>bg</code> цвет фона. <code>_bold</code> и <code>_no_bold</code> регулируют оттенок. Команды должны быть обрамлены в <code>%{ ... %}</code>, чтобы не показывались. Доступные цвета:</p>
{% highlight bash %}
black
red
green
yellow
blue
magenta
cyan
white
{% endhighlight %}
<p>Доступные переменные:</p>
{% highlight bash %}
%n - имя пользователя
%m - хостнейм (выставляется только в начале сессии)
%M - хостнейм
%l - текущая tty
%? - код возврата предыдущего приложения
%# - # для рута и % для обычных пользователей
%T - время (HH:MM)
%* - время (HH:MM:SS)
%D - дата (YY-MM-DD)
%d - текущая директория
%~ - то же, домашняя директория будет заменена на ~
%1/ - то же, но только последняя директория
{% endhighlight %}
<p>RPROMPT (необходим пакет <code>acpi</code>):</p>
{% highlight bash %}
precmd () {
# battery charge
function batcharge {
bat_perc=`acpi | awk {'print $4;'} | sed -e "s/\s//" -e "s/%.*//"`
if [[ $bat_perc < 15 ]]; then
col="%{$fg_bold[red]%}"
elif [[ $bat_perc < 50 ]]; then
col="%{$fg_bold[yellow]%}"
else
col="%{$fg_bold[green]%}"
fi
echo "%{$fg_bold[white]%}["$col$bat_perc"%{$fg_bold[white]%}%%]%{$reset_color%}"
}
# last command
returncode="%(?.%{$fg[green]%}.%{$fg[red]%})%?%{$resetcolor%}"
RPROMPT="%{$fg_bold[white]%}[%{$reset_color%}\
%{$fg_bold[cyan]%}%T%{$reset_color%}\
%{$fg_bold[white]%}] %{$reset_color%}"\
$(batcharge)\
"%{$fg_bold[white]%}[%{$reset_color%}"\
$returncode\
"%{$fg_bold[white]%}]%{$reset_color%}"
{% endhighlight %}
<p>Мой RPROMPT показывает текущее время, заряд батареи и код возврата последнего приложения. <code>precmd()</code> необходимо для автоматического обновления. Конструкция <code>$(if.true.false)</code> является условным оператором в <code>zsh</code>.</p>
<h2><a href="#aliases" class="anchor" id="aliases"><span class="octicon octicon-link"></span></a>Аллиасы</h2>
<p><b>Копируйте только те аллиасы, которые Вам необходимы.</b> Если какой-либо аллиас использует приложение, которое не установлено, это приведет к сбою загрузки конфигурационного файла.</p>
<p>Полезная (или не очень) функция:</p>
{% highlight bash %}
show_which() {
OUTPUT=$(which $1 | cut -d " " -f7-)
echo "Running '$OUTPUT'" 1>&2
}
{% endhighlight %}
<p>Первая группа аллиасов:</p>
{% highlight bash %}
## alias
# цветной grep
alias grep='grep --colour=auto'
# замена top на htop
alias top='show_which top && htop'
# chromium с различными прокси серверами (i2p и tor в наличии)
alias chrommsu='show_which chrommsu && chromium --proxy-server=cache.msu:3128'
alias chromtor='show_which chromtor && chromium --proxy-server="socks://localhost:9050" --incognito'
alias chromi2p='show_which chromi2p && chromium --proxy-server="http=127.0.0.1:4444;https=127.0.0.1:4445" --incognito'
# человеческие df и du
alias df='show_which df && df -k --print-type --human-readable'
alias du='show_which du && du -k --total --human-readable'
# замена less и zless на vimpager
alias less='vimpager'
alias zless='vimpager'
{% endhighlight %}
<p>ls аллиасы (смотри <a href="//unixhelp.ed.ac.uk/CGI/man-cgi?ls" title="Мануал">man ls</a>):</p>
{% highlight bash %}
alias ls='show_which ls && ls --color=auto --group-directories-first'
alias ll='show_which ll && ls -l --human-readable'
alias lr='show_which lr && ls --recursive'
alias la='show_which la && ll --almost-all'
alias lx='show_which lx && ll -X --ignore-backups'
alias lz='show_which lz && ll -S --reverse'
alias lt='show_which lt && ll -t --reverse'
alias lm='show_which lm && la | more'
{% endhighlight %}
<p>Аллиасы для быстрого просмотра файлов из консоли (просто набери имя файла!):</p>
{% highlight bash %}
# alias -s
alias -s {avi,mpeg,mpg,mov,m2v,mkv}=mpv
alias -s {mp3,flac}=qmmp
alias -s {odt,doc,xls,ppt,docx,xlsx,pptx,csv}=libreoffice
alias -s {pdf}=okular
autoload -U pick-web-browser
alias -s {html,htm}=opera
{% endhighlight %}
<p>"sudo" аллиасы:</p>
{% highlight bash %}
# sudo alias
if [[ $EUID == 0 ]]; then
alias fat32mnt='show_which fat32mnt && mount -t vfat -o codepage=866,iocharset=utf8,umask=000'
alias synctime='show_which synctime && { ntpd -qg; hwclock -w; date; }'
else
alias fat32mnt='show_which fat32mnt && sudo mount -t vfat -o codepage=866,iocharset=utf8,umask=000'
alias umount='show_which umount && sudo umount'
alias mount='show_which mount && sudo mount'
alias netctl='show_which netctl && sudo netctl'
alias synctime='show_which synctime && { sudo ntpd -qg; sudo hwclock -w; date; }'
alias wifi-menu='show_which wifi-menu && sudo wifi-menu'
alias dhcpcd='show_which dhcpcd && sudo dhcpcd'
alias journalctl='show_which journalctl && sudo journalctl'
alias systemctl='show_which systemctl && sudo systemctl'
alias modprobe='show_which modprobe && sudo modprobe'
alias rmmod='show_which rmmod && sudo rmmod'
alias staging-i686-build='show_which staging-i686-build && sudo staging-i686-build'
alias staging-x86_64-build='show_which staging-x86_64-build && sudo staging-x86_64-build'
fi
{% endhighlight %}
<p>Некоторые глобальные аллиасы. Если они включены, команда <code>cat foo g bar</code> будет эквивалентна <code>cat foo | grep bar</code>:</p>
{% highlight bash %}
# global alias
alias -g g="| grep"
alias -g l="| less"
alias -g t="| tail"
alias -g h="| head"
alias -g dn="&> /dev/null &"
{% endhighlight %}
<h2><a href="#functions" class="anchor" id="functions"><span class="octicon octicon-link"></span></a>Функции</h2>
<p>Специальная функция для <code>xrandr</code>:</p>
{% highlight bash %}
# function to contorl xrandr
# EXAMPLE: projctl 1024x768
projctl () {
if [ $1 ] ; then
if [ $1 = "-h" ]; then
echo "Usage: projctl [ off/resolution ]"
return
fi
if [ $1 = "off" ]; then
echo "Disable VGA1"
xrandr --output VGA1 --off --output LVDS1 --mode 1366x768
else
echo "Using resolution: $1"
xrandr --output VGA1 --mode $1 --output LVDS1 --mode $1
fi
else
echo "Using default resolution"
xrandr --output VGA1 --mode 1366x768 --output LVDS1 --mode 1366x768
fi
}
{% endhighlight %}
<p>К сожалению, я не могу запомнить флаги <code>tar</code>, поэтому я использую специальные функции:</p>
{% highlight bash %}
# function to extract archives
# EXAMPLE: unpack file
unpack () {
if [[ -f $1 ]]; then
case $1 in
*.tar.bz2) tar xjfv $1 ;;
*.tar.gz) tar xzfv $1 ;;
*.tar.xz) tar xvJf $1 ;;
*.bz2) bunzip2 $1 ;;
*.gz) gunzip $1 ;;
*.rar) unrar x $1 ;;
*.tar) tar xf $1 ;;
*.tbz) tar xjvf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "I don't know how to extract '$1'" ;;
esac
else
case $1 in
*help) echo "Usage: unpack ARCHIVE_NAME" ;;
*) echo "'$1' is not a valid file" ;;
esac
fi
}
# function to create archives
# EXAMPLE: pack tar file
pack () {
if [ $1 ]; then
case $1 in
tar.bz2) tar -cjvf $2.tar.bz2 $2 ;;
tar.gz) tar -czvf $2.tar.bz2 $2 ;;
tar.xz) tar -cf - $2 | xz -9 -c - > $2.tar.xz ;;
bz2) bzip $2 ;;
gz) gzip -c -9 -n $2 > $2.gz ;;
tar) tar cpvf $2.tar $2 ;;
tbz) tar cjvf $2.tar.bz2 $2 ;;
tgz) tar czvf $2.tar.gz $2 ;;
zip) zip -r $2.zip $2 ;;
7z) 7z a $2.7z $2 ;;
*help) echo "Usage: pack TYPE FILES" ;;
*) echo "'$1' cannot be packed via pack()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
{% endhighlight %}
<p>Специальная функция для <code>su</code>:</p>
{% highlight bash %}
su () {
CHECKSU=0
for FLAG in $*; do
[[ $FLAG == "-" ]] && CHECKSU=1
[[ $FLAG == "-l" ]] && CHECKSU=1
[[ $FLAG == "--login" ]] && CHECKSU=1
done
if [[ $CHECKSU == 0 ]]; then
echo "Use 'su -', Luke"
/usr/bin/su - $*
else
/usr/bin/su $*
fi
}
{% endhighlight %}
<p>Функция, которая заменяет оригиналькую команду <code>rm</code>. Если Вы наберете <code>rm</code>, это будет эквивалентно перемещению в корзину, также, Вы можете легко восстановить удаленный файл:</p>
{% highlight bash %}
rm () {
# error check
[ $# -eq 0 ] && { echo "Files are not set!"; return 1 }
echo "$@" | grep -qe '-h\|--help' && { echo "Usage: rm FILE..."; return 0 }
echo "$@" | grep -q "-" && echo "Warning: this function doesn't support any flags"
# set trash path
TRASHDIR="$HOME/.local/share/Trash"
TRASHFILE="${TRASHDIR}/files"
TRASHINFO="${TRASHDIR}/info"
for DIRECTORY in "${TRASHDIR}" "${TRASHFILE}" "${TRASHINFO}"; do
if [ -e "${DIRECTORY}" ]; then
[ -d "${DIRECTORY}" ] || { echo "'${DIRECTORY}' is a file"; return 1 }
else
mkdir -p -m755 "${DIRECTORY}"
fi
done
# confirm
CONFIRM=""
echo -n "You realy want to remove '$@'? [y/n] "; read -k1 CONFIRM; echo
[[ ! $CONFIRM =~ [yY] ]] && return 1
# move
for FILE in "$@"; do
DESTFILE="$(basename -- "${FILE}")"
SUFFIX='';
ITER=0;
while [ -e "${TRASHFILE}/${DESTFILE}${SUFFIX}" ]; do
SUFFIX="_${ITER}";
ITER=$(expr ${ITER} + 1)
done
echo "Remove '${FILE}'"
if [ "$(dirname -- "$(realpath -- "${FILE}")")" == "${TRASHFILE}" ]; then
/usr/bin/rm -rf -- "${FILE}"
/usr/bin/rm -rf -- "${TRASHINFO}/${DESTFILE}.trashinfo"
else
mv -- "${FILE}" "${TRASHFILE}/${DESTFILE}${SUFFIX}" || return 1
echo "[Trash Info]\nPath=$(realpath -- "${FILE}")\nDeletionDate=$(date +%Y-%m-%dT%H:%M:%S)" > "${TRASHINFO}/${DESTFILE}${SUFFIX}.trashinfo" || return 1
fi
done
}
{% endhighlight %}
<p>Функция для автоматических обновлений путей после установки пакетов:</p>
{% highlight bash %}
pacman () {
/usr/bin/sudo /usr/bin/pacman $* && echo "$*" | grep -q "S\|R\|U" && rehash
}
yaourt () {
/usr/bin/yaourt $* && echo "$*" | grep -q "S\|R\|U" && rehash
}
# for testing repo
yatest () {
/usr/bin/yaourt --config /etc/pactest.conf $* && echo "$*" | grep -q "S\|R\|U" && rehash
}
{% endhighlight %}
<h2><a href="#variables" class="anchor" id="variables"><span class="octicon octicon-link"></span></a>Переменные</h2>
<p>Рекомендуется хранить свои переменные в <code>~/.zshenv</code>. Но я все храню в одном файле.</p>
<p>Пути, маска создаваемых файлов, редактор и пейджер:</p>
{% highlight bash %}
# path
export PATH="$PATH:$HOME/.local/bin"
# umask
umask 022
# editor
export EDITOR="vim"
export PAGER="vimpager"
{% endhighlight %}
<p>Хэши. Если они включены, команда <code>~global</code> будет эквивалентна команде <code>/mnt/global</code>:</p>
{% highlight bash %}
# hash
hash -d global=/mnt/global
hash -d windows=/mnt/windows
hash -d iso=/mnt/iso
hash -d u1=/mnt/usbdev1
hash -d u2=/mnt/usbdev2
{% endhighlight %}
<h2><a href="#screenshot" class="anchor" id="screenshot"><span class="octicon octicon-link"></span></a>Скриншот</h2>
<div class="thumbnails">
{% assign scrdesc = "Как оно выглядит" %}
{% assign scrname = "zshrc_demo" %}
{% include prj_scr.html %}
</div>
<h2><a href="#file" class="anchor" id="file"><span class="octicon octicon-link"></span></a>Файл</h2>
<p><a href="//raw.github.com/arcan1s/dotfiles/master/zshrc" title="Github" type="text/plain">Мой</a> <code>.zshrc</code>.</p>