1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-06-03 13:56:03 +02:00

Seth House, Simon Ruderich and myself: 27948: various vcs_info changes

Here's a diff-stat:

 Doc/Zsh/contrib.yo                                |  506 ++++++++++++++-------
 Functions/VCS_Info/.distfiles                     |    1 +
 Functions/VCS_Info/Backends/VCS_INFO_detect_hg    |   14 +-
 Functions/VCS_Info/Backends/VCS_INFO_get_data_git |   35 +-
 Functions/VCS_Info/Backends/VCS_INFO_get_data_hg  |  295 +++++++++----
 Functions/VCS_Info/VCS_INFO_formats               |   26 +-
 Functions/VCS_Info/VCS_INFO_hook                  |   10 +-
 Functions/VCS_Info/VCS_INFO_quilt                 |  190 ++++++++
 Functions/VCS_Info/vcs_info                       |   30 +-
 Misc/.distfiles                                   |    1 +
 Misc/vcs_info-examples                            |  496 ++++++++++++++++++++
 11 files changed, 1303 insertions(+), 301 deletions(-)

The major changes are vast improvements for the mercurial (hg) backend
(which was done almost entirely by Seth); improved documentation (mostly
done by Simon and again Seth); quilt support (as an addon and stand
alone, see the manual for details); a number of new hooks and a fair
share of bugfixes.
This commit is contained in:
Frank Terbeck 2010-05-10 10:46:48 +00:00
parent 144a06bf95
commit 0501efc54a
12 changed files with 1326 additions and 312 deletions

View File

