do ... while
и if ... else
там для создания его так, чтобы точка с запятой после макроса всегда означала то же самое. Скажем, у Вас было что-то как Ваш второй макрос.
#define BAR(X) f(x); g(x)
Теперь, если необходимо было использовать BAR(X);
в if ... else
оператор, где тела, если бы оператор не был обернут в фигурные скобки, Вы получили бы плохое удивление.
if (corge)
BAR(corge);
else
gralt();
вышеупомянутый код расширился бы в [1 124]
if (corge)
f(corge); g(corge);
else
gralt();
, который является синтаксически неправильным, поскольку еще больше не связывается с если. Это не помогает обернуть вещи в фигурные скобки в рамках макроса, потому что точка с запятой после фигурных скобок является синтаксически неправильной.
if (corge)
{f(corge); g(corge);};
else
gralt();
существует два способа решить проблему. Первое должно использовать запятую для упорядочивания операторов в рамках макроса, не отнимая у него его способность действовать как выражение.
#define BAR(X) f(X), g(X)
вышеупомянутая версия панели BAR
разворачивает вышеупомянутый код в то, что следует, который синтаксически корректен.
if (corge)
f(corge), g(corge);
else
gralt();
Это не работает, если вместо [1 113] у Вас более сложное тело кода, который должен войти в его собственный блок, сказать, например, для объявления локальных переменных. В наиболее общем случае решение состоит в том, чтобы использовать что-то как [1 114], чтобы заставить макрос быть отдельным оператором, который берет точку с запятой без беспорядка.
#define BAR(X) do { \
int i = f(X); \
if (i > 4) g(i); \
} while (0)
Вы не должны использовать do ... while
, Вы могли приготовить что-то с [1 116] также, хотя, когда if ... else
расширяется в if ... else
, это еще приводит к" свисание ", который еще мог сделать существующее свисание проблемой еще тяжелее для нахождения, как в следующем коде.
if (corge)
if (1) { f(corge); g(corge); } else;
else
gralt();
точка должна израсходовать точку с запятой в контекстах, где повисшая точка с запятой ошибочна. Конечно, это могло (и вероятно должен), будьте обсуждены в этой точке, которую было бы лучше объявить BAR
как фактическая функция, не макрос.
, Таким образом, эти do ... while
там для работы вокруг недостатков препроцессора C. Когда те руководства по стилю C говорят Вам откладывать препроцессор C, это - вид вещи, по поводу которой они волнуются.
__ git_ps1
взято из git-completion.bash. В zsh вам, вероятно, придется предоставить свою собственную функцию для определения ветки git текущих каталогов. В блоге довольно много сообщений о приглашении git для zsh.
Вам просто нужно:
Например
git_prompt() {
ref=$(git symbolic-ref HEAD | cut -d'/' -f3)
echo $ref
}
setopt prompt_subst
PS1=$(git_prompt)%#
autoload -U promptinit
promptinit
Обновление: используйте модуль zsh vcs_info вместо git_prompt ()
setopt prompt_subst
autoload -Uz vcs_info
zstyle ':vcs_info:*' actionformats \
'%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{3}|%F{1}%a%F{5}]%f '
zstyle ':vcs_info:*' formats \
'%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{5}]%f '
zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{3}%r'
zstyle ':vcs_info:*' enable git cvs svn
# or use pre_cmd, see man zshcontrib
vcs_info_wrapper() {
vcs_info
if [ -n "$vcs_info_msg_0_" ]; then
echo "%{$fg[grey]%}${vcs_info_msg_0_}%{$reset_color%}$del"
fi
}
RPROMPT=$'$(vcs_info_wrapper)'
Спасибо за ссылки!
Я сделал на их основе следующую подсказку
# get the name of the branch we are on
git_prompt_info() {
git branch | awk '/^\*/ { print $2 }'
}
get_git_dirty() {
git diff --quiet || echo '*'
}
autoload -U colors
colors
setopt prompt_subst
PROMPT='%{$fg[blue]%}%c %{$fg_bold[red]%}$(git_prompt_info)$(get_git_dirty)%{$fg[blue]%} $ %{$reset_color%}'
RPROMPT='%{$fg[green]%}%1(j.%j.)'
Пожалуйста, предложите какие-либо улучшения.
Вот расширенная подсказка git для zsh: zsh-git-prompt.