145 Commits
v3.4 ... v3.7

Author SHA1 Message Date
Tim Pope
96c1009fcf fugitive.vim 3.7
Move "Unpushed" sections above "Unpulled".
Show commits that are unpushed anywhere when no upstream is set.
Provide czs map as :Git stash push --staged.
Support the MSYS Vim bundled with Git for Windows.
Turn remaining deprecated commands (:Gbrowse, etc.) into error stubs.
2022-06-07 01:03:24 -04:00
Tim Pope
5920f807f5 Expire b:git_dir on buffer rename 2022-06-03 20:33:48 -04:00
Tim Pope
f60fc79e53 Avoid unnamed buffer with :set hidden
Resolves: https://github.com/tpope/vim-fugitive/issues/2004
2022-06-01 12:54:13 -04:00
Tim Pope
fb07620878 Retool $GIT_INDEX_FILE handling
* Don't attempt to handle relative paths, as there's no guarantee the
  current working directory is the one Vim was started with.  In
  practice, the only relative path I've seen is `.git/index`, which is
  already the default and thus harmless to ignore.
* Cache the result of FugitiveVimPath(), to allow for slow
  implementations.
2022-05-31 16:11:22 -04:00
Tim Pope
8fba012775 Fix fugitive#simplify() with summary URL 2022-05-31 16:11:22 -04:00
Tim Pope
596621dc6e Support Git for Windows bundled MSYS Vim
References: https://github.com/tpope/vim-fugitive/issues/1970
2022-05-30 16:48:48 -04:00
Tim Pope
5bf3fd40f6 Provide FugitiveActualDir()
This is intended to free up FugitiveGitDir() to refer to the ".git" file
in that work tree and submodule repositories use.  I wish I had better
names for these two.  Settling for "Actual" as that at least has a
pleasing 6 letter symmetry with "Common".
2022-05-30 14:03:43 -04:00
Tim Pope
950f9c49fc Introduce helper to normalize to backslashes on win32
FugitiveVimPath() is intended to potentially convert between UNIX and
Windows paths in mixed environments.  Let's separate uses that require
that from those that simply normalize slashes.
2022-05-30 14:03:43 -04:00
Tim Pope
92870eb6d2 Remove dead code for resolving symlinked buffer name
The `:p` flag resolves symlinks, so the resolve() call is a no-op, and
the subsequent conditional is always false.  It also appears to be no
longer necessary, though I'd have to do a bit more digging to figure out
why.
2022-05-28 21:57:21 -04:00
Tim Pope
5ec0793b88 Accept both fugitive://C:/ and fugitive:///C:/ on win32
The 2 slash version slots the drive letter into the host field, which
I'm worried will cause problems when the URLs are used non-opaquely, for
example, with an LSP.  Let's start transitioning to the convention used
by file:// URLs.
2022-05-28 21:00:24 -04:00
Tim Pope
a504abb8b8 Avoid reusing variable 2022-05-28 21:00:24 -04:00
Tim Pope
ad16275775 Fix statusline indicator on older Vim
Vim was clearing the statusline due to an error, despite the fact the
exception was caught and ignored.
2022-05-27 22:56:20 -04:00
Tim Pope
41939b09cb Move s:SameRepo() next to other Git dir functions 2022-05-27 21:01:42 -04:00
Tim Pope
097ce939da Make summary buffer available at fugitive:// URL
Using $GIT_DIR/index for the summary buffer has 2 problems:

* It requires a BufReadCmd for all files named "index", necessitating
  special handling for false positives.
* It forces us to resolve ".git" files and symlinks, decoupling us from
  the worktree and thus forcing us to depend on `core.worktree`.  Git
  always sets this when necessary, but users and third-party tooling
  sometimes do not.

Using a fugitive:// URL for the buffer solves both.

This is a large, breaking change, so let's leave $GIT_DIR/index as the
default for now.
2022-05-27 19:50:53 -04:00
Tim Pope
9a4f1e9df2 Extract helper for checking for same repository 2022-05-27 18:20:45 -04:00
Tim Pope
0e9f763c7b Allow :GBrowse : to browse to repository homepage 2022-05-22 22:26:45 -04:00
Tim Pope
fb32927ff5 Use correct normalization of URL in fugitive#Path() 2022-05-22 22:26:45 -04:00
Tim Pope
22a843f8e6 Add missing ! to function definition 2022-05-22 22:26:45 -04:00
Tim Pope
9f30e4d904 Experimentally allow passing Git dir to fugitive#Command()
References: https://github.com/tpope/vim-fugitive/issues/1981
2022-05-22 17:33:53 -04:00
Tim Pope
cdacef342d Distinguish between uses of Git dir, part 2
See 5d1a276b45.
2022-05-21 21:35:50 -04:00
Tim Pope
f48cbb92c5 Read more of config file for core.worktree check
References: https://github.com/tpope/vim-fugitive/issues/1920
2022-05-21 21:35:50 -04:00
Tim Pope
589e8b51c2 Track correct window when blaming twice-open buffer
Resolves: https://github.com/tpope/vim-fugitive/issues/1992
2022-05-21 21:35:49 -04:00
Tim Pope
5b62c75238 Extract Git dir cache keys to local variables
Allow for a non-string representation of the repository to replace the
dir parameter.
2022-05-14 02:35:39 -04:00
Tim Pope
a8139d37b2 Properly normalize Git dir in 'keywordprg' 2022-05-13 01:56:20 -04:00
Tim Pope
f529acef74 Force Vim path normalization in fugitive#Path()
This only matters for use cases where the paths differ by more than just
slashes (theoretically possible with mixed WSL setups).
2022-05-11 02:12:21 -04:00
Tim Pope
87923d1b1b Fix HEAD cache expiry on FugitiveDidChange() 2022-05-11 00:23:14 -04:00
Tim Pope
af8b352dbf Remove redundant "dir" keys from dictionaries 2022-05-11 00:23:14 -04:00
Tim Pope
b81c59bd6a Remove fugitive#head() 2022-05-10 22:47:05 -04:00
Tim Pope
b7287bd542 Provide explicit explanation of command naming 2022-04-26 16:21:33 -04:00
Tim Pope
b5bbd0d181 Clarify ~ and P maps in blame window
Resolves: https://github.com/tpope/vim-fugitive/issues/1980
2022-04-21 15:05:35 -04:00
Tim Pope
b04708af2d Revert "Avoid IO from ":p" during detection"
This change failed to account for the directory edge case, where ":p:h"
has the very nice property of giving us back the original input, due to
":p" appending a trailing slash.  Without this, we fail to detect when
editing the root of the repository.

This reverts commit 1b811b88a4.

Resolves: https://github.com/tpope/vim-fugitive/issues/1978
Resolves: https://github.com/tpope/vim-fugitive/issues/1979
2022-04-20 23:25:14 -04:00
Tim Pope
1b811b88a4 Avoid IO from ":p" during detection 2022-04-20 18:29:45 -04:00
Tim Pope
ed1ff363df Remove another acwrite check 2022-04-20 18:29:45 -04:00
Tim Pope
e064f42770 Don't consider buftype=acwrite buffers to have real filenames
Immediately after I changed this I rediscovered the documentation at
`:help E676`.
2022-04-20 18:28:44 -04:00
Maksim Odnoletkov
70251a915f Show local commits when no upstream is set
References: https://github.com/tpope/vim-fugitive/issues/1963
Resolves: https://github.com/tpope/vim-fugitive/issues/1977
2022-04-20 14:47:15 -04:00
Tim Pope
200593827e Adjust handling of 'buftype' during detection 2022-04-19 18:35:15 -04:00
Tim Pope
4b0f2b6045 Default g:ceiling_directories to parent of $HOME
References: https://github.com/tpope/vim-fugitive/issues/1457
2022-04-14 02:31:49 -04:00
Tim Pope
a252be79c0 Check for ch_close_in() to ensure full Vim jobs support
Resolves: https://github.com/tpope/vim-fugitive/issues/1973
2022-04-12 19:51:42 -04:00
Tim Pope
cba863444c Move unpushed sections above unpulled, again
This reverts commit 279d56eb47
(effectively).

References: https://github.com/tpope/vim-fugitive/issues/1963
2022-04-05 12:13:40 -04:00
Tim Pope
d725ef529e Turn remaining deprecated commands into error stubs 2022-04-01 18:27:49 -04:00
Tim Pope
8f169a84ff Allow simultaneous blames in diffed buffers
References: https://github.com/tpope/vim-fugitive/pull/1327
2022-04-01 18:27:49 -04:00
Tim Pope
d9a914b14d Replace 'cursorbind' in blame with manual line syncing
This is the only way to sync the line without also syncing the column.
Syncing the column is particularly problematic when it causes the blame
window to vertically scroll while typing.
2022-04-01 18:27:44 -04:00
Tim Pope
c0701f7a0e Fix expansion of SSH host aliases
Resolves: https://github.com/tpope/vim-fugitive/issues/1962
2022-03-30 11:08:14 -04:00
Tim Pope
321328c6c5 Avoid I/O from ":p" when handling temp files
This isn't a big deal for temp files themselves, but if we're checking
an arbitrary buffer, it's possible we'll end up hitting a slow network
share just to find out if the path is relative.