@ -1,3 +1,15 @@
2010-05-10 Frank Terbeck <ft@bewatermyfriend.org>
* Seth House, Simon Ruderich and myself: 27948:
Doc/Zsh/contrib.yo, Functions/VCS_Info/.distfiles, Misc/.distfiles,
Misc/vcs_info-examples, Functions/VCS_Info/Backends/VCS_INFO_detect_hg,
Functions/VCS_Info/Backends/VCS_INFO_get_data_git,
Functions/VCS_Info/Backends/VCS_INFO_get_data_hg,
Functions/VCS_Info/VCS_INFO_formats, Functions/VCS_Info/VCS_INFO_hook,
Functions/VCS_Info/VCS_INFO_quilt, Functions/VCS_Info/vcs_info: various
vcs_info changes: mercurial backend improvements, new hooks, quilt
support, documentation improvements and bugfixes
2010-05-05 Peter Stephenson <pws@csr.com> 2010-05-05 Peter Stephenson <pws@csr.com>
* users/15031: Completion/Unix/Type/_path_files: fix (still * users/15031: Completion/Unix/Type/_path_files: fix (still
@ -13105,5 +13117,5 @@
***************************************************** *****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL * This is used by the shell to define $ZSH_PATCHLEVEL
* $Revision: 1.4973 $ * $Revision: 1.4974 $
***************************************************** *****************************************************

View File

@ -334,16 +334,20 @@ startsitem()
sitem(Bazaar (tt(bzr)))(http://bazaar-vcs.org/) sitem(Bazaar (tt(bzr)))(http://bazaar-vcs.org/)
sitem(Codeville (tt(cdv)))(http://codeville.org/) sitem(Codeville (tt(cdv)))(http://codeville.org/)
sitem(Concurrent Versioning System (tt(cvs)))(http://www.nongnu.org/cvs/) sitem(Concurrent Versioning System (tt(cvs)))(http://www.nongnu.org/cvs/)
sitem(tt(darcs))(http://darcs.net/) sitem(Darcs (tt(darcs)))(http://darcs.net/)
sitem(tt(git))(http://git.or.cz/) sitem(Git (tt(git)))(http://git-scm.com/)
sitem(GNU arch (tt(tla)))(http://www.gnu.org/software/gnu-arch/) sitem(GNU arch (tt(tla)))(http://www.gnu.org/software/gnu-arch/)
sitem(Mercurial (tt(hg)))(http://selenic.com/mercurial/) sitem(Mercurial (tt(hg)))(http://mercurial.selenic.com/)
sitem(Monotone (tt(mtn)))(http://monotone.ca/) sitem(Monotone (tt(mtn)))(http://monotone.ca/)
sitem(Perforce (tt(p4)))(http://www.perforce.com/) sitem(Perforce (tt(p4)))(http://www.perforce.com/)
sitem(Subversion (tt(svn)))(http://subversion.tigris.org/) sitem(Subversion (tt(svn)))(http://subversion.tigris.org/)
sitem(SVK (tt(svk)))(http://svk.bestpractical.com/) sitem(SVK (tt(svk)))(http://svk.bestpractical.com/)
endsitem() endsitem()
There is also support for the patch management system tt(quilt)
(http://savannah.nongnu.org/projects/quilt). See tt(Quilt Support)
below for details.
To load var(vcs_info): To load var(vcs_info):
example(autoload -Uz vcs_info) example(autoload -Uz vcs_info)
@ -364,7 +368,7 @@ zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{3}%r'
precmd () { vcs_info } precmd () { vcs_info }
PS1='%F{5}[%F{2}%n%F{5}] %F{3}%3~ ${vcs_info_msg_0_}%f%# ') PS1='%F{5}[%F{2}%n%F{5}] %F{3}%3~ ${vcs_info_msg_0_}%f%# ')
Obviously, the last two lines are there for demonstration: You need to Obviously, the last two lines are there for demonstration. You need to
call var(vcs_info) from your var(precmd) function. Once that is done you need call var(vcs_info) from your var(precmd) function. Once that is done you need
a tt(single quoted) var('${vcs_info_msg_0_}') in your prompt. a tt(single quoted) var('${vcs_info_msg_0_}') in your prompt.
@ -391,7 +395,10 @@ tla
## are enabled and disabled with their master [git-svn -> git]) ## are enabled and disabled with their master [git-svn -> git])
## they *can* be used in contexts: ':vcs_info:git-svn:*'. ## they *can* be used in contexts: ':vcs_info:git-svn:*'.
git-p4 git-p4
git-svn) git-svn
hg-git
hg-hgsubversion
hg-hgsvn)
You may not want all of these because there is no point in running the You may not want all of these because there is no point in running the
code to detect systems you do not use. So there is a way to disable code to detect systems you do not use. So there is a way to disable
@ -409,6 +416,7 @@ var(enable) style - if you used that) marked as disabled by a hash sign.
That means the detection of these systems is skipped tt(completely). No That means the detection of these systems is skipped tt(completely). No
wasted time there. wasted time there.
subsect(Configuration) subsect(Configuration)
The var(vcs_info) feature can be configured via var(zstyle). The var(vcs_info) feature can be configured via var(zstyle).
@ -418,9 +426,9 @@ example(:vcs_info:<vcs-string>:<user-context>:<repo-root-name>)
startitem() startitem()
item(tt(<vcs-string>))( item(tt(<vcs-string>))(
is one of: git, git-svn, git-p4, hg, darcs, bzr, is one of: git, git-svn, git-p4, hg, hg-git, hg-hgsubversion, hg-hgsvn,
cdv, mtn, svn, cvs, svk, tla or p4. When hooks are active the hooks name darcs, bzr, cdv, mtn, svn, cvs, svk, tla or p4. When hooks are active the
is added after a `+'. (See tt(Hooks in vcs_info) below.) hooks name is added after a `+'. (See tt(Hooks in vcs_info) below.)
) )
item(tt(<user-context>))( item(tt(<user-context>))(
is a freely configurable string, assignable by is a freely configurable string, assignable by
@ -430,13 +438,13 @@ below).
item(tt(<repo-root-name>))( item(tt(<repo-root-name>))(
is the name of a repository in which you want a is the name of a repository in which you want a
style to match. So, if you want a setting specific to var(/usr/src/zsh), style to match. So, if you want a setting specific to var(/usr/src/zsh),
with that being a cvs checkout, you can set tt(<repo-root-name>) to with that being a CVS checkout, you can set tt(<repo-root-name>) to
var(zsh) to make it so. var(zsh) to make it so.
) )
enditem() enditem()
There are three special values for tt(<vcs-string>): The first is named There are three special values for tt(<vcs-string>): The first is named
var(-init-), that is in effect as long as there was no decision what vcs var(-init-), that is in effect as long as there was no decision what VCS
backend to use. The second is var(-preinit-); it is used tt(before) backend to use. The second is var(-preinit-); it is used tt(before)
var(vcs_info) is run, when initializing the data exporting variables. The var(vcs_info) is run, when initializing the data exporting variables. The
third special value is var(formats) and is used by the tt(vcs_info_lastmsg) third special value is var(formats) and is used by the tt(vcs_info_lastmsg)
@ -469,36 +477,28 @@ A list of formats, used when actionformats is not used
kindex(actionformats) kindex(actionformats)
item(tt(actionformats))( item(tt(actionformats))(
A list of formats, used if a there is a special A list of formats, used if a there is a special
action going on in your current repository; (like an interactive rebase or action going on in your current repository; like an interactive rebase or
a merge conflict). a merge conflict.
) )
kindex(branchformat) kindex(branchformat)
item(tt(branchformat))( item(tt(branchformat))(
Some backends replace var(%b) in the formats and Some backends replace var(%b) in the formats and
actionformats styles above, not only by a branch name but also by a actionformats styles above, not only by a branch name but also by a
revision number. This style lets you modify how that string should look revision number. This style lets you modify how that string should look.
like.
) )
kindex(nvcsformats) kindex(nvcsformats)
item(tt(nvcsformats))( item(tt(nvcsformats))(
These "formats" are exported, when we didn't detect These "formats" are exported when we didn't detect
a version control system for the current directory. This is useful, if you a version control system for the current directory. This is useful if you
want var(vcs_info) to completely take over the generation of your prompt. want var(vcs_info) to completely take over the generation of your prompt.
You would do something like tt(PS1='${vcs_info_msg_0_}') to accomplish You would do something like tt(PS1='${vcs_info_msg_0_}') to accomplish
that. that.
) )
kindex(stgitformat)
item(tt(stgitformat))(
The tt(git) backend replaces var(%m) in the formats and
actionformats styles with tt(stgit)-specific information for
tt(stgit)-initialized branches. This style lets you modify how that string
should look like.
)
kindex(hgrevformat) kindex(hgrevformat)
item(tt(hgrevformat))( item(tt(hgrevformat))(
tt(hg) uses both a hash and a revision number to reference a specific tt(hg) uses both a hash and a revision number to reference a specific
changeset in a repository. With this style you can format the revision changeset in a repository. With this style you can format the revision
string (see var(branchformat)) to include either of both. It's only string (see var(branchformat)) to include either or both. It's only
useful when var(get-revision) is true. useful when var(get-revision) is true.
) )
kindex(max-exports) kindex(max-exports)
@ -508,16 +508,15 @@ var(vcs_info_msg_*_) variables var(vcs_info) will export.
) )
kindex(enable) kindex(enable)
item(tt(enable))( item(tt(enable))(
A list of backends you want to use. Checked in the A list of backends you want to use. Checked in the var(-init-) context. If
var(-init-) context. If this list contains an item called tt(NONE) no this list contains an item called tt(NONE) no backend is used at all and
backend is used at all and var(vcs_info) will do nothing. If this list var(vcs_info) will do nothing. If this list contains tt(ALL) var(vcs_info)
contains tt(ALL) var(vcs_info) will use all backends known to it. Only with will use all known backends. Only with tt(ALL) in tt(enable) will the
tt(ALL) in tt(enable), the tt(disable) style has any effect. tt(ALL) and tt(disable) style have any effect. tt(ALL) and tt(NONE) are case insensitive.
tt(NONE) are actually tested case insensitively.
) )
kindex(disable) kindex(disable)
item(tt(disable))( item(tt(disable))(
A list of VCSs, you don't want var(vcs_info) to test for A list of VCSs you don't want var(vcs_info) to test for
repositories (checked in the var(-init-) context, too). Only used if repositories (checked in the var(-init-) context, too). Only used if
tt(enable) contains tt(ALL). tt(enable) contains tt(ALL).
) )
@ -531,19 +530,37 @@ Say, tt(~/.zsh) is a directory under version control, in which you do
not want var(vcs_info) to be active, do: not want var(vcs_info) to be active, do:
example(zstyle ':vcs_info:*' disable-patterns "$HOME/.zsh+LPAR()|/*+RPAR()") example(zstyle ':vcs_info:*' disable-patterns "$HOME/.zsh+LPAR()|/*+RPAR()")
) )
kindex(use-quilt)
item(tt(use-quilt))(
If enabled, the tt(quilt) support code is active in `addon' mode.
See tt(Quilt Support) for details.
)
kindex(quilt-standalone)
item(tt(quilt-standalone))(
If enabled, `standalone' mode detection is attempted if no VCS is active
in a given directory. See tt(Quilt Support) for details.
)
kindex(quilt-patch-dir)
item(tt(quilt-patch-dir))(
Overwrite the value of the var($QUILT_PATCHES) environment variable. See
tt(Quilt Support) for details.
)
kindex(quiltcommand)
item(tt(quiltcommand))(
When tt(quilt) itself is called in quilt support the value of this style
is used as the command name.
)
kindex(check-for-changes) kindex(check-for-changes)
item(tt(check-for-changes))( item(tt(check-for-changes))(
If enabled, this style causes the tt(%c) and tt(%u) format escapes to be filled If enabled, this style causes the tt(%c) and tt(%u) format escapes to show
with information. The strings filled into these escapes can be controlled via when the working directory has uncommitted changes. The strings displayed by
the var(stagedstr) and var(unstagedstr) styles. The only backends that these escapes can be controlled via the var(stagedstr) and var(unstagedstr)
currently support this option are tt(git) and tt(hg) (tt(hg) only supports styles. The only backends that currently support this option are tt(git) and
unstaged). tt(hg) (tt(hg) only supports unstaged).
Note, that the actions taken if this style is enabled are potentially expensive Note, the actions taken if this style is enabled are potentially expensive
(read: they take time, depending on how big the current repository is). (read: they may be slow, depending on how big the current repository is).
Therefore, it is disabled by default. In order to use this style with Therefore, it is disabled by default.
the tt(hg) backend you must also use the var(get-revision) style to avoid
having to start the interpreter more than once.
) )
kindex(stagedstr) kindex(stagedstr)
item(tt(stagedstr))( item(tt(stagedstr))(
@ -552,25 +569,25 @@ the repository.
) )
kindex(unstagedstr) kindex(unstagedstr)
item(tt(unstagedstr))( item(tt(unstagedstr))(
This string will be used in the tt(%u) escape if there are unstaged changes in This string will be used in the tt(%u) escape if there are unstaged changes
the repository. in the repository.
) )
kindex(command) kindex(command)
item(tt(command))( item(tt(command))(
This style causes var(vcs_info) to use the supplied string as the command This style causes var(vcs_info) to use the supplied string as the command
to use as the vcs's binary. Note, that setting this in ':vcs_info:*' is to use as the VCS's binary. Note, that setting this in ':vcs_info:*' is
not a good idea. not a good idea.
If the value of this style is empty (which is the default), the used binary If the value of this style is empty (which is the default), the used binary
name is the name of the backend in use (e.g. var(svn) is used in a var(svn) name is the name of the backend in use (e.g. var(svn) is used in an var(svn)
repository). repository).
The var(repo-root-name) part in the context is always the default tt(-all-) The var(repo-root-name) part in the context is always the default tt(-all-)
when this style is looked up. when this style is looked up.
For example, this style can be used to use binaries from non-default For example, this style can be used to use binaries from non-default
installation directories. Assume, var(git) is installed in /usr/bin, but installation directories. Assume, var(git) is installed in /usr/bin but
your sysadmin installed a newer version in /usr/bin/local. Now, instead of your sysadmin installed a newer version in /usr/bin/local. Instead of
changing the order of your tt($PATH) parameter, you can do this: changing the order of your tt($PATH) parameter, you can do this:
example(zstyle ':vcs_info:git:*:-all-' command /usr/local/bin/git) example(zstyle ':vcs_info:git:*:-all-' command /usr/local/bin/git)
) )
@ -581,8 +598,8 @@ contact the Perforce server to find out if a directory is managed
by Perforce. This is the only reliable way of doing this, but runs by Perforce. This is the only reliable way of doing this, but runs
the risk of a delay if the server name cannot be found. If the the risk of a delay if the server name cannot be found. If the
server (more specifically, the var(host)tt(:)var(port) pair describing the server (more specifically, the var(host)tt(:)var(port) pair describing the
server) cannot be contacted its name is put into the associative array server) cannot be contacted, its name is put into the associative array
tt(vcs_info_p4_dead_servers) and not contacted again during the session tt(vcs_info_p4_dead_servers) and is not contacted again during the session
until it is removed by hand. If you do not set this style, the tt(p4) until it is removed by hand. If you do not set this style, the tt(p4)
backend is only usable if you have set the environment variable backend is only usable if you have set the environment variable
tt(P4CONFIG) to a file name and have corresponding files in the root tt(P4CONFIG) to a file name and have corresponding files in the root
@ -594,8 +611,10 @@ item(tt(use-simple))(
If there are two different ways of gathering If there are two different ways of gathering
information, you can select the simpler one by setting this style to true; information, you can select the simpler one by setting this style to true;
the default is to use the not-that-simple code, which is potentially a lot the default is to use the not-that-simple code, which is potentially a lot
slower but might be more accurate in all possible cases. This style is only slower but might be more accurate in all possible cases. This style is
used by the tt(bzr) backend. used by the tt(bzr) and tt(hg) backends. In the case of tt(hg) it will invoke
the external hexdump program to parse the binary dirstate cache file; this
method will not return the local revision number.
) )
kindex(get-revision) kindex(get-revision)
item(tt(get-revision))( item(tt(get-revision))(
@ -604,15 +623,17 @@ a repository's work tree (currently for the tt(git) and tt(hg) backends,
where this kind of information is not always vital). For tt(git), the where this kind of information is not always vital). For tt(git), the
hash value of the currently checked out commit is available via the tt(%i) hash value of the currently checked out commit is available via the tt(%i)
expansion. With tt(hg), the local revision number and the corresponding expansion. With tt(hg), the local revision number and the corresponding
global hash are available via tt(%i); in addition, the topmost global hash are available via tt(%i).
applied tt(mq) patch and bookmarks are available via tt(%m). )
If this style is set in the tt(hg) context, the backend supports the kindex(get-mq)
var(branchformat) style. item(tt(get-mq))(
If set to true, the tt(hg) backend will look for a Mercurial Queue (tt(mq))
patch directory. Information will be available via the `tt(%m)' replacement.
) )
kindex(get-bookmarks) kindex(get-bookmarks)
item(tt(get-bookmarks))( item(tt(get-bookmarks))(
If set to true, the tt(hg) backend will try to get a list of current If set to true, the tt(hg) backend will try to get a list of current
bookmarks. They will be available in via the `tt(%m)' replacement. bookmarks. They will be available via the `tt(%m)' replacement.
) )
kindex(use-prompt-escapes) kindex(use-prompt-escapes)
item(tt(use-prompt-escapes))( item(tt(use-prompt-escapes))(
@ -622,12 +643,12 @@ tt(vcs_info_lastmsg).)
) )
kindex(debug) kindex(debug)
item(tt(debug))( item(tt(debug))(
Enable debugging output, to track possible problems. Currently this style Enable debugging output to track possible problems. Currently this style
is only used by tt(vcs_info)'s hooks system. is only used by var(vcs_info)'s hooks system.
) )
kindex(hooks) kindex(hooks)
item(tt(hooks))( item(tt(hooks))(
A list style, that defines hook-function names. See tt(Hooks in vcs_info) A list style that defines hook-function names. See tt(Hooks in vcs_info)
below for details. below for details.
) )
enditem() enditem()
@ -639,7 +660,6 @@ sitem(tt(formats))(" (%s)-[%b]-")
sitem(tt(actionformats))(" (%s)-[%b|%a]-") sitem(tt(actionformats))(" (%s)-[%b|%a]-")
sitem(tt(branchformat))("%b:%r" (for bzr, svn, svk and hg)) sitem(tt(branchformat))("%b:%r" (for bzr, svn, svk and hg))
sitem(tt(nvcsformats))("") sitem(tt(nvcsformats))("")
sitem(tt(stgitformat))(" %p (%c)")
sitem(tt(hgrevformat))("%r:%h") sitem(tt(hgrevformat))("%r:%h")
sitem(tt(max-exports))(2) sitem(tt(max-exports))(2)
sitem(tt(enable))(ALL) sitem(tt(enable))(ALL)
@ -652,62 +672,70 @@ sitem(tt(command))((empty string))
sitem(tt(use-server))(false) sitem(tt(use-server))(false)
sitem(tt(use-simple))(false) sitem(tt(use-simple))(false)
sitem(tt(get-revision))(false) sitem(tt(get-revision))(false)
sitem(tt(get-mq))(true)
sitem(tt(get-bookmarks))(false) sitem(tt(get-bookmarks))(false)
sitem(tt(use-prompt-escapes))(true) sitem(tt(use-prompt-escapes))(true)
sitem(tt(debug))(false) sitem(tt(debug))(false)
sitem(tt(hooks))((empty list)) sitem(tt(hooks))((empty list))
sitem(tt(use-quilt))(false)
sitem(tt(quilt-standalone))(false)
sitem(tt(quilt-patch-dir))(empty - use var($QUILT_PATCHES))
sitem(tt(quiltcommand))(quilt)
endsitem() endsitem()
In normal tt(formats) and tt(actionformats), the following replacements are In normal tt(formats) and tt(actionformats) the following replacements are
done: done:
startsitem() startsitem()
sitem(tt(%s))(The vcs in use (git, hg, svn etc.)) sitem(tt(%s))(The VCS in use (git, hg, svn, etc.).)
sitem(tt(%b))(Information about the current branch.) sitem(tt(%b))(Information about the current branch.)
sitem(tt(%a))(An identifier, that describes the action. Only makes sense in sitem(tt(%a))(An identifier that describes the action. Only makes sense in
actionformats.) var(actionformats).)
sitem(tt(%i))(The current revision number or identifier. For tt(hg) sitem(tt(%i))(The current revision number or identifier. For tt(hg)
the var(hgrevformat) style may be used to customize the output.) the var(hgrevformat) style may be used to customize the output.)
sitem(tt(%c))(The string from the var(stagedstr) style if there are staged sitem(tt(%c))(The string from the var(stagedstr) style if there are staged
changes in the repository.) changes in the repository.)
sitem(tt(%u))(The string from the var(unstagedstr) style if there are unstaged sitem(tt(%u))(The string from the var(unstagedstr) style if there are
changes in the repository.) unstaged changes in the repository.)
sitem(tt(%R))(base directory of the repository.) sitem(tt(%R))(The base directory of the repository.)
sitem(tt(%r))(repository name. If tt(%R) is var(/foo/bar/repoXY), tt(%r) is sitem(tt(%r))(The repository name. If tt(%R) is var(/foo/bar/repoXY), tt(%r)
var(repoXY).) is var(repoXY).)
sitem(tt(%S))(subdirectory within a repository. If tt($PWD) is sitem(tt(%S))(A subdirectory within a repository. If tt($PWD) is
var(/foo/bar/repoXY/beer/tasty), tt(%S) is var(beer/tasty).) var(/foo/bar/repoXY/beer/tasty), tt(%S) is var(beer/tasty).)
sitem(tt(%m))(A "misc" replacement. It is at the discretion of the backend sitem(tt(%m))(A "misc" replacement. It is at the discretion of the backend to
to decide what this replacement expands to. It is currently used by decide what this replacement expands to. It is currently used by the tt(hg)
the tt(hg) and tt(git) backends. The tt(hg) backend replaces tt(%m) with the and tt(git) backends to display patch information from the tt(mq) and
topmost tt(mq) patch applied (qtop) and a list of any current bookmarks. The tt(stgit) extensions.)
tt(git) backend replaces it with the string from the var(stgitformat)
style.)
endsitem() endsitem()
In tt(branchformat) these replacements are done: In tt(branchformat) these replacements are done:
startsitem() startsitem()
sitem(tt(%b))(the branch name) sitem(tt(%b))(The branch name.)
sitem(tt(%r))(the current revision number or the var(hgrevformat) style for tt(hg)) sitem(tt(%r))(The current revision number or the var(hgrevformat) style for
endsitem() tt(hg).)
In tt(stgitformat) these replacements are done:
startsitem()
sitem(tt(%p))(the name of the patch currently on top of the stack)
sitem(tt(%c))(the number of unapplied patches)
endsitem() endsitem()
In tt(hgrevformat) these replacements are done: In tt(hgrevformat) these replacements are done:
startsitem() startsitem()
sitem(tt(%r))(the current revision number) sitem(tt(%r))(The current local revision number.)
sitem(tt(%h))(the hash identifier for the current resivion in short form) sitem(tt(%h))(The current 40-character changeset ID hash identifier.)
endsitem() endsitem()
Not all vcs backends have to support all replacements. For tt(nvcsformats) In tt(patch-format) and tt(nopatch-format) these replacements are done:
no replacements are performed at all. It is just a string.
startsitem()
sitem(tt(%p))(The name of the top-most applied patch.)
sitem(tt(%u))(The number of unapplied patches.)
sitem(tt(%n))(The number of applied patches.)
sitem(tt(%c))(The number of unapplied patches.)
sitem(tt(%g))(The names of active tt(mq) guards (tt(hg) backend).)
sitem(tt(%G))(The number of active tt(mq) guards (tt(hg) backend).)
endsitem()
Not all VCS backends have to support all replacements. For tt(nvcsformats)
no replacements are performed at all, it is just a string.
subsect(Oddities) subsect(Oddities)
@ -720,21 +748,110 @@ cannot be easily avoided. Luckily we do not clash with a lot of prompt
expansions and this only needs to be done for those. expansions and this only needs to be done for those.
subsect(Function descriptions (public API)) subsect(Quilt Support)
tt(Quilt) is not a version control system, therefore this is not implemented
as a backend. It can help keeping track of a series of patches. People use it
to keep a set of changes they want to use on top of software packages (which
is tightly integrated into the package build process - the Debian project
does this for a large number of packages). Quilt can also help individual
developers keep track of their own patches on top of real version control
systems.
The var(vcs_info) integration tries to support both ways of using quilt by
having two slightly different modes of operation: `addon' mode and
`standalone' mode).
For `addon' mode to become active var(vcs_info) must have already detected a
real version control system controlling the directory. If that is the case,
a directory that holds quilt's patches needs to be found. That directory is
configurable via the var(`QUILT_PATCHES') environment variable. If that
variable exists its value is used, otherwise the value tt(`patches') is
assumed. The value from var($QUILT_PATCHES) can be overwritten using the
tt(`quilt-patches') style. (Note: you can use var(vcs_info) to keep the value
of var($QUILT_PATCHES) correct all the time via the tt(post-quilt) hook).
When the directory in question is found, quilt is assumed to be active. To
gather more information, var(vcs_info) looks for a directory called `.pc';
Quilt uses that directory to track its current state. If this directory does
not exist we know that quilt has not done anything to the working directory
(read: no patches have been applied yet).
If patches are applied, var(vcs_info) will try to find out which. If you want
to know which patches of a series are not yet applied, you need to activate
the tt(get-unapplied) style in the appropriate context.
var(vcs_info) allows for very detailed control over how the gathered
information is presented (see the below sections, tt(Styles) and tt(Hooks in
vcs_info)), all of which are documented below. Note there are a number of
other patch tracking systems that work on top of a certain version control
system (like tt(stgit) for tt(git), or tt(mq) for tt(hg)); the configuration
for systems like that are generally configured the same way as the tt(quilt)
support.
If the tt(quilt) support is working in `addon' mode, the produced string is
available as a simple format replacement (var(%Q) to be precise), which can
be used in tt(formats) and tt(actionformats); see below for details).
If, on the other hand, the support code is working in `standalone' mode,
var(vcs_info) will pretend as if tt(quilt) were an actual version control
system. That means that the version control system identifier (which
otherwise would be something like `svn' or `cvs') will be set to
`tt(-quilt-)'. This has implications on the used style context where this
identifier is the second element. var(vcs_info) will have filled in a proper
value for the "repository's" root directory and the string containing the
information about quilt's state will be available as the `misc' replacement
(and var(%Q) for compatibility with `addon' mode.
What is left to discuss is how `standalone' mode is detected. The detection
itself is a series of searches for directories. You can have this detection
enabled all the time in every directory that is not otherwise under version
control. If you know there is only a limited set of trees where you would
like var(vcs_info) to try and look for Quilt in `standalone' mode to minimise
the amount of searching on every call to var(vcs_info), there are a number of
ways to do that:
Essentially, `standalone' mode detection is controlled by a style called
`tt(quilt-standalone)'. It is a string style and its value can have different
effects. The simplest values are: `tt(always)' to run detection every time
var(vcs_info) is run, and `tt(never)' to turn the detection off entirely.
If the value of tt(quilt-standalone) is something else, it is interpreted
differently. If the value is the name of a scalar variable the value of that
variable is checked and that value is used in the same `always'/`never' way
as described above.
If the value of tt(quilt-standalone) is an array, the elements of that array
are used as directory names under which you want the detection to be active.
If tt(quilt-standalone) is an associative array, the keys are taken as
directory names under which you want the detection to be active, but only if
the corresponding value is the string `tt(true)'.
Last, but not least, if the value of tt(quilt-standalone) is the name of a
function, the function is called without arguments and the return value
decides whether detection should be active. A `0' return value is true; a
non-zero return value is interpreted as false.
Note, if there is both a function and a variable by the name of
tt(quilt-standalone), the function will take precedence.
subsect(Function Descriptions (Public API))
startitem() startitem()
findex(vcs_info) findex(vcs_info)
item(tt(vcs_info) [var(user-context)])( item(tt(vcs_info) [var(user-context)])(
The main function, that runs all The main function, that runs all backends and assembles all data into
backends and assembles all data into var(${vcs_info_msg_*_}). This is the var(${vcs_info_msg_*_}). This is the function you want to call from
function you want to call from tt(precmd) if you want to include up-to-date tt(precmd) if you want to include up-to-date information in your prompt (see
information in your prompt (see Variable description below). If an argument tt(Variable description) below). If an argument is given, that string will be
is given, that string will be used instead of tt(default) in the used instead of tt(default) in the tt(user-context) field of the style
user-context field of the style context. context.
) )
item(tt(vcs_info_lastmsg))( item(tt(vcs_info_lastmsg))(
Outputs the last var(${vcs_info_msg_*_}) value. Outputs the last var(${vcs_info_msg_*_}) value.
Takes into account the value of the use-prompt-escapes style in Takes into account the value of the tt(use-prompt-escapes) style in
var(':vcs_info:formats:command:-all-'). It also only prints tt(max-exports) var(':vcs_info:formats:command:-all-'). It also only prints tt(max-exports)
values. values.
) )
@ -753,14 +870,14 @@ enditem()
All functions named VCS_INFO_* are for internal use only. All functions named VCS_INFO_* are for internal use only.
subsect(Variable description) subsect(Variable Description)
startitem() startitem()
item(tt(${vcs_info_msg_N_}) (Note the trailing underscore)) item(tt(${vcs_info_msg_N_}) (Note the trailing underscore))
( (
Where var(N) is an integer, eg: var(vcs_info_msg_0_) These variables Where var(N) is an integer, e.g., var(vcs_info_msg_0_). These variables
are the storage for the informational message the last var(vcs_info) call are the storage for the informational message the last var(vcs_info) call
has assembled. These are strongly connected to the formats, has assembled. These are strongly connected to the tt(formats),
tt(actionformats) and tt(nvcsformats) styles described above. Those styles tt(actionformats) and tt(nvcsformats) styles described above. Those styles
are lists. The first member of that list gets expanded into are lists. The first member of that list gets expanded into
var(${vcs_info_msg_0_}), the second into var(${vcs_info_msg_1_}) var(${vcs_info_msg_0_}), the second into var(${vcs_info_msg_1_})
@ -773,7 +890,7 @@ All variables named VCS_INFO_* are for internal use only.
subsect(Hooks in vcs_info) subsect(Hooks in vcs_info)
Hooks are places in tt(vcs_info) where you can run your own code. That Hooks are places in var(vcs_info) where you can run your own code. That
code can communicate with the code that called it and through that, code can communicate with the code that called it and through that,
change the system's behaviour. change the system's behaviour.
@ -799,114 +916,152 @@ When you register more than one function to a hook, all functions are
executed one after another until one function returns non-zero or until executed one after another until one function returns non-zero or until
all functions have been called. all functions have been called.
There are a number of variables, that are special in hook contexts: You may pass data between functions via an associative array, tt(user_data).
For example:
example(
+vi-git-myfirsthook+LPAR()RPAR(){
user_data[myval]=$myval
}
+vi-git-mysecondhook+LPAR()RPAR(){
# do something with ${user_data[myval]}
})
There are a number of variables that are special in hook contexts:
startitem() startitem()
item(tt(ret))( item(tt(ret))(
The return value, that the hooks system will return to the caller. The The return value that the hooks system will return to the caller. The
default is an integer `zero'. If and how a changed tt(ret) value changes default is an integer `zero'. If and how a changed tt(ret) value changes
the execution of the caller depends on the specific hook. See the hook's the execution of the caller depends on the specific hook. See the hook
documentation below for details. documentation below for details.
) )
item(tt(hook_com))( item(tt(hook_com))(
An associated array, which is used for bidirectional communication from An associated array which is used for bidirectional communication from
the caller to hook functions. The used keys depend on the specific hook. the caller to hook functions. The used keys depend on the specific hook.
) )
item(tt(context))( item(tt(context))(
The active context of the hook. Functions that wish to change this The active context of the hook. Functions that wish to change this
variable should make it local scope first. variable should make it local scope first.
) )
item(tt(vcs))(
The current VCS after it was detected. The same values as in the
enable/disable style are used. Available in all hooks except tt(start-up).
)
enditem() enditem()
Finally, the full list of currently available hooks: Finally, the full list of currently available hooks:
startitem() startitem()
item(tt(start-up))(
Called after starting var(vcs_info) but before the VCS in this directory is
determined. It can be used to deactivate var(vcs_info) temporarily if
necessary. When tt(ret) is set to var(1), var(vcs_info) aborts and does
nothing; when set to var(2), var(vcs_info) sets up everything as if no
version control were active and exits.
)
item(tt(pre-get-data))(
Same as tt(start-up) but after the VCS was detected.
)
item(tt(gen-hg-bookmark-string))( item(tt(gen-hg-bookmark-string))(
Called in the Mercurial backend (the tt(get-revision) and tt(get-bookmarks) Called in the Mercurial backend when a bookmark string is generated; the
styles must be active) when a bookmark string is generated. tt(get-revision) and tt(get-bookmarks) styles must be true.
This hook gets the names of the Mercurial bookmarks, that This hook gets the names of the Mercurial bookmarks that
tt(vcs_info) collected from `hg'. var(vcs_info) collected from `hg'.
When setting tt(ret) to non-zero, the string in When setting tt(ret) to non-zero, the string in
tt(${hook_com[hg-bookmark-string]}) will be used as the tt(${hook_com[hg-bookmark-string]}) will be used in the var(%m) escape in
`tt(misc1)' replacement in the variables set by tt(vcs_info). tt(formats) and tt(actionformats) and will be availabe in the global
var(backend_misc) array as tt(${backend_misc[bookmarks]}).
) )
item(tt(gen-mq-patch-string))( item(tt(gen-applied-string))(
Called in the Mercurial backend when a mq-patch string is generated. That Called in the tt(git) (with tt(stgit)), and tt(hg) (with tt(mq)) backends
only happens if a tt(.hg/patches) directory exists in the repository. and in tt(quilt) support when the var(applied-string) is generated; the
tt(use-quilt) zstyle must be true for tt(quilt) (the tt(mq) and tt(stgit)
backends are active by default).
This hook gets the names of all applied mq patches which tt(vcs_info) This hook gets the names of all applied patches which var(vcs_info) collected
collected so far in the opposite order, which mean that the first argument so far in the opposite order, which means that the first argument is the
is the top-most patch and so forth. top-most patch and so forth.
When setting tt(ret) to non-zero, the string in When setting tt(ret) to non-zero, the string in
tt(${hook_com[hg-mqpatch-string]}) will be used as the tt(${hook_com[applied-string]}) will be used in the var(%m) escape in
`tt(misc0)' replacement in the variables set by tt(vcs_info). tt(formats) and tt(actionformats); it will be available in the global
var(backend_misc) array as tt($backend_misc[patches]}); and it will be
available as var(%p) in the tt(patch-format) and tt(nopatch-format) styles.
) )
item(tt(gen-stgit-patch-string))( item(tt(gen-unapplied-string))(
Called in the git backend when a stgit-patch string is generated. That Called in the tt(git) (with tt(stgit)), and tt(hg) (with tt(mq)) backend
only happens if stgit is in use in the repository. and in tt(quilt) support when the var(unapplied-string) is generated; the
tt(get-unapplied) style must be true.
This hook gets the names of all applied stgit patches which tt(vcs_info) This hook gets the names of all unapplied patches which var(vcs_info)
collected so far in the opposite order, which mean that the first argument collected so far in the opposite order, which mean that the first argument is
is the top-most patch and so forth. the patch next-in-line to be applied and so forth.
When setting tt(ret) to non-zero, the string in When setting tt(ret) to non-zero, the string in
tt(${hook_com[stgit-patch-string]}) will be used as the tt(${hook_com[unapplied-string]}) will be available as var(%u) in the
`tt(misc0)' replacement in the variables set by tt(vcs_info). tt(patch-format) and tt(nopatch-format) styles.
) )
item(tt(gen-stgit-unapplied-string))( item(tt(gen-mqguards-string))(
Called in the git backend when a stgit-unapplied string is generated. That Called in the tt(hg) backend when tt(guards-string) is generated; the
only happens if stgit is in use in the repository. tt(get-mq) style must be true (default).
This hook gets the names of all unapplied stgit patches which tt(vcs_info) This hook gets the names of any active tt(mq) guards.
collected so far.
When setting tt(ret) to non-zero, the string in When setting tt(ret) to non-zero, the string in
tt(${hook_com[stgit-unapplied-string]}) will be used as the tt(${hook_com[guards-string]}) will be used in the var(%g) escape in the
`tt(misc0)' replacement in the variables set by tt(vcs_info). tt(patch-format) and tt(nopatch-format) styles.
)
item(tt(post-quilt))(
Called after the tt(quilt) support is done. The following information
is passed as arguments to the hook: 1. the quilt-support mode (`addon' or
`standalone'); 2. the directory that contains the patch series; 3. the
directory that holds quilt's status information (the `.pc' directory) or
the string tt("-nopc-") if that directory wasn't found.
The `hook_com' parameter is not used.
) )
item(tt(set-branch-format))( item(tt(set-branch-format))(
Called before a `tt(branchformat)' is set. The only argument to the Called before `tt(branchformat)' is set. The only argument to the
hook is the format that is configured at this point. hook is the format that is configured at this point.
The `tt(hook_com)' keys considered are `tt(branch)' and `tt(revision)'. The `tt(hook_com)' keys considered are `tt(branch)' and `tt(revision)'.
They are set to the values figured out so far by tt(vcs_info) and any They are set to the values figured out so far by var(vcs_info) and any
change will be used directly when the actual replacement is done. change will be used directly when the actual replacement is done.
If tt(ret) is set to to non-zero, the string in If tt(ret) is set to to non-zero, the string in
tt(${hook_com[branch-replace]}) will be used unchanged as the tt(${hook_com[branch-replace]}) will be used unchanged as the
`tt(%b)' replacement in the variables set by tt(vcs_info). `tt(%b)' replacement in the variables set by var(vcs_info).
) )
item(tt(set-hgrev-format))( item(tt(set-hgrev-format))(
Called before a `tt(hgrevformat)' is set. The only argument to the Called before a `tt(hgrevformat)' is set. The only argument to the
hook is the format that is configured at this point. hook is the format that is configured at this point.
The `tt(hook_com)' keys considered are `tt(hash)' and `tt(localref)'. The `tt(hook_com)' keys considered are `tt(hash)' and `tt(localrev)'.
They are set to the values figured out so far by tt(vcs_info) and any They are set to the values figured out so far by var(vcs_info) and any
change will be used directly when the actual replacement is done. change will be used directly when the actual replacement is done.
If tt(ret) is set to to non-zero, the string in If tt(ret) is set to to non-zero, the string in
tt(${hook_com[rev-replace]}) will be used unchanged as the tt(${hook_com[rev-replace]}) will be used unchanged as the
`tt(%i)' replacement in the variables set by tt(vcs_info). `tt(%i)' replacement in the variables set by var(vcs_info).
) )
item(tt(set-message))( item(tt(set-message))(
Called each time before a `tt(vcs_info_msg_N_)' message is set. Called each time before a `tt(vcs_info_msg_N_)' message is set.
It takes two arguments; the first being the `N' in the message It takes two arguments; the first being the `N' in the message
variable name, the second is the currently configured format or variable name, the second is the currently configured tt(formats) or
actionformat. tt(actionformats).
There are a number of `tt(hook_com)' keys, that are used here: There are a number of `tt(hook_com)' keys, that are used here:
`tt(action)', `tt(branch)', `tt(base)', `tt(base-name)', `tt(subdir)', `tt(action)', `tt(branch)', `tt(base)', `tt(base-name)', `tt(subdir)',
`tt(staged)', `tt(unstaged)', `tt(revision)', `tt(misc)', `tt(vcs)' `tt(staged)', `tt(unstaged)', `tt(revision)', `tt(misc)', `tt(vcs)'
and one `tt(miscN)' entry for each backend-specific data field (tt(N) and one `tt(miscN)' entry for each backend-specific data field (tt(N)
starting at zero). They are set to the values figured out so far by starting at zero). They are set to the values figured out so far by
tt(vcs_info) and any change will be used directly when the actual var(vcs_info) and any change will be used directly when the actual
replacement is done. replacement is done.
Since this hook is triggered multiple times (once for each configured Since this hook is triggered multiple times (once for each configured
format or actionformat), each of the `tt(hook_com)' keys mentioned tt(formats) or tt(actionformats)), each of the `tt(hook_com)' keys mentioned
above (except for the tt(miscN) entries) has an `tt(_orig)' counterpart, above (except for the tt(miscN) entries) has an `tt(_orig)' counterpart,
so even if you changed a value to your liking you can still get the so even if you changed a value to your liking you can still get the
original value in the next run. Changing the `tt(_orig)' values is original value in the next run. Changing the `tt(_orig)' values is
@ -914,28 +1069,16 @@ probably not a good idea.
If tt(ret) is set to to non-zero, the string in If tt(ret) is set to to non-zero, the string in
tt(${hook_com[message]}) will be used unchanged as the message by tt(${hook_com[message]}) will be used unchanged as the message by
tt(vcs_info). var(vcs_info).
) )
item(tt(set-stgit-format))(
Called before a `tt(stgitformat)' is set. The only argument to the
hook is the format that is configured at this point.
The `tt(hook_com)' keys considered are `tt(patch)' and `tt(unapplied)'.
They are set to the values figured out so far by tt(vcs_info) and any
change will be used directly when the actual replacement is done.
If tt(ret) is set to to non-zero, the string in
tt(${hook_com[stgit-replace]}) will be used unchanged as the
`tt(misc0)' replacement in the variables set by tt(vcs_info).
)
enditem()
If all of this sounds rather confusing, take a look at the tt(Examples) If all of this sounds rather confusing, take a look at the tt(Examples)
section below. It contains some explanatory code. section below and also in the Misc/vcs_info-examples file in the Zsh source.
They contain some explanatory code.
subsect(Examples) subsect(Examples)
Don't use tt(vcs_info) at all (even though it's in your prompt): Don't use var(vcs_info) at all (even though it's in your prompt):
example(zstyle ':vcs_info:*' enable NONE) example(zstyle ':vcs_info:*' enable NONE)
Disable the backends for tt(bzr) and tt(svk): Disable the backends for tt(bzr) and tt(svk):
@ -948,6 +1091,17 @@ Provide a special formats for tt(git):
example(zstyle ':vcs_info:git:*' formats ' GIT, BABY! [%b]' example(zstyle ':vcs_info:git:*' formats ' GIT, BABY! [%b]'
zstyle ':vcs_info:git:*' actionformats ' GIT ACTION! [%b|%a]') zstyle ':vcs_info:git:*' actionformats ' GIT ACTION! [%b|%a]')
All tt(%x) expansion in all sorts of formats ("formats", "actionformats",
branchformat, you name it) are done using the `tt(zformat)' builtin from
the `tt(zsh/zutil)' module. That means you can do everything with these
tt(%x) items what zformat supports. In particular, if you want something
that is really long to have a fixed width, like a hash in a mercurial
branchformat, you can do this: tt(%12.12i). That'll shrink the 40 character
hash to its 12 leading characters. The form is actually
`tt(%)var(min)tt(.)var(max)tt(x)'. More is possible.
See ifzman(the section `The zsh/zutil Module' in zmanref(zshmodules))\
ifnzman(noderef(The zsh/zutil Module)) for details.
Use the quicker tt(bzr) backend Use the quicker tt(bzr) backend
example(zstyle ':vcs_info:bzr:*' use-simple true) example(zstyle ':vcs_info:bzr:*' use-simple true)
@ -956,10 +1110,10 @@ If you do use tt(use-simple), please report if it does `the-right-thing[tm]'.
Display the revision number in yellow for tt(bzr) and tt(svn): Display the revision number in yellow for tt(bzr) and tt(svn):
example(zstyle ':vcs_info:(svn|bzr):*' branchformat '%b%{'${fg[yellow]}'%}:%r') example(zstyle ':vcs_info:(svn|bzr):*' branchformat '%b%{'${fg[yellow]}'%}:%r')
If you want colors, make sure you enclose the color codes in tt(%{...%}), If you want colors, make sure you enclose the color codes in tt(%{...%})
if you want to use the string provided by tt(vcs_info) in prompts. if you want to use the string provided by var(vcs_info) in prompts.
Here is how to print the vcs information as a command (not in a prompt): Here is how to print the VCS information as a command (not in a prompt):
example(alias vcsi='vcs_info command; vcs_info_lastmsg') example(alias vcsi='vcs_info command; vcs_info_lastmsg')
This way, you can even define different formats for output via This way, you can even define different formats for output via
@ -967,15 +1121,15 @@ tt(vcs_info_lastmsg) in the ':vcs_info:*:command:*' namespace.
Now as promised, some code that uses hooks: Now as promised, some code that uses hooks:
say, you'd like to replace the string `svn' by `subversion' in say, you'd like to replace the string `svn' by `subversion' in
tt(vcs_info)'s tt(%s) format-replacement. var(vcs_info)'s tt(%s) tt(formats) replacement.
First, we will tell tt(vcs_info) to call a function when populating First, we will tell var(vcs_info) to call a function when populating
the message variables with the gathered information: the message variables with the gathered information:
example(zstyle ':vcs_info:*+set-message:*' hooks svn2subversion) example(zstyle ':vcs_info:*+set-message:*' hooks svn2subversion)
Nothing happens. Which is reasonable, since there we didn't define Nothing happens. Which is reasonable, since we didn't define the actual
the actual function yet. To see what the hooks subsystem is trying to function yet. To see what the hooks subsystem is trying to do, enable the
do, enable the `tt(debug)' style: `tt(debug)' style:
example(zstyle ':vcs_info:*+*:*' debug true) example(zstyle ':vcs_info:*+*:*' debug true)
That should give you an idea what is going on. Specifically, the function That should give you an idea what is going on. Specifically, the function
@ -1010,7 +1164,7 @@ And then we define the `tt(+vi-hgbookmarks) function:
example( example(
function +vi-hgbookmarks+LPAR()RPAR() { function +vi-hgbookmarks+LPAR()RPAR() {
# The default is to connect all bookmark names by # The default is to connect all bookmark names by
# semicolons. This mixes things up a little. # commas. This mixes things up a little.
# Imagine, there's one type of bookmarks that is # Imagine, there's one type of bookmarks that is
# special to you. Say, because it's *your* work. # special to you. Say, because it's *your* work.
# Those bookmarks look always like this: "sh/*" # Those bookmarks look always like this: "sh/*"
@ -1018,8 +1172,7 @@ function +vi-hgbookmarks+LPAR()RPAR() {
# This makes the bookmarks string use only those # This makes the bookmarks string use only those
# bookmarks. If there's more than one, it # bookmarks. If there's more than one, it
# concatenates them using commas. # concatenates them using commas.
local s i) local s i
example(
# The bookmarks returned by `hg' are available in # The bookmarks returned by `hg' are available in
# the functions positional parameters. # the functions positional parameters.
(( $# == 0 )) && return 0 (( $# == 0 )) && return 0
@ -1028,22 +1181,25 @@ example(
[[ -n $s ]] && s=$s, [[ -n $s ]] && s=$s,
s=${s}$i s=${s}$i
fi fi
done) done
example(
# Now, the communication with the code that calls # Now, the communication with the code that calls
# the hook functions is done via the hook_com[] # the hook functions is done via the hook_com[]
# hash. The key, at which the `gen-hg-bookmark-string' # hash. The key, at which the `gen-hg-bookmark-string'
# hook looks at is `hg-bookmark-string'. So: # hook looks at is `hg-bookmark-string'. So:
hook_com[hg-bookmark-string]=$s) hook_com[hg-bookmark-string]=$s
example(
# And to signal, that we want to use the sting we # And to signal, that we want to use the sting we
# just generated, set the special variable `ret' to # just generated, set the special variable `ret' to
# something other than the default zero: # something other than the default zero:
ret=1 ret=1
return 0 return 0
}) }
)
This concludes our guided tour through zsh's tt(vcs_info). Some longer examples and code snippets which might be useful are available in
the examples file located at Misc/vcs_info-examples in the Zsh source
directory.
This concludes our guided tour through zsh's var(vcs_info).
texinode(Prompt Themes)(ZLE Functions)(Version Control Information)(User Contributions) texinode(Prompt Themes)(ZLE Functions)(Version Control Information)(User Contributions)

View File

@ -11,6 +11,7 @@ vcs_info_lastmsg
VCS_INFO_maxexports VCS_INFO_maxexports
VCS_INFO_nvcsformats VCS_INFO_nvcsformats
vcs_info_printsys vcs_info_printsys
VCS_INFO_quilt
VCS_INFO_realpath VCS_INFO_realpath
VCS_INFO_reposub VCS_INFO_reposub
VCS_INFO_set VCS_INFO_set

View File

@ -4,9 +4,17 @@
setopt localoptions NO_shwordsplit setopt localoptions NO_shwordsplit
[[ $1 == '--flavours' ]] && return 1 [[ $1 == '--flavours' ]] && { print -l hg-git hg-hgsubversion hg-hgsvn; return 0 }
VCS_INFO_check_com ${vcs_comm[cmd]} || return 1 VCS_INFO_check_com ${vcs_comm[cmd]} || return 1
vcs_comm[detect_need_file]=store vcs_comm[detect_need_file]=store
VCS_INFO_bydir_detect '.hg' VCS_INFO_bydir_detect '.hg' || return 1
return $?
if [[ -d ${vcs_comm[basedir]}/.hg/svn ]] ; then
vcs_comm[overwrite_name]='hg-hgsubversion'
elif [[ -d ${vcs_comm[basedir]}/.hgsvn ]] ; then
vcs_comm[overwrite_name]='hg-hgsvn'
elif [[ -e ${vcs_comm[basedir]}/.hg/git-mapfile ]] ; then
vcs_comm[overwrite_name]='hg-git'
fi
return 0