This new s:AbsoluteVimPath() helper could potentially be reused in a lot
of places.  But this diff is big enough as is; save that for later.
2022-03-26 15:41:55 -04:00
Tim Pope
8157efff49 Provide g:fugitive_defer_to_existing_maps
References: https://github.com/tpope/vim-fugitive/issues/1425
2022-03-25 18:08:01 -04:00
Tim Pope
b6405d8908 Provide literally named <Plug> maps
For every map X, also provide a map <Plug>fugitive:X.

References: https://github.com/tpope/vim-fugitive/issues/1425
2022-03-25 17:50:32 -04:00
Tim Pope
5716e11776 Fix line wrap in README 2022-03-24 08:02:43 -04:00
Tim Pope
46652a304f Add :GUnlink, like in eunuch.vim
This currently mirrors :GRemove, but gives us the option to add a third
variant.
2022-03-09 10:50:24 -05:00
Tim Pope
afd6c13c6b Fix infinite loop when summary window contains no sections
Resolves: https://github.com/tpope/vim-fugitive/issues/1954
2022-03-01 07:35:31 -05:00
Tim Pope
485ce07c27 Match FugitiveRemote() interface to window.location in JS 2022-02-11 13:02:45 -05:00
Tim Pope
c29ef11cd6 Parse anchor in remote URL
I've never seen this in practice, but if it does happen, we shouldn't
include it in the value for "path".
2022-02-11 13:02:45 -05:00
Tim Pope
6c19f1ddfb More robut escaping of +cmd arguments
Resolves: https://github.com/tpope/vim-fugitive/issues/1938
2022-02-02 11:53:01 -05:00
Tim Pope
a443104489 Add czs as :Git stash push --staged
Resolves: https://github.com/tpope/vim-fugitive/issues/1941
2022-02-02 05:49:09 -05:00
Roger Bongers
59529a2c36 Add basic bisect subcommand completion 2022-01-24 21:13:07 -05:00
Tim Pope
a93ceff61f Support extensions.worktreeConfig
Resolves: https://github.com/tpope/vim-fugitive/issues/1898
2022-01-13 14:06:42 -05:00
Tim Pope
f4d94c5985 Move CommonDir() from autoload to plugin 2022-01-11 18:47:38 -05:00
Tim Pope
bb4f9e660b Add core.worktree to FAQ 2022-01-11 18:39:40 -05:00
Tim Pope
189e3c406e Eliminate filereadable() guards by catching readfile() error 2022-01-11 18:36:36 -05:00
Tim Pope
944dc602c6 Require core.bare=true for bare repositories
Resolves: https://github.com/tpope/vim-fugitive/issues/1920
2022-01-11 13:50:55 -05:00
Tim Pope
fa20e5e77c Remove :silent from all :checktime uses
This can appear to hang with 'noautoread', or if the buffer has changed
in memory.  In reality it's not hanging, it's just silenced the
interactive prompt.

Resolves: https://github.com/tpope/vim-fugitive/issues/1917
2022-01-10 11:08:29 -05:00
Tim Pope
57968b63c2 Support tab complete of :Git push remote \+branch
Resolves: https://github.com/tpope/vim-fugitive/issues/1916
2022-01-05 11:10:57 -05:00
Tim Pope
88a97127d1 Account for optional escaping in tab complete
Tab complete results are always passed to fnameescape(), which can
result in the output having more backslashes than the input, causing
those results to be filtered out.  Attempt to reconcile this.

References: https://github.com/tpope/vim-fugitive/issues/1916
2022-01-05 11:08:38 -05:00
Tim Pope
b6dbb97759 Extend lazy detection to netrw
The requires dropping support for b:netrw_curdir, which was added in
fecd42864a for the vague reason of
handling "unusually named netrw buffers".  I'll figure out what to do
about those alleged buffers when one of them surfaces again.
2022-01-05 11:07:15 -05:00
Tim Pope
b1c3cdffc9 Fix status reload after staging entire section
Resolves: https://github.com/tpope/vim-fugitive/issues/1912
2021-12-29 16:50:00 -05:00
Tim Pope
ee992c808c Narrow application of broken jobwait() workaround
Neovim seemlingly forces a redraw if :sleep is called while defocused,
but only if at least one FocusGained/FocusLost autocommand is defined.
The purpose of this :sleep is to force the exit callback to run when
jobwait() erroneously refuses to do the job.  Our exit callback removes
the job from the dictionary, so we can use the lack of a job key in any
dictionary as a signal that we can skip it.  Hacks on top of hacks.

Resolves: https://github.com/tpope/vim-fugitive/issues/1909
References: https://github.com/tpope/vim-fugitive/issues/1857
2021-12-28 16:03:34 -05:00
Tim Pope
831fdab983 Simplify extraction of directory of buffer name
The behavior of :p is more predictable than I realized when I first
wrote this.
2021-12-28 16:03:34 -05:00
Tim Pope
da30818d17 Resize EDITOR window automatically when necessary
Resolves: https://github.com/tpope/vim-fugitive/issues/1907
2021-12-24 12:53:00 -05:00
Tim Pope
ab57abf1d0 Don't feedkeys() into terminal window
Resolves: https://github.com/tpope/vim-fugitive/issues/1908
2021-12-23 21:47:29 -05:00
Tim Pope
f18571e647 Remove redundant ":p" modification during detection
Every ":p" does I/O to check for a directory, so let's do away with the
belt-and-suspenders usage.
2021-12-23 15:00:14 -05:00
Tim Pope
3fb9beacbc Fix possible infinite loop 2021-12-12 13:28:20 -05:00
Tim Pope
365231384c Don't treat buftype=nofile buffer names as file names
Resolves: https://github.com/tpope/vim-fugitive/issues/1905
2021-12-08 16:17:41 -05:00
Tim Pope
c04e80c6eb Fix accidental :execute 0 2021-12-08 16:13:28 -05:00
Tim Pope
79c2b3f48d Try nested autocmds for ReadCmd/WriteCmd
I'm trying to leverage OptionSet for something.  Let's see if this
causes issues for anybody.
2021-12-07 09:17:47 -05:00
Tim Pope
2064312ad7 Don't reject invalid Git dir when detecting common dir
Consumers of this function should be giving us a valid Git dir, and if
they don't, returning an empty string will only make matters worse.

References: https://github.com/tpope/vim-fugitive/pull/1898
2021-12-01 20:05:47 -05:00
Tim Pope
c666c86882 Fix blame from stage buffer
References: https://github.com/tpope/vim-fugitive/issues/1892
2021-12-01 19:48:43 -05:00
Tim Pope
a099a2631c Disable diff.suppressBlankEmpty for summary window diff
Resolves: https://github.com/tpope/vim-fugitive/issues/1897
2021-12-01 19:27:29 -05:00
Tim Pope
82f2841bdf Fix gf error in commit message outside of repository 2021-11-28 15:36:44 -05:00
Tim Pope
5a24c25275 fugitive.vim 3.6
* Fix support for older Vim 7 patch levels.
* Support copies on :Gclog --follow.
2021-11-25 14:53:57 -05:00
Tim Pope
e82332ee9e Try to avoid trailing newline blame issues
Resolves: https://github.com/tpope/vim-fugitive/issues/1892
2021-11-22 13:24:21 -05:00
Tim Pope
64bc1a3431 Remove dead code
The use of remove() here wouldn't actually work as it expects an index,
not a value.
2021-11-19 17:42:33 -05:00
Tim Pope
4a8db6b856 Support copies with :Gclog --follow
Resolves: https://github.com/tpope/vim-fugitive/issues/1891
2021-11-19 17:19:30 -05:00
Tim Pope
3d5d23fe80 Remove q map stubs
Resolves: https://github.com/tpope/vim-fugitive/issues/1890
2021-11-19 17:16:36 -05:00
Tim Pope
2dfaf17f9e Use dummy events to prevent "No matching autocommands" message
This list of events was hand-curated to eliminate events already defined
elsewhere in the autoload file.

Resolves: https://github.com/tpope/vim-fugitive/issues/1887
2021-11-16 16:09:59 -05:00
Tim Pope
69ae31d402 Fix command execution on Vim 7
This worked on my test environment of 7.4.888, but did not work on
7.4.000.

References: https://github.com/tpope/vim-fugitive/issues/1889
2021-11-16 13:44:55 -05:00
Tim Pope
f9c0b8eafe Fix readfile() usage
Resolves: https://github.com/tpope/vim-fugitive/issues/1886
2021-11-15 20:54:19 -05:00
Tim Pope
e47121f8fd Fix typo 2021-11-15 00:31:32 -05:00
Tim Pope
cd67d087df fugitive.vim 3.5
* Lazy initialization.
* Make status buffer diff retrieval asynchronous.
* Support jump to diff from :Git log --name-status.
* Use smudge filters when viewing blobs.
* Provide User FugitiveEditor event.
* Provide FugitiveRemote() API function.
2021-11-15 00:17:52 -05:00
Tim Pope
b736e457b3 Provide FugitiveRemote() 2021-11-13 16:25:36 -05:00
Tim Pope
2e4ee0b5d6 Don't scroll :Git! window for paginated commands
References: https://github.com/tpope/vim-fugitive/issues/1832
2021-11-11 00:44:14 -05:00
Tim Pope
a6b823b8d0 Fix race condition on nvim 0.4
I could have sworn this wasn't necessary on 0.4, which is why I added
the extra clause, but I can consistently reproduce E716 now.

Resolves: https://github.com/tpope/vim-fugitive/issues/1881
2021-11-02 14:07:58 -04:00
Tim Pope
174fd6a39b Revert "Use :redrawstatus rather than &ro = &ro"
Turns out :redrawstatus is a lot more aggressive and can prevent seeing
Fugitive output.

This reverts commit 6ad15506cc.

References: https://github.com/tpope/vim-fugitive/issues/1180
2021-10-27 03:17:44 -04:00
Tim Pope
6ad15506cc Use :redrawstatus rather than &ro = &ro
References: https://github.com/tpope/vim-fugitive/issues/1180
2021-10-26 09:22:33 -04:00
Tim Pope
30933405bb Support blame maps without filetype plugin on
References: https://github.com/tpope/vim-fugitive/issues/1745
2021-10-19 11:44:22 -04:00
Tim Pope
4d29c1d6a0 Provide for retrieving parsed remote URL
The plan is to expose this as FugitiveRemote(), but let's give it some
bake time before making it official.
2021-10-17 20:25:23 -04:00
Tim Pope
93f41ace7d Move to beginning of line in "(" map
Resolves: https://github.com/tpope/vim-fugitive/issues/1867
2021-10-17 11:22:10 -04:00
Tim Pope
d5a6419fcf Guard against parallel status reload
Resolves: https://github.com/tpope/vim-fugitive/issues/1863
2021-10-17 11:22:10 -04:00
Tim Pope
88c7f867cf Further decouple #BufReadStatus() from v:cmdbang 2021-10-16 12:58:13 -04:00
Tim Pope
0615cd2baf Ignore v:cmdbang when not in autocommand 2021-10-16 10:57:04 -04:00
Tim Pope
ca61174e9d Remove leading slash when parsing scpremote:/~user 2021-10-16 10:43:42 -04:00
Tim Pope
a4c6fb74ee Help file formatting fix 2021-10-16 10:43:42 -04:00
Tim Pope
2e66b3ad05 Don't show diff on root commits
The diff on a root commit is often large and seldom helpful, so let's
get rid of it.  This will also be one less thing to worry about when
changing to a fugitive file type.
2021-10-12 12:34:43 -04:00
Tim Pope
e38d029500 Adjust encapsulation of escaped completion handling
Most calls to s:FilterEscape() pass the original escaped argument, so
we should fix the callers that don't.
2021-10-11 00:38:57 -04:00
Tim Pope
69f5fcbd45 Allow escaped characters in tab complete
Resolves: https://github.com/tpope/vim-fugitive/issues/1859
2021-10-10 13:24:20 -04:00
Tim Pope
b540332a3e Improve parallelism of status buffer with earlier diff
This is a trivial gain, but also trivial to implement.
2021-10-08 19:05:18 -04:00
Tim Pope
ae93dbea2e Ensure jobstart on_exit runs when waiting
Resolves: https://github.com/tpope/vim-fugitive/issues/1857
2021-10-08 19:05:18 -04:00
Tim Pope
bcf7478e6b Make status buffer diff retrieval asynchronous
Resolves: https://github.com/tpope/vim-fugitive/issues/1856
2021-10-06 14:45:36 -04:00
Tim Pope
a67854368e Collapse all status buffer diffs on :edit!
References: https://github.com/tpope/vim-fugitive/issues/1563
2021-10-01 14:28:13 -04:00
Tim Pope
e2883a5426 Support reload on custom chmod and unlink events
These were recently added to eunuch.vim, but other plugins may use them
as well.
2021-09-30 12:43:23 -04:00
Tim Pope
194d63da4f Restore laziness of status reload after write
This got lost in a refactor.
2021-09-30 12:43:23 -04:00
Tim Pope
dd39902e3d Minor performance improvement to global map definition 2021-09-30 12:43:23 -04:00
Tim Pope
7e483dc60d Show overflow sections as 255+ not 256
Resolves: https://github.com/tpope/vim-fugitive/issues/1853
2021-09-29 16:59:38 -04:00
Steven Humphrey
1213953abf Fix default remote in fugitive#RemoteUrl
A previous refactor resulted in fugitive#RemoteUrl() with no arguments
returning the string 'origin' instead of git@github.com....
2021-09-28 10:49:14 -04:00
Tim Pope
7b05afd548 Add experimental behavior for X on commit line
Resolves: https://github.com/tpope/vim-fugitive/issues/1847
2021-09-25 10:21:58 -04:00
Tim Pope
915c050724 Fix :GBrowse - destination 2021-09-25 10:20:09 -04:00
Tim Pope
142a0dc0c4 Fix wrong variable name in fugitive#RemoteUrl()
Resolves: https://github.com/tpope/vim-fugitive/pull/1843
2021-09-23 04:39:47 -04:00
Tim Pope
1352646890 Extract helper to parse fugitive#RemoteUrl() arguments 2021-09-19 14:44:42 -04:00
Tim Pope
e1d382b3e7 Fix resolution of scp style URLs 2021-09-19 14:44:42 -04:00
Tim Pope
3d67d23f47 Normalize path when parsing remote URL
Change an empty path to "/" as is the standard interpretation.  And for
git:// and ssh:// URLs, change a leading "/~" to "~", like Git itself
does.
2021-09-19 12:26:14 -04:00
Tim Pope
f02217b776 Avoid repeat config retrieval in :GBrowse 2021-09-19 12:26:12 -04:00
Tim Pope
12c40427a0 Separate remote resolution from URL reassembly 2021-09-19 08:29:40 -04:00
Tim Pope
bb89a7a497 Invert flag for lazy initialization
I think this second argument might become an optional buffer number at
some point, so change the special value for lazy to an invalid buffer
number.
2021-09-19 07:54:03 -04:00
Tim Pope
a67e1f8189 Try to avoid interference by $GIT_DIR and $GIT_WORK_TREE
Resolves: https://github.com/tpope/vim-fugitive/issues/1841
2021-09-17 06:16:58 -04:00
Tim Pope
27abc3f1bd Respect 'splitright' instead of 'splitbelow' for :vertical
Resolves: https://github.com/tpope/vim-fugitive/issues/1839
2021-09-16 08:13:00 -04:00
Tim Pope
67c4c031fa Support jump to diff from :Git log --name-status
Resolves: https://github.com/tpope/vim-fugitive/issues/1838
2021-09-14 18:19:16 -04:00
Tim Pope
79a6a1941d Fix typo 2021-09-14 14:04:42 -04:00
Tim Pope
ba52c2b446 Make RemoteUrl() option parsing a bit less convoluted 2021-09-14 03:38:26 -04:00
Tim Pope
529311cec7 Fix check for wrong executable 2021-09-14 02:12:50 -04:00
Tim Pope
5f387d4783 Fix FugitiveRemoteUrl('origin', FugitiveConfig()) 2021-09-14 00:06:58 -04:00
Tim Pope
5be8263f16 Override GPG_TTY to prevent terminal garbling
Resolves: https://github.com/tpope/vim-fugitive/issues/1836
2021-09-13 21:05:03 -04:00
Tim Pope
1651cd7f20 Extract helper to determine PTY availability
I constantly have to ask about this to troubleshoot bug reports, so make
it easier to determine.

Also rename g:fugitive_pty to make it clearer that it's not a preference
but a debugging tool.
2021-09-13 16:58:42 -04:00
Yuriy Taraday
630ecc8c3a Use --filters in cat-file whenever possible
Starting with Git 2.11 cat-file provides --filters option that can be
specified instead of "blob" type. This option tells Git to use all
filters specified in .gitattributes.

This enables diffs for files with filters, for example, git-crypt.