View File

@ -3,7 +3,7 @@
## Distributed under the same BSD-ish license as zsh itself. ## Distributed under the same BSD-ish license as zsh itself.
setopt localoptions extendedglob NO_shwordsplit setopt localoptions extendedglob NO_shwordsplit
local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1 gitmisc local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1
local stgitpatch stgitunapplied local stgitpatch stgitunapplied
local -xA hook_com local -xA hook_com
@ -139,33 +139,40 @@ if [[ -d $patchdir ]] ; then
stgit_unapplied=(${(f)"$(< "${patchdir}/unapplied")"}) stgit_unapplied=(${(f)"$(< "${patchdir}/unapplied")"})
stgit_unapplied=( ${(oa)stgit_applied} ) stgit_unapplied=( ${(oa)stgit_applied} )
if VCS_INFO_hook 'gen-stgit-patch-string' "${stgit_applied[@]}"; then if VCS_INFO_hook 'gen-applied-string' "${stgit_applied[@]}"; then
if (( ${#stgit_applied} )); then if (( ${#stgit_applied} )); then
stgitpatch=${stgit_applied[1]} stgitpatch=${stgit_applied[1]}
else else
stgitpatch="no patch applied" stgitpatch=""
fi fi
else else
stgitpatch=${hook_com[stgit-patch-string]} stgitpatch=${hook_com[patch-string]}
fi fi
if VCS_INFO_hook 'gen-stgit-unapplied-string' "${stgit_unapplied[@]}"; then hook_com=()
if VCS_INFO_hook 'gen-unapplied-string' "${stgit_unapplied[@]}"; then
stgitunapplied=${#stgit_unapplied} stgitunapplied=${#stgit_unapplied}
else else
stgitunapplied=${hook_com[stgit-unapplied-string]} stgitunapplied=${hook_com[unapplied-string]}
fi fi
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" stgitformat stgitmsg || stgitmsg=" %p (%c)" if (( ${#stgit_applied} )); then
hook_com=( patch "${stgitpatch}" unapplied "${stgitunapplied}" ) zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format stgitmsg || stgitmsg="%p (%n applied)"
if VCS_INFO_hook 'set-stgit-format' "${stgitformat}"; then
zformat -f stgitmsg "${stgitmsg}" "p:${hook_com[patch]}" "c:${hook_com[unapplied]}"
gitmisc=${stgitmsg}
else else
gitmisc=${hook_com[stgit-replace]} zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format stgitmsg || stgitmsg="no patch applied"
fi
hook_com=( applied "${stgitpatch}" unapplied "${stgitunapplied}"
applied-n ${#stgit_applied} unapplied-n ${#stgit_unapplied} )
if VCS_INFO_hook 'set-patch-format' "${stgitmsg}"; then
zformat -f stgitmsg "${stgitmsg}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
"n:${#stgit_applied}" "c:${#stgit_unapplied}"
else
stgitmsg=${hook_com[patch-replace]}
fi fi
hook_com=() hook_com=()
else else
gitmisc='' stgitmsg=''
fi fi
VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${gitmisc}" backend_misc[patches]="${stgitmsg}"
VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${stgitmsg}"
return 0 return 0

View File

@ -1,128 +1,239 @@
## vim:ft=zsh ## vim:ft=zsh
## mercurial support by: Frank Terbeck <ft@bewatermyfriend.org> ## mercurial support by: Frank Terbeck <ft@bewatermyfriend.org>
## with large contributions by Seth House <seth@eseth.com>
## Distributed under the same BSD-ish license as zsh itself. ## Distributed under the same BSD-ish license as zsh itself.
setopt localoptions NO_shwordsplit setopt localoptions extendedglob NO_shwordsplit
local file hgbranch hgbranch_name hgbase hghash hglrev hgmqstring \
r_branch hgchanges revformat bookmarks r_bmhash r_bmname hgbmstring local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \
local -i getbookmarks mqstatusfile mqguardsfile patchdir mergedir \
local -a hgbm mqpatches hgmisc_args r_csetid r_lrev r_branch i_bmhash i_bmname \
revformat branchformat hgactionstring hgchanges \
hgbmstring hgmqstring applied_string unapplied_string guards_string
local -a hgid_args defrevformat defbranchformat \
hgbmarks mqpatches mqseries mqguards mqunapplied hgmisc \
i_patchguards i_negguards i_posguards
local -xA hook_com local -xA hook_com
hgbase=${vcs_comm[basedir]} hgbase=${vcs_comm[basedir]}
rrn=${hgbase:t} rrn=${hgbase:t}
r_csetid='' # changeset id (long hash)
r_lrev='' # local revision
patchdir="${hgbase}/.hg/patches"
mergedir="${hgbase}/.hg/merge/"
bmfile="${hgbase}/.hg/bookmarks"
branchfile="${hgbase}/.hg/branch"
rebasefile="${hgbase}/.hg/rebasestate"
dirstatefile="${hgbase}/.hg/dirstate"
mqstatusfile="${patchdir}/status" # currently applied patches
mqseriesfile="${patchdir}/series" # all patches
mqguardsfile="${patchdir}/guards"
file="${hgbase}/.hg/branch" # Look for any --flavours
if [[ -r ${file} ]] ; then VCS_INFO_adjust
hgbranch_name=$(< ${file})
else
hgbranch_name="default"
fi
hghash='' # Calling the 'hg' program is quite a bit too slow for prompts.
hglrev='' # Disabled by default anyway, so no harm done.
hgbm=()
bookmarks="${hgbase}/.hg/bookmarks"
if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then
# Calling the 'hg' program is quite a bit too slow for prompts. # Calling hexdump is (much) faster than hg but doesn't get the local rev
# If there's a way around that, I'd be interested. if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple \
# Disabled by default anyway, so no harm done. && ( VCS_INFO_check_com hexdump ) && [[ -r ${dirstatefile} ]] ; then
local HGRCPATH r_csetid=$(hexdump -n 20 -e '1/1 "%02x"' ${dirstatefile})
if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \
"check-for-changes" ; then
HGRCPATH="/dev/null" ${vcs_comm[cmd]} id --debug -i -n -b \
| read -r hghash hglrev r_branch
# Are there uncommitted-changes?
if [[ $hglrev[-1] == + ]] ; then
hgchanges=1
fi
# Remove uncommitted-changes marker, if any
hglrev=${hglrev/+/}
hghash=${hghash/+/}
else else
HGRCPATH="/dev/null" ${vcs_comm[cmd]} \ hgid_args=( --debug id -i -n -b )
parents --template="{node} {rev} {branches}\n" \
| read -r hghash hglrev r_branch
fi
if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" "get-bookmarks" \ # Looking for changes is a tad bit slower since the dirstate cache must
&& getbookmarks=1 || getbookmarks=0 # first be refreshed before being read
zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \
"check-for-changes" || hgid_args+=( -r. )
if (( getbookmarks )) && [[ -r "${bookmarks}" ]] ; then local HGRCPATH
while read -r r_bmhash r_bmname ; do HGRCPATH="/dev/null" ${vcs_comm[cmd]} ${(z)hgid_args} \
if [[ $hghash == $r_bmhash ]] ; then | read -r r_csetid r_lrev r_branch
hgbm=( "$r_bmname" ${hgbm} )
fi
done < ${bookmarks}
fi fi
if [[ -n ${hglrev} ]] ; then
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" hgrevformat revformat || revformat="%r:%h"
hook_com=( localrev "${hglrev}" "hash" "${hghash}" )
if VCS_INFO_hook 'set-hgrev-format' "${revformat}"; then
zformat -f hglrev "${revformat}" "r:${hook_com[localrev]}" "h:${hook_com[hash]}"
else
hglrev=${hook_com[rev-replace]}
fi
hook_com=()
if (( getbookmarks )) ; then
if VCS_INFO_hook 'gen-hg-bookmark-string' "${hgbm[@]}"; then
hgbmstring=${(j.;.)hgbm}
else
hgbmstring=${hook_com[hg-bookmark-string]}
fi
hook_com=()
fi
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat hgbranch || hgbranch="%b:%r"
hook_com=( branch "${hgbranch_name}" revision "${hglrev}" )
if VCS_INFO_hook 'set-branch-format' "${hgbranch}"; then
zformat -f hgbranch "${hgbranch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}"
else
hgbranch=${hook_com[branch-replace]}
fi
hook_com=()
fi
else
hgbranch="${hgbranch_name}"
fi fi
local patchdir=${hgbase}/.hg/patches/ # If the user doesn't opt to invoke hg we can still get the current branch
if [[ -z ${r_branch} && -r ${branchfile} ]] ; then
r_branch=$(< ${branchfile})
else
r_branch="default"
fi
if [[ -d $patchdir ]] ; then # The working dir has uncommitted-changes if the revision ends with a +
local -a mqpatches if [[ $r_lrev[-1] == + ]] ; then
if [[ -e "${patchdir}/status" ]]; then hgchanges=1
r_lrev=${r_lrev%+}
r_csetid=${r_csetid%+}
fi
# This directory only exists during a merge
[[ -d $mergedir ]] && hgactionstring="merging"
# This file only exists during a rebase
[[ -e $rebasefile ]] && hgactionstring="rebasing"
### Build the current revision display
[[ -n ${r_csetid} ]] && defrevformat+=( "%h" )
[[ -n ${r_lrev} ]] && defrevformat+=( "%r" )
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" \
"hgrevformat" revformat || revformat=${(j/:/)defrevformat}
hook_com=( localrev "${r_lrev}" "hash" "${r_csetid}" )
if VCS_INFO_hook 'set-hgrev-format' "${revformat}"; then
zformat -f r_lrev "${revformat}" \
"r:${hook_com[localrev]}" "h:${hook_com[hash]}"
else
r_lrev=${hook_com[rev-replace]}
fi
hook_com=()
### Build the branch display
[[ -n ${r_branch} ]] && defbranchformat+=( "%b" )
[[ -n ${r_lrev} ]] && defbranchformat+=( "%r" )
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" \
branchformat branchformat || branchformat=${(j/:/)defbranchformat}
hook_com=( branch "${r_branch}" revision "${r_lrev}" )
if VCS_INFO_hook 'set-branch-format' "${branchformat}"; then
zformat -f branchformat "${branchformat}" \
"b:${hook_com[branch]}" "r:${hook_com[revision]}"
else
branchformat=${hook_com[branch-replace]}
fi
hook_com=()
### Look for current Bookmarks (this requires knowing the changeset id)
if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-bookmarks \
&& [[ -r "${bmfile}" ]] && [[ -n "$r_csetid" ]] ; then
while read -r i_bmhash i_bmname ; do
# Compare hash in bookmarks file with changeset id
[[ $r_csetid == $i_bmhash ]] && hgbmarks+=( $i_bmname )
done < ${bmfile}
if VCS_INFO_hook 'gen-hg-bookmark-string' "${hgbmarks[@]}"; then
hgbmstring=${(j:, :)hgbmarks}
else
hgbmstring=${hook_com[hg-bookmark-string]}
fi
hook_com=()
fi
### Look for any applied Mercurial Queue patches
if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \
&& [[ -d $patchdir ]] ; then
if [[ -e $mqstatusfile ]]; then
mqpatches=( ${${(f)"$(< "${patchdir}/status")"}/(#s)[a-f0-9]##:/} ) mqpatches=( ${${(f)"$(< "${patchdir}/status")"}/(#s)[a-f0-9]##:/} )
mqpatches=( ${(Oa)mqpatches} ) mqpatches=( ${(Oa)mqpatches} )
else
mqpatches=( )
fi fi
if VCS_INFO_hook 'gen-mq-patch-string' "${mqpatches[@]}"; then if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied \
if (( ${#mqpatches} )); then && [[ -r ${mqseriesfile} ]]; then
hgmqstring=${mqpatches[1]} # Okay, here's a little something that assembles a list of unapplied
else # patches that takes into account if mq-guards are active or not.
hgmqstring="no patch applied"
# Collect active guards
if [[ -r ${mqguardsfile} ]]; then
mqguards=( ${(f)"$(< "${mqguardsfile}")"} )
mqguards=( ${(oa)mqguards} )
fi fi
else
hgbmstring=${hook_com[hg-mqpatch-string]} while read -r i_patch i_patchguards ; do
# Skip commented lines
[[ ${i_patch} == [[:space:]]#"#"* ]] && continue
# Keep list of all patches
mqseries+=( $i_patch )
# Separate negative and positive guards to more easily find the
# intersection of active guards with patch guards
i_patchguards=( ${(s: :)i_patchguards} )
i_negguards=( ${${(M)i_patchguards:#*"#-"*}/(#s)\#-/} )
i_posguards=( ${${(M)i_patchguards:#*"#+"*}/(#s)\#+/} )
# Patch with any negative guards is never pushed if guard is active
if [[ ${#i_negguards} -gt 0
&& ${#${(@M)mqguards:#${(~j,|,)i_negguards}}} -gt 0 ]] ; then
continue
fi
# Patch with positive guards is only pushed if guard is active
if [[ ${#i_posguards} -gt 0 ]] ; then
if [[ ${#${(@M)mqguards:#${(~j,|,)i_posguards}}} -gt 0 ]] ; then
mqunapplied+=( $i_patch )
fi
continue
fi
# If we made it this far the patch isn't guarded and should be pushed
mqunapplied+=( $i_patch )
done < ${mqseriesfile}
fi fi
if VCS_INFO_hook 'gen-applied-string' "${mqpatches[@]}"; then
(( ${#mqpatches} )) && applied_string=${mqpatches[1]}
else
applied_string=${hook_com[applied-string]}
fi
hook_com=()
if VCS_INFO_hook 'gen-unapplied-string' "${mqunapplied[@]}"; then
unapplied_string=${#mqunapplied}
else
unapplied_string=${hook_com[unapplied-string]}
fi
hook_com=()
if VCS_INFO_hook 'gen-mqguards-string' "${mqguards[@]}"; then
guards_string=${(j:,:)mqguards}
else
guards_string=${hook_com[guards-string]}
fi
if (( ${#mqpatches} )); then
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format \
hgmqstring || hgmqstring="%p (%n applied)"
else
zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format \
hgmqstring || hgmqstring="no patch applied"
fi
hook_com=( applied "${applied_string}" unapplied "${unapplied_string}"
applied-n ${#mqpatches} unapplied-n ${#mqunapplied}
guards "${guards_string}" guards-n ${#mqguards} )
if VCS_INFO_hook 'set-patch-format' ${qstring}; then
zformat -f hgmqstring "${hgmqstring}" \
"p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
"n:${#mqpatches}" "c:${#mqunapplied}" \
"g:${hook_com[guards]}" "G:${#mqguards}"
else
hgmqstring=${hook_com[patch-replace]}
fi
hook_com=() hook_com=()
else
hgmqstring=''
fi fi
if [[ -z "${hgmqstring}" ]] && [[ -z "${hgbmstring}" ]]; then
hgmisc_args=( '' ) # make sure there's at least *one* misc argument ### Build the misc string
elif [[ -z "${hgmqstring}" ]]; then hgmisc+=( ${hgmqstring} )
hgmisc_args=( "${hgmqstring}" ) hgmisc+=( ${hgbmstring} )
elif [[ -z "${hgbmstring}" ]]; then
hgmisc_args=( "${hgbmstring}" ) backend_misc[patches]="${hgmqstring}"
else backend_misc[bookmarks]="${hgbmstring}"
hgmisc_args=( "${hgmqstring}" "${hgbmstring}" )
fi VCS_INFO_formats "${hgactionstring}" "${branchformat}" "${hgbase}" '' "${hgchanges}" "${r_lrev}" "${(j:;:)hgmisc}"
VCS_INFO_formats '' "${hgbranch}" "${hgbase}" '' "${hgchanges}" "${hglrev}" "${hgmisc_args[@]}"
return 0 return 0

View File

@ -22,21 +22,18 @@ hook_com=(
unstaged_orig "$5" unstaged_orig "$5"
revision "$6" revision "$6"
revision_orig "$6" revision_orig "$6"
misc "$7"
misc_orig "$7"
vcs "${vcs}" vcs "${vcs}"
vcs_orig "${vcs}" vcs_orig "${vcs}"
) )
shift 6
i=0
for tmp in "$@"; do
hook_com[misc$((i++))]="${tmp}"
done
hook_com[misc]=${(j:,:)argv}
hook_com[misc_orig]=${hook_com[misc]}
hook_com[base-name]="${${hook_com[base]}:t}" hook_com[base-name]="${${hook_com[base]}:t}"
hook_com[base-name_orig]="${hook_com[base_name]}" hook_com[base-name_orig]="${hook_com[base_name]}"
hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})" hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
hook_com[subdir_orig]="${hook_com[subdir]}" hook_com[subdir_orig]="${hook_com[subdir]}"
VCS_INFO_hook 'post-backend'
## description: ## description:
# action: a string that signals a certain non-default condition in the # action: a string that signals a certain non-default condition in the
# repository (like 'rebase-i' in git). If this in non-empty, # repository (like 'rebase-i' in git). If this in non-empty,
@ -46,8 +43,7 @@ hook_com[subdir_orig]="${hook_com[subdir]}"
# staged: non-empty if the repository contains staged changes. # staged: non-empty if the repository contains staged changes.
# unstaged: non-empty if the repository contains unstaged changes. # unstaged: non-empty if the repository contains unstaged changes.
# revision: an identifier of the currently checked out revision. # revision: an identifier of the currently checked out revision.
# misc0..N: a set of strings that may contain anything the author likes. # misc: a string that may contain anything the backend author likes.
# the backends should document what they put in it and when.
# #
# If an argument has no valid value for a given backend, an empty value # If an argument has no valid value for a given backend, an empty value
# should be provided. eg: # should be provided. eg:
@ -71,6 +67,15 @@ if [[ -n ${hook_com[unstaged]} ]] ; then
[[ -z ${tmp} ]] && hook_com[unstaged]='U' || hook_com[unstaged]=${tmp} [[ -z ${tmp} ]] && hook_com[unstaged]='U' || hook_com[unstaged]=${tmp}
fi fi
if [[ ${quiltmode} != 'standalone' ]] && VCS_INFO_hook "pre-addon-quilt"; then
local -x REPLY
VCS_INFO_quilt addon
hook_com[quilt]="${REPLY}"
unset REPLY
elif [[ ${quiltmode} == 'standalone' ]]; then
hook_com[quilt]=${hook_com[misc]}
fi
(( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=() (( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=()
for i in {1..${#msgs}} ; do for i in {1..${#msgs}} ; do
if VCS_INFO_hook "set-message" $(( $i - 1 )) "${msgs[$i]}"; then if VCS_INFO_hook "set-message" $(( $i - 1 )) "${msgs[$i]}"; then
@ -83,6 +88,7 @@ for i in {1..${#msgs}} ; do
r:${hook_com[base-name]} \ r:${hook_com[base-name]} \
s:${hook_com[vcs]} \ s:${hook_com[vcs]} \
u:${hook_com[unstaged]} \ u:${hook_com[unstaged]} \
Q:${hook_com[quilt]} \
R:${hook_com[base]} \ R:${hook_com[base]} \
S:${hook_com[subdir]} S:${hook_com[subdir]}
msgs[$i]=${msg} msgs[$i]=${msg}
@ -90,4 +96,6 @@ for i in {1..${#msgs}} ; do
msgs[$i]=${hook_com[message]} msgs[$i]=${hook_com[message]}
fi fi
done done
hook_com=()
backend_misc=()
return 0 return 0

View File

@ -20,8 +20,11 @@ if (( debug )); then
fi fi
zstyle -a "${context}" hooks hooks || return 0 zstyle -a "${context}" hooks hooks || return 0
# protect some internal variables in hooks # Protect some internal variables in hooks. The `-g' parameter to
typeset -r vcs rrn usercontext maxexports msgs vcs_comm # typeset does *not* make the parameters global here (they are already
# "*-local-export). It prevents typeset from creating *new* *local*
# parameters in this function's scope.
typeset -g -r vcs rrn usercontext maxexports msgs vcs_comm
for hook in ${hooks} ; do for hook in ${hooks} ; do
func="+vi-${hook}" func="+vi-${hook}"
if (( ${+functions[$func]} == 0 )); then if (( ${+functions[$func]} == 0 )); then
@ -29,6 +32,7 @@ for hook in ${hooks} ; do
continue continue
fi fi
(( debug )) && printf ' + Running function: "%s"\n' "${func}" (( debug )) && printf ' + Running function: "%s"\n' "${func}"
true
${func} "$@" ${func} "$@"
case $? in case $? in
(0) (0)
@ -38,5 +42,5 @@ for hook in ${hooks} ; do
;; ;;
esac esac
done done
typeset +r vcs rrn usercontext maxexports msgs vcs_comm typeset -g +r vcs rrn usercontext maxexports msgs vcs_comm
return $ret return $ret

View File

@ -0,0 +1,190 @@
## vim:ft=zsh:foldmethod=marker
function VCS_INFO_quilt-match() {
emulate -L zsh
setopt extendedglob
local d mode="$1" param="$2"
local -a list
case ${mode} in
(assoc) list=( ${(kOP)param} );;
(array) : "${foo[@]}" ${(t)foo}; list=( ${(OP)param} );;
(*) return 1;;
esac
for d in "${list[@]}"; do
if [[ ${PWD} == ${d%/##}(|/*) ]]; then
print "$d"
return 0
fi
done
return 1
}
function VCS_INFO_quilt-standalone-detect() {
emulate -L zsh
setopt extendedglob
local param
local -i ret
zstyle -s "${context}" quilt-standalone param || return 1
[[ "${param}" == 'never' ]] && return 1
[[ "${param}" == 'always' ]] && return 0
if (( ${+functions[$param]} )); then
${param}
return $?
fi
case ${(Pt)param} in
*association*)
local m
local -A A
m="$(VCS_INFO_quilt-match assoc ${param})"
A=(${(kvP)param})
(( $? == 0 )) && [[ ${A[$m]} == "true" ]] && return 0
return 1
;;
*array*)
typeset -gU ${param}
VCS_INFO_quilt-match array ${param} > /dev/null
return $?
;;
*scalar*)
[[ "${(P)param}" == 'always' ]] && return 0
[[ "${(P)param}" == 'never' ]] && return 1
;;
esac
# If nothing hit yet, it just wasn't meant to be.
return 1
}
function VCS_INFO_quilt-dirfind() {
# This is a wrapper around VCS_INFO_bydir_detect(). It makes sure
# that $vcs_comm[] is unchanged. Currently, changing anything in it
# should not be an issue, but this makes sure the code can safely
# be called elsewhere, too - if needed.
emulate -L zsh
setopt extendedglob
local dir="$1" file="$2"; shift $#
local ret oldfile olddir
olddir=${vcs_comm[basedir]}
vcs_comm[basedir]=''
if [[ -n "${file}" ]]; then
oldfile=${vcs_comm[detect_need_file]}
vcs_comm[detect_need_file]=${file}
fi
VCS_INFO_bydir_detect ${dir}
ret=$?
[[ -n "${file}" ]] && vcs_comm[detect_need_file]=${oldfile}
printf '%s' ${vcs_comm[basedir]}
vcs_comm[basedir]="${olddir}"
return ${ret}
}
function VCS_INFO_quilt() {
emulate -L zsh
setopt extendedglob
local mode="$1"
local patches pc tmp qstring root
local -i ret
local -x context
local -a applied unapplied applied_string unapplied_string quiltcommand
local -Ax hook_com
context=":vcs_info:${vcs}.quilt-${mode}:${usercontext}:${rrn}"
zstyle -t "${context}" use-quilt || return 1
case ${mode} in
(standalone)
VCS_INFO_quilt-standalone-detect || return 1
;;
(addon)
;;
(*)
printf 'Invalid mode: `%s'\''\n' "$1"
return 2
;;
esac
zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
if [[ "${patches}" != /* ]]; then
tmp=${patches:-patches}
patches="$(VCS_INFO_quilt-dirfind "${tmp}")"
ret=$?
(( ret )) && return ${ret}
patches=${patches}/${tmp}
else
[[ -d ${patches} ]] || return 1
fi
pc="$(VCS_INFO_quilt-dirfind .pc .version)"
ret=$?
if (( ret == 0 )); then
[[ ${quiltmode} == 'standalone' ]] && root=${pc}
pc=${pc}/.pc
if [[ -e ${pc}/applied-patches ]]; then
applied=( ${(f)"$(<$pc/applied-patches)"} )
# throw away empty entries
applied=( ${applied:#} )
applied=( ${(Oa)applied} )
else
applied=()
fi
fi
if zstyle -t "${context}" get-unapplied; then
# This zstyle call needs to be moved further up if `quilt' needs
# to be run in more places than this one.
zstyle -s "${context}" quiltcommand quiltcommand || quiltcommand='quilt'
unapplied=( ${(f)"$(QUILT_PATCHES=$patches $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
unapplied=( ${unapplied:#} )
else
unapplied=()
fi
if VCS_INFO_hook 'gen-applied-string' "${applied[@]}"; then
if (( ${#applied} )); then
applied_string=${applied[1]}
else
applied_string=""
fi
else
applied_string=${hook_com[applied-string]}
fi
hook_com=()
if VCS_INFO_hook 'gen-unapplied-string' "${unapplied[@]}"; then
unapplied_string="${#unapplied}"
else
unapplied_string=${hook_com[unapplied-string]}
fi
if (( ${#applied} )); then
zstyle -s "${context}" patch-format qstring || qstring="%p (%n applied)"
else
zstyle -s "${context}" nopatch-format qstring || qstring="no patch applied"
fi
hook_com=( applied "${applied_string}" unapplied "${unapplied_string}"
applied-n ${#applied} unapplied-n ${#unapplied} )
if VCS_INFO_hook 'set-patch-format' ${qstring}; then
zformat -f qstring "${qstring}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
"n:${#applied}" "c:${#unapplied}"
else
qstring=${hook_com[patch-replace]}
fi
hook_com=()
case ${mode} in
(standalone)
VCS_INFO_formats '' '' "${root}" '' '' '' "${qstring}"
VCS_INFO_set
;;
(addon)
# When VCS_INFO_quilt() is called with "addon" a "local -x REPLY" variable
# should be in place. That variable can be unset after it's being used.
REPLY="${qstring}"
;;
esac
VCS_INFO_hook 'post-quilt' ${mode} ${patches} ${pc:-\\-nopc-}
}
VCS_INFO_quilt "$@"

View File

@ -21,6 +21,7 @@ static_functions=(
VCS_INFO_hook VCS_INFO_hook
VCS_INFO_maxexports VCS_INFO_maxexports
VCS_INFO_nvcsformats VCS_INFO_nvcsformats
VCS_INFO_quilt
VCS_INFO_realpath VCS_INFO_realpath
VCS_INFO_reposub VCS_INFO_reposub
VCS_INFO_set VCS_INFO_set
@ -45,12 +46,12 @@ vcs_info () {
[[ -r . ]] || return 0 [[ -r . ]] || return 0
local pat local pat
local -i found local -i found retval
local -a enabled disabled dps local -a enabled disabled dps
local -x usercontext vcs rrn LC_MESSAGES local -x usercontext vcs rrn quiltmode LC_MESSAGES
local -ix maxexports local -ix maxexports
local -ax msgs local -ax msgs
local -Ax vcs_comm local -Ax vcs_comm hook_com backend_misc user_data
LC_MESSAGES=C LC_MESSAGES=C
if [[ -n ${LC_ALL} ]]; then if [[ -n ${LC_ALL} ]]; then
@ -58,9 +59,18 @@ vcs_info () {
LANG=${LC_ALL} LANG=${LC_ALL}
local -x LC_ALL local -x LC_ALL
fi fi
vcs='-init-'; rrn='-all-' vcs='-init-'; rrn='-all-'; quiltmode='addon'
usercontext=${1:-default} usercontext=${1:-default}
VCS_INFO_hook "start-up"
retval=$?
if (( retval == 1 )); then
return 0
elif (( retval == 2 )); then
VCS_INFO_set --nvcs
return 0
fi
zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "enable" enabled zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "enable" enabled
(( ${#enabled} == 0 )) && enabled=( all ) (( ${#enabled} == 0 )) && enabled=( all )
@ -99,10 +109,20 @@ vcs_info () {
done done
(( found == 0 )) && { (( found == 0 )) && {
VCS_INFO_set --nvcs vcs='-quilt-'; quiltmode='standalone'
VCS_INFO_quilt standalone || VCS_INFO_set --nvcs
return 0 return 0
} }
VCS_INFO_hook "pre-get-data"
retval=$?
if (( retval == 1 )); then
return 0
elif (( retval == 2 )); then
VCS_INFO_set --nvcs
return 0
fi
VCS_INFO_get_data_${vcs} || { VCS_INFO_get_data_${vcs} || {
VCS_INFO_set --nvcs VCS_INFO_set --nvcs
return 1 return 1

View File

@ -3,4 +3,5 @@ DISTFILES_SRC='
bash2zshprompt bash2zshprompt
c2z compctl-examples globtests globtests.ksh c2z compctl-examples globtests globtests.ksh
job-control-tests lete2ctl make-zsh-urls job-control-tests lete2ctl make-zsh-urls
vcs_info-examples
' '

496
Misc/vcs_info-examples Normal file
View File

@ -0,0 +1,496 @@
# A collection of vcs_info usage examples
### Running vcs_info #########################################################
# As always, there's more than one way to skin a cat. Running vcs_info is
# exception. Here is a rundown of three common ways to get it into action.
#
# All three ways need vcs_info to be marked for autoloading first, so you'd
# do this somewhere in your setup:
autoload -Uz vcs_info
# Episode I: "The prompt_subst way"
# Also known as the Quick-Start-Way. Probably the simplest way to add
# vcs_info functionality to existing setups. You just drop a vcs_info call
# to your `precmd' (or into a `precmd_functions[]' entry) and include a
# single-quoted ${vcs_info_msg_0_} in your PS1 definition:
precmd() { vcs_info }
# This needs prompt_subst set, hence the name. So:
setopt prompt_subst
PS1='%!-%3~ ${vcs_info_msg_0_}%# '
# Episode II: "The way of the psvar"
# With $psvar you got a simple way to get user defined things into your
# prompt without having to set `prompt_subst', which requires extra
# attention to quoting if you like characters like ` in your prompt...
# As described in <http://xana.scru.org/xana2/quanks/vcsinfoprompt/>:
precmd() {
psvar=()
vcs_info
[[ -n $vcs_info_msg_0_ ]] && psvar[1]="$vcs_info_msg_0_"
}
# You can now use `%1v' to drop the $vcs_info_msg_0_ contents in your prompt;
# like this:
PS1="%m%(1v.%F{red}%1v%f.)%# "
# Episode III: "The justsetitinprecmd way"
# This is the way I prefer. When you see it, you may think "Setting that
# variable in precmd() each time? What a waste..."; but let me assure you,
# you're running vcs_info already, setting one variable is not an issue.
#
# You're getting the benefit of being able to programmatically setting your
# prompt, which is nice especially when you're going to do weird things in
# there anyway. Here goes:
precmd() {
# As always first run the system so everything is setup correctly.
vcs_info
# And then just set PS1, RPS1 and whatever you want to. This $PS1
# is (as with the other examples above too) just an example of a very
# basic single-line prompt. See "man zshmisc" for details on how to
# make this less readable. :-)
if [[ -n ${vcs_info_msg_0_} ]]; then
# Oh hey, nothing from vcs_info, so we got more space.
# Let's print a longer part of $PWD...
PS1="%5~%# "
else
# vcs_info found something, that needs space. So a shorter $PWD
# makes sense.
PS1="%3~${vcs_info_msg_0_}%# "
fi
}
### Hooks ####################################################################
# A number of examples in this file revolve around the concept of `hooks'
# in vcs_info. Hooks are places in vcs_info where you may put in your
# own code to achieve something "totally awesome"[tm].
#
# Hooks can be confusing. It's hard to keep track of what's going on.
# In order to help you with that vcs_info can output some debugging
# information when it processes hooks. This will tell you which hooks
# are being run and which functions are attempted to run (and if the
# functions in question were found or not).
#
# If you feel like you need to see what's attempted and where, I suggest
# you use the following line and see for yourself.
zstyle ':vcs_info:*+*:*' debug true
# You can just comment it out (or disable it) again when you've seen enough.
# Debugging is off by default - of course.
zstyle ':vcs_info:*+*:*' debug false
# Further down, every example that uses a function named `+vi-*' uses a hook.
### check-for-changes just in some places ####################################
# Some backends (git and mercurial at the time of writing) can tell you
# whether there are local changes in the current repository. While that's
# nice, the actions needed to obtain the information can be potentially
# expensive. So if you're working on something the size of the linux kernel
# or some corporate code monstrosity you may want to think twice about
# enabling the `check-for-changes' style unconditionally.
#
# Zsh's zstyle configuration system let's you do some magic to enable styles
# only depending on some code you're running.
#
# So, what I'm doing is this: I'm keeping my own projects in `~/src/code'.
# There are the projects I want the information for most. They are also
# a lot smaller than the linux kernel so the information can be retrieved
# instantaneously - even on my old laptop at 600MHz. And the following code
# enables `check-for-changes' only in that subtree:
zstyle -e ':vcs_info:git:*' \
check-for-changes 'estyle-cfc && reply=( true ) || reply=( false )'
function estyle-cfc() {
local d
local -a cfc_dirs
cfc_dirs=(
${HOME}/src/code/*(/)
)
for d in ${cfc_dirs}; do
d=${d%/##}
[[ $PWD == $d(|/*) ]] && return 0
done
return 1
}
### Mercurial Tips #########################################################
### Truncate Long Hashes ####################################################
### Truncate a long hash to 12 characters (which is usually unique enough)
# NOTE: On Mercurial this will hide the second parent hash during a merge
# (see an example in the Mercurial section below on how to retain both parents)
# Use zformat syntax (remember %i is the hash): %12.12i
# First, remove the hash from the default 'branchformat':
zstyle ':vcs_info:hg:*' branchformat '%b'
# Then add the hash to 'formats' as %i and truncate it to 12 chars:
zstyle ':vcs_info:hg:*' formats ' (%s)-[%12.12i %b]-'
### Truncate long hash to 12-chars but also allow for multiple parents
# Hashes are joined with a + to mirror the output of `hg id`.
zstyle ':vcs_info:hg+set-hgrev-format:*' hooks hg-shorthash
function +vi-hg-shorthash() {
local -a parents
parents=( ${(s:+:)hook_com[hash]} )
parents=( ${(@r:12:)parents} )
hook_com[rev-replace]=${(j:+:)parents}
ret=1
}
### Show marker when the working directory is not on a branch head
# This may indicate that running `hg up` will do something
# NOTE: the branchheads.cache file is not updated with every Mercurial
# operation, so it will sometimes give false positives. Think of this more as a
# hint that you might not be on a branch head instead of the final word.
zstyle ':vcs_info:hg+set-hgrev-format:*' hooks hg-storerev
zstyle ':vcs_info:hg+set-message:*' hooks hg-branchhead
# The hash is availabe in the hgrev-format hook, store a copy of it in the
# user_data array so we can access it in the second function
function +vi-hg-storerev() {
user_data[hash]=${hook_com[hash]}
}
function +vi-hg-branchhead() {
local branchheadsfile i_tiphash i_branchname
local -a branchheads
local branchheadsfile=${hook_com[base]}/.hg/branchheads.cache
# Bail out if any mq patches are applied
[[ -s ${hook_com[base]}/.hg/patches/status ]] && return 0
if [[ -r ${branchheadsfile} ]] ; then
while read -r i_tiphash i_branchname ; do
branchheads+=( $i_tiphash )
done < ${branchheadsfile}
if [[ ! ${branchheads[(i)${user_data[hash]}]} -le ${#branchheads} ]] ; then
hook_com[revision]="^ ${hook_com[revision]}"
fi
fi
}
### Run vcs_info selectively to increase speed in large repos #################
# The following example shows a possible setup for vcs_info which displays
# staged and unstaged changes in the vcs_info prompt and prevents running
# it too often for speed reasons.
# Allow substitutions and expansions in the prompt, necessary for
# using a single-quoted $vcs_info_msg_0_ in PS1, RPOMPT (as used here) and
# similar. Other ways of using the information are described above.
setopt promptsubst
# Load vcs_info to display information about version control repositories.
autoload -Uz vcs_info
# Check the repository for changes so they can be used in %u/%c (see
# below). This comes with a speed penalty for bigger repositories.
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:*' get-revision true
# Improve default formats/actionformats to display staged (%c) and
# unstaged (%u) changes. You can change the displayed string with the
# 'unstagedstr' and 'stagedstr' settings.
zstyle ':vcs_info:*' formats " (%s)-[%b]%u%c-"
zstyle ':vcs_info:*' actionformats " (%s)-[%b|%a]%u%c-"
# Default to running vcs_info. If possible we prevent running it later for
# speed reasons. If set to a non empty value vcs_info is run.
FORCE_RUN_VCS_INFO=1
# Only run vcs_info when necessary to speed up the prompt and make using
# check-for-changes bearable in bigger repositories. This setup was
# inspired by Bart Trojanowski
# (http://jukie.net/~bart/blog/pimping-out-zsh-prompt).
#
# This setup is by no means perfect. It can only detect changes done
# through the VCS's commands run by the current shell. If you use your
# editor to commit changes to the VCS or if you run them in another shell
# this setup won't detect them. To fix this just run "cd ." which causes
# vcs_info to run and update the information. If you use aliases to run
# the VCS commands update the case check below.
zstyle ':vcs_info:*+pre-get-data:*' hooks pre-get-data
+vi-pre-get-data() {
# Only Git and Mercurial support and need caching. Abort if any other
# VCS is used.
[[ "$vcs" != git && "$vcs" != hg ]] && return
# If the shell just started up or we changed directories (or for other
# custom reasons) we must run vcs_info.
if [[ -n $FORCE_RUN_VCS_INFO ]]; then
FORCE_RUN_VCS_INFO=
return
fi
# If we got to this point, running vcs_info was not forced, so now we
# default to not running it and selectively choose when we want to run
# it (ret=1 means run it, ret=0 means don't).
ret=1
# If a git/hg command was run then run vcs_info as the status might
# need to be updated.
case "$(fc -ln $(($HISTCMD-1)))" in
git*)
ret=0
;;
hg*)
ret=0
;;
esac
}
# Call vcs_info as precmd before every prompt.
prompt_precmd() {
vcs_info
}
add-zsh-hook precmd prompt_precmd
# Must run vcs_info when changing directories.
prompt_chpwd() {
FORCE_RUN_VCS_INFO=1
}
add-zsh-hook chpwd prompt_chpwd
# Display the VCS information in the right prompt. The {..:- } is a
# workaround for Zsh below 4.3.9.
RPROMPT='${vcs_info_msg_0_:- }'
### Quilt support ############################################################
# Vcs_info does its best to support the patch management system quilt
# <http://savannah.nongnu.org/projects/quilt>. The information gathered by
# the quilt support always (and I'm saying always, because there are two
# ways quilt support can be active - see "man zshcontrib" for details)
# ends up in the `%Q' replacement in formats.
#
# Quilt support is also disabled by default. To turn its `addon' mode
# on for all backends, do:
zstyle ':vcs_info:*' use-quilt true
# Then use `%Q' somewhere in the `formats' and `actionformats' styles:
zstyle ':vcs_info:*' formats " (%s)-[%b%Q]-"
zstyle ':vcs_info:*' actionformats " (%s)-[%b%Q|%a]-"
# In the quilt support code, the zstyle context changes a little, it's now:
# :vcs_info:<vcs>.quilt-<quiltmode>:*:*
# "<vcs>" is the version-control-system string and "<quiltmode>" is either
# `addon' or `standalone'. So, if you'd use quilt on top of CVS, the
# context becomes ":vcs_info:cvs.quilt-addon:*:*".
# That's almost all you need to know. Almost.
#
# Quilt support has a standalone mode. Even though quilt is not really
# a version control system, it keeps track of patches. It can work on top
# of a real VCS (like subversion or CVS - which is covered by addon mode)
# or apply patches to a normal directory tree that's not under version
# control. The debian project does this for a large number of packages,
# during their automatic build process.
# The `use-quilt' style only enables# addon-mode, because for standalone
# mode we'd have to try to detect whether quilt is "active" in a directory.
# You can fine-tune that "detection" using the `quilt-standalone' style.
# If the value of that style is a function name, that function is executed
# without arguments to determine whether quilt-detection should be attempted.
# It's the most powerful way of doing this and we'll give a simple
# example later.
# First let's assume you want standalone mode to be active only in
# /usr/src/debian, ~/src/debian and their subdirectories. That's simple:
typeset -a foobar
foobar=(
/usr/src/debian
~/src/debian
)
zstyle ':vcs_info:*' quilt-standalone foobar
# As mentioned earlier, using a function in this style is more powerful:
function foobar() {
# You can do any sort of wicked wizardry here. This example just
# checks if we're in "/usr/src/debian" or a subdirectory and if so
# enables standalone detection.
[[ $PWD == /usr/src/debian(|/*) ]] && return 0
# Returning non-zero means false, which means don't enable the
# "detection".
return 1
}
# In standalone-mode, vcs_info pretends as if quilt actually was a VCS.
# Well, kind of. The vcs string is set to '-quilt-'. So let's define a
# format just for that mode:
zstyle ':vcs_info:-quilt-:*' formats " [%s%Q]-"
# As with other format insertions, you got total control over what is being
# inserted. The `%Q' insertion is controlled by the `quiltformat' and
# `quilt-nopatch-format' styles.
# quiltformat (default: "%p (%n applied)")
# The `%p' replacement tells you which patches are applied. `%n' tells you
# How many patches are applied. `%u' and `%N' do the same for unapplied patches.
#
# Now you might say, that's way too much. That'll eat up my entire screen if I
# all my 1002 patches applied. Well, true.
# By default, `%p' contains the top-most applied patch. `%u' says contains the
# number of unapplied patches and is therefore the same as `%c'.
# There are two hooks you can use to setup what these contain. Those would be
# `gen-applied-string' and `gen-unapplied-string'. We'll go with the default
# here... ...no need to go into every insane detail.
zstyle ':vcs_info:*' quiltformat '#%p [%n|%c]'
# quilt-nopatch-format (default: "no patch applied")
zstyle ':vcs_info:*' quilt-nopatch-format '#cleeaaaaan!1!!'
# To retrieve inforamation about unapplied patches, vcs_info invokes `quilt'
# itself. Even though that's pretty quick, it's not needed for the default
# behaviour. If we want to have `%c' and `%u' to contain meaningful data,
# we have to enable retrieval of unapplied data:
zstyle ':vcs_info:*' quilt-get-unapplied true
# With quilt, the location of its patches are configurable. It's either
# $QUILT_PATCHES or `patches' if that's unset. Let's assume we're a debian
# developer and want $QUILT_PATCHES to always be `debian/patches' in stand-
# alone mode:
zstyle ':vcs_info:-quilt-.quilt-standalone:*:*' quilt-patch-dir debian/patches
# Since we're a debian developer, we also have some packages of our own,
# and so we want addon mode to also use a $QUILT_PATCHES value of
# `debian/patches' in some directories. In the other directories we never
# want the default `patches' though but a dedicated place for them.
# Say `~/patches/<repository-name>'. Now we'll use some evaluated-style
# magic to achieve all that:
zstyle -e ':vcs_info:*.quilt-addon:*:*' quilt-patch-dir 'my-patches-func'
# That runs something called `my-patches-func', and the value of $reply is
# used as the value for the `quilt-patch-dir' style. We'll define the thing
# as a function - as the name suggests:
function my-patches-func() {
local p
# As the tidy debian developer we are, we're keeping our packages
# in VCSs and they are located in one place `~/src/mypkgs/'
if [[ $PWD == ${HOME}/src/mypkgs(|/*) ]]; then
reply=( debian/patches )
return 0
fi
# Now the part about the dedicated directory is a little trickier.
# It requires some knowledge of vcs_info's internals. Not much though.
# Everything about this is described in the manual because this
# variable (plus a few others) may be of interest in hooks, where
# they are available, too.
#
# The variable in question here is `$rrn' which is an abbreviation
# of repository-root-name. if you're in
# /usr/src/zsh/Functions
# and the repository being
# /usr/src/zsh
# then the value of `$rrn' is `zsh'. Now in case the variable is
# empty (it shouldn't at this point, but you never know), let's
# drop back to quilt's default "patches".
if [[ -z ${rrn} ]]; then
reply=( patches )
return 0
fi
# If we're here, there's something in $rrn, so:
p="${HOME}/patches/${rrn}"
if [[ ! -d $p ]]; then
# ...and while we're at it, make sure it exists...
mkdir -p "$p"
fi
reply=( $p )
}
# And finally, let's use the `post-quilt' hook to let vcs_info help us
# with setting the $QUILT_PATCHES variable. Since vcs_info already knows
# which $QUILT_PATCHES value is correct, it should just export that variable
# for us. No need to configure something twice when it can work
# automatically. :-)
# Register the hook:
zstyle ':vcs_info:*+post-quilt:*:*' hooks set-quilt-patches
# Define the corresponding function:
function +vi-set-quilt-patches() {
# The `post-quilt' hook functions are called with three arguments:
# $1 the mode (`addon' vs. `standalone').
# $2 the path-name of the detected patches directory.
# $3 the path-name of the `.pc' directory (or "-nopc-" if it
# could not be found).
# So, what we're after is in $2 already, which makes this function
# rather trivial:
export QUILT_PATCHES="$2"
return 0
}
# This would take care of all the dedicated-patches-directory-in-${HOME}
# from earlier examples, too.
### Using vcs_info from CVS ##################################################
# You've decided you desperately need a newer feature of vcs_info than
# there is in your installed version of zsh. That's possible, but be aware
# that you are choosing not only the newest features but potentially also
# the newest bugs of vcs_info. Also note, that vcs_info from CVS *may* rely
# on features of zsh that are only available in a newer version than you
# got installed on your system.
#
# So, now that the warnings are out of the way - let's cut to the chase:
# First you'll need to decide where to put the files from CVS. Many people
# keep a directory for personal function files such as `~/.zfuncs' or
# similar. That's what we'll use here.
#
# Step one: "get the thing from CVS"
# % mkdir -p ~/.zfuncs
# % cd ~/.zfuncs
# % cvs -z3 -d:pserver:anonymous@zsh.cvs.sourceforge.net:/cvsroot/zsh \
# co -d VCS_Info -PA zsh/Functions/VCS_Info
#
# There, now you got a `~/.zfuncs/VCS_Info' directory that has all the files
# you need. Whenever you feel like updating the checkout, you can do:
# % cd ~/.zfuncs/VCS_Info; cvs up; cd -
#
# Step two: "Tell zsh to use the checkout"
# Zsh looks for function files in the directories listed in $fpath. If
# you're already using `~/.zfuncs' you probably have something like this
# in your setup:
fpath=( ~/.zfuncs $fpath )
# Note, that the private directory is added in *front* of the default
# value, so that files from that directory supersede the ones from system
# directories. To add the VCS_Info subtree (excluding the CVS directories)
# in front, change that line to this:
fpath=( ~/.zfuncs ~/.zfuncs/VCS_Info/**/*~*/(CVS)#(/) $fpath )
# The weirdly looking pattern requires the `extended_glob' option to be
# active, so make sure it is.
#
# Step three: "Restart Z shell"
# A simple
# % exec zsh
# gets you there. You should be all set now. Have fun.