Closes #1509
2021-09-13 16:16:32 -04:00
Tim Pope
e2927fb467 Force current buffer number for FugitiveStatusline()
This is normally the default, but might be different during an event
like FugitiveChanged.
2021-09-10 16:13:51 -04:00
Tim Pope
1a652c0cdf Tab complete :Git ++options and --options
Resolves: https://github.com/tpope/vim-fugitive/issues/1833
2021-09-10 16:11:39 -04:00
Tim Pope
6b1d90251e Support lazy initialization in statusline indicator
Resolves: https://github.com/tpope/vim-fugitive/issues/1834
2021-09-10 15:51:47 -04:00
Tim Pope
bb4d1dd9a8 Eliminate internal use of FugitiveCommonDir()
Lead by example.
2021-09-10 15:51:41 -04:00
Tim Pope
b6545ad389 Fix inconsistency when scrolling :Git! preview window
Scrolling with win_execute() works fine while the command is running,
but once the job has finished, it fails to update the viewport until the
window is focused.  I don't get it.  It's not like the window knows a
job is running.  The only obvious trigger I could find is that
'nobuflisted' is set once once the job completes, but even disabling
that behavior fails to rectify the problem.  Screw it, manual focus
bouncing for everyone.

References: https://github.com/tpope/vim-fugitive/issues/1832
2021-09-10 02:47:21 -04:00
Tim Pope
be0abe0b21 Standardize <mods> handling for quickfix commands
Use <mods> for :copen rather than :cfirst, as that seems to be the more
useful of the two.

When I call :vertical copen, I get a window that is initially 10
columns wide, but which resizes to 20 columns upon blurring and
refocusing. Not sure what's up with that, but 10 columns is comically
narrow, so let's go ahead and open at 20 columns to begin with.

Resolves: https://github.com/tpope/vim-fugitive/issues/1831
2021-09-08 16:04:35 -04:00
Tim Pope
02eb2e871c Fix typo in error message 2021-09-07 14:16:27 -04:00
Tim Pope
404c3c24e1 Use new tab for --patch maps
References: https://github.com/tpope/vim-fugitive/discussions/1830
2021-09-07 13:59:52 -04:00
Tim Pope
ed6b45a81a Drop unused args parameter from :Gcommand implementations
We stopped using this in 6356bbc4a7.
2021-09-07 13:56:14 -04:00
Tim Pope
6f07d7e6cd Make initialization lazy 2021-09-06 19:03:55 -04:00
Tim Pope
8c243a7f0d Provide User FugitiveEditor event
I'm not sure if this should trigger every time the buffer is loaded, or
only on the initial split.  Arbitrarily pick the latter for now.

References: https://github.com/tpope/vim-fugitive/issues/1828
2021-09-06 15:54:37 -04:00
Tim Pope
0840f001fe Avoid error when mapcheck() and <unique> semantics differ
References: https://github.com/tpope/vim-fugitive/issues/1826
2021-09-05 10:00:39 -04:00
Tim Pope
8d25dd777c Fix pedit map in :Git -p grep
Resolves: https://github.com/tpope/vim-fugitive/issues/1825
2021-09-04 00:13:35 -04:00
Tim Pope
d488a7090f Add >/ and >:/ as work-tree version expansions
Not sure I want to waste the easy to type ">" on the work tree version,
so adding some alternatives.
2021-09-04 00:13:00 -04:00
5 changed files with 907 additions and 510 deletions

View File

@@ -86,7 +86,8 @@ For more information, see `:help fugitive`.
## Installation ## Installation
Install using your favorite package manager, or use Vim's built-in package support: Install using your favorite package manager, or use Vim's built-in package
support:
mkdir -p ~/.vim/pack/tpope/start mkdir -p ~/.vim/pack/tpope/start
cd ~/.vim/pack/tpope/start cd ~/.vim/pack/tpope/start
@@ -103,6 +104,17 @@ it was removed. Use `:Git! push` to use Fugitive's own asynchronous
execution, or retroactively make `:Git push` asynchronous by pressing execution, or retroactively make `:Git push` asynchronous by pressing
`CTRL-D`. `CTRL-D`.
> Why am I getting `core.worktree is required when using an external Git dir`?
Git generally sets `core.worktree` for you automatically when necessary, but
if you're doing something weird, or using a third-party tool that does
something weird, you may need to set it manually:
git config core.worktree "$PWD"
This may be necessary even when simple `git` commands seem to work fine
without it.
> So I have a symlink and... > So I have a symlink and...
Stop. Just stop. If Git won't deal with your symlink, then Fugitive won't Stop. Just stop. If Git won't deal with your symlink, then Fugitive won't

File diff suppressed because it is too large Load Diff

View File

@@ -70,8 +70,8 @@ that are part of Git repositories).
O jump to patch or blob in new tab O jump to patch or blob in new tab
p jump to patch or blob in preview window p jump to patch or blob in preview window
- reblame at commit - reblame at commit
~ reblame at [count]th first grandparent ~ reblame at commit~[count]
P reblame at [count]th parent (like HEAD^[count]) P reblame at commit^[count]
*g:fugitive_dynamic_colors* *g:fugitive_dynamic_colors*
In the GUI or a 256 color terminal, commit hashes will In the GUI or a 256 color terminal, commit hashes will
@@ -98,6 +98,12 @@ that are part of Git repositories).
*:Git_mergetool* *:Git_mergetool*
:Git mergetool [args] Like |:Git_difftool|, but target merge conflicts. :Git mergetool [args] Like |:Git_difftool|, but target merge conflicts.
Wrappers for Vim built-ins ~
These all directly map onto a built-in Vim command, and generally have names
that prepend "G" to the command they are wrapping. For example, :Ggrep is G
plus |:grep|.
*:Ggrep* *:Git_grep* *:Ggrep* *:Git_grep*
:Ggrep[!] [args] An approximation of |:grep|[!] with git-grep as :Ggrep[!] [args] An approximation of |:grep|[!] with git-grep as
:Git[!] grep -O [args] 'grepprg'. :Git[!] grep -O [args] 'grepprg'.
@@ -113,11 +119,12 @@ that are part of Git repositories).
*:Gclog* *:Gclog*
:Gclog[!] [args] Use git-log [args] to load the commit history into the :Gclog[!] [args] Use git-log [args] to load the commit history into the
|quickfix| list. Jumps to the first commit unless [!] |quickfix| list. Jumps to the first commit unless [!]
is given. is given. This command wraps |:cfile|.
The quickfix list can be awkward for many use cases The quickfix list can be awkward for many use cases
and exhibits extremely poor performance with larger and exhibits extremely poor performance with larger
data sets. Consider using |:Git| log instead. data sets. Consider using |:Git| log --oneline
instead.
:{range}Gclog[!] [args] Use git-log -L to load previous revisions of the given :{range}Gclog[!] [args] Use git-log -L to load previous revisions of the given
range of the current file into the |quickfix| list. range of the current file into the |quickfix| list.
@@ -213,6 +220,13 @@ that are part of Git repositories).
'diffopt'. The split will still be vertical if 'diffopt'. The split will still be vertical if
combined with |:vertical|. combined with |:vertical|.
Other commands ~
These do not directly correspond to any built-in Vim command, and have a
capital letter after the "G" to convey this. For example, the file move
operation has nothing to do with the |:move| built-in, so it is named :GMove,
not :Gmove.
*:GMove* *:GMove*
:GMove {destination} Wrapper around git-mv that renames the buffer :GMove {destination} Wrapper around git-mv that renames the buffer
afterward. Add a ! to pass -f. afterward. Add a ! to pass -f.
@@ -227,8 +241,9 @@ that are part of Git repositories).
passed. Add a ! to pass -f and forcefully discard the passed. Add a ! to pass -f and forcefully discard the
buffer. buffer.
*:GRemove* *:GRemove* *:GUnlink*
:GRemove Like |:GDelete|, but keep the (now empty) buffer around. :GRemove Like |:GDelete|, but keep the (now empty) buffer around.
:GUnlink
*:GBrowse* *:GBrowse*
:GBrowse Open the current file, blob, tree, commit, or tag :GBrowse Open the current file, blob, tree, commit, or tag
@@ -318,6 +333,7 @@ dv Perform a |:Gvdiffsplit| on the file under the cursor.
*fugitive_ds* *fugitive_dh* *fugitive_ds* *fugitive_dh*
ds Perform a |:Ghdiffsplit| on the file under the cursor. ds Perform a |:Ghdiffsplit| on the file under the cursor.
dh dh
*fugitive_dq* *fugitive_dq*
dq Close all but one diff buffer, and |:diffoff|! the dq Close all but one diff buffer, and |:diffoff|! the
last one. last one.
@@ -656,6 +672,10 @@ FugitiveIndex After loading the |fugitive-summary| buffer.
FugitivePager After loading a temp file created by a command like FugitivePager After loading a temp file created by a command like
:Git --paginate or :Git blame. :Git --paginate or :Git blame.
*User_FugitiveEditor*
FugitiveEditor After a :Git command (e.g., :Git commit) edits a file
(e.g., the commit message).
*User_FugitiveChanged* *User_FugitiveChanged*
FugitiveChanged After any event which can potentially change the FugitiveChanged After any event which can potentially change the
repository, for example, any invocation of |:Git|. repository, for example, any invocation of |:Git|.

View File

@@ -1,6 +1,6 @@
" fugitive.vim - A Git wrapper so awesome, it should be illegal " fugitive.vim - A Git wrapper so awesome, it should be illegal
" Maintainer: Tim Pope <http://tpo.pe/> " Maintainer: Tim Pope <http://tpo.pe/>
" Version: 3.4 " Version: 3.7
" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim " GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim
if exists('g:loaded_fugitive') if exists('g:loaded_fugitive')
@@ -25,14 +25,14 @@ function! FugitiveGitDir(...) abort
let dir = get(b:, 'git_dir', '') let dir = get(b:, 'git_dir', '')
if empty(dir) && (empty(bufname('')) || &buftype =~# '^\%(nofile\|acwrite\|quickfix\|terminal\|prompt\)$') if empty(dir) && (empty(bufname('')) || &buftype =~# '^\%(nofile\|acwrite\|quickfix\|terminal\|prompt\)$')
return FugitiveExtractGitDir(getcwd()) return FugitiveExtractGitDir(getcwd())
elseif (!exists('b:git_dir') || b:git_dir =~# s:bad_git_dir) && empty(&buftype) elseif (!exists('b:git_dir') || b:git_dir =~# s:bad_git_dir) && &buftype =~# '^\%(nowrite\)\=$'
let b:git_dir = FugitiveExtractGitDir(expand('%:p')) let b:git_dir = FugitiveExtractGitDir(bufnr(''))
return b:git_dir return b:git_dir
endif endif
return dir =~# s:bad_git_dir ? '' : dir return dir =~# s:bad_git_dir ? '' : dir
elseif type(a:1) == type(0) && a:1 isnot# 0 elseif type(a:1) == type(0) && a:1 isnot# 0
if a:1 == bufnr('') && (!exists('b:git_dir') || b:git_dir =~# s:bad_git_dir) && empty(&buftype) if a:1 == bufnr('') && (!exists('b:git_dir') || b:git_dir =~# s:bad_git_dir) && &buftype =~# '^\%(nowrite\)\=$'
let b:git_dir = FugitiveExtractGitDir(expand('%:p')) let b:git_dir = FugitiveExtractGitDir(a:1)
endif endif
let dir = getbufvar(a:1, 'git_dir') let dir = getbufvar(a:1, 'git_dir')
return dir =~# s:bad_git_dir ? '' : dir return dir =~# s:bad_git_dir ? '' : dir
@@ -58,7 +58,7 @@ function! FugitiveReal(...) abort
if type(file) ==# type({}) if type(file) ==# type({})
let dir = FugitiveGitDir(file) let dir = FugitiveGitDir(file)
let tree = s:Tree(dir) let tree = s:Tree(dir)
return FugitiveVimPath(empty(tree) ? dir : tree) return s:VimSlash(empty(tree) ? dir : tree)
elseif file =~# '^\a\a\+:' || a:0 > 1 elseif file =~# '^\a\a\+:' || a:0 > 1
return call('fugitive#Real', [file] + a:000[1:-1]) return call('fugitive#Real', [file] + a:000[1:-1])
elseif file =~# '^/\|^\a:\|^$' elseif file =~# '^/\|^\a:\|^$'
@@ -88,12 +88,12 @@ endfunction
" the inverse of FugitiveFind(). " the inverse of FugitiveFind().
function! FugitiveParse(...) abort function! FugitiveParse(...) abort
let path = s:Slash(a:0 ? a:1 : @%) let path = s:Slash(a:0 ? a:1 : @%)
if path !~# '^fugitive:' if path !~# '^fugitive://'
return ['', ''] return ['', '']
endif endif
let vals = matchlist(path, '\c^fugitive:\%(//\)\=\(.\{-\}\)\%(//\|::\)\(\x\{40,\}\|[0-3]\)\(/.*\)\=$') let vals = matchlist(path, s:dir_commit_file)
if len(vals) if len(vals)
return [(vals[2] =~# '^.$' ? ':' : '') . vals[2] . substitute(vals[3], '^/', ':', ''), vals[1]] return [(vals[2] =~# '^.\=$' ? ':' : '') . vals[2] . substitute(vals[3], '^/', ':', ''), vals[1]]
endif endif
let v:errmsg = 'fugitive: invalid Fugitive URL ' . path let v:errmsg = 'fugitive: invalid Fugitive URL ' . path
throw v:errmsg throw v:errmsg
@@ -210,6 +210,24 @@ function! FugitiveRemoteUrl(...) abort
return call('fugitive#RemoteUrl', a:000) return call('fugitive#RemoteUrl', a:000)
endfunction endfunction
" FugitiveRemote() returns a data structure parsed from the remote URL.
" For example, for remote URL "https://me@example.com:1234/repo.git", the
" returned dictionary will contain the following:
"
" * "scheme": "https"
" * "authority": "user@example.com:1234"
" * "path": "/repo.git" (for SSH URLs this may be a relative path)
" * "pathname": "/repo.git" (always coerced to absolute path)
" * "host": "example.com:1234"
" * "hostname": "example.com"
" * "port": "1234"
" * "user": "me"
" * "path": "/repo.git"
" * "url": "https://me@example.com:1234/repo.git"
function! FugitiveRemote(...) abort
return call('fugitive#Remote', a:000)
endfunction
" FugitiveDidChange() triggers a FugitiveChanged event and reloads the summary " FugitiveDidChange() triggers a FugitiveChanged event and reloads the summary
" buffer for the current or given buffer number's repository. You can also " buffer for the current or given buffer number's repository. You can also
" give the result of a FugitiveExecute() and that context will be made " give the result of a FugitiveExecute() and that context will be made
@@ -259,18 +277,38 @@ function! FugitivePath(...) abort
endfunction endfunction
function! FugitiveStatusline(...) abort function! FugitiveStatusline(...) abort
if empty(get(b:, 'git_dir', '')) if empty(FugitiveGitDir(bufnr('')))
return '' return ''
endif endif
return fugitive#Statusline() return fugitive#Statusline()
endfunction endfunction
function! FugitiveActualDir(...) abort
return call('FugitiveGitDir', a:000)
endfunction
let s:commondirs = {}
function! FugitiveCommonDir(...) abort function! FugitiveCommonDir(...) abort
let dir = FugitiveGitDir(a:0 ? a:1 : -1) let dir = call('FugitiveActualDir', a:000)
if empty(dir) if empty(dir)
return '' return ''
endif endif
return fugitive#Find('.git/refs/..', dir) if has_key(s:commondirs, dir)
return s:commondirs[dir]
endif
if getfsize(dir . '/HEAD') >= 10
let cdir = get(s:ReadFile(dir . '/commondir', 1), 0, '')
if cdir =~# '^/\|^\a:/'
let s:commondirs[dir] = s:Slash(FugitiveVimPath(cdir))
elseif len(cdir)
let s:commondirs[dir] = simplify(dir . '/' . cdir)
else
let s:commondirs[dir] = dir
endif
else
let s:commondirs[dir] = dir
endif
return s:commondirs[dir]
endfunction endfunction
function! FugitiveWorkTree(...) abort function! FugitiveWorkTree(...) abort
@@ -292,6 +330,17 @@ function! FugitiveIsGitDir(...) abort
\ getftype(path.'commondir') ==# 'file') \ getftype(path.'commondir') ==# 'file')
endfunction endfunction
function! s:ReadFile(path, line_count) abort
if v:version < 800 && !filereadable(a:path)
return []
endif
try
return readfile(a:path, 'b', a:line_count)
catch
return []
endtry
endfunction
let s:worktree_for_dir = {} let s:worktree_for_dir = {}
let s:dir_for_worktree = {} let s:dir_for_worktree = {}
function! s:Tree(path) abort function! s:Tree(path) abort
@@ -303,23 +352,32 @@ function! s:Tree(path) abort
endif endif
if !has_key(s:worktree_for_dir, dir) if !has_key(s:worktree_for_dir, dir)
let s:worktree_for_dir[dir] = '' let s:worktree_for_dir[dir] = ''
let config_file = dir . '/config' let ext_wtc_pat = 'v:val =~# "^\\s*worktreeConfig *= *\\%(true\\|yes\\|on\\|1\\) *$"'
if filereadable(config_file) let config = s:ReadFile(dir . '/config', 50)
let config = readfile(config_file,'',10)
let wt_config = filter(copy(config),'v:val =~# "^\\s*worktree *="')
if len(wt_config) == 1
let worktree = FugitiveVimPath(matchstr(wt_config[0], '= *\zs.*'))
else
call filter(config,'v:val =~# "^\\s*bare *= *false *$"')
if len(config) if len(config)
let s:worktree_for_dir[dir] = 0 let ext_wtc_config = filter(copy(config), ext_wtc_pat)
if len(ext_wtc_config) == 1 && filereadable(dir . '/config.worktree')
let config += s:ReadFile(dir . '/config.worktree', 50)
endif endif
endif else
elseif filereadable(dir . '/gitdir') let worktree = fnamemodify(FugitiveVimPath(get(s:ReadFile(dir . '/gitdir', 1), '0', '')), ':h')
let worktree = fnamemodify(FugitiveVimPath(readfile(dir . '/gitdir')[0]), ':h')
if worktree ==# '.' if worktree ==# '.'
unlet! worktree unlet! worktree
endif endif
if len(filter(s:ReadFile(FugitiveCommonDir(dir) . '/config', 50), ext_wtc_pat))
let config = s:ReadFile(dir . '/config.worktree', 50)
endif
endif
if len(config)
let wt_config = filter(copy(config), 'v:val =~# "^\\s*worktree *="')
if len(wt_config)
let worktree = FugitiveVimPath(matchstr(wt_config[0], '= *\zs.*'))
elseif !exists('worktree')
call filter(config,'v:val =~# "^\\s*bare *= *true *$"')
if empty(config)
let s:worktree_for_dir[dir] = 0
endif
endif
endif endif
if exists('worktree') if exists('worktree')
let s:worktree_for_dir[dir] = s:Slash(resolve(worktree)) let s:worktree_for_dir[dir] = s:Slash(resolve(worktree))
@@ -341,48 +399,39 @@ function! s:CeilingDirectories() abort
if empty(dir) if empty(dir)
let resolve = 0 let resolve = 0
elseif resolve elseif resolve
call add(s:ceiling_directories, resolve(dir)) call add(s:ceiling_directories, s:Slash(resolve(dir)))
else else
call add(s:ceiling_directories, dir) call add(s:ceiling_directories, s:Slash(dir))
endif endif
endfor endfor
endif endif
return s:ceiling_directories + get(g:, 'ceiling_directories', []) return s:ceiling_directories + get(g:, 'ceiling_directories', [s:Slash(fnamemodify(expand('~'), ':h'))])
endfunction endfunction
function! FugitiveExtractGitDir(path) abort function! FugitiveExtractGitDir(path) abort
if type(a:path) ==# type({}) if type(a:path) ==# type({})
return get(a:path, 'git_dir', '') return get(a:path, 'git_dir', '')
elseif type(a:path) == type(0) elseif type(a:path) == type(0)
let path = s:Slash(a:path >= 0 ? bufname(a:path) : bufname('')) let path = s:Slash(a:path > 0 ? bufname(a:path) : bufname(''))
else else
let path = s:Slash(a:path) let path = s:Slash(a:path)
endif endif
if path =~# '^fugitive:' if path =~# '^fugitive://'
return matchstr(path, '\C^fugitive:\%(//\)\=\zs.\{-\}\ze\%(//\|::\|$\)') return get(matchlist(path, s:dir_commit_file), 1, '')
elseif empty(path) elseif empty(path)
return '' return ''
elseif isdirectory(path)
let path = fnamemodify(path, ':p:s?/$??')
else
let path = fnamemodify(path, ':p:h:s?/$??')
endif endif
let pre = substitute(matchstr(path, '^\a\a\+\ze:'), '^.', '\u&', '') let pre = substitute(matchstr(path, '^\a\a\+\ze:'), '^.', '\u&', '')
if len(pre) && exists('*' . pre . 'Real') if len(pre) && exists('*' . pre . 'Real')
let path = s:Slash({pre}Real(path)) let path = {pre}Real(path)
endif
let root = resolve(path)
if root !=# path
silent! exe (haslocaldir() ? 'lcd' : exists(':tcd') && haslocaldir(-1) ? 'tcd' : 'cd') '.'
endif endif
let root = s:Slash(fnamemodify(path, ':p:h'))
let previous = "" let previous = ""
let env_git_dir = len($GIT_DIR) ? s:Slash(simplify(fnamemodify(FugitiveVimPath($GIT_DIR), ':p:s?[\/]$??'))) : '' let env_git_dir = len($GIT_DIR) ? s:Slash(simplify(fnamemodify(FugitiveVimPath($GIT_DIR), ':p:s?[\/]$??'))) : ''
call s:Tree(env_git_dir) call s:Tree(env_git_dir)
while root !=# previous let ceiling_directories = s:CeilingDirectories()
if root =~# '\v^//%([^/]+/?)?$' while root !=# previous && root !~# '^$\|^//[^/]*$'
break if index(ceiling_directories, root) >= 0
endif
if index(s:CeilingDirectories(), root) >= 0
break break
endif endif
if root ==# $GIT_WORK_TREE && FugitiveIsGitDir(env_git_dir) if root ==# $GIT_WORK_TREE && FugitiveIsGitDir(env_git_dir)
@@ -396,10 +445,10 @@ function! FugitiveExtractGitDir(path) abort
return dir return dir
elseif type ==# 'link' && FugitiveIsGitDir(dir) elseif type ==# 'link' && FugitiveIsGitDir(dir)
return resolve(dir) return resolve(dir)
elseif type !=# '' && filereadable(dir) elseif type !=# ''
let line = get(readfile(dir, '', 1), 0, '') let line = get(s:ReadFile(dir, 1), 0, '')
let file_dir = s:Slash(FugitiveVimPath(matchstr(line, '^gitdir: \zs.*'))) let file_dir = s:Slash(FugitiveVimPath(matchstr(line, '^gitdir: \zs.*')))
if file_dir !~# '^/\|^\a:' && FugitiveIsGitDir(root . '/' . file_dir) if file_dir !~# '^/\|^\a:\|^$' && FugitiveIsGitDir(root . '/' . file_dir)
return simplify(root . '/' . file_dir) return simplify(root . '/' . file_dir)
elseif len(file_dir) && FugitiveIsGitDir(file_dir) elseif len(file_dir) && FugitiveIsGitDir(file_dir)
return file_dir return file_dir
@@ -420,6 +469,9 @@ function! FugitiveDetect(...) abort
if exists('b:git_dir') && b:git_dir =~# '^$\|' . s:bad_git_dir if exists('b:git_dir') && b:git_dir =~# '^$\|' . s:bad_git_dir
unlet b:git_dir unlet b:git_dir
endif endif
if a:0 > 1 && a:2 is# 0 && !exists('#User#Fugitive')
return ''
endif
if !exists('b:git_dir') if !exists('b:git_dir')
let b:git_dir = FugitiveExtractGitDir(a:0 ? a:1 : bufnr('')) let b:git_dir = FugitiveExtractGitDir(a:0 ? a:1 : bufnr(''))
endif endif
@@ -442,32 +494,54 @@ function! FugitiveDetect(...) abort
return '' return ''
endfunction endfunction
function! FugitiveVimPath(path) abort
if exists('+shellslash') && !&shellslash
return tr(a:path, '/', '\')
else
return a:path
endif
endfunction
function! FugitiveGitPath(path) abort function! FugitiveGitPath(path) abort
return s:Slash(a:path) return s:Slash(a:path)
endfunction endfunction
if exists('+shellslash') if exists('+shellslash')
let s:dir_commit_file = '\c^fugitive://\%(/\a\@=\)\=\(.\{-\}\)//\%(\(\x\{40,\}\|[0-3]\)\(/.*\)\=\)\=$'
function! s:Slash(path) abort function! s:Slash(path) abort
return tr(a:path, '\', '/') return tr(a:path, '\', '/')
endfunction endfunction
function! s:VimSlash(path) abort
return tr(a:path, '\/', &shellslash ? '//' : '\\')
endfunction
function FugitiveVimPath(path) abort
return tr(a:path, '\/', &shellslash ? '//' : '\\')
endfunction
else else
let s:dir_commit_file = '\c^fugitive://\(.\{-\}\)//\%(\(\x\{40,\}\|[0-3]\)\(/.*\)\=\)\=$'
function! s:Slash(path) abort function! s:Slash(path) abort
return a:path return a:path
endfunction endfunction
function! s:VimSlash(path) abort
return a:path
endfunction
if has('win32unix') && filereadable('/git-bash.exe')
function! FugitiveVimPath(path) abort
return substitute(a:path, '^\(\a\):', '/\l\1', '')
endfunction
else
function! FugitiveVimPath(path) abort
return a:path
endfunction
endif
endif endif
function! s:ProjectionistDetect() abort function! s:ProjectionistDetect() abort
let file = s:Slash(get(g:, 'projectionist_file', '')) let file = s:Slash(get(g:, 'projectionist_file', ''))
let dir = FugitiveExtractGitDir(file) let dir = FugitiveExtractGitDir(file)
let base = matchstr(file, '^fugitive://.\{-\}//\x\+') let base = get(matchlist(file, s:dir_commit_file), 1, '')
if empty(base) if empty(base)
let base = s:Tree(dir) let base = s:Tree(dir)
endif endif
@@ -475,7 +549,7 @@ function! s:ProjectionistDetect() abort
if exists('+shellslash') && !&shellslash if exists('+shellslash') && !&shellslash
let base = tr(base, '/', '\') let base = tr(base, '/', '\')
endif endif
let file = FugitiveCommonDir(dir) . '/info/projections.json' let file = FugitiveFind('.git/info/projections.json', dir)
if filereadable(file) if filereadable(file)
call projectionist#append(base, file) call projectionist#append(base, file)
endif endif
@@ -529,51 +603,65 @@ exe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete
exe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete Gllog :exe fugitive#LogCommand(<line1>,<count>,+"<range>",<bang>0,"<mods>",<q-args>, "l")' exe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete Gllog :exe fugitive#LogCommand(<line1>,<count>,+"<range>",<bang>0,"<mods>",<q-args>, "l")'
exe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete GlLog :exe fugitive#LogCommand(<line1>,<count>,+"<range>",<bang>0,"<mods>",<q-args>, "l")' exe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete GlLog :exe fugitive#LogCommand(<line1>,<count>,+"<range>",<bang>0,"<mods>",<q-args>, "l")'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Ge exe fugitive#Open("edit<bang>", 0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Ge exe fugitive#Open("edit<bang>", 0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gedit exe fugitive#Open("edit<bang>", 0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gedit exe fugitive#Open("edit<bang>", 0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#ReadComplete Gpedit exe fugitive#Open("pedit", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#ReadComplete Gpedit exe fugitive#Open("pedit", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -range=-1' s:addr_other '-complete=customlist,fugitive#ReadComplete Gsplit exe fugitive#Open((<count> > 0 ? <count> : "").(<count> ? "split" : "edit"), <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -range=-1' s:addr_other '-complete=customlist,fugitive#ReadComplete Gsplit exe fugitive#Open((<count> > 0 ? <count> : "").(<count> ? "split" : "edit"), <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -range=-1' s:addr_other '-complete=customlist,fugitive#ReadComplete Gvsplit exe fugitive#Open((<count> > 0 ? <count> : "").(<count> ? "vsplit" : "edit!"), <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -range=-1' s:addr_other '-complete=customlist,fugitive#ReadComplete Gvsplit exe fugitive#Open((<count> > 0 ? <count> : "").(<count> ? "vsplit" : "edit!"), <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -range=-1' s:addr_tabs '-complete=customlist,fugitive#ReadComplete Gtabedit exe fugitive#Open((<count> >= 0 ? <count> : "")."tabedit", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -range=-1' s:addr_tabs '-complete=customlist,fugitive#ReadComplete Gtabedit exe fugitive#Open((<count> >= 0 ? <count> : "")."tabedit", <bang>0, "<mods>", <q-args>)'
if exists(':Gr') != 2 if exists(':Gr') != 2
exe 'command! -bar -bang -nargs=* -range=-1 -complete=customlist,fugitive#ReadComplete Gr exe fugitive#ReadCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -range=-1 -complete=customlist,fugitive#ReadComplete Gr exe fugitive#ReadCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
endif endif
exe 'command! -bar -bang -nargs=* -range=-1 -complete=customlist,fugitive#ReadComplete Gread exe fugitive#ReadCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -range=-1 -complete=customlist,fugitive#ReadComplete Gread exe fugitive#ReadCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gdiffsplit exe fugitive#Diffsplit(1, <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gdiffsplit exe fugitive#Diffsplit(1, <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Ghdiffsplit exe fugitive#Diffsplit(0, <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Ghdiffsplit exe fugitive#Diffsplit(0, <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gvdiffsplit exe fugitive#Diffsplit(0, <bang>0, "vertical <mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gvdiffsplit exe fugitive#Diffsplit(0, <bang>0, "vertical <mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gw exe fugitive#WriteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gw exe fugitive#WriteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gwrite exe fugitive#WriteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gwrite exe fugitive#WriteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gwq exe fugitive#WqCommand( <line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gwq exe fugitive#WqCommand( <line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=0 GRemove exe fugitive#RemoveCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=0 GRemove exe fugitive#RemoveCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=0 GDelete exe fugitive#DeleteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=0 GUnlink exe fugitive#UnlinkCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#CompleteObject GMove exe fugitive#MoveCommand( <line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=0 GDelete exe fugitive#DeleteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#RenameComplete GRename exe fugitive#RenameCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#CompleteObject GMove exe fugitive#MoveCommand( <line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
if exists(':Gremove') != 2 && get(g:, 'fugitive_legacy_commands', 1) exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#RenameComplete GRename exe fugitive#RenameCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
exe 'command! -bar -bang -nargs=0 Gremove exe fugitive#RemoveCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' if exists(':Gremove') != 2 && get(g:, 'fugitive_legacy_commands', 0)
exe 'command! -bar -bang -nargs=0 Gremove exe fugitive#RemoveCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
\ '|echohl WarningMSG|echomsg ":Gremove is deprecated in favor of :GRemove"|echohl NONE' \ '|echohl WarningMSG|echomsg ":Gremove is deprecated in favor of :GRemove"|echohl NONE'
elseif exists(':Gremove') != 2 && !exists('g:fugitive_legacy_commands')
exe 'command! -bar -bang -nargs=0 Gremove echoerr ":Gremove has been removed in favor of :GRemove"'
endif endif
if exists(':Gdelete') != 2 && get(g:, 'fugitive_legacy_commands', 1) if exists(':Gdelete') != 2 && get(g:, 'fugitive_legacy_commands', 0)
exe 'command! -bar -bang -nargs=0 Gdelete exe fugitive#DeleteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=0 Gdelete exe fugitive#DeleteCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
\ '|echohl WarningMSG|echomsg ":Gdelete is deprecated in favor of :GDelete"|echohl NONE' \ '|echohl WarningMSG|echomsg ":Gdelete is deprecated in favor of :GDelete"|echohl NONE'
elseif exists(':Gdelete') != 2 && !exists('g:fugitive_legacy_commands')
exe 'command! -bar -bang -nargs=0 Gdelete echoerr ":Gremove has been removed in favor of :GRemove"'
endif endif
if exists(':Gmove') != 2 && get(g:, 'fugitive_legacy_commands', 1) if exists(':Gmove') != 2 && get(g:, 'fugitive_legacy_commands', 0)
exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#CompleteObject Gmove exe fugitive#MoveCommand( <line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#CompleteObject Gmove exe fugitive#MoveCommand( <line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
\ '|echohl WarningMSG|echomsg ":Gmove is deprecated in favor of :GMove"|echohl NONE' \ '|echohl WarningMSG|echomsg ":Gmove is deprecated in favor of :GMove"|echohl NONE'
elseif exists(':Gmove') != 2 && !exists('g:fugitive_legacy_commands')
exe 'command! -bar -bang -nargs=? -complete=customlist,fugitive#CompleteObject Gmove'
\ 'echoerr ":Gmove has been removed in favor of :GMove"'
endif endif
if exists(':Grename') != 2 && get(g:, 'fugitive_legacy_commands', 1) if exists(':Grename') != 2 && get(g:, 'fugitive_legacy_commands', 0)
exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#RenameComplete Grename exe fugitive#RenameCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#RenameComplete Grename exe fugitive#RenameCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
\ '|echohl WarningMSG|echomsg ":Grename is deprecated in favor of :GRename"|echohl NONE' \ '|echohl WarningMSG|echomsg ":Grename is deprecated in favor of :GRename"|echohl NONE'
elseif exists(':Grename') != 2 && !exists('g:fugitive_legacy_commands')
exe 'command! -bar -bang -nargs=? -complete=customlist,fugitive#RenameComplete Grename'
\ 'echoerr ":Grename has been removed in favor of :GRename"'
endif endif
exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject GBrowse exe fugitive#BrowseCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject GBrowse exe fugitive#BrowseCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
if exists(':Gbrowse') != 2 && get(g:, 'fugitive_legacy_commands', 1) if exists(':Gbrowse') != 2 && get(g:, 'fugitive_legacy_commands', 0)
exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject Gbrowse exe fugitive#BrowseCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>, [<f-args>])' exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject Gbrowse exe fugitive#BrowseCommand(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)'
\ '|if <bang>1|redraw!|endif|echohl WarningMSG|echomsg ":Gbrowse is deprecated in favor of :GBrowse"|echohl NONE' \ '|if <bang>1|redraw!|endif|echohl WarningMSG|echomsg ":Gbrowse is deprecated in favor of :GBrowse"|echohl NONE'
elseif exists(':Gbrowse') != 2 && !exists('g:fugitive_legacy_commands')
exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject Gbrowse'
\ 'echoerr ":Gbrowse has been removed in favor of :GBrowse"'
endif endif
if v:version < 703 if v:version < 703
@@ -600,8 +688,9 @@ let g:io_fugitive = {
augroup fugitive augroup fugitive
autocmd! autocmd!
autocmd BufNewFile,BufReadPost * call FugitiveDetect(expand('<amatch>:p')) autocmd BufNewFile,BufReadPost * call FugitiveDetect(+expand('<abuf>'), 0)
autocmd FileType netrw call FugitiveDetect(fnamemodify(get(b:, 'netrw_curdir', expand('<amatch>')), ':p')) autocmd FileType netrw call FugitiveDetect(+expand('<abuf>'), 0)
autocmd BufFilePost * unlet! b:git_dir
autocmd FileType git autocmd FileType git
\ call fugitive#MapCfile() \ call fugitive#MapCfile()
@@ -621,26 +710,26 @@ augroup fugitive
\ endif | \ endif |
\ let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') . '|setl inex= inc=' \ let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') . '|setl inex= inc='
autocmd BufReadCmd index{,.lock} autocmd BufReadCmd index{,.lock} nested
\ if FugitiveIsGitDir(expand('<amatch>:p:h')) | \ if FugitiveIsGitDir(expand('<amatch>:p:h')) |
\ let b:git_dir = s:Slash(expand('<amatch>:p:h')) | \ let b:git_dir = s:Slash(expand('<amatch>:p:h')) |
\ exe fugitive#BufReadStatus() | \ exe fugitive#BufReadStatus(v:cmdbang) |
\ elseif filereadable(expand('<amatch>')) | \ elseif filereadable(expand('<amatch>')) |
\ silent doautocmd BufReadPre | \ silent doautocmd BufReadPre |
\ keepalt read <amatch> | \ keepalt noautocmd read <amatch> |
\ 1delete_ | \ silent 1delete_ |
\ silent doautocmd BufReadPost | \ silent doautocmd BufReadPost |
\ else | \ else |
\ silent doautocmd BufNewFile | \ silent doautocmd BufNewFile |
\ endif \ endif
autocmd BufReadCmd fugitive://*//* exe fugitive#BufReadCmd() | autocmd BufReadCmd fugitive://*//* nested exe fugitive#BufReadCmd() |
\ if &path =~# '^\.\%(,\|$\)' | \ if &path =~# '^\.\%(,\|$\)' |
\ let &l:path = substitute(&path, '^\.,\=', '', '') | \ let &l:path = substitute(&path, '^\.,\=', '', '') |
\ endif \ endif
autocmd BufWriteCmd fugitive://*//[0-3]/* exe fugitive#BufWriteCmd() autocmd BufWriteCmd fugitive://*//[0-3]/* nested exe fugitive#BufWriteCmd()
autocmd FileReadCmd fugitive://*//* exe fugitive#FileReadCmd() autocmd FileReadCmd fugitive://*//* nested exe fugitive#FileReadCmd()
autocmd FileWriteCmd fugitive://*//[0-3]/* exe fugitive#FileWriteCmd() autocmd FileWriteCmd fugitive://*//[0-3]/* nested exe fugitive#FileWriteCmd()
if exists('##SourceCmd') if exists('##SourceCmd')
autocmd SourceCmd fugitive://*//* nested exe fugitive#SourceCmd() autocmd SourceCmd fugitive://*//* nested exe fugitive#SourceCmd()
endif endif
@@ -656,15 +745,12 @@ endif
let s:nowait = v:version >= 704 ? '<nowait>' : '' let s:nowait = v:version >= 704 ? '<nowait>' : ''
function! s:Map(mode, lhs, rhs, ...) abort function! s:Map(mode, lhs, rhs, flags) abort
for mode in split(a:mode, '\zs') let flags = a:flags . (a:rhs =~# '<Plug>' ? '' : '<script>')
let flags = (a:0 ? a:1 : '') . (a:rhs =~# '<Plug>' ? '' : '<script>')
let head = a:lhs let head = a:lhs
let tail = '' let tail = ''
let keys = get(g:, mode.'remap', {}) let keys = get(g:, a:mode.'remap', {})
if type(keys) == type([]) if len(keys) && type(keys) == type({})
return
endif
while !empty(head) while !empty(head)
if has_key(keys, head) if has_key(keys, head)
let head = keys[head] let head = keys[head]
@@ -676,11 +762,13 @@ function! s:Map(mode, lhs, rhs, ...) abort
let tail = matchstr(head, '<[^<>]*>$\|.$') . tail let tail = matchstr(head, '<[^<>]*>$\|.$') . tail
let head = substitute(head, '<[^<>]*>$\|.$', '', '') let head = substitute(head, '<[^<>]*>$\|.$', '', '')
endwhile endwhile
if flags !~# '<unique>' || empty(mapcheck(head.tail, mode))
exe mode.'map' s:nowait flags head.tail a:rhs
endif endif
endfor if empty(mapcheck(head.tail, a:mode))
exe a:mode.'map' s:nowait flags head.tail a:rhs
endif
endfunction endfunction
call s:Map('c', '<C-R><C-G>', 'fnameescape(fugitive#Object(@%))', '<expr>') call s:Map('c', '<C-R><C-G>', 'fnameescape(fugitive#Object(@%))', '<expr>')
call s:Map('n', 'y<C-G>', ':<C-U>call setreg(v:register, fugitive#Object(@%))<CR>', '<silent>') call s:Map('n', 'y<C-G>', ':<C-U>call setreg(v:register, fugitive#Object(@%))<CR>', '<silent>')
nmap <script><silent> <Plug>fugitive:y<C-G> :<C-U>call setreg(v:register, fugitive#Object(@%))<CR>
nmap <script> <Plug>fugitive: <Nop>

View File

@@ -13,10 +13,10 @@ syn match fugitiveHeader /^Pull:\|^Rebase:\|^Merge:\|^Push:/ nextgroup=fugitiveS
syn match fugitiveHelpHeader /^Help:/ nextgroup=fugitiveHelpTag skipwhite syn match fugitiveHelpHeader /^Help:/ nextgroup=fugitiveHelpTag skipwhite
syn match fugitiveHelpTag /\S\+/ contained syn match fugitiveHelpTag /\S\+/ contained
syn region fugitiveSection start=/^\%(.*(\d\+)$\)\@=/ contains=fugitiveHeading end=/^$/ syn region fugitiveSection start=/^\%(.*(\d\++\=)$\)\@=/ contains=fugitiveHeading end=/^$/
syn cluster fugitiveSection contains=fugitiveSection syn cluster fugitiveSection contains=fugitiveSection
syn match fugitiveHeading /^[A-Z][a-z][^:]*\ze (\d\+)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite syn match fugitiveHeading /^[A-Z][a-z][^:]*\ze (\d\++\=)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite
syn match fugitiveCount /(\d\+)/hs=s+1,he=e-1 contained syn match fugitiveCount /(\d\++\=)/hs=s+1,he=e-1 contained
syn match fugitivePreposition /\<\%([io]nto\|from\|to\|Rebasing\%( detached\)\=\)\>/ transparent contained nextgroup=fugitiveHash,fugitiveSymbolicRef skipwhite syn match fugitivePreposition /\<\%([io]nto\|from\|to\|Rebasing\%( detached\)\=\)\>/ transparent contained nextgroup=fugitiveHash,fugitiveSymbolicRef skipwhite
syn match fugitiveInstruction /^\l\l\+\>/ contained containedin=@fugitiveSection nextgroup=fugitiveHash skipwhite syn match fugitiveInstruction /^\l\l\+\>/ contained containedin=@fugitiveSection nextgroup=fugitiveHash skipwhite
@@ -30,10 +30,10 @@ syn match fugitiveHash /\S\@<!\x\{4,\}\S\@!/ contained
syn region fugitiveHunk start=/^\%(@@\+ -\)\@=/ end=/^\%([A-Za-z?@]\|$\)\@=/ contains=diffLine,diffRemoved,diffAdded,diffNoEOL containedin=@fugitiveSection fold syn region fugitiveHunk start=/^\%(@@\+ -\)\@=/ end=/^\%([A-Za-z?@]\|$\)\@=/ contains=diffLine,diffRemoved,diffAdded,diffNoEOL containedin=@fugitiveSection fold
for s:section in ['Untracked', 'Unstaged', 'Staged'] for s:section in ['Untracked', 'Unstaged', 'Staged']
exe 'syn region fugitive' . s:section . 'Section start=/^\%(' . s:section . ' .*(\d\+)$\)\@=/ contains=fugitive' . s:section . 'Heading end=/^$/' exe 'syn region fugitive' . s:section . 'Section start=/^\%(' . s:section . ' .*(\d\++\=)$\)\@=/ contains=fugitive' . s:section . 'Heading end=/^$/'
exe 'syn match fugitive' . s:section . 'Modifier /^[MADRCU?] / contained containedin=fugitive' . s:section . 'Section' exe 'syn match fugitive' . s:section . 'Modifier /^[MADRCU?] / contained containedin=fugitive' . s:section . 'Section'
exe 'syn cluster fugitiveSection add=fugitive' . s:section . 'Section' exe 'syn cluster fugitiveSection add=fugitive' . s:section . 'Section'
exe 'syn match fugitive' . s:section . 'Heading /^[A-Z][a-z][^:]*\ze (\d\+)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite' exe 'syn match fugitive' . s:section . 'Heading /^[A-Z][a-z][^:]*\ze (\d\++\=)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite'
endfor endfor
unlet s:section unlet s:section