225 Commits

Author SHA1 Message Date
Eric Amodio
11eacb27a1 Preps v5.0.0 2017-09-12 19:06:15 -04:00
Eric Amodio
543d39246f Closes #138 - adds ignore whitespace setting 2017-09-12 17:46:22 -04:00
Eric Amodio
6837414f22 Adds more details to remotes in custom view 2017-09-12 15:48:36 -04:00
Eric Amodio
ea6fdbaaf2 Adds groupBy function 2017-09-12 15:47:57 -04:00
Eric Amodio
ccc29e3dfc Reworks remote parsing
Combines same url into same remote
Adds a change event for custom remote providers
Adds a repo change event for custom remote providers
2017-09-12 15:46:44 -04:00
Eric Amodio
48814d4213 Changes show all commits icon 2017-09-12 13:02:04 -04:00
Eric Amodio
c3dd83cf3c Updates documention with remotes exanple 2017-09-12 11:56:17 -04:00
Eric Amodio
77482f4930 Adds openChangedFileChanges to custom view
Adds openChangedFileChangesWithWorking to custom view
Removes unneeded context checks from custom view commands
2017-09-12 11:11:03 -04:00
Eric Amodio
503b2a3785 Fixes issue where the revision wasn't properly opened
Adds ability to provide a branch to open file in remote
2017-09-12 10:38:51 -04:00
Eric Amodio
9464f7e79f Preps v5.0.0-beta.2 2017-09-11 23:51:27 -04:00
Eric Amodio
77ae37c54c Adds rudimentary "paging" to custom view branch history 2017-09-11 23:47:51 -04:00
Eric Amodio
e20ec552b7 Removes branches remote commands if no remotes
Removes branch remote commands if not tracked
2017-09-11 23:41:47 -04:00
Eric Amodio
f911447c5e Formats svg like other icons 2017-09-11 23:38:47 -04:00
Eric Amodio
38c44c808d Fixes double getRemotes call 2017-09-11 21:32:52 -04:00
Eric Amodio
655afb358e Fixes double hovers on blank lines 2017-09-11 21:32:52 -04:00
Eric Amodio
21e0963600 Adds bitbucket server support 2017-09-11 21:32:40 -04:00
Eric Amodio
62580da702 Preps v5.0.0-beta 2017-09-11 03:02:56 -04:00
Eric Amodio
6b97c107eb Updates dependencies 2017-09-11 02:27:49 -04:00
Eric Amodio
92b57580b8 Fixes #120 - Adds custom remotes support 2017-09-11 02:09:32 -04:00
Eric Amodio
e400f27c84 Adds refs changes into repo watcher
Catches branch & remote changes
2017-09-11 00:50:40 -04:00
Eric Amodio
4221e06ae3 Removes history limit for custom view 2017-09-11 00:41:32 -04:00
Eric Amodio
a2dc65c044 Adds message truncation at newline 2017-09-11 00:41:11 -04:00
Eric Amodio
4102bdd471 Reworks git command error handling
Switches to use the new diffWith command
2017-09-11 00:39:52 -04:00
Eric Amodio
d420d82ab2 Removes unneeded shortSha parameter 2017-09-11 00:36:38 -04:00
Eric Amodio
260874fa1d Adds better filename sanitization 2017-09-10 17:44:26 -04:00
Eric Amodio
9d83fbcacb Switches to use the new diffWith command 2017-09-09 15:48:44 -04:00
Eric Amodio
a50f04c569 Adds commands to hover links 2017-09-09 01:57:12 -04:00
Eric Amodio
df0599a832 Adds shortenSha method 2017-09-09 00:43:20 -04:00
Eric Amodio
f05d236e79 Updates dependencies
Updates to latest vscode engine
2017-09-08 18:47:25 -04:00
Eric Amodio
1b7610857a Fixes issue where repo change wasn't fired in some cases
Consolidates repo watching into a single watcher
Adds debounce to repo changes in the custom view
2017-09-08 18:02:43 -04:00
Eric Amodio
04d2c00ebf Fixes issue with branch name truncations (rebase) 2017-09-08 17:03:21 -04:00
Eric Amodio
ece34dba32 Cleans up some command overrides 2017-09-05 21:30:07 -04:00
Eric Amodio
68fcbf713d Fixes regression with not opening line in remote 2017-09-05 21:29:22 -04:00
Eric Amodio
e192c547b1 Fixes #130 - Stops repeated welcome for some users
No idea why the version check fails, but hopefully this will help
2017-09-04 03:30:19 -04:00
Eric Amodio
3835193118 Updates images 2017-09-04 03:05:26 -04:00
Eric Amodio
d161084ccd Fixes issue with stashing untracked files 2017-09-04 03:04:05 -04:00
Eric Amodio
b9c4468cf7 Updates changelog 2017-09-04 01:46:29 -04:00
Eric Amodio
4bacb6fbff Hides remote menus if there are no remotes 2017-09-04 01:46:28 -04:00
Eric Amodio
c98755cc87 Adds refresh of custom view on settings change 2017-09-04 01:46:28 -04:00
Eric Amodio
6d759daaad Avoids remote disambiguation quick pick 2017-09-04 01:46:28 -04:00
Eric Amodio
5a42ce4ed4 Adds remote tracking branch to custom view
Adds setting to show remote tracking branch in custom view
2017-09-04 01:46:28 -04:00
Eric Amodio
a5af318269 Adds message in custom view if no remotes 2017-09-04 01:46:28 -04:00
Eric Amodio
5a2bd02402 Reworks branch parsing to include tracking info
Reworks current branch retrieval for better performance
2017-09-04 01:46:21 -04:00
Eric Amodio
2bba14260f Adds Open Branches in Remote command to the Remote custom view items
Adds Open Repository in Remote command to the Remote custom view items
2017-09-03 16:33:52 -04:00
Eric Amodio
22378d5f25 Updates changelog and readme 2017-09-03 16:03:33 -04:00
Eric Amodio
d1d1db18e2 Changes the icon of the File History custom view items
Provides more information rather than just a commit icon
2017-09-03 15:49:50 -04:00
Eric Amodio
3dab90709b Adds Open File command to History custom view item
Adds Open File in Remote command to History custom view item
2017-09-03 15:44:18 -04:00
Eric Amodio
f58d085352 Adds Open Branches in Remote command
Adds Open Branches in Remote command to the Branches custom view item
Adds Open Repository in Remote command to the Repository Status custom view item
2017-09-03 15:37:52 -04:00
Eric Amodio
a77bb36ee3 Preps v5.0.0-alpha.2 2017-09-03 13:47:13 -04:00
Eric Amodio
5cc9365fa1 Adds more info to the status nodes 2017-09-03 13:40:46 -04:00
Eric Amodio
a587108cab Adds Stash Changes command to the Stashes custom view item 2017-09-03 13:29:33 -04:00
Eric Amodio
1b4350e476 Removes Stash Unstaged Changes option
Changes Stash Changes icon to a +
2017-09-03 13:23:17 -04:00
Eric Amodio
586785cfb8 Changes stashes icon to match custom view 2017-09-03 13:22:40 -04:00
Eric Amodio
04df931902 Adds Refresh command to most custom view items
Updates custom view when repo changes (brute force for now)
2017-09-03 12:59:16 -04:00
Eric Amodio
d31eb25451 Adds Apply Changes command to custom view files
Adds Stash Changes command to SCM view items
2017-09-03 12:58:05 -04:00
Eric Amodio
35b16a78ba Adds status indicator to repo icon 2017-09-03 00:25:01 -04:00
Eric Amodio
825b9661fb Preps v5.0.0-alpha
Updates dependencies
2017-09-02 01:53:04 -04:00
Eric Amodio
9782a81e46 Adds new GitLens custom view 2017-09-02 01:43:08 -04:00
Eric Amodio
ed58dc3b49 Preps v4.5.0-beta 2017-08-30 12:25:51 -04:00
Eric Amodio
480dcb95fb Adds a file history explorer view 2017-08-30 12:25:07 -04:00
Eric Amodio
ef41176ea7 Defaults stashes format to ${filePath}
Adds message when there are no stashes
Cleans up the stash explorer
2017-08-30 12:25:07 -04:00
Eric Amodio
bcd83566a1 Reworks ExplorerNode base class
Adds TextExplorerNode for messages
2017-08-30 12:25:07 -04:00
Eric Amodio
ca089777db Adds ${filePath} support to status file formatting 2017-08-30 12:25:07 -04:00
Eric Amodio
a255eea949 Splits code lens out of GitService 2017-08-30 12:25:07 -04:00
Eric Amodio
1ffb42a090 Updates dependencies 2017-08-30 12:25:07 -04:00
Eric Amodio
bc2f1b192a Preps v4.4.3 2017-08-30 12:19:57 -04:00
Eric Amodio
7d99624068 Adds more logging to track down #130 2017-08-30 12:19:33 -04:00
Eric Amodio
c258d04381 Fixes #135 - Full-width chars break gutter annotations (really) 2017-08-30 11:46:41 -04:00
Eric Amodio
4c4926c8b5 Preps v4.4.2 2017-08-29 22:48:59 -04:00
Eric Amodio
6255b26fd2 Fixes #135 - Full-width chars break gutter annotations 2017-08-29 22:47:12 -04:00
Eric Amodio
4db2b116c2 Preps v4.4.1 2017-08-23 21:01:16 -04:00
Eric Amodio
b40579f4b2 Updates dependencies 2017-08-23 21:01:01 -04:00
Eric Amodio
15c981ba06 Fixes #114 - Stylus file jumpiness 2017-08-23 21:00:29 -04:00
Eric Amodio
c2f78a7242 Preps v4.4.0 2017-08-18 11:58:23 -04:00
Eric Amodio
d3013a03d4 Preps v4.4.0-beta 2017-08-17 03:30:28 -04:00
Eric Amodio
323148d9ab Disables whitespace toggling by default 2017-08-17 03:24:09 -04:00
Eric Amodio
03fefaad3b Disables current line blame annotations when debugging 2017-08-17 03:22:07 -04:00
Eric Amodio
f11c00ceda Changes the annotation line separator rendering 2017-08-17 02:23:35 -04:00
Eric Amodio
0e338308c6 Fixes jumpiness when opening a diff 2017-08-17 01:18:00 -04:00
Eric Amodio
e39bd5dad3 Removes setting & command to show/hide stashes view 2017-08-16 23:33:27 -04:00
Eric Amodio
00cdd2e375 Adds "on" state to file annotation command
Adds "progress" state to file annotation command
2017-08-15 01:35:50 -04:00
Eric Amodio
787e0e6aa1 Updates dependencies 2017-08-14 20:52:45 -04:00
Eric Amodio
46554e93f3 Changes gitter to slack 2017-08-02 10:51:23 -04:00
Eric Amodio
4160234962 Add slack chat badge 2017-08-02 10:49:55 -04:00
Eric Amodio
0bd31099ce Keeps the hover info in the whitespace area at the start of the current line 2017-07-28 22:00:01 -04:00
Eric Amodio
a272f8f6a4 Preps v4.3.3 2017-07-28 17:37:08 -04:00
Eric Amodio
e10d7eb648 Increases performance of blame annotations
especially for larger file
2017-07-28 17:09:34 -04:00
Eric Amodio
9d9c3181f7 Fixes #107 - Double-byte characters break blame layout 2017-07-27 00:56:33 -04:00
Eric Amodio
68a42fd0c7 Adds progress indicator for long annotation operations 2017-07-26 23:26:07 -04:00
Eric Amodio
28db0bf2f5 Updates to v2.0 task schema 2017-07-26 23:25:32 -04:00
Eric Amodio
5f85388db7 Preps v4.3.2
Fixes #118 - stopped working on latest insiders build
2017-07-20 22:37:51 +02:00
Eric Amodio
4d167c3cdd Fixes lint issues 2017-07-20 22:19:58 +02:00
Eric Amodio
4826e99986 Updates dependencies 2017-07-20 22:14:13 +02:00
Johannes Rieken
459a8dce1d mixin state of super type
As discussed, this should be ok for Insiders and Stable and accommodate for our URI changes.
2017-07-20 21:54:37 +02:00
Eric Amodio
2650a84105 Preps v4.3.1 2017-07-03 09:50:31 -04:00
Eric Amodio
a2cd57cf95 Fixes #108 - hides stash explorer by default
Adds stash explorer toggle command
2017-07-03 09:50:12 -04:00
Eric Amodio
62a148c156 Adds rebornix thank you 2017-07-03 02:33:37 -04:00
Eric Amodio
be682c5def Preps v4.3.0 2017-07-03 02:30:06 -04:00
Eric Amodio
12d310bdf1 Adds git stashes screenshot 2017-07-03 02:23:13 -04:00
Eric Amodio
af4f433972 Adds stash commands similar to SCM 2017-07-03 02:00:15 -04:00
Eric Amodio
52275215fe Adds content uri from GitUri 2017-07-03 01:59:02 -04:00
Eric Amodio
71edb1b99a Stops error message with stash apply conflict 2017-07-03 01:57:26 -04:00
Eric Amodio
7f3fdb48fd Removes insiders flag from stash view 2017-07-02 23:16:55 -04:00
Eric Amodio
81a9092455 Removes stash list in explorer command
Rename Show File History in Explorer back to Open File History Explorer
Removes the git explorer view (for now)
2017-07-02 23:12:01 -04:00
Eric Amodio
d288985c26 Adapts stash commands to new structure for views
Adds onDidChangeRepo event to GitService
Refreshes stash view when repo changes
2017-07-02 22:34:55 -04:00
rebornix
b81d873a34 WIP of Stash Explorer commands
# Conflicts:
#	src/commands/stashApply.ts
2017-07-02 22:34:05 -04:00
Eric Amodio
c96a659e9e Fixes uris on nodes 2017-07-02 22:34:05 -04:00
Eric Amodio
d193676502 Adds status icons to explorer views
Adds templating support to explorer views
2017-07-02 22:33:56 -04:00
Eric Amodio
6410a274d5 Renames explorer views
Adds refresh commands for explorer views
Adds context menu commands to both explorer views
2017-07-02 22:33:09 -04:00
Eric Amodio
272bb4db45 Sets line to avoid diff jumping 2017-07-02 22:33:09 -04:00
Eric Amodio
7fbee675f0 Spits branch and status nodes into separate files
Removes status node for now
2017-07-02 22:33:09 -04:00
Eric Amodio
bc21272409 Defers command construction until later
Gets a properly constructed commit to improve performance of opening the diff
2017-07-02 22:32:59 -04:00
Eric Amodio
da450a614d Renames explorerNodes 2017-07-02 22:32:05 -04:00
rebornix
0e4664bab1 Rename Stash Explorer 2017-07-02 22:32:04 -04:00
rebornix
1b4800571d extract stash explorer 2017-07-02 22:32:04 -04:00
Eric Amodio
c812a56eac Adds an experimental custom view (wip) 2017-07-02 22:31:04 -04:00
Eric Amodio
3081632815 Updates dependencies (typescript)
Fixes newly detected typescript errors
2017-07-02 22:23:54 -04:00
Eric Amodio
3d32d86998 Renames onDidBlameabilityChange for consistency 2017-06-29 01:41:10 -04:00
Eric Amodio
0a9559f5a5 Reworks commanding structure for less redundancy
Adds command args copying when needed
2017-06-28 01:06:20 -04:00
Eric Amodio
8693c87523 Updates dependencies 2017-06-27 18:34:28 -04:00
Eric Amodio
54c077eb8d Switches to png icon 2017-06-27 01:45:13 -04:00
Eric Amodio
ee124b5325 Preps v4.2.0 2017-06-27 01:34:00 -04:00
Eric Amodio
63a0646c8f Adds commands to the SCM menus 2017-06-27 01:34:00 -04:00
Eric Amodio
cb360c5a3d Renames Compare File with... command 2017-06-27 01:34:00 -04:00
Eric Amodio
3bf5f23c66 Adds diffWithRevision command 2017-06-27 01:34:00 -04:00
Eric Amodio
1751987868 Reworks more commands deal with context 2017-06-27 01:33:59 -04:00
Eric Amodio
9179b70875 Avoids re-setting the line if it is already set 2017-06-27 01:33:59 -04:00
Eric Amodio
93ea2c7145 Fixes another infinite loop in close command 2017-06-27 01:33:59 -04:00
Eric Amodio
f9275a8e1a Reworks command structure with context 2017-06-27 01:33:59 -04:00
Eric Amodio
ceb9c5e126 Removes "Line" from some command titles 2017-06-27 01:33:53 -04:00
Eric Amodio
e42af14b11 Adds status formatter 2017-06-26 23:54:50 -04:00
Eric Amodio
bcfa2cb4d7 Renames icon references to octicon 2017-06-26 23:53:18 -04:00
Eric Amodio
16963ee054 Fixes typo 2017-06-26 23:48:44 -04:00
Eric Amodio
db1bdaa778 Updates excludes 2017-06-26 23:47:31 -04:00
Eric Amodio
ccac13088c Fixes #103 - toggled line annotation state is sometimes forgotten
Often happened when also toggling file annotations
2017-06-26 23:37:16 -04:00
Eric Amodio
899a69357c Fixes a few spelling errors
Adds a better description to blame.line.enabled to be clearer about its behavior
Adds a better description to codeLens.enabled to be clearer about its behavior
2017-06-26 22:49:23 -04:00
Eric Amodio
c78c3c7525 Preps v4.1.4 2017-06-25 13:26:33 -04:00
Eric Amodio
1cbf0b2c73 Updates dependencies 2017-06-25 13:26:33 -04:00
Eric Amodio
191a158b3b Optimizes diff with previous command 2017-06-25 13:26:33 -04:00
Eric Amodio
f553980146 Attempts to fix #99
undo/redo spawns too many git processes
2017-06-25 13:26:19 -04:00
Eric Amodio
a306ba2b98 Stops trying to set the line if we don't have one 2017-06-25 00:29:11 -04:00
Eric Amodio
1cdd94cb46 Adds a with method to commit 2017-06-24 17:54:19 -04:00
Eric Amodio
12caa017a9 Fixes issues with changes showing wrong diff
Refactors diff parsing
2017-06-24 17:52:52 -04:00
Eric Amodio
ad790b274b Preps v4.1.3 2017-06-20 01:30:05 -04:00
Eric Amodio
55ef004332 Fixes changes hover not showing the correct diff when showing recent changes annotations 2017-06-19 23:23:20 -04:00
Eric Amodio
329d5a496d Preps v4.1.2 2017-06-15 23:54:43 -04:00
Eric Amodio
6b4642d8c8 Fixes #96 - stops opening external diff if configured 2017-06-15 23:44:41 -04:00
Eric Amodio
45aa9b17ac Changes to use enum for glyphs 2017-06-13 22:34:51 -04:00
Eric Amodio
9b908e27ba Preps v4.1.1 2017-06-13 03:21:49 -04:00
Eric Amodio
0eb6026a82 Fixes missing icons 2017-06-13 03:18:14 -04:00
Eric Amodio
5823457ea0 Removes invalid signature 2017-06-13 03:15:15 -04:00
Eric Amodio
64b929fd5b Preps v4.1.0 2017-06-13 01:33:23 -04:00
Eric Amodio
a618b7efe6 Adds ability to esc out of file annotations 2017-06-13 01:31:13 -04:00
Eric Amodio
a2903ce4a9 Refactors formatters
Moves annotation messages from formatter to annotations
Moves icons into dark/light folders
2017-06-13 00:14:10 -04:00
Eric Amodio
12debe583c Cleans up more duplicate code 2017-06-12 12:25:35 -04:00
Eric Amodio
0160e064be Preps v4.1-beta.2 2017-06-12 12:13:48 -04:00
Eric Amodio
76961d6697 Fixes #33 - escape commit message 2017-06-12 12:13:48 -04:00
Eric Amodio
cc827f4711 Adds more notes on copy commands 2017-06-12 12:13:48 -04:00
Eric Amodio
6f3441a9e7 Adds default date format 2017-06-12 12:13:48 -04:00
Eric Amodio
64ae82075e Cleans up some duplicate code 2017-06-12 12:13:48 -04:00
Eric Amodio
5624567daa Fixes regression with code lens 2017-06-12 12:13:48 -04:00
Eric Amodio
c1c65127b7 Fixes extra newline in multiline commit messages 2017-06-11 17:56:07 -04:00
Eric Amodio
ce98f02706 Adds details hover to recent changes annotations 2017-06-11 17:43:53 -04:00
Eric Amodio
7f2ec30164 Preps v4.1-beta 2017-06-10 04:21:02 -04:00
Eric Amodio
48a1ca704d Adds new recent changes annotations 2017-06-10 04:19:07 -04:00
Eric Amodio
23c7171d7f Preps v4.0.2-beta 2017-06-10 00:57:56 -04:00
Eric Amodio
dd0b95498e Fixes excessive memory usages with diff regex 2017-06-10 00:49:22 -04:00
Eric Amodio
e6316400f0 Optimized parsers for speed & memory usage
Switches to lazy parsing of diff chunks
2017-06-10 00:16:46 -04:00
Eric Amodio
eeff31cf27 Removes I from interface naming of "things" 2017-06-09 18:00:54 -04:00
Eric Amodio
eb3b9ad6c9 Preps v4.0.1 2017-06-09 17:27:54 -04:00
Eric Amodio
10674124c8 Fixes #87 - Can't open files in remote when using git@ urls (ssh) 2017-06-09 17:26:20 -04:00
Eric Amodio
e0f66247cf Preps v4.0.0 2017-06-09 16:35:52 -04:00
Eric Amodio
badd999db1 Defaults toggleWhitespace.enabled to true
Turns off whitespace toggling if already 'none'
2017-06-09 16:32:05 -04:00
Eric Amodio
9ae4cc36a1 Adds ability to suppress most warning messages 2017-06-09 15:42:56 -04:00
Eric Amodio
30bb4398a3 Changes formatting & ordering 2017-06-09 15:41:49 -04:00
Eric Amodio
9c7a971e21 Changes to undefined checks 2017-06-09 15:41:49 -04:00
Eric Amodio
ba59fb29ad Fixes #85 - Show File Commit Details doesn't work on last line if it is empty 2017-06-09 15:41:49 -04:00
Eric Amodio
50ba3e1446 Fixes #84 - diff w/ previous should only compare w/ working tree if file is uncommitted 2017-06-09 15:41:49 -04:00
Eric Amodio
62e5ef6225 Fixes issue with open in remote not showing with no editors 2017-06-09 10:18:10 -04:00
Eric Amodio
ed54d289dd Stops collecting initialized event (data cap issues) 2017-06-09 09:36:00 -04:00
Eric Amodio
2a8dafd9e9 Fixes #83 - Close Unchanged Files command can infinitely loop 2017-06-08 00:54:46 -04:00
Eric Amodio
016c561ead Preps v4.0.0-beta.2 2017-06-07 12:55:07 -04:00
Eric Amodio
9cf86a41ec Adds setting to explicitly control telemetry
Disables zone.js monkey patching by application insights
2017-06-07 12:52:56 -04:00
Eric Amodio
4eb1c3e36a Renames interpolation method 2017-06-07 12:52:56 -04:00
Eric Amodio
95e0a6c71b Adds code lens range to debug info 2017-06-07 12:52:56 -04:00
Eric Amodio
35ca8106c9 Adds customizable code lens strings 2017-06-07 12:52:56 -04:00
Eric Amodio
948a75de79 Don't wait for settings message before continuing 2017-06-07 12:52:56 -04:00
Eric Amodio
4b0891b949 Adds settings migration support 2017-06-07 12:52:56 -04:00
Eric Amodio
a9d94868e7 Preps v4.0.0-beta 2017-06-07 12:52:56 -04:00
Eric Amodio
3c45c7e049 Anchors the code lens to the end of the line 2017-06-07 12:51:00 -04:00
Eric Amodio
ba0d55d5d4 Updates dependencies 2017-06-07 12:50:59 -04:00
Eric Amodio
d2dc172042 Attempts to fix #80 - on line with link, annotation gets underlined 2017-06-07 12:49:52 -04:00
Eric Amodio
e5e582d300 Fixes #81 - Current line annotation is too sticky 2017-06-07 12:49:52 -04:00
Eric Amodio
7c9e4b911c Adds better formatting of settings 2017-06-07 12:49:52 -04:00
Eric Amodio
42fdf9f327 Updates screenshots 2017-06-07 12:49:52 -04:00
Eric Amodio
547d50fed6 Adds another screenshot to README 2017-06-07 12:49:52 -04:00
Eric Amodio
6c33686335 Adds vscode issue TODO 2017-06-07 12:49:52 -04:00
Eric Amodio
28355d41b6 Adds more screenshots to README 2017-06-07 12:49:52 -04:00
Eric Amodio
6e5bb2343e Preps v4.0.0-alpha.2 2017-06-07 12:49:51 -04:00
Eric Amodio
d01c592533 Adds welcome message for first-time users 2017-06-07 12:48:22 -04:00
Eric Amodio
37e48ded2d Major refactor/rework -- many new features and breaking changes
Adds all-new, beautiful, highly customizable and themeable, file blame annotations
Adds all-new configurability and themeability to the current line blame annotations
Adds all-new configurability to the status bar blame information
Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting
Adds better configurability over where Git code lens will be shown -- both by default and per language
Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version
Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off
Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations
Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off
Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations
Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu
Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu
Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group
Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off
Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise
Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`)
Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
2017-06-07 12:48:22 -04:00
Eric Amodio
e3e7605268 Preps v3.6.1 2017-06-07 12:43:22 -04:00
Eric Amodio
f16c3857e5 Fixes zone.js monkey patching by application-insights 2017-06-07 12:42:33 -04:00
Eric Amodio
5298511bb9 Preps v3.6.0 2017-06-02 18:45:04 -04:00
Eric Amodio
4400ab1da9 Updates dependencies 2017-06-02 15:12:57 -04:00
Eric Amodio
6a9977b954 Fixes issue where the wrong diff line could be shown 2017-06-02 15:12:31 -04:00
Eric Amodio
c0d5f55baa Preps v3.6.0-beta 2017-05-27 04:33:27 -04:00
Eric Amodio
68f6ae8f3a Updates dependencies 2017-05-27 04:32:42 -04:00
Eric Amodio
53c691898f Changes behavior of diffWithWorking to always does what it says
Compares the current file with the working tree -- if the current file *is* the working file, it will show a `File matches the working tree` message
2017-05-27 04:26:51 -04:00
Eric Amodio
365af9c54b Changes behavior of diffWithPrevious to always does what it says
Compares the current file with the previous commit to that file
2017-05-27 04:26:12 -04:00
Eric Amodio
55b1a66ec0 Adds 'gitlens.diffWithWorking' status bar command option
Changes 'gitlens.diffWithPrevious' status bar command option behavior
2017-05-27 04:25:12 -04:00
Eric Amodio
522e5a49a2 Renames 'Compare with *' in quick pick menus
Renames 'Compare File with Previous Commit' command
Renames 'Compare Line with Previous Commit' command
Renames 'Compare Line with Working Tree' command
2017-05-27 04:20:25 -04:00
Eric Amodio
e99febb52d Adds diff info to active line hover always 2017-05-27 02:39:10 -04:00
Eric Amodio
2036c8abaf Preps v3.5.1 2017-05-25 01:39:16 -04:00
Eric Amodio
021a5b833a Fixes #71 - blame invalid on external edit 2017-05-25 01:31:24 -04:00
Eric Amodio
f1042de9c7 Stops some code lens actions when uncommitted 2017-05-25 01:30:28 -04:00
Eric Amodio
efd3d40aa8 Switches to use GitUris in more places 2017-05-25 01:05:18 -04:00
Eric Amodio
9c7062020e Fixes issue with blame on versioned files
Stops falling back to the cached blame of the working file
Handles git scheme urls properly
2017-05-25 00:49:36 -04:00
Eric Amodio
9da80c121b Debounces other active line events 2017-05-25 00:35:12 -04:00
Eric Amodio
5380724323 Preps v3.5.0 2017-05-24 23:01:28 -04:00
Eric Amodio
77651701aa Removes insiders flag from stash commands 2017-05-24 22:59:41 -04:00
Eric Amodio
bb834f2e0a Removes insiders flag from remotes 2017-05-24 22:58:54 -04:00
Eric Amodio
535e627048 Preps v3.5.0-beta.2 2017-05-24 13:02:02 -04:00
Eric Amodio
8a74950708 Fixes #40 - encoding issues
This is only a partial fix, as vscode doesn't allow enough controls to fix everything
2017-05-24 12:52:47 -04:00
Eric Amodio
3502bdf6c7 Adds more linting rules
Fixes lint issues
2017-05-23 18:48:04 -04:00
220 changed files with 12833 additions and 4378 deletions

View File

@@ -1,13 +1,13 @@
{
"editor.insertSpaces": true,
"files.exclude": {
"node_modules": true,
"out": true
"**/node_modules": true,
"**/out": true
},
"files.trimTrailingWhitespace": true,
"search.exclude": {
"node_modules": true,
"out": true
"**/node_modules": true,
"**/out": true
},
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
"typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version

38
.vscode/tasks.json vendored
View File

@@ -9,26 +9,38 @@
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "2.0.0",
"showOutput": "always",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"tasks": [
{
"taskName": "compile",
"command": "npm run compile",
"isBuildCommand": true,
"isShellCommand": true,
"problemMatcher": [ "$tsc", "$tslint5" ]
"label": "compile",
"type": "npm",
"script": "compile",
"group": "build",
"problemMatcher": [
"$tsc",
{
"base": "$tslint5",
"fileLocation": "relative"
}
]
},
{
"taskName": "lint",
"command": "npm run lint",
"isShellCommand": true,
"problemMatcher": "$tslint5"
"type": "npm",
"script": "lint",
"problemMatcher": {
"base": "$tslint5",
"fileLocation": "relative"
}
},
{
"taskName": "watch",
"command": "npm run watch",
"type": "npm",
"script": "watch",
"isBackground": true,
"isShellCommand": true,
"problemMatcher": "$tsc-watch"
}
]

View File

@@ -1,4 +1,6 @@
!images/*.svg
!images/dark/**
!images/light/**
!images/gitlens-icon.png
images/**
.vscode/**
.vscode-test/**

View File

@@ -4,20 +4,328 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
## [3.5.0-beta] - 2017-05-23
## [5.0.0] - 2017-09-12
### Added
- Adds an all-new `GitLens` custom view to the Explorer activity
- `Repository View` - provides a full repository explorer
![GitLens Repository view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-repository.png)
- `Repository Status` node — provides the status of the repository
- Provides the name of the current branch, its upstream tracking branch (if available), and its upstream status (if available)
- Provides indicator dots on the repository icon which denote the following:
- `None` - up-to-date with the upstream
- `Green` - ahead of the upstream
- `Red` - behind the upstream
- `Yellow` - both ahead of and behind the upstream
- Provides additional nodes, if the current branch is not synchronized with the upstream, to quickly see and explore the specific commits ahead and/or behind the upstream
- Provides a context menu with `Open Repository in Remote`, and `Refresh` commands
- `Branches` node — provides a list of the local branches
- Indicates which branch is the current branch and optionally shows the remote tracking branch
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, `Show File History`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`, `Show Commit Details`, and `Refresh` commands
- Provides a context menu on each branch with `Open Branch in Remote`, and `Refresh` commands
- Provides a context menu with `Open Branches in Remote`, and `Refresh` commands
- `Remotes` node — provides a list of remotes
- Indicates the direction of the remote (fetch, push, both), remote service (if applicable), and repository path
- Expand each remote to see its list of branches
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`,`Show Commit Details`, and `Refresh` commands
- Provides a context menu on each remote with `Open Branches in Remote`, `Open Repository in Remote`, and `Refresh` commands
- Provides a context menu with a `Refresh` command
- `Stashes` node — provides a list of stashed changes
- Expand each stash to quickly see the set of files stashed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu with `Stash Changes`, and `Refresh` commands
- Provides a context menu on each stash with `Apply Stashed Changes` (confirmation required), `Delete Stashed Changes` (confirmation required), `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit Message to Clipboard`, and `Refresh` commands
- Provides a context menu on each stashed file with `Apply Changes`, `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, and `Show File History` commands
- `History View` - provides the revision history of the active file
![GitLens History view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-history.png)
- Automatically updates to track the active editor
- Provides a context menu with `Open File`, `Open File in Remote`, and `Refresh` commands
- Provides a context menu on each revision (commit) with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Quickly switch between views using the `Switch to Repository View` or `Switch to History View` commands
- Provides toolbar commands to `Search Commits`, `Switch to Repository View` or `Switch to History View`, and `Refresh`
- Adds all-new interactivity to the hover annotations
![Hover Annotations](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotations.png)
- Adds the following command-links to the `details` hover annotation
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds the following command-links to the `changes` hover annotation
- Clicking on `Changes` will run the `Compare File Revisions` command (`gitlens.diffWith`)
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds support for remote services with custom domains -- closes [#120](https://github.com/eamodio/vscode-gitlens/issues/120)
- Adds support for the Bitbucket Server (previously called Stash) remote service -- closes [#120](https://github.com/eamodio/vscode-gitlens/issues/120)
- Adds `gitlens.blame.ignoreWhitespace` setting to specify whether or not to ignore whitespace when comparing revisions during blame operations -- closes [#138](https://github.com/eamodio/vscode-gitlens/issues/138)
- Adds `Compare File Revisions` command (`gitlens.diffWith`) - compares the specified file revisions
- Adds `Open Branches in Remote` command (`gitlens.openBranchesInRemote`) - opens the branches in the supported remote service
- Adds `Stash Changes` command (`gitlens.stashSave`) to the source control group context menu -- can now stash a group of files
- Adds `Stash Changes` command (`gitlens.stashSave`) to the source control resource context menu -- can now stash individual files (works with multi-select too!)
- Adds `gitlens.gitExplorer.view` setting to specify the starting view (mode) of the `GitLens` custom view
- Adds `gitlens.gitExplorer.showTrackingBranch` setting to specify whether or not to show the tracking branch when displaying local branches in the `GitLens` custom view
- Adds `gitlens.gitExplorer.commitFormat` setting to specify the format of committed changes in the `GitLens` custom view
- Adds `gitlens.gitExplorer.commitFileFormat` setting to specify the format of a committed file in the `GitLens` custom view
- Adds `gitlens.gitExplorer.stashFormat` setting to specify the format of stashed changes in the `GitLens` custom view
- Adds `gitlens.gitExplorer.stashFileFormat` setting to specify the format of a stashed file in the `GitLens` custom view
- Adds `${filePath}` token to file formatting settings
### Changed
- Changes `Show Stashed Changes` option icon in repository status quick pick menu to match the `GitLens` custom view
- Changes `Stash Changes` option icon in stashed changes quick pick menu to a plus (+)
- Renames `Compare File with Previous` command (`gitlens.diffWithPrevious`) to `Compare File with Previous Revision`
- Renames `Compare File with Next Commit` command (`gitlens.diffWithNext`) to `Compare File with Next Revision`
- Renames `Compare File with Working Tree` command (`gitlens.diffWithWorking`) to `Compare File with Working Revision`
- Renames `Compare Line Commit with Previous` command (`gitlens.diffLineWithPrevious`) to `Compare Line Revision with Previous`
- Renames `Compare Line Commit with Working Tree` command (`gitlens.diffLineWithWorking`) to `Compare Line Revision with Working`
### Removed
- Removes `Git Stashes` custom view view - as it's functionality has been folded into the new `GitLens` custom view
- Removes `gitlens.stashExplorer.stashFormat` setting
- Removes `gitlens.stashExplorer.stashFileFormat` setting
- Removes `Stash Unstaged Changes` option from stashed changes quick pick menu -- didn't work as intended
- Removes the seeding of the commit search command from the clipboard
### Fixed
- Fixes an issue where double hover annotations could be shown on blank lines
- Fixes an issue where remote branches couldn't be opened properly in their remote service
- Fixes [#130](https://github.com/eamodio/vscode-gitlens/issues/130) - First-run "Thank you for choosing GitLens! [...]" info message shown on every start up
- Fixes an issue where sometimes diffs (via branch name) wouldn't open properly
- Fixes an issue where remotes are queried more than once on startup
## [4.4.3] - 2017-08-30
## Fixed
- Fixes [#135](https://github.com/eamodio/vscode-gitlens/issues/135) - Full-width characters break gutter annotations (really this time)
## [4.4.2] - 2017-08-29
## Fixed
- Fixes [#135](https://github.com/eamodio/vscode-gitlens/issues/135) - Full-width characters break gutter annotations
## [4.4.1] - 2017-08-23
## Fixed
- Fixes [#114](https://github.com/eamodio/vscode-gitlens/issues/114) - Stylus files makes code lens freak out
## [4.4.0] - 2017-08-18
## Added
- Adds a progress indicator to the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) icon -- pulses while annotations are computed
- Adds an active state to the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) icon -- turns orange while the annotations are visible
- Adds automatic disabling of the current line blame annotations when starting a debug session and will restore them when the debug session ends -- can still be manually toggled via the `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`)
## Changed
- Changes chat links from Gitter to [Slack](https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ)
- Changes the look of the line separators on the gutter blame annotations
- Changes the `gitlens.advanced.toggleWhitespace.enabled` configuration setting to default to `false` -- thanks to the awesome work in vscode by Alexandru Dima ([@alexandrudima](https://github.com/alexandrudima)) this is no longer required!
## Removed
- Removes unneeded `gitlens.stashExplorer.enabled` configuration setting since users can add or remove custom views natively now
- Removes unneeded `Toggle Git Stashes Explorer` command (`gitlens.stashExplorer.toggle`) since users can add or remove custom views natively now
- Removes the `gitlens.theme.annotations.file.hover.separateLines` configuration setting
## Fixed
- Fixes jumpiness when opening a diff to a certain line
## [4.3.3] - 2017-07-28
## Added
- Adds progress indicator for when computing annotations takes a while
## Changed
- Optimizes performance of the providing blame annotations, especially for large files (saw a 3.5x improvement on some files)
## Fixed
- Fixes [#107](https://github.com/eamodio/vscode-gitlens/issues/107) - Double-byte characters break blame layout (still requires proper font support)
## [4.3.2] - 2017-07-20
## Fixed
- Fixes [#118](https://github.com/eamodio/vscode-gitlens/issues/118) - GitLens stopped working on latest insiders build -- thanks to [PR #121](https://github.com/eamodio/vscode-gitlens/pull/121) by Johannes Rieken ([@jrieken](https://github.com/jrieken))
## [4.3.1] - 2017-07-03
## Added
- Adds `gitlens.stashExplorer.enabled` setting to specify whether or not to show the `Git Stashes` custom view
- Adds `Toggle Git Stashes Explorer` command (`gitlens.stashExplorer.toggle`) - toggles the `Git Stashes` custom view on and off
## Changed
- Hides the `Git Stashes` custom view by default
## Fixed
- Fixes [#108](https://github.com/eamodio/vscode-gitlens/issues/108) - Option to remove stash explorer from the main explorer?
## [4.3.0] - 2017-07-03
## Added
- Adds `Git Stashes` custom view to the Explorer activity
- Shows all of the stashed changes in the repository
- Provides toolbar buttons to `Stash Changes` and `Refresh`
- Provides a context menu with `Apply Stashed Changes` and `Delete Stashed Changes` commands - both require a confirmation
- Expand each stash to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu with `Open Changes`, `Open File`, `Open Stashed File`, `Open File in Remote`, and `Compare File with Working Tree` commands
## [4.2.0] - 2017-06-27
## Added
- Adds `Compare File with Revision...` command (`gitlens.diffWithRevision`) - compares the active file with the selected revision of the same file
- Adds `Open Changed Files` command (`gitlens.openChangedFiles`) to the source control group context menu
- Adds `Close Unchanged Files` command (`gitlens.closeUnchangedFiles`) to the source control group context menu
- Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the source control resource context menu
- Adds `Compare File with Revision...` command (`gitlens.diffWithRevision`) to the source control resource context menu
- Adds `Show File History` command (`gitlens.showQuickFileHistory`) to the source control resource context menu
## Changed
- Renames `Compare File with...` command to `Compare File with Branch...`
- Renames `Open Line Commit in Remote` command to `Open Commit in Remote`
- Renames `Show Line Commit Details` command to `Show Commit File Details`
- Updates the description of `gitlens.blame.line.enabled` to be clearer about its behavior
- Updates the description of `gitlens.codeLens.enabled` to be clearer about its behavior
### Fixed
- Fixes [#103](https://github.com/eamodio/vscode-gitlens/issues/103) - Toggle file blame annotations disables line blame annotations if line blame annotations are off by default
- Fixes another infinite loop in the `Close Unchanged Files` command
## [4.1.4] - 2017-06-25
## Changed
- Optimizes performance of the `Compare with Previous` commands - also avoids trying to focus a line if we don't have one
### Fixed
- Fixes `changes` (diff) hover not showing the correct previous line (for real this time)
- Attempts to fix [#99](https://github.com/eamodio/vscode-gitlens/issues/99) - undo/redo spawns too many git processes
## [4.1.3] - 2017-06-20
### Fixed
- Fixes `changes` (diff) hover not showing the correct previous line when showing recent changes annotations of the whole-file
## [4.1.2] - 2017-06-15
### Fixed
- Fixes [#96](https://github.com/eamodio/vscode-gitlens/issues/96) - External diff command can be unintentionally triggered
## [4.1.1] - 2017-06-13
### Added
- Adds an `alt` command to the `Toggle File Blame Annotations` command button, which when you hold down `alt` and click it will execute the `Toggle Recent File Changes Annotations` command instead
### Fixed
- Fixes missing `Toggle File Blame Annotations` command icon
## [4.1.0] - 2017-06-13
### Added
- Adds all-new recent changes annotations of the whole-file - annotates and highlights all of lines changed in the most recent commit
- Can customize the [layout](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#file-recent-changes-annotation-settings), as well as the [theme](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#theme-settings)
- Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) - toggles the recent changes annotations on and off
- Adds ability to press `Escape` to quickly toggle any whole-file annotations off
- Improves performance
- Optimized git output parsing to increase speed and dramatically reduce memory usage
- Defers diff chunk parsing until it is actually required
- Adds `gitlens.defaultDateFormat` setting to specify how all absolute dates will be formatted by default
### Fixed
- Fixes excessive memory usage when parsing diffs
- Fixes extra newline in multi-line commit messages
- Fixes (again) [#33](https://github.com/eamodio/vscode-gitlens/issues/33) - Commit messages can causes markdown formatting in hovers
## [4.0.1] - 2017-06-09
### Fixed
- Fixes [#87](https://github.com/eamodio/vscode-gitlens/issues/87) - Can't open files in remote when using git@ urls (ssh)
## [4.0.0] - 2017-06-09
### Added
- Adds all-new, beautiful, highly customizable and themeable, file blame annotations
- Can now fully customize the [layout and content](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#file-blame-annotation-settings), as well as the [theme](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#theme-settings)
- Adds all-new configurability and themeability to the current line blame annotations
- Can now fully customize the [layout and content](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#line-blame-annotation-settings), as well as the [theme](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#theme-settings)
- Adds all-new configurability to the status bar blame information
- Can now fully customize the [layout and content](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#status-bar-settings)
- Adds all-new [configurability](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#advanced-settings) over which commands are added to which menus via the `gitlens.advanced.menus` setting
- Adds better [configurability](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#code-lens-settings) over where Git code lens will be shown -- both by default and per language
- Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version
- Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off
- Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations
- Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off
- Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations
- Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu
- Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu
- Adds `gitlens.strings.*` settings to allow for the customization of certain strings displayed
- Adds `gitlens.theme.*` settings to allow for the theming of certain elements
- Adds `gitlens.advanced.telemetry.enabled` settings to explicitly opt-in or out of telemetry, but still ultimately honors the `telemetry.enableTelemetry` setting
- Adds ability to suppress most warning messages - which can be re-enabled using the `Reset Suppressed Warnings` command (`gitlens.resetSuppressedWarnings`)
### Changed
- (BREAKING) Almost all of the GitLens settings have either been renamed, removed, or otherwise changed - see the [README](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#extension-settings)`
- Changes the positioning of the Git code lens to try to be at the end of any other code lens on the same line
- Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group
- Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off
- Changes the default of `gitlens.advanced.toggleWhitespace.enabled` back to `true`, but automatically disables whitespace toggling if whitespace rendering is not on
### Removed
- Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise
- Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`)
- Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
### Fixed
- Fixes [#81](https://github.com/eamodio/vscode-gitlens/issues/81) - Current line annotation feels too sticky
- Fixes [#83](https://github.com/eamodio/vscode-gitlens/issues/83) - Calling "close unchanged files" results in no new files being openable
- Fixes issues with the zone.js monkey patching done by application insights (telemetry) - disables all the monkey patching
- Fixes issue with `Open Branch in Remote` & `Open Repository in Remote` not showing when there are no open editors
## [3.6.1] - 2017-06-07
### Fixed
- Fixes issues with the zone.js monkey patching done by application insights (telemetry) - disables all the monkey patching
## [3.6.0] - 2017-06-02
### Added
- Adds diff information (the line's previous version) into the active line hover
- Adds a `gitlens.diffWithWorking` status bar command option - compares the current line commit with the working tree
### Changed
- Changes the behavior of the `Compare File with Working Tree` command (`gitlens.diffWithWorking`) - always does what it says :)
- Compares the current file with the working tree -- if the current file *is* the working file, it will show a `File matches the working tree` message
- Changes the behavior of the `Compare File with Previous` command (`gitlens.diffWithPrevious`) - always does what it says :)
- Compares the current file with the previous commit to that file
- Changes the behavior of the `gitlens.diffWithPrevious` status bar command option - compares the current line commit with the previous
- Renames `Compare File with Previous Commit` command to `Compare File with Previous`
- Renames `Compare Line with Previous Commit` command to `Compare Line Commit with Previous`
- Renames `Compare Line with Working Tree` command to `Compare Line Commit with Working Tree`
- Renames `Compare with Previous Commit` in quick pick menus to `Compare File with Previous`
- Renames `Compare with Working Tree` in quick pick menus to `Compare File with Working Tree`
### Fixed
- Fixes [#79](https://github.com/eamodio/vscode-gitlens/issues/79) - Application insights package breaks GitLens + eslint
## [3.5.1] - 2017-05-25
### Changed
- Changes certain code lens actions to be unavailable (unclickable) when the commit referenced is uncommitted - avoids unwanted error messages
- Debounces more events when tracking the active line to further reduce lag
### Fixed
- Fixes [#71](https://github.com/eamodio/vscode-gitlens/issues/71) - Blame information is invalid when a file has changed outside of vscode
- Fixes issue with showing the incorrect blame for versioned files (i.e. files on the left of a diff, etc)
## [3.5.0] - 2017-05-24
### Added
- Improves performance
- Reduces the number of git calls on known "untrackables"
- Caches many more git commands to reduce git command roundtrips and parsing
- Caches many more git commands to reduce git command round-trips and parsing
- Increases the debounce (delay) on cursor movement to reduce lag when navigating around a file
- Adds diff information (previous line's code) into the active line hover when the current line is uncommitted
- Adds `gitlens.statusBar.alignment` settings to control the alignment of the status bar -- thanks to Zack Schuster (@zackschuster)!
- Adds diff information (the line's previous version) into the active line hover when the current line is uncommitted
- Adds `gitlens.statusBar.alignment` settings to control the alignment of the status bar -- thanks to [PR #72](https://github.com/eamodio/vscode-gitlens/pull/72) by Zack Schuster ([@zackschuster](https://github.com/zackschuster))!
- Adds `Open Branch in Remote` command (`gitlens.openBranchInRemote`) - opens the current branch commits in the supported remote service
- Adds `Open Repository in Remote` command (`gitlens.openRepoInRemote`) - opens the repository in the supported remote service
- Adds `Stash Changes` option to stashed changes quick pick menu -- no longer hidden behind the `"gitlens.insiders": true` setting
- Adds `Stash Unstaged Changes` option to stashed changes quick pick menu -- no longer hidden behind the `"gitlens.insiders": true` setting
- Adds `Apply Stashed Changes` command (`gitlens.stashApply`) to apply the selected stashed changes to the working tree -- no longer hidden behind the `"gitlens.insiders": true` setting
- Adds `Stash Changes` command (`gitlens.stashSave`) to stash any working tree changes -- no longer hidden behind the `"gitlens.insiders": true` setting
- Adds support to the `Search commits` command (`gitlens.showCommitSearch`) to work without any active editor
- Adds commit search pre-population -- if there is an active editor it will use the commit sha of the current line commit, otherwise it will use the current clipboard
### Changed
- Changes `Open File in Remote` and `Open Line Commit in Remote` commands to actually work for everyone (part of their implementation was still behind the `gitlens.insiders` setting)
- Changes the active line hover to only show at the beginning and end of a line if `gitlens.blame.annotation.activeLine` is `both`
- Changes `alt+f` shortcut to `alt+/` for the `Search commits` command (`gitlens.showCommitSearch`)
- Changes `alt+right` on commit details quick pick menu to execute the `Compare File with Previous Commit` command (`gitlens.diffWithPrevious`) when a file is selected
@@ -26,6 +334,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Fixed
- Fixes [#73](https://github.com/eamodio/vscode-gitlens/issues/73) - GitLens doesn't work with Chinese filenames
- Fixes [#40](https://github.com/eamodio/vscode-gitlens/issues/40) - Encoding issues
- Given the limitations of the vscode api, I'm unable to fix all the encoding issues, but many of them should now be squashed
- `files.encoding` is now honored for the cases where the encoding cannot currently be gleaned
- Fixes incorrect file selection from the commit details quick pick menu
- Fixes incorrect command execution when using `"gitlens.statusBar.command": "gitlens.showQuickRepoHistory"`
- Fixes a bunch of issues that were revealed by enabling Typescript `strict` mode
@@ -59,7 +370,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [3.4.5] - 2017-04-13
### Added
- Completely overhauls the [GitLens documentation](https://github.com/eamodio/vscode-gitlens/blob/master/README.md) and messaging -- make sure to check it out to see all the powerful features GitLen provides!
- Completely overhauls the [GitLens documentation](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) and messaging -- make sure to check it out to see all the powerful features GitLen provides!
- Adds `gitlens.blame.annotation.activeLineDarkColor` & `gitlens.blame.annotation.activeLineLightColor` settings to control the colors of the active line blame annotation
### Changed
@@ -191,7 +502,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Fixed
- Fixes issue with `gitlens.diffWithPrevious` command execution via code lens when the code lens was not at the document/file level
- Fixes issue where full shas were displayed on the file/blame history explorers
- Fixes [#30](https://github.com/eamodio/vscode-gitlens/issues/30) - Diff with Working Tree fails from repo/commit quickpick list if file was renamed (and the commit was before the rename)
- Fixes [#30](https://github.com/eamodio/vscode-gitlens/issues/30) - Diff with Working Tree fails from repo/commit quick pick list if file was renamed (and the commit was before the rename)
- Fixes various other quick pick menu command issues when a file was renamed
- Fixes various issues when caching is disabled
- Fixes issues with parsing commits history
@@ -294,7 +605,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [2.9.0]
### Changed
- To accomodate the realization that blame information is invalid when a file has unsaved changes, the following behavior changes have been made
- To accommodate the realization that blame information is invalid when a file has unsaved changes, the following behavior changes have been made
- Status bar blame information will hide
- Code lens change to a `Cannot determine...` message and become unclickable
- Many menu choices and commands will hide
@@ -332,7 +643,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Fixed
- Fixes [#34](https://github.com/eamodio/vscode-gitlens/issues/34) - Open file should open the selected version of the file
- Fixes some issue where some editors opened by the quickpick would not be opened in preview tabs
- Fixes some issue where some editors opened by the quick pick would not be opened in preview tabs
- Fixes issue where copy to clipboard commands would fail if there was no active editor
- Fixes issue where active line annotations would show for opened versioned files
- Fixes issue where code lens compare commands on opened versioned files would fail

385
README.md
View File

@@ -1,94 +1,189 @@
[![](https://vsmarketplacebadge.apphb.com/version/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
[![](https://vsmarketplacebadge.apphb.com/installs/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
[![](https://vsmarketplacebadge.apphb.com/rating/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
[![Chat at https://gitter.im/vscode-gitlens/Lobby](https://badges.gitter.im/vscode-gitlens/Lobby.svg)](https://gitter.im/vscode-gitlens/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Chat at https://vscode-gitlens.slack.com/](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/chat-badge.png)](https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ)
# GitLens
GitLens **supercharges** the built-in Visual Studio Code Git capabilities. It helps you to **visualize code authorship** at a glance via inline Git blame annotations and code lens, **seamlessly navigate and explore** the history of a file or branch, **gain valuable insights** via powerful comparision commands, and so much more.
GitLens **supercharges** the built-in Visual Studio Code Git capabilities. It helps you to **visualize code authorship** at a glance via Git blame annotations and code lens, **seamlessly navigate and explore** the history of a file or branch, **gain valuable insights** via powerful comparison commands, and so much more.
GitLens provides an unobtrusive blame annotation at the end of the selected line, a status bar item showing the commit author and date of the selected line, code lens showing the most recent commit and # of authors of the file and/or code block, and many commands for exploring commits and histories, comparing and navigating revisions, stash access, repository status, and more. GitLens is also [highly customizable](#extension-settings) to meet your specific needs — find code lens intrusive or the selected line blame annotation distracting — no problem, it is easy to [turn them off or change how they behave](#extension-settings).
GitLens provides an unobtrusive blame annotation at the end of the current line, a status bar item showing the commit information (author and date, by default) of the current line, code lens showing the most recent commit and # of authors of the file and/or code block, and many commands for exploring commits and histories, comparing and navigating revisions, stash access, repository status, and more. GitLens is also [highly customizable](#extension-settings) to meet your specific needs — find code lens intrusive or the current line blame annotation distracting — no problem, it is easy to [turn them off or change how they behave](#extension-settings).
## Previews
#### Featuring code lens, whole file inline blame annotations, and navigation and exploration via quick pick menus
![GitLens preview 1](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/gitlens-preview1.gif)
#### Featuring selected line blame annotation and hovers, status bar commit details, quick pick menus, compare with previous, and more
![GitLens preview 2](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/gitlens-preview2.gif)
### Preview — featuring blame annotations, code lens, status bar details, quick pick menus for navigation and exploration, compare with previous, and more
![GitLens preview](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/gitlens-preview.gif)
## Features
#### Git Blame Annotations
### Git Blame Annotations
- Adds a **blame annotation** to the end of the selected line showing the commit id and message, with more details in a hover popup ([optional](#extension-settings), on by default)
- Adds an unobtrusive, highly [customizable](#line-blame-annotation-settings) and [themeable](#theme-settings), **Git blame annotation** to the end of the current line ([optional](#line-blame-annotation-settings), on by default)
- Adds a `Toggle Blame Annotations` command (`gitlens.toggleBlame`) with a shortcut of `alt+b` to toggle **inline Git blame annotations** for a whole file with multiple styles — compact, expanded, and trailing
- Also adds a `Show Blame Annotations` command (`gitlens.showBlame`)
![Line Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotation.png)
- Contains the author, date, and message of the line's most recent commit, by [default](#line-blame-annotation-settings)
- Adds a `details` hover annotation to the current line annotation, which provides more commit details ([optional](#line-blame-annotation-settings), on by default)
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds a `changes` (diff) hover annotation to the current line annotation, which provides **instant** access to the line's previous version ([optional](#line-blame-annotation-settings), on by default)
- Clicking on `Changes` will run the `Compare File Revisions` command (`gitlens.diffWith`)
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds **author and date blame information** about the selected line to the **status bar** ([optional](#extension-settings), on by default)
- By default clicking on the status bar shows a **commit details quick pick menu** with commands for comparing, navigating and exploring commits, and more
![Line Blame Annotations](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotations.png)
- Provides [customizable](#extension-settings) click behavior of the status bar — choose between one of the following
- Toggle whole file blame annotations on and off
- Toggle code lens on and off — only available if [`"gitlens.codeLens.visibility": "ondemand"`](#extension-settings) is set
- Compare the file with the previous commit
- Show a quick pick menu with details and commands for the commit
- Adds on-demand, beautiful, highly [customizable](#file-blame-annotation-settings) and [themeable](#theme-settings), **Git blame annotations** of the whole file
![File Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-file-blame-annotations.png)
- Choose between `gutter` (default) and `hover` [annotation styles](#file-blame-annotation-settings)
- Contains the commit message and date, by [default](#file-blame-annotation-settings)
- Adds a `details` hover annotation to the line's annotation, which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds a `heatmap` (age) indicator to the gutter annotations (on right edge by [default](#file-blame-annotation-settings)), which provides an easy, at-a-glance way to tell the age of a line ([optional](#file-blame-annotation-settings), on by default)
- Indicator ranges from bright yellow (newer) to dark brown (older)
- Press `Escape` to quickly toggle the annotations off
- Adds [customizable](#status-bar-settings) **blame information** about the current line to the **status bar** ([optional](#status-bar-settings), on by default)
![Status Bar Blame](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-status-bar.png)
- Contains the commit author and date, by [default](#status-bar-settings)
- Clicking the status bar item will, by [default](#status-bar-settings), show a **commit details quick pick menu** with commands for comparing, navigating and exploring commits, and more
- Provides [customizable](#status-bar-settings) click behavior — choose between one of the following
- Toggle file blame annotations on and off
- Toggle code lens on and off
- Compare the line commit with the previous commit
- Compare the line commit with the working tree
- Show a quick pick menu with details and commands for the commit (default)
- Show a quick pick menu with file details and commands for the commit
- Show a quick pick menu with the commit history of the file
- Show a quick pick menu with the commit history of the current branch
#### Git Code Lens
- Adds a `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) with a shortcut of `alt+b` to toggle the file blame annotations on and off
- Also adds a `Show File Blame Annotations` command (`gitlens.showFileBlame`)
- Adds **code lens** to the top of the file and on code blocks ([optional](#extension-settings), on by default)
- Adds a `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) to toggle the current line blame annotations on and off
- Also adds a `Show Line Blame Annotations` command (`gitlens.showLineBlame`)
### Git Recent Changes Annotations
- Adds on-demand, [customizable](#file-recent-changes-annotation-settings) and [themeable](#theme-settings), **recent changes annotations** of the whole file
- Highlights all of lines changed in the most recent commit
- Adds a `details` hover annotation to each line, which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds a `changes` (diff) hover annotation to each line, which provides **instant** access to the line's previous version ([optional](#file-recent-changes-annotation-settings), on by default)
- Clicking on `Changes` will run the `Compare File Revisions` command (`gitlens.diffWith`)
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Press `Escape` to quickly toggle the annotations off
- Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) to toggle the recent changes annotations on and off
### Git Code Lens
- Adds **code lens** to the top of the file and on code blocks ([optional](#code-lens-settings), on by default)
![Git Code Lens](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-code-lens.png)
- **Recent Change** — author and date of the most recent commit for the file or code block
- By default, clicking on the code lens shows a **commit file details quick pick menu** with commands for comparing, navigating and exploring commits, and more
- Clicking the code lens will, by [default](#code-lens-settings), show a **commit file details quick pick menu** with commands for comparing, navigating and exploring commits, and more
- **Authors** — number of authors of the file or code block and the most prominent author (if there is more than one)
- By default, clicking on the code lens toggles the inline Git blame annotations on and off for the whole file
- Clicking the code lens will, by [default](#code-lens-settings), toggle the file Git blame annotations on and off of the whole file
- Will be hidden if the author of the most recent commit is also the only author of the file or block, to avoid duplicate information and reduce visual noise
- Provides [customizable](#extension-settings) click behavior for each code lens — choose between one of the following
- Toggle whole file blame annotations on and off
- Compare the file with the previous commit
- Provides [customizable](#code-lens-settings) click behavior for each code lens — choose between one of the following
- Toggle file blame annotations on and off
- Compare the commit with the previous commit
- Show a quick pick menu with details and commands for the commit
- Show a quick pick menu with file details and commands for the commit
- Show a quick pick menu with the commit history of the file
- Show a quick pick menu with the commit history of the current branch
- Adds a `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) with a shortcut of `shift+alt+b` to toggle the code lens on and off — only available if [`"gitlens.codeLens.visibility": "ondemand"`](#extension-settings) is set
- Adds a `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) with a shortcut of `shift+alt+b` to toggle the code lens on and off
#### Powerful Comparison Tools
### Powerful Comparison Tools
- Effortlessly navigate between comparisions via the `alt+,` and `alt+.` shortcut keys to go back and forth through a file's revisions
- Effortlessly navigate between comparisons via the `alt+,` and `alt+.` shortcut keys to go back and forth through a file's revisions
- Provides easy access to the following comparison commands via the `Command Palette` as well as in context via the many provided quick pick menus
- Adds a `Directory Compare` command (`gitlens.diffDirectory`) to open the configured Git difftool to compare directories between branches
- Adds a `Compare File with...` command (`gitlens.diffWithBranch`) to compare the active file with the same file on the selected branch
- Adds a `Compare File with Branch...` command (`gitlens.diffWithBranch`) to compare the active file with the same file on the selected branch
- Adds a `Compare File with Next Commit` command (`gitlens.diffWithNext`) with a shortcut of `alt+.` to compare the active file/diff with the next commit revision
- Adds a `Compare File with Next Revision` command (`gitlens.diffWithNext`) with a shortcut of `alt+.` to compare the active file/diff with the next commit revision
- Adds a `Compare File with Previous Commit` command (`gitlens.diffWithPrevious`) with a shortcut of `alt+,` to compare the active file/diff with the previous commit revision
- Adds a `Compare File with Previous Revision` command (`gitlens.diffWithPrevious`) with a shortcut of `alt+,` to compare the active file/diff with the previous commit revision
- Adds a `Compare Line with Previous Commit` command (`gitlens.diffLineWithPrevious`) with a shortcut of `shift+alt+,` to compare the active file/diff with the previous line commit revision
- Adds a `Compare Line Revision with Previous` command (`gitlens.diffLineWithPrevious`) with a shortcut of `shift+alt+,` to compare the active file/diff with the previous line commit revision
- Adds a `Compare File with Working Tree` command (`gitlens.diffWithWorking`) with a shortcut of `shift+alt+w` to compare the most recent commit revision of the active file/diff with the working tree
- Adds a `Compare File with Revision...` command (`gitlens.diffWithRevision`) to compare the active file with the selected revision of the same file
- Adds a `Compare Line with Working Tree` command (`gitlens.diffLineWithWorking`) with a shortcut of `alt+w` to compare the commit revision of the active line with the working tree
- Adds a `Compare File with Working Revision` command (`gitlens.diffWithWorking`) with a shortcut of `shift+alt+w` to compare the most recent commit revision of the active file/diff with the working tree
#### Navigate and Explore
- Adds a `Compare Line Revision with Working` command (`gitlens.diffLineWithWorking`) with a shortcut of `alt+w` to compare the commit revision of the active line with the working tree
### Navigate and Explore
- Adds a [customizable](#gitlens-custom-view-settings) `GitLens` custom view to the Explorer activity
- `Repository View` - provides a full repository explorer
![GitLens Repository view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-repository.png)
- `Repository Status` node — provides the status of the repository
- Provides the name of the current branch, its upstream tracking branch (if available), and its upstream status (if available)
- Provides indicator dots on the repository icon which denote the following:
- `None` - up-to-date with the upstream
- `Green` - ahead of the upstream
- `Red` - behind the upstream
- `Yellow` - both ahead of and behind the upstream
- Provides additional nodes, if the current branch is not synchronized with the upstream, to quickly see and explore the specific commits ahead and/or behind the upstream
- Provides a context menu with `Open Repository in Remote`, and `Refresh` commands
- `Branches` node — provides a list of the local branches
- Indicates which branch is the current branch and [optionally](#gitlens-custom-view-settings) shows the remote tracking branch
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`, `Show Commit Details`, and `Refresh` commands
- Provides a context menu on each branch with `Open Branch in Remote`, and `Refresh` commands
- Provides a context menu with `Open Branches in Remote`, and `Refresh` commands
- `Remotes` node — provides a list of remotes
- Indicates the direction of the remote (fetch, push, both), remote service (if applicable), and repository path
- Expand each remote to see its list of branches
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, `Show File History`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`,`Show Commit Details`, and `Refresh` commands
- Provides a context menu on each remote with `Open Branches in Remote`, `Open Repository in Remote`, and `Refresh` commands
- Provides a context menu with a `Refresh` command
- `Stashes` node — provides a list of stashed changes
- Expand each stash to quickly see the set of files stashed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu with `Stash Changes`, and `Refresh` commands
- Provides a context menu on each stash with `Apply Stashed Changes` (confirmation required), `Delete Stashed Changes` (confirmation required), `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit Message to Clipboard`, and `Refresh` commands
- Provides a context menu on each stashed file with `Apply Changes`, `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, and `Show File History` commands
- `History View` - provides the revision history of the active file
![GitLens History view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-history.png)
- Automatically updates to track the active editor
- Provides a context menu with `Open File`, `Open File in Remote`, and `Refresh` commands
- Provides a context menu on each revision (commit) with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Quickly switch between views using the `Switch to Repository View` or `Switch to History View` commands
- Provides toolbar commands to `Search Commits`, `Switch to Repository View` or `Switch to History View`, and `Refresh`
- Adds a `Search Commits` command (`gitlens.showCommitSearch`) with a shortcut of `alt+/` to search for commits by message, author, file(s), or commit id
- Adds commands to open files, commits, branches, and the repository in the supported remote services, currently **BitBucket, GitHub, GitLab, and Visual Studio Team Services** — only available if a Git upstream service is configured in the repository
- Also supports [remote services with custom domains](#custom-remotes-settings), such as **BitBucket, Bitbucket Server (previously called Stash), GitHub, GitHub Enterprise, GitLab**
- `Open Branches in Remote` command (`gitlens.openBranchesInRemote`) — opens the branches in the supported remote service
- `Open Branch in Remote` command (`gitlens.openBranchInRemote`) — opens the current branch commits in the supported remote service
- `Open Line Commit in Remote` command (`gitlens.openCommitInRemote`) — opens the commit revision of the active line in the supported remote service
- `Open Commit in Remote` command (`gitlens.openCommitInRemote`) — opens the commit revision of the active line in the supported remote service
- `Open File in Remote` command (`gitlens.openFileInRemote`) — opens the active file/revision in the supported remote service
- `Open Repository in Remote` command (`gitlens.openRepoInRemote`) — opens the repository in the supported remote service
- Adds a `Show Current Branch History` command (`gitlens.showQuickRepoHistory`) with a shortcut of `shift+alt+h` to show a paged **branch history quick pick menu** of the current branch for exploring its commit history
![Branch History Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-branch-history.png)
![Branch History Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-branch-history.png)
- Provides entries to `Show Commit Search` and `Open Branch in <remote-service>` when available
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
@@ -99,7 +194,7 @@ GitLens provides an unobtrusive blame annotation at the end of the selected line
- Adds a `Show File History` command (`gitlens.showQuickFileHistory`) to show a paged **file history quick pick menu** of the active file for exploring its commit history
![File History Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-file-history.png)
![File History Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-file-history.png)
- Provides entries to `Show Branch History` and `Open File in <remote-service>` when available
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
@@ -107,54 +202,51 @@ GitLens provides an unobtrusive blame annotation at the end of the selected line
- Adds a `Show Commit Details` command (`gitlens.showQuickCommitDetails`) to show a **commit details quick pick menu** of the most recent commit of the active file
![Commit Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-commit-details.png)
![Commit Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-commit-details.png)
- Quickly see the set of files changed in the commit, complete with status indicators for adds, changes, renames, and deletes
- Provides entries to `Copy to Clipboard`, `Directory Compare`, `Open Changed Files`, `Open File in <remote-service>` when available, and more
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the current revision of the while leaving the quick pick menu open
- NOTE: Once [vscode issue #10568](https://github.com/Microsoft/vscode/issues/10568) is resolved this will change to preview the comparison of the current revision with the previous one
- Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one
- Adds a `Show Line Commit Details` command (`gitlens.showQuickCommitFileDetails`) with a shortcut of `alt+c` to show a **file commit details quick pick menu** of the most recent commit of the active file
- Adds a `Show Commit File Details` command (`gitlens.showQuickCommitFileDetails`) with a shortcut of `alt+c` to show a **file commit details quick pick menu** of the most recent commit of the active file
![Line Commit Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-commit-file-details.png)
![Commit File Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-commit-file-details.png)
- Provides entries to `Show Commit Details`, `Show File History`, `Compare with...`, `Copy to Clipboard`, `Open File`, `Open File in <remote-service>` when available, and more
- Provides entries to `Show Commit Details`, `Show File History`, `Compare File with...`, `Copy to Clipboard`, `Open File`, `Open File in <remote-service>` when available, and more
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Adds a `Show Repository Status` command (`gitlens.showQuickRepoStatus`) with a shortcut of `alt+s` to show a **repository status quick pick menu** for visualizing the current repository status
![Repository Status Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-repo-status.png)
![Repository Status Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-repo-status.png)
- Quickly see upstream status (if an Git upstream is configured) — complete with ahead and behind information
- If you are ahead of the upstream, an entry will be shown with the number of commits ahead. Chosing it will show a limited **branch history quick pick menu** containing just the commits ahead of the upstream
- If you are behind the upstream, an entry will be shown with the number of commits behind. Chosing it will show a limited **branch history quick pick menu** containing just the commits behind the upstream
- If you are ahead of the upstream, an entry will be shown with the number of commits ahead. Choosing it will show a limited **branch history quick pick menu** containing just the commits ahead of the upstream
- If you are behind the upstream, an entry will be shown with the number of commits behind. Choosing it will show a limited **branch history quick pick menu** containing just the commits behind the upstream
- Quickly see all working changes, both staged and unstaged, complete with status indicators for adds, changes, renames, and deletes
- Provides entries to `Show Stashed Changes`, `Open Changed Files`, and `Close Unchanged Files`
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Use the `alt+right arrow` shortcut on a file entry in the `Staged Files` or `Unstaged Files` sections to preview the working file while leaving the quick pick menu open
- NOTE: Once [vscode issue #10568](https://github.com/Microsoft/vscode/issues/10568) is resolved this will change to preview the comparison of the working file with the previous revision
- Use the `alt+right arrow` shortcut on a file entry in the `Staged Files` or `Unstaged Files` sections to preview the comparison of the working file with the previous revision
- Adds a `Show Stashed Changes` command (`gitlens.showQuickStashList`) to show a **stashed changes quick pick menu** for exploring your repository stash history
![Stashed Changes Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-stash-list.png)
![Stashed Changes Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-stash-list.png)
- [Insiders only](#insiders) — Provides entries to `Stash Changes`
- Provides entries to `Stash Changes`
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Chosing a stash entry shows a **stash details quick pick menu** which is very similar to the **commit details quick pick menu** above
- Choosing a stash entry shows a **stash details quick pick menu** which is very similar to the **commit details quick pick menu** above
![Stash Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/screenshot-stash-details.png)
![Stash Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-stash-details.png)
- Quickly see the set of files changed in the stash, complete with status indicators for adds, changes, renames, and deletes
- Provides entries to `Copy Message to Clipboard`, `Directory Compare`, and `Open Changed Files`
- [Insiders only](#insiders) — Provides entries to `Apply Stashed Changes` and `Delete Stashed Changes` — both require a confirmation
- Provides entries to `Apply Stashed Changes` and `Delete Stashed Changes` — both require a confirmation
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the current revision of the while leaving the quick pick menu open
- NOTE: Once [vscode issue #10568](https://github.com/Microsoft/vscode/issues/10568) is resolved this will change to preview the comparison of the current revision with the previous one
- Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one
- Adds a `Show Last Opened Quick Pick` command (`gitlens.showLastQuickPick`) with a shortcut of `alt+-` to quickly get back to where you were when the last GitLens quick pick menu closed
@@ -164,58 +256,173 @@ GitLens provides an unobtrusive blame annotation at the end of the selected line
- Adds a `Open Blame History Explorer` command (`gitlens.showBlameHistory`) to show a **blame history explorer** (peek style) to visualize the blame history of a file or code block
- Likely to be deprecated in a future release, add your voice to [#66](https://github.com/eamodio/vscode-gitlens/issues/66) if you feel it should not be removed
#### And More
### And More
- Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard
- Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor
- Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard
- Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor
- Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes
- Adds a `Close Unchanged Files` command (`gitlens.closeUnchangedFiles`) to close any files without working tree changes
- [Insiders only](#insiders) — Adds a `Apply Stashed Changes` command (`gitlens.stashApply`) to chose a stash entry to apply to the working tree from a quick pick menu
- Adds a `Apply Stashed Changes` command (`gitlens.stashApply`) to chose a stash entry to apply to the working tree from a quick pick menu
- [Insiders only](#insiders) — Adds a `Stash Changes` command (`gitlens.stashSave`) to save any working tree changes to the stash — can optionally provide a stash message
- Adds a `Stash Changes` command (`gitlens.stashSave`) to save any working tree changes to the stash — can optionally provide a stash message
- Also adds the command to the Source Control items context menu to stash an individual or group of files, works with multi-select too!
## Insiders
Add [`"gitlens.insiders": true`](#extension-settings) to your settings to join the insiders channel and get early access to upcoming features. Be aware that because this provides early access expect there to be issues.
Add [`"gitlens.insiders": true`](#general-extension-settings) to your settings to join the insiders channel and get early access to upcoming features. Be aware that because this provides early access expect there to be issues.
## Extension Settings
GitLens is highly customizable and provides many configuration settings to allow the personalization of almost all features
### General Settings
|Name | Description
|-----|------------
|`gitlens.defaultDateFormat`|Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.insiders`|Opts into the insiders channel -- provides access to upcoming features
|`gitlens.outputLevel`|Specifies how much (if any) output will be sent to the GitLens output channel
|`gitlens.blame.annotation.activeLine`|Specifies whether and how to show blame annotations on the active line. `off` - no annotation. `inline` - adds a trailing annotation to the active line. `hover` - adds hover annotation to the active line. `both` - adds both `inline` and `hover` annotations
|`gitlens.blame.annotation.activeLineDarkColor`|Specifies the color of the active line blame annotation to use with a dark theme. Must be a valid css color
|`gitlens.blame.annotation.activeLineLightColor`|Specifies the color of the active line blame annotation to use with a light theme. Must be a valid css color
|`gitlens.blame.annotation.highlight`|Specifies whether and how to highlight blame annotations. `none` - no highlight. `gutter` - adds a gutter icon. `line` - adds a full-line highlight. `both` - adds both `gutter` and `line` highlights
|`gitlens.blame.annotation.style`|Specifies the style of the blame annotations. `compact` - groups annotations to limit the repetition and also adds author and date when possible. `expanded` - shows an annotation on every line
|`gitlens.blame.annotation.author`|Specifies whether the committer will be shown in the blame annotations. Applies only to the `expanded` & `trailing` annotation styles
|`gitlens.blame.annotation.date`|Specifies whether and how the commit date will be shown in the blame annotations. `off` - no date. `relative` - relative date (e.g. 1 day ago). `absolute` - date format specified by `gitlens.blame.annotation.dateFormat`. Applies only to the `expanded` & `trailing` annotation styles
|`gitlens.blame.annotation.dateFormat`|Specifies the date format of how absolute dates will be shown in the blame annotations. See https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.blame.annotation.message`|Specifies whether the commit message will be shown in the blame annotations. Applies only to the `expanded` & `trailing` annotation styles
|`gitlens.blame.annotation.sha`|Specifies whether the commit sha will be shown in the blame annotations. Applies only to the `expanded` & `trailing` annotation styles
|`gitlens.codeLens.visibility`|Specifies when code lens will be shown in the active document. `auto` - always shown. `ondemand` - never shown, unless toggled via the `gitlens.toggleCodeLens` command. `off` - never shown
|`gitlens.codeLens.authors.enabled`|Specifies whether the authors code lens is shown
|`gitlens.codeLens.authors.command`|Specifies the command executed when the authors code lens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current committed file with the previous commit. `gitlens.showQuickCommitDetails` - shows a commit details quick pick. `gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick. `gitlens.showQuickFileHistory` - shows a file history quick pick. `gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.codeLens.recentChange.enabled`|Specifies whether the recent change code lens is shown
|`gitlens.codeLens.recentChange.command`|"Specifies the command executed when the recent change code lens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current committed file with the previous commit. `gitlens.showQuickCommitDetails` - shows a commit details quick pick. `gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick. `gitlens.showQuickFileHistory` - shows a file history quick pick. `gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.codeLens.location`|Specifies where code lens will be rendered in the active document. `all` - render at the top of the document, on container-like (classes, modules, etc), and on member-like (methods, functions, properties, etc) lines. `document+containers` - render at the top of the document and on container-like lines. `document` - only render at the top of the document. `custom` - rendering controlled by `gitlens.codeLens.locationCustomSymbols`
|`gitlens.codeLens.locationCustomSymbols`|Specifies the set of document symbols to render active document code lens on. Must be a member of `SymbolKind`
|`gitlens.codeLens.languageLocations`|Specifies where code lens will be rendered in the active document for the specified languages
|`gitlens.menus.diff.enabled`|Specifies whether diff commands will be added to the context menus
|`gitlens.statusBar.enabled`|Specifies whether blame information is shown in the status bar
|`gitlens.statusBar.alignment`|Specifies the blame alignment in the status bar. `left` - align to the left, `right` - align to the right
|`gitlens.statusBar.command`|"Specifies the command executed when the blame status bar item is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current committed file with the previous commit. `gitlens.toggleCodeLens` - toggles Git code lens. `gitlens.showQuickCommitDetails` - shows a commit details quick pick. `gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick. `gitlens.showQuickFileHistory` - shows a file history quick pick. `gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.statusBar.date`|Specifies whether and how the commit date will be shown in the blame status bar. `off` - no date. `relative` - relative date (e.g. 1 day ago). `absolute` - date format specified by `gitlens.statusBar.dateFormat`
|`gitlens.statusBar.dateFormat`|Specifies the date format of how absolute dates will be shown in the blame status bar. See https://momentjs.com/docs/#/displaying/format/ for valid formats
### Blame Settings
|Name | Description
|-----|------------
|`gitlens.blame.ignoreWhitespace`|Specifies whether or not to ignore whitespace when comparing revisions during blame operations
#### File Blame Annotation Settings
|Name | Description
|-----|------------
|`gitlens.blame.file.annotationType`|Specifies the type of blame annotations that will be shown for the current file<br />`gutter` - adds an annotation to the beginning of each line<br />`hover` - shows annotations when hovering over each line
|`gitlens.blame.file.lineHighlight.enabled`|Specifies whether or not to highlight lines associated with the current line
|`gitlens.blame.file.lineHighlight.locations`|Specifies where the associated line highlights will be shown<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`overviewRuler` - adds a decoration to the overviewRuler (scroll bar)
|`gitlens.annotations.file.gutter.format`|Specifies the format of the gutter blame annotations<br />Available tokens<br />`${id}` - commit id<br />`${author}` - commit author<br />`${message}` - commit message<br />`${ago}` - relative commit date (e.g. 1 day ago)<br />`${date}` - formatted commit date (format specified by `gitlens.annotations.file.gutter.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.annotations.file.gutter.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in gutter blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.annotations.file.gutter.compact`|Specifies whether or not to compact (deduplicate) matching adjacent gutter blame annotations
|`gitlens.annotations.file.gutter.heatmap.enabled`|Specifies whether or not to provide a heatmap indicator in the gutter blame annotations
|`gitlens.annotations.file.gutter.heatmap.location`|Specifies where the heatmap indicators will be shown in the gutter blame annotations<br />`left` - adds a heatmap indicator on the left edge of the gutter blame annotations<br />`right` - adds a heatmap indicator on the right edge of the gutter blame annotations
|`gitlens.annotations.file.gutter.hover.details`|Specifies whether or not to provide a commit details hover annotation over the gutter blame annotations
|`gitlens.annotations.file.gutter.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
|`gitlens.annotations.file.hover.heatmap.enabled`|Specifies whether or not to provide heatmap indicators on the left edge of each line
|`gitlens.annotations.file.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
#### Line Blame Annotation Settings
|Name | Description
|-----|------------
|`gitlens.blame.line.enabled`|Specifies whether or not to provide a blame annotation for the current line, by default<br />Use the `gitlens.toggleLineBlame` command to toggle the annotations on and off for the current session
|`gitlens.blame.line.annotationType`|Specifies the type of blame annotations that will be shown for the current line<br />`trailing` - adds an annotation to the end of the current line<br />`hover` - shows annotations when hovering over the current line
|`gitlens.annotations.line.trailing.format`|Specifies the format of the trailing blame annotations<br />Available tokens<br />`${id}` - commit id<br />`${author}` - commit author<br />`${message}` - commit message<br />`${ago}` - relative commit date (e.g. 1 day ago)<br />`${date}` - formatted commit date (format specified by `gitlens.annotations.line.trailing.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.annotations.line.trailing.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in trailing blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.annotations.line.trailing.hover.details`|Specifies whether or not to provide a commit details hover annotation over the trailing blame annotations
|`gitlens.annotations.line.trailing.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation over the trailing blame annotations
|`gitlens.annotations.line.trailing.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
|`gitlens.annotations.line.hover.details`|Specifies whether or not to provide a commit details hover annotation for the current line
|`gitlens.annotations.line.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation for the current line
### File Recent Changes Annotation Settings
|Name | Description
|-----|------------
|`gitlens.recentChanges.file.lineHighlight.locations`|Specifies where the highlights of the recently changed lines will be shown<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`overviewRuler` - adds a decoration to the overviewRuler (scroll bar)
|`gitlens.annotations.file.recentChanges.hover.details`|Specifies whether or not to provide a commit details hover annotation
|`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation
|`gitlens.annotations.file.recentChanges.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
### Code Lens Settings
|Name | Description
|-----|------------
|`gitlens.codeLens.enabled`|Specifies whether or not to provide any Git code lens, by default<br />Use the `gitlens.toggleCodeLens` command to toggle the Git code lens on and off for the current session
|`gitlens.codeLens.recentChange.enabled`|Specifies whether or not to show a `recent change` code lens showing the author and date of the most recent commit for the file or code block
|`gitlens.codeLens.recentChange.command`|Specifies the command to be executed when the `recent change` code lens is clicked<br />`gitlens.toggleFileBlame` - toggles file blame annotations<br />`gitlens.showBlameHistory` - opens the blame history explorer<br />`gitlens.showFileHistory` - opens the file history explorer<br />`gitlens.diffWithPrevious` - compares the current committed file with the previous commit<br />`gitlens.showQuickCommitDetails` - shows a commit details quick pick<br />`gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick<br />`gitlens.showQuickFileHistory` - shows a file history quick pick<br />`gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.codeLens.authors.enabled`|Specifies whether or not to show an `authors` code lens showing number of authors of the file or code block and the most prominent author (if there is more than one)
|`gitlens.codeLens.authors.command`|Specifies the command to be executed when the `authors` code lens is clicked<br />`gitlens.toggleFileBlame` - toggles file blame annotations<br />`gitlens.showBlameHistory` - opens the blame history explorer<br />`gitlens.showFileHistory` - opens the file history explorer<br />`gitlens.diffWithPrevious` - compares the current committed file with the previous commit<br />`gitlens.showQuickCommitDetails` - shows a commit details quick pick<br />`gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick<br />`gitlens.showQuickFileHistory` - shows a file history quick pick<br />`gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.codeLens.locations`|Specifies where Git code lens will be shown in the document<br />`document` - adds code lens at the top of the document<br />`containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)<br />`blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines<br />`custom` - adds code lens at the start of symbols contained in `gitlens.codeLens.locationCustomSymbols`
|`gitlens.codeLens.customLocationSymbols`|Specifies the set of document symbols where Git code lens will be shown in the document
|`gitlens.codeLens.perLanguageLocations`|Specifies where Git code lens will be shown in the document for the specified languages
### GitLens Custom View Settings
|Name | Description
|-----|------------
|`gitlens.gitExplorer.view`|Specifies the starting view (mode) of the `GitLens` custom view<br />`history` - shows the commit history of the active file<br />`repository` - shows a repository explorer"
|`gitlens.gitExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the `GitLens` custom view"
|`gitlens.gitExplorer.commitFormat`|Specifies the format of committed changes in the `GitLens` custom view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.gitExplorer.commitFileFormat`|Specifies the format of a committed file in the `GitLens` custom view<br />Available tokens<br /> ${file} - file name<br /> ${filePath} - file name and path<br /> ${path} - file path
|`gitlens.gitExplorer.stashFormat`|Specifies the format of stashed changes in the `GitLens` custom view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.gitExplorer.stashFileFormat`|Specifies the format of a stashed file in the `GitLens` custom view<br />Available tokens<br /> ${file} - file name<br /> ${filePath} - file name and path<br /> ${path} - file path
### Custom Remotes Settings
|Name | Description
|-----|------------
|`gitlens.remotes`|Specifies any custom domains for remote (code-hosting) services<br />Example: ```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]```
### Status Bar Settings
|Name | Description
|-----|------------
|`gitlens.statusBar.enabled`|Specifies whether or not to provide blame information on the status bar
|`gitlens.statusBar.alignment`|Specifies the blame alignment in the status bar<br />`left` - align to the left, `right` - align to the right
|`gitlens.statusBar.command`|Specifies the command to be executed when the blame status bar item is clicked<br />`gitlens.toggleFileBlame` - toggles file blame annotations<br />`gitlens.showBlameHistory` - opens the blame history explorer<br />`gitlens.showFileHistory` - opens the file history explorer<br />`gitlens.diffWithPrevious` - compares the current line commit with the previous<br />`gitlens.diffWithWorking` - compares the current line commit with the working tree<br />`gitlens.toggleCodeLens` - toggles Git code lens<br />`gitlens.showQuickCommitDetails` - shows a commit details quick pick<br />`gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick<br />`gitlens.showQuickFileHistory` - shows a file history quick pick<br />`gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.statusBar.format`|Specifies the format of the blame information on the status bar<br />Available tokens<br />`${id}` - commit id<br />`${author}` - commit author<br />`${message}` - commit message<br />`${ago}` - relative commit date (e.g. 1 day ago)<br />`${date}` - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.statusBar.dateFormat`|Specifies the date format of absolute dates shown in the blame information on the status bar<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
### Strings Settings
|Name | Description
|-----|------------
|`gitlens.strings.codeLens.unsavedChanges.recentChangeAndAuthors`|Specifies the string to be shown in place of both the `recent change` and `authors` code lens when there are unsaved changes
|`gitlens.strings.codeLens.unsavedChanges.recentChangeOnly`|Specifies the string to be shown in place of the `recent change` code lens when there are unsaved changes
|`gitlens.strings.codeLens.unsavedChanges.authorsOnly`|Specifies the string to be shown in place of the `authors` code lens when there are unsaved changes
### Theme Settings
|Name | Description
|-----|------------
|`gitlens.theme.annotations.file.gutter.separateLines`|Specifies whether or not gutter blame annotations will have line separators
|`gitlens.theme.annotations.file.gutter.dark.backgroundColor`|Specifies the dark theme background color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.light.backgroundColor`|Specifies the light theme background color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.dark.foregroundColor`|Specifies the dark theme foreground color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.light.foregroundColor`|Specifies the light theme foreground color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.dark.uncommittedForegroundColor`|Specifies the dark theme foreground color of an uncommitted line in the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.light.uncommittedForegroundColor`|Specifies the light theme foreground color of an uncommitted line in the gutter blame annotations
|`gitlens.theme.annotations.line.trailing.dark.backgroundColor`|Specifies the dark theme background color of the trailing blame annotation
|`gitlens.theme.annotations.line.trailing.light.backgroundColor`|Specifies the light theme background color of the trailing blame annotation
|`gitlens.theme.annotations.line.trailing.dark.foregroundColor`|Specifies the dark theme foreground color of the trailing blame annotation
|`gitlens.theme.annotations.line.trailing.light.foregroundColor`|Specifies the light theme foreground color of the trailing blame annotation
|`gitlens.theme.lineHighlight.dark.backgroundColor`|Specifies the dark theme background color of the associated line highlights in blame annotations. Must be a valid css color
|`gitlens.theme.lineHighlight.light.backgroundColor`|Specifies the light theme background color of the associated line highlights in blame annotations. Must be a valid css color
|`gitlens.theme.lineHighlight.dark.overviewRulerColor`|Specifies the dark theme overview ruler color of the associated line highlights in blame annotations
|`gitlens.theme.lineHighlight.light.overviewRulerColor`|Specifies the light theme overview ruler color of the associated line highlights in blame annotations
### Advanced Settings
|Name | Description
|-----|------------
|`gitlens.advanced.telemetry.enabled`|Specifies whether or not to enable GitLens telemetry (even if enabled still abides by the overall `telemetry.enableTelemetry` setting
|`gitlens.advanced.menus`|Specifies which commands will be added to which menus
|`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached
|`gitlens.advanced.caching.maxLines`|Specifies the threshold for caching larger documents
|`gitlens.advanced.git`|Specifies the git path to use
|`gitlens.advanced.gitignore.enabled`|Specifies whether or not to parse the root .gitignore file for better performance (i.e. avoids blaming excluded files)
|`gitlens.advanced.maxQuickHistory`|Specifies the maximum number of QuickPick history entries to show
|`gitlens.advanced.quickPick.closeOnFocusOut`|Specifies whether or not to close the QuickPick menu when focus is lost
## Known Issues
- If the `Copy to * clipboard` commands don't work on Linux -- `xclip` needs to be installed. You can install it via `sudo apt-get install xclip`
- Visible whitespace causes issues ([vscode issue #11485](https://github.com/Microsoft/vscode/issues/11485)) with the `expanded` and `compact` blame annotation styles when using a non-monospace font -- set `"gitlens.advanced.toggleWhitespace.enabled": true` if you are using a non-monospace font
## Contributors
A big thanks to the people that have contributed to this project:
- Peng Lyu ([@rebornix](https://github.com/rebornix)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=rebornix))
- Aurelio Ogliari ([@nobitagit](https://github.com/nobitagit)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=nobitagit)
- Johannes Rieken ([@jrieken](https://github.com/jrieken)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=jrieken))
- Zack Schuster ([@zackschuster](https://github.com/zackschuster)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=zackschuster)

BIN
images/chat-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

88
images/chat-badge.svg Normal file
View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="92" height="20" xml:space="preserve">
<style type="text/css">
.white{fill:#FFF;}
.shadow{fill:#2e840e;}
</style>
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="a">
<rect width="92" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#a)">
<path fill="#555" d="M0 0h34v20H0z"/>
<path fill="#4c1" d="M34 0h58v20H34z"/>
<path fill="url(#b)" d="M0 0h92v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="17" y="15" fill="#010101" fill-opacity=".3">chat</text>
<text x="17" y="14">chat</text>
<g transform="scale(0.1) translate(340, -21)">
<path class="shadow" d="M263.5,105.5c3.9,1.7,4.2,3,1.1,8.8c-3.1,6-3.9,6.3-7.7,4.8c-4.8-2.1-11-3.6-15-3.6c-6.5,0-10.9,2.3-10.9,5.9
c0,11.7,37.4,5.4,37.4,30.4c0,12.6-10.8,21-27,21c-8.5,0-19-2.8-26.3-6.5c-3.6-1.8-3.8-2.9-0.7-8.9c2.7-5.3,3.6-5.8,7.5-4.2
c6.2,2.7,14,4.8,19.3,4.8c6,0,9.9-2.4,9.9-6c0-11.4-38.1-6-38.1-30.2c0-12.9,10.7-21.5,26.8-21.5
C247.4,100.2,256.9,102.5,263.5,105.5z"/>
<path class="shadow" d="M293.7,75.8V169c0,1.4-1.5,2.9-3.6,2.9h-9.8c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5
C293.4,70.7,293.7,71.3,293.7,75.8z"/>
<path class="shadow" d="M363.4,128.2v40.1c0,2.1-1.5,3.6-3.6,3.6h-9.7c-2.2,0-3.8-1.6-3.6-3.8l0.1-4.3c-5.3,5.8-12.8,8.9-20.3,8.9
c-14.6,0-24.4-8.5-24.4-21.1c0-13.4,11.1-22.5,27.7-22.5c6.3,0,12.1,1.1,16.8,3.1v-4.6c0-7.4-5.8-11.8-15.7-11.8
c-4.6,0-10.3,1.8-14.8,4.5c-3.5,2-4.3,1.8-8.1-3.8c-3.7-5.6-3.6-6.7,0-9c6.8-4.4,16.1-7.2,24.6-7.2
C351.4,100.2,363.4,110.6,363.4,128.2z M318.2,151.4c0,4.8,4,8,10.2,8c7.4,0,14.1-3.6,18-9.6v-6.3c-3.9-1.5-8.7-2.3-12.9-2.3
C324.3,141.2,318.2,145.5,318.2,151.4z"/>
<path class="shadow" d="M429.9,105.6c3.6,2.1,3.7,3.2-0.2,9.2c-3.7,5.7-4.3,6-8.2,4c-3-1.6-7.7-2.9-11.7-2.9
c-12.3,0-20.5,8.1-20.5,20.3c0,12.7,8.2,21.2,20.5,21.2c4.3,0,9.6-1.6,13.1-3.6c3.6-2.1,4.3-1.9,8.1,3.6c3.4,5.1,3.3,6.3,0.3,8.5
c-5.5,3.8-14.1,6.7-21.7,6.7c-22.7,0-37.9-14.6-37.9-36.4c0-21.7,15.2-36.1,38.1-36.1C416.6,100.2,424.8,102.6,429.9,105.6z"/>
<path class="shadow" d="M504.1,163.1c2.8,3.6,1.7,4.9-5.4,7.5c-7.2,2.6-8.2,2.5-10.8-0.9l-20.3-27.1l-9.1,8.8V169
c0,1.4-1.5,2.9-3.6,2.9H445c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5c8.2,0,8.5,0.6,8.5,5v53l27.8-26.7
c3.1-2.9,4.8-2.7,10.2,0.9c6,3.9,6.5,5,3.6,7.8L479.3,131L504.1,163.1z"/>
</g>
<g transform="scale(0.1) translate(340, -21)">
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="shadow" width="17.6" height="17"/>
<g>
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="shadow" width="17.6" height="17"/>
<path class="shadow" d="M182,117.5c-12.9-43-31.5-53-74.5-40.1s-53,31.5-40.1,74.5s31.5,53,74.5,40.1S194.9,160.5,182,117.5z
M160.3,145.4l-8.1,2.7l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-16.7,5.6
l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3
c-2.6-0.1-5.1-1.8-6-4.4c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-5.4-16.1l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4
c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-2.8-8.4c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l16.7-5.6l-2.8-8.4
c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1c1.1,3.4-0.7,7.1-4.1,8.2l-8.1,2.7l5.4,16.1
l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1C165.5,140.6,163.7,144.3,160.3,145.4z"/>
</g>
</g>
<g transform="scale(0.1) translate(340, -31)">
<path class="white" d="M263.5,105.5c3.9,1.7,4.2,3,1.1,8.8c-3.1,6-3.9,6.3-7.7,4.8c-4.8-2.1-11-3.6-15-3.6c-6.5,0-10.9,2.3-10.9,5.9
c0,11.7,37.4,5.4,37.4,30.4c0,12.6-10.8,21-27,21c-8.5,0-19-2.8-26.3-6.5c-3.6-1.8-3.8-2.9-0.7-8.9c2.7-5.3,3.6-5.8,7.5-4.2
c6.2,2.7,14,4.8,19.3,4.8c6,0,9.9-2.4,9.9-6c0-11.4-38.1-6-38.1-30.2c0-12.9,10.7-21.5,26.8-21.5
C247.4,100.2,256.9,102.5,263.5,105.5z"/>
<path class="white" d="M293.7,75.8V169c0,1.4-1.5,2.9-3.6,2.9h-9.8c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5
C293.4,70.7,293.7,71.3,293.7,75.8z"/>
<path class="white" d="M363.4,128.2v40.1c0,2.1-1.5,3.6-3.6,3.6h-9.7c-2.2,0-3.8-1.6-3.6-3.8l0.1-4.3c-5.3,5.8-12.8,8.9-20.3,8.9
c-14.6,0-24.4-8.5-24.4-21.1c0-13.4,11.1-22.5,27.7-22.5c6.3,0,12.1,1.1,16.8,3.1v-4.6c0-7.4-5.8-11.8-15.7-11.8
c-4.6,0-10.3,1.8-14.8,4.5c-3.5,2-4.3,1.8-8.1-3.8c-3.7-5.6-3.6-6.7,0-9c6.8-4.4,16.1-7.2,24.6-7.2
C351.4,100.2,363.4,110.6,363.4,128.2z M318.2,151.4c0,4.8,4,8,10.2,8c7.4,0,14.1-3.6,18-9.6v-6.3c-3.9-1.5-8.7-2.3-12.9-2.3
C324.3,141.2,318.2,145.5,318.2,151.4z"/>
<path class="white" d="M429.9,105.6c3.6,2.1,3.7,3.2-0.2,9.2c-3.7,5.7-4.3,6-8.2,4c-3-1.6-7.7-2.9-11.7-2.9
c-12.3,0-20.5,8.1-20.5,20.3c0,12.7,8.2,21.2,20.5,21.2c4.3,0,9.6-1.6,13.1-3.6c3.6-2.1,4.3-1.9,8.1,3.6c3.4,5.1,3.3,6.3,0.3,8.5
c-5.5,3.8-14.1,6.7-21.7,6.7c-22.7,0-37.9-14.6-37.9-36.4c0-21.7,15.2-36.1,38.1-36.1C416.6,100.2,424.8,102.6,429.9,105.6z"/>
<path class="white" d="M504.1,163.1c2.8,3.6,1.7,4.9-5.4,7.5c-7.2,2.6-8.2,2.5-10.8-0.9l-20.3-27.1l-9.1,8.8V169
c0,1.4-1.5,2.9-3.6,2.9H445c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5c8.2,0,8.5,0.6,8.5,5v53l27.8-26.7
c3.1-2.9,4.8-2.7,10.2,0.9c6,3.9,6.5,5,3.6,7.8L479.3,131L504.1,163.1z"/>
</g>
<g transform="scale(0.1) translate(340, -31)">
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="white" width="17.6" height="17"/>
<g>
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="white" width="17.6" height="17"/>
<path class="white" d="M182,117.5c-12.9-43-31.5-53-74.5-40.1s-53,31.5-40.1,74.5s31.5,53,74.5,40.1S194.9,160.5,182,117.5z
M160.3,145.4l-8.1,2.7l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-16.7,5.6
l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3
c-2.6-0.1-5.1-1.8-6-4.4c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-5.4-16.1l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4
c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-2.8-8.4c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l16.7-5.6l-2.8-8.4
c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1c1.1,3.4-0.7,7.1-4.1,8.2l-8.1,2.7l5.4,16.1
l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1C165.5,140.6,163.7,144.3,160.3,145.4z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#F05133" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 795 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#FFFFFF" fill-opacity="0.74" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z">
<animate attributeName="fill" values="#FFFFFF;#F05133;#FFFFFF" dur="1s" repeatCount="indefinite"/>
</path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 815 B

After

Width:  |  Height:  |  Size: 815 B

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18" xml:space="preserve">
<g>
<rect fill="#FFFFFF" fill-opacity="0.75" x="1" y="0" width="4" height="18"/>
<rect fill="#00bcf2" fill-opacity="0.6" x="7" y="0" width="3" height="18"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 312 B

5
images/dark/icon-add.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect fill="#C5C5C5" x="6.5" y="5.5" width="3" height="11"/>
<rect fill="#C5C5C5" x="2.5" y="9.5" width="11" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 253 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m13,8c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -2,0.89 -2,2c0,0.73 0.41,1.38 1,1.72l0,0.3c-0.02,0.52 -0.23,0.98 -0.63,1.38c-0.4,0.4 -0.86,0.61 -1.38,0.63c-0.83,0.02 -1.48,0.16 -2,0.45l0,-4.76c0.59,-0.34 1,-0.98 1,-1.72c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -1.99,0.89 -1.99,2c0,0.73 0.41,1.38 1,1.72l0,6.56c-0.59,0.35 -1,0.99 -1,1.72c0,1.11 0.89,2 2,2c1.11,0 2,-0.89 2,-2c0,-0.53 -0.2,-1 -0.53,-1.36c0.09,-0.06 0.48,-0.41 0.59,-0.47c0.25,-0.11 0.56,-0.17 0.94,-0.17c1.05,-0.05 1.95,-0.45 2.75,-1.25c0.8,-0.8 1.2,-1.98 1.25,-3.02l-0.02,0c0.61,-0.36 1.02,-1 1.02,-1.73l0,0zm-8,-3.2c0.66,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2c-0.65,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2l0,0zm0,12.41c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0zm6,-8c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m11.86,10c-0.45,-1.72 -2,-3 -3.86,-3c-1.86,0 -3.41,1.28 -3.86,3l-3.14,0l0,2l3.14,0c0.45,1.72 2,3 3.86,3c1.86,0 3.41,-1.28 3.86,-3l3.14,0l0,-2l-3.14,0zm-3.86,3.2c-1.22,0 -2.2,-0.98 -2.2,-2.2c0,-1.22 0.98,-2.2 2.2,-2.2c1.22,0 2.2,0.98 2.2,2.2c0,1.22 -0.98,2.2 -2.2,2.2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m9,15l2,0l-3,3l-3,-3l2,0l0,-5l2,0l0,5l0,0zm3,-8c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 557 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m9,16l-2,0l0,-7l5,0l0,2l-3,0l0,5l0,0zm-1,-12c-2.19,0 -4.13,1.02 -5.41,2.59l-1.59,-1.59l0,4l4,0l-1.5,-1.5c1.05,-1.33 2.67,-2.2 4.5,-2.2c3.14,0 5.7,2.56 5.7,5.7c0,3.14 -2.56,5.7 -5.7,5.7c-3.14,0 -5.7,-2.56 -5.7,-5.7c0,-0.34 0.03,-0.67 0.09,-1l-1.31,0c-0.05,0.33 -0.08,0.66 -0.08,1c0,3.86 3.14,7 7,7c3.86,0 7,-3.14 7,-7c0,-3.86 -3.14,-7 -7,-7l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 500 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.901149,9.091851l-0.094,0.071c-0.269,0.333 -0.746,1.096 -0.91,2.375c0.057,0.277 0.092,0.495 0.092,0.545c0,2.206 -1.794,4 -4,4a3.986,3.986 0 0 1 -2.817,-1.164a3.987,3.987 0 0 1 -1.163,-2.815c0,-2.206 1.794,-4 4,-4l0.351,0.025l0,1.85s1.626,-1.342 1.631,-1.339l1.869,-1.577l-3.5,-2.917l0,2.218l-0.371,-0.03a5.75,5.75 0 0 0 -4.055,9.826a5.75,5.75 0 0 0 9.826,-4.056a5.725,5.725 0 0 0 -0.859,-3.012z" />
</svg>

After

Width:  |  Height:  |  Size: 553 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.519592,15.157073l-9.039184,0c-1.367793,0 -2.480539,-1.112828 -2.480539,-2.480622s1.112746,-2.480539 2.480539,-2.480539l0.281314,0c0.349178,-0.47173 0.888523,-0.771191 1.476341,-0.815025c0.321917,-1.471535 1.619609,-2.537962 3.165139,-2.537962c1.221543,0 2.341663,0.699516 2.889377,1.772488c0.083027,-0.008618 0.166386,-0.012926 0.250076,-0.012926c1.190221,0 2.194667,0.874105 2.378785,2.027867c0.670514,0.460047 1.07869,1.225023 1.07869,2.046096c0,1.367793 -1.112828,2.480622 -2.480539,2.480622z" />
</svg>

After

Width:  |  Height:  |  Size: 655 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#32cd32" stroke="#C5C5C5" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cd3131" stroke="#C5C5C5" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cdcd32" stroke="#C5C5C5" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 490 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m14.414133,16.199437l-3.415492,-3.433421c0.627518,-0.878526 0.995065,-1.945307 0.995065,-3.110698c0,-2.967265 -2.411463,-5.378728 -5.378728,-5.378728c-2.967265,0 -5.378728,2.411463 -5.378728,5.378728c0,2.967265 2.411463,5.378728 5.378728,5.378728c1.165391,0 2.223207,-0.367546 3.110698,-0.995065l3.433421,3.415492c0.170326,0.179291 0.403405,0.268936 0.627518,0.268936c0.224114,0 0.466156,-0.080681 0.627518,-0.268936c0.349617,-0.349617 0.349617,-0.914384 0,-1.264001l0,0.008965zm-7.799155,-2.330782c-2.321817,0 -4.213337,-1.891519 -4.213337,-4.213337c0,-2.321817 1.891519,-4.213337 4.213337,-4.213337c2.321817,0 4.213337,1.891519 4.213337,4.213337c0,2.321817 -1.891519,4.213337 -4.213337,4.213337l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 857 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m14.687501,11.955358l-1.079554,-6.821251c-0.076429,-0.458572 -0.477679,-0.821607 -0.955357,-0.821607l-9.30518,0c-0.477679,0 -0.878929,0.363036 -0.955357,0.821607l-1.079554,6.821251l0,4.776787c0,0.525447 0.429911,0.955357 0.955357,0.955357l11.464288,0c0.525447,0 0.955357,-0.429911 0.955357,-0.955357l0,-4.776787l0,0zm-3.133572,0.525447l-0.420357,0.850268c-0.162411,0.324821 -0.496786,0.535 -0.869375,0.535l-4.547501,0c-0.363036,0 -0.687857,-0.210179 -0.850268,-0.525447l-0.420357,-0.869375c-0.162411,-0.315268 -0.496786,-0.525447 -0.850268,-0.525447l-1.327947,0l0.955357,-6.687501l9.553573,0l0.955357,6.687501l-1.318393,0c-0.372589,0 -0.697411,0.210179 -0.869375,0.525447l0.009554,0.009554z" />
</svg>

After

Width:  |  Height:  |  Size: 846 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#3c8746" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
A
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#7F4E7E" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#692C77" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#9E121D" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
D
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#969696" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
I
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#1B80B2" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
M
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#CC6633" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
R
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#6C6C6C" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
U
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.24,10.4c0.19,1.28 -0.2,2.62 -1.2,3.6c-1.47,1.45 -3.74,1.63 -5.41,0.54l1.17,-1.14l-4.3,-0.6l0.6,4.2l1.31,-1.26c2.36,1.74 5.7,1.57 7.84,-0.54c1.24,-1.23 1.81,-2.85 1.74,-4.46l-1.75,-0.34l0,0zm-7.28,-2.4c1.47,-1.45 3.74,-1.63 5.41,-0.54l-1.17,1.14l4.3,0.6l-0.6,-4.2l-1.31,1.26c-2.36,-1.74 -5.7,-1.57 -7.85,0.54c-1.24,1.23 -1.8,2.85 -1.73,4.46l1.75,0.35c-0.19,-1.28 0.2,-2.63 1.2,-3.61l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.5,11l2.5,2.5c0,0.55 -0.45,1 -1,1l-4,0l0,-1l3.5,0l-2,-2l-7,0l-2,2l3.5,0l0,1l-4,0c-0.55,0 -1,-0.45 -1,-1l2.5,-2.5l-2.5,-2.5c0,-0.55 0.45,-1 1,-1l4,0l0,1l-3.5,0l2,2l7,0l2,-2l-3.5,0l0,-1l4,0c0.55,0 1,0.45 1,1l-2.5,2.5l0,0zm-5.5,-1.5l2,0l0,-3l2,0l-3,-3l-3,3l2,0l0,3l0,0zm2,3l-2,0l0,3l-2,0l3,3l3,-3l-2,0l0,-3l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 467 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m7,12l-2,0l3,-3l3,3l-2,0l0,5l-2,0l0,-5l0,0zm5,-4c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 558 B

BIN
images/gitlens-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

BIN
images/gitlens-preview.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#F05133" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 795 B

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#000000" fill-opacity="0.6" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z">
<animate attributeName="fill" values="#000000;#F05133;#000000" dur="1s" repeatCount="indefinite"/>
</path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 814 B

After

Width:  |  Height:  |  Size: 814 B

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18" xml:space="preserve">
<g>
<rect fill="#000000" fill-opacity="0.75" x="1" y="0" width="4" height="18"/>
<rect fill="#00bcf2" fill-opacity="0.6" x="7" y="0" width="3" height="18"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 314 B

After

Width:  |  Height:  |  Size: 313 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect fill="#424242" x="6.5" y="5.5" width="3" height="11"/>
<rect fill="#424242" x="2.5" y="9.5" width="11" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 253 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m13,8c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -2,0.89 -2,2c0,0.73 0.41,1.38 1,1.72l0,0.3c-0.02,0.52 -0.23,0.98 -0.63,1.38c-0.4,0.4 -0.86,0.61 -1.38,0.63c-0.83,0.02 -1.48,0.16 -2,0.45l0,-4.76c0.59,-0.34 1,-0.98 1,-1.72c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -1.99,0.89 -1.99,2c0,0.73 0.41,1.38 1,1.72l0,6.56c-0.59,0.35 -1,0.99 -1,1.72c0,1.11 0.89,2 2,2c1.11,0 2,-0.89 2,-2c0,-0.53 -0.2,-1 -0.53,-1.36c0.09,-0.06 0.48,-0.41 0.59,-0.47c0.25,-0.11 0.56,-0.17 0.94,-0.17c1.05,-0.05 1.95,-0.45 2.75,-1.25c0.8,-0.8 1.2,-1.98 1.25,-3.02l-0.02,0c0.61,-0.36 1.02,-1 1.02,-1.73l0,0zm-8,-3.2c0.66,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2c-0.65,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2l0,0zm0,12.41c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0zm6,-8c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m11.86,10c-0.45,-1.72 -2,-3 -3.86,-3c-1.86,0 -3.41,1.28 -3.86,3l-3.14,0l0,2l3.14,0c0.45,1.72 2,3 3.86,3c1.86,0 3.41,-1.28 3.86,-3l3.14,0l0,-2l-3.14,0zm-3.86,3.2c-1.22,0 -2.2,-0.98 -2.2,-2.2c0,-1.22 0.98,-2.2 2.2,-2.2c1.22,0 2.2,0.98 2.2,2.2c0,1.22 -0.98,2.2 -2.2,2.2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m9,15l2,0l-3,3l-3,-3l2,0l0,-5l2,0l0,5l0,0zm3,-8c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 557 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m9,16l-2,0l0,-7l5,0l0,2l-3,0l0,5l0,0zm-1,-12c-2.19,0 -4.13,1.02 -5.41,2.59l-1.59,-1.59l0,4l4,0l-1.5,-1.5c1.05,-1.33 2.67,-2.2 4.5,-2.2c3.14,0 5.7,2.56 5.7,5.7c0,3.14 -2.56,5.7 -5.7,5.7c-3.14,0 -5.7,-2.56 -5.7,-5.7c0,-0.34 0.03,-0.67 0.09,-1l-1.31,0c-0.05,0.33 -0.08,0.66 -0.08,1c0,3.86 3.14,7 7,7c3.86,0 7,-3.14 7,-7c0,-3.86 -3.14,-7 -7,-7l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 500 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.901149,9.091851l-0.094,0.071c-0.269,0.333 -0.746,1.096 -0.91,2.375c0.057,0.277 0.092,0.495 0.092,0.545c0,2.206 -1.794,4 -4,4a3.986,3.986 0 0 1 -2.817,-1.164a3.987,3.987 0 0 1 -1.163,-2.815c0,-2.206 1.794,-4 4,-4l0.351,0.025l0,1.85s1.626,-1.342 1.631,-1.339l1.869,-1.577l-3.5,-2.917l0,2.218l-0.371,-0.03a5.75,5.75 0 0 0 -4.055,9.826a5.75,5.75 0 0 0 9.826,-4.056a5.725,5.725 0 0 0 -0.859,-3.012z" />
</svg>

After

Width:  |  Height:  |  Size: 553 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.519592,15.157073l-9.039184,0c-1.367793,0 -2.480539,-1.112828 -2.480539,-2.480622s1.112746,-2.480539 2.480539,-2.480539l0.281314,0c0.349178,-0.47173 0.888523,-0.771191 1.476341,-0.815025c0.321917,-1.471535 1.619609,-2.537962 3.165139,-2.537962c1.221543,0 2.341663,0.699516 2.889377,1.772488c0.083027,-0.008618 0.166386,-0.012926 0.250076,-0.012926c1.190221,0 2.194667,0.874105 2.378785,2.027867c0.670514,0.460047 1.07869,1.225023 1.07869,2.046096c0,1.367793 -1.112828,2.480622 -2.480539,2.480622z" />
</svg>

After

Width:  |  Height:  |  Size: 655 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#32cd32" stroke="#424242" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cd3131" stroke="#424242" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cdcd32" stroke="#424242" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 490 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m14.414133,16.199437l-3.415492,-3.433421c0.627518,-0.878526 0.995065,-1.945307 0.995065,-3.110698c0,-2.967265 -2.411463,-5.378728 -5.378728,-5.378728c-2.967265,0 -5.378728,2.411463 -5.378728,5.378728c0,2.967265 2.411463,5.378728 5.378728,5.378728c1.165391,0 2.223207,-0.367546 3.110698,-0.995065l3.433421,3.415492c0.170326,0.179291 0.403405,0.268936 0.627518,0.268936c0.224114,0 0.466156,-0.080681 0.627518,-0.268936c0.349617,-0.349617 0.349617,-0.914384 0,-1.264001l0,0.008965zm-7.799155,-2.330782c-2.321817,0 -4.213337,-1.891519 -4.213337,-4.213337c0,-2.321817 1.891519,-4.213337 4.213337,-4.213337c2.321817,0 4.213337,1.891519 4.213337,4.213337c0,2.321817 -1.891519,4.213337 -4.213337,4.213337l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 857 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m14.687501,11.955358l-1.079554,-6.821251c-0.076429,-0.458572 -0.477679,-0.821607 -0.955357,-0.821607l-9.30518,0c-0.477679,0 -0.878929,0.363036 -0.955357,0.821607l-1.079554,6.821251l0,4.776787c0,0.525447 0.429911,0.955357 0.955357,0.955357l11.464288,0c0.525447,0 0.955357,-0.429911 0.955357,-0.955357l0,-4.776787l0,0zm-3.133572,0.525447l-0.420357,0.850268c-0.162411,0.324821 -0.496786,0.535 -0.869375,0.535l-4.547501,0c-0.363036,0 -0.687857,-0.210179 -0.850268,-0.525447l-0.420357,-0.869375c-0.162411,-0.315268 -0.496786,-0.525447 -0.850268,-0.525447l-1.327947,0l0.955357,-6.687501l9.553573,0l0.955357,6.687501l-1.318393,0c-0.372589,0 -0.697411,0.210179 -0.869375,0.525447l0.009554,0.009554z" />
</svg>

After

Width:  |  Height:  |  Size: 846 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#2d883e" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
A
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#9B4F96" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#682079" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#B9131A" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
D
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#969696" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
I
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#007ACC" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
M
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#CC6633" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
R
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#6C6C6C" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
U
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.24,10.4c0.19,1.28 -0.2,2.62 -1.2,3.6c-1.47,1.45 -3.74,1.63 -5.41,0.54l1.17,-1.14l-4.3,-0.6l0.6,4.2l1.31,-1.26c2.36,1.74 5.7,1.57 7.84,-0.54c1.24,-1.23 1.81,-2.85 1.74,-4.46l-1.75,-0.34l0,0zm-7.28,-2.4c1.47,-1.45 3.74,-1.63 5.41,-0.54l-1.17,1.14l4.3,0.6l-0.6,-4.2l-1.31,1.26c-2.36,-1.74 -5.7,-1.57 -7.85,0.54c-1.24,1.23 -1.8,2.85 -1.73,4.46l1.75,0.35c-0.19,-1.28 0.2,-2.63 1.2,-3.61l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.5,11l2.5,2.5c0,0.55 -0.45,1 -1,1l-4,0l0,-1l3.5,0l-2,-2l-7,0l-2,2l3.5,0l0,1l-4,0c-0.55,0 -1,-0.45 -1,-1l2.5,-2.5l-2.5,-2.5c0,-0.55 0.45,-1 1,-1l4,0l0,1l-3.5,0l2,2l7,0l2,-2l-3.5,0l0,-1l4,0c0.55,0 1,0.45 1,1l-2.5,2.5l0,0zm-5.5,-1.5l2,0l0,-3l2,0l-3,-3l-3,3l2,0l0,3l0,0zm2,3l-2,0l0,3l-2,0l3,3l3,-3l-2,0l0,-3l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 467 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m7,12l-2,0l3,-3l3,3l-2,0l0,5l-2,0l0,-5l0,0zm5,-4c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

2762
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,9 +16,9 @@ interface AutoCollectConsole {
}
interface AutoCollectExceptions {
constructor(client:Client): AutoCollectExceptions;
constructor(client: Client): AutoCollectExceptions;
isInitialized(): boolean;
enable(isEnabled:boolean): void;
enable(isEnabled: boolean): void;
}
interface AutoCollectPerformance {
@@ -348,7 +348,7 @@ interface Client {
* @param max the max sample for this set
* @param stdDev the standard deviation of the set
*/
trackMetric(name: string, value: number, count?:number, min?: number, max?: number, stdDev?: number, properties?: {
trackMetric(name: string, value: number, count?: number, min?: number, max?: number, stdDev?: number, properties?: {
[key: string]: string;
}): void;
@@ -374,7 +374,8 @@ interface Client {
* @param error An error that was returned for this request if it was unsuccessful. Defaults to null.
*/
trackRequestSync(request: any /*http.IncomingMessage */, response: any /*http.ServerResponse */, ellapsedMilliseconds?: number, properties?: {
[key: string]: string;}, error?: any) : void;
[key: string]: string;
}, error?: any): void;
/**
* Log information about a dependency of your app. Typically used to track the time database calls or outgoing http requests take from your server.
@@ -503,6 +504,11 @@ interface ApplicationInsights {
*
*/
setOfflineMode(value: boolean, resentIntervall?: number): ApplicationInsights;
/**
*
*/
setAutoDependencyCorrelation(value: boolean): ApplicationInsights;
}
declare module "applicationinsights" {

View File

@@ -1,5 +1,6 @@
'use strict';
import { Functions } from './system';
import { commands, Disposable, TextEditor, window } from 'vscode';
import { BuiltInCommands } from './constants';
@@ -11,19 +12,20 @@ export class ActiveEditorTracker extends Disposable {
constructor() {
super(() => this.dispose());
this._disposable = window.onDidChangeActiveTextEditor(e => this._resolver && this._resolver(e));
const fn = Functions.debounce((e: TextEditor) => this._resolver && this._resolver(e), 50);
this._disposable = window.onDidChangeActiveTextEditor(fn);
}
dispose() {
this._disposable && this._disposable.dispose();
}
async awaitClose(timeout: number = 500): Promise<TextEditor> {
async awaitClose(timeout: number = 500): Promise<TextEditor | undefined> {
this.close();
return this.wait(timeout);
}
async awaitNext(timeout: number = 500): Promise<TextEditor> {
async awaitNext(timeout: number = 500): Promise<TextEditor | undefined> {
this.next();
return this.wait(timeout);
}
@@ -36,15 +38,15 @@ export class ActiveEditorTracker extends Disposable {
return commands.executeCommand(BuiltInCommands.NextEditor);
}
async wait(timeout: number = 500): Promise<TextEditor> {
async wait(timeout: number = 500): Promise<TextEditor | undefined> {
const editor = await new Promise<TextEditor>((resolve, reject) => {
let timer: any;
this._resolver = (editor: TextEditor) => {
this._resolver = (e: TextEditor) => {
if (timer) {
clearTimeout(timer as any);
timer = 0;
resolve(editor);
resolve(e);
}
};
@@ -53,8 +55,8 @@ export class ActiveEditorTracker extends Disposable {
timer = 0;
}, timeout) as any;
});
this._resolver = undefined;
return editor;
}
}
}

View File

@@ -0,0 +1,406 @@
'use strict';
import { Functions, Objects } from '../system';
import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, Progress, ProgressLocation, TextDocument, TextDocumentChangeEvent, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode';
import { AnnotationProviderBase } from './annotationProvider';
import { Keyboard, KeyboardScope, KeyCommand, Keys } from '../keyboard';
import { TextDocumentComparer, TextEditorComparer } from '../comparers';
import { ExtensionKey, IConfig, LineHighlightLocations, themeDefaults } from '../configuration';
import { CommandContext, setCommandContext } from '../constants';
import { BlameabilityChangeEvent, GitContextTracker, GitService, GitUri } from '../gitService';
import { GutterBlameAnnotationProvider } from './gutterBlameAnnotationProvider';
import { HoverBlameAnnotationProvider } from './hoverBlameAnnotationProvider';
import { Logger } from '../logger';
import { RecentChangesAnnotationProvider } from './recentChangesAnnotationProvider';
import { WhitespaceController } from './whitespaceController';
import * as path from 'path';
export type FileAnnotationType = 'gutter' | 'hover' | 'recentChanges';
export const FileAnnotationType = {
Gutter: 'gutter' as FileAnnotationType,
Hover: 'hover' as FileAnnotationType,
RecentChanges: 'recentChanges' as FileAnnotationType
};
export const Decorations = {
blameAnnotation: window.createTextEditorDecorationType({
isWholeLine: true,
textDecoration: 'none'
} as DecorationRenderOptions),
blameHighlight: undefined as TextEditorDecorationType | undefined,
recentChangesAnnotation: undefined as TextEditorDecorationType | undefined,
recentChangesHighlight: undefined as TextEditorDecorationType | undefined
};
export class AnnotationController extends Disposable {
private _onDidToggleAnnotations = new EventEmitter<void>();
get onDidToggleAnnotations(): Event<void> {
return this._onDidToggleAnnotations.event;
}
private _annotationsDisposable: Disposable | undefined;
private _annotationProviders: Map<number, AnnotationProviderBase> = new Map();
private _config: IConfig;
private _disposable: Disposable;
private _whitespaceController: WhitespaceController | undefined;
constructor(private context: ExtensionContext, private git: GitService, private gitContextTracker: GitContextTracker) {
super(() => this.dispose());
this._onConfigurationChanged();
const subscriptions: Disposable[] = [];
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
dispose() {
this._annotationProviders.forEach(async (p, i) => await this.clear(i));
Decorations.blameAnnotation && Decorations.blameAnnotation.dispose();
Decorations.blameHighlight && Decorations.blameHighlight.dispose();
this._annotationsDisposable && this._annotationsDisposable.dispose();
this._whitespaceController && this._whitespaceController.dispose();
this._disposable && this._disposable.dispose();
}
private _onConfigurationChanged() {
let toggleWhitespace = workspace.getConfiguration(`${ExtensionKey}.advanced.toggleWhitespace`).get<boolean>('enabled');
// Until https://github.com/Microsoft/vscode/issues/11485 is fixed we need to toggle whitespace for non-monospace fonts and ligatures
// TODO: detect monospace vs non-monospace font
// if (!toggleWhitespace) {
// // Since we know ligatures will break the whitespace rendering -- turn it back on
// toggleWhitespace = workspace.getConfiguration('editor').get<boolean>('fontLigatures', false);
// }
// If the setting is on and we aren't showing any annotations, make sure it is necessary (i.e. only when rendering whitespace)
if (toggleWhitespace && this._annotationProviders.size === 0) {
toggleWhitespace = (workspace.getConfiguration('editor').get<string>('renderWhitespace') !== 'none');
}
let changed = false;
if (toggleWhitespace && this._whitespaceController === undefined) {
changed = true;
this._whitespaceController = new WhitespaceController();
}
else if (!toggleWhitespace && this._whitespaceController !== undefined) {
changed = true;
this._whitespaceController.dispose();
this._whitespaceController = undefined;
}
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
const cfgBlameHighlight = cfg.blame.file.lineHighlight;
const cfgChangesHighlight = cfg.recentChanges.file.lineHighlight;
const cfgTheme = cfg.theme.lineHighlight;
if (!Objects.areEquivalent(cfgBlameHighlight, this._config && this._config.blame.file.lineHighlight) ||
!Objects.areEquivalent(cfgChangesHighlight, this._config && this._config.recentChanges.file.lineHighlight) ||
!Objects.areEquivalent(cfgTheme, this._config && this._config.theme.lineHighlight)) {
changed = true;
Decorations.blameHighlight && Decorations.blameHighlight.dispose();
if (cfgBlameHighlight.enabled) {
Decorations.blameHighlight = window.createTextEditorDecorationType({
gutterIconSize: 'contain',
isWholeLine: true,
overviewRulerLane: OverviewRulerLane.Right,
dark: {
backgroundColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.Line)
? cfgTheme.dark.backgroundColor || themeDefaults.lineHighlight.dark.backgroundColor
: undefined,
gutterIconPath: cfgBlameHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/dark/highlight-gutter.svg')
: undefined,
overviewRulerColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.dark.overviewRulerColor || themeDefaults.lineHighlight.dark.overviewRulerColor
: undefined
},
light: {
backgroundColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.Line)
? cfgTheme.light.backgroundColor || themeDefaults.lineHighlight.light.backgroundColor
: undefined,
gutterIconPath: cfgBlameHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/light/highlight-gutter.svg')
: undefined,
overviewRulerColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.light.overviewRulerColor || themeDefaults.lineHighlight.light.overviewRulerColor
: undefined
}
});
}
else {
Decorations.blameHighlight = undefined;
}
Decorations.recentChangesHighlight && Decorations.recentChangesHighlight.dispose();
Decorations.recentChangesHighlight = window.createTextEditorDecorationType({
gutterIconSize: 'contain',
isWholeLine: true,
overviewRulerLane: OverviewRulerLane.Right,
dark: {
backgroundColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.Line)
? cfgTheme.dark.backgroundColor || themeDefaults.lineHighlight.dark.backgroundColor
: undefined,
gutterIconPath: cfgChangesHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/dark/highlight-gutter.svg')
: undefined,
overviewRulerColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.dark.overviewRulerColor || themeDefaults.lineHighlight.dark.overviewRulerColor
: undefined
},
light: {
backgroundColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.Line)
? cfgTheme.light.backgroundColor || themeDefaults.lineHighlight.light.backgroundColor
: undefined,
gutterIconPath: cfgChangesHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/light/highlight-gutter.svg')
: undefined,
overviewRulerColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.light.overviewRulerColor || themeDefaults.lineHighlight.light.overviewRulerColor
: undefined
}
});
}
if (!Objects.areEquivalent(cfg.blame.file, this._config && this._config.blame.file) ||
!Objects.areEquivalent(cfg.recentChanges.file, this._config && this._config.recentChanges.file) ||
!Objects.areEquivalent(cfg.annotations, this._config && this._config.annotations) ||
!Objects.areEquivalent(cfg.theme.annotations, this._config && this._config.theme.annotations)) {
changed = true;
}
this._config = cfg;
if (changed) {
// Since the configuration has changed -- reset any visible annotations
for (const provider of this._annotationProviders.values()) {
if (provider === undefined) continue;
if (provider.annotationType === FileAnnotationType.RecentChanges) {
provider.reset(Decorations.recentChangesAnnotation, Decorations.recentChangesHighlight);
}
else {
provider.reset(Decorations.blameAnnotation, Decorations.blameHighlight, this._whitespaceController);
}
}
}
}
async clear(column: number) {
const provider = this._annotationProviders.get(column);
if (provider === undefined) return;
this._annotationProviders.delete(column);
await provider.dispose();
if (this._annotationProviders.size === 0) {
Logger.log(`Remove listener registrations for annotations`);
await setCommandContext(CommandContext.AnnotationStatus, undefined);
this._keyboardScope && this._keyboardScope.dispose();
this._keyboardScope = undefined;
this._annotationsDisposable && this._annotationsDisposable.dispose();
this._annotationsDisposable = undefined;
}
this._onDidToggleAnnotations.fire();
}
getAnnotationType(editor: TextEditor | undefined): FileAnnotationType | undefined {
const provider = this.getProvider(editor);
return provider === undefined ? undefined : provider.annotationType;
}
getProvider(editor: TextEditor | undefined): AnnotationProviderBase | undefined {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return undefined;
return this._annotationProviders.get(editor.viewColumn || -1);
}
private _keyboardScope: KeyboardScope | undefined = undefined;
async showAnnotations(editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;
const currentProvider = this._annotationProviders.get(editor.viewColumn || -1);
if (currentProvider && TextEditorComparer.equals(currentProvider.editor, editor)) {
await currentProvider.selection(shaOrLine);
return true;
}
return window.withProgress({ location: ProgressLocation.Window }, async (progress: Progress<{ message: string }>) => {
await setCommandContext(CommandContext.AnnotationStatus, 'computing');
const computingAnnotations = this._showAnnotationsCore(currentProvider, editor, type, shaOrLine, progress);
const result = await computingAnnotations;
await setCommandContext(CommandContext.AnnotationStatus, result ? 'computed' : undefined);
return computingAnnotations;
});
}
private async _showAnnotationsCore(currentProvider: AnnotationProviderBase | undefined, editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number, progress?: Progress<{ message: string}>): Promise<boolean> {
if (progress !== undefined) {
let annotationsLabel = 'annotations';
switch (type) {
case FileAnnotationType.Gutter:
case FileAnnotationType.Hover:
annotationsLabel = 'blame annotations';
break;
case FileAnnotationType.RecentChanges:
annotationsLabel = 'recent changes annotations';
break;
}
progress!.report({ message: `Computing ${annotationsLabel} for ${path.basename(editor.document.fileName)}` });
}
// Allows pressing escape to exit the annotations
if (this._keyboardScope === undefined) {
this._keyboardScope = await Keyboard.instance.beginScope({
escape: {
onDidPressKey: (key: Keys) => {
const e = window.activeTextEditor;
if (e === undefined) return Promise.resolve(undefined);
this.clear(e.viewColumn || -1);
return Promise.resolve(undefined);
}
} as KeyCommand
});
}
const gitUri = await GitUri.fromUri(editor.document.uri, this.git);
let provider: AnnotationProviderBase | undefined = undefined;
switch (type) {
case FileAnnotationType.Gutter:
provider = new GutterBlameAnnotationProvider(this.context, editor, Decorations.blameAnnotation, Decorations.blameHighlight, this._whitespaceController, this.git, gitUri);
break;
case FileAnnotationType.Hover:
provider = new HoverBlameAnnotationProvider(this.context, editor, Decorations.blameAnnotation, Decorations.blameHighlight, this._whitespaceController, this.git, gitUri);
break;
case FileAnnotationType.RecentChanges:
provider = new RecentChangesAnnotationProvider(this.context, editor, undefined, Decorations.recentChangesHighlight!, this.git, gitUri);
break;
}
if (provider === undefined || !(await provider.validate())) return false;
if (currentProvider) {
await this.clear(currentProvider.editor.viewColumn || -1);
}
if (!this._annotationsDisposable && this._annotationProviders.size === 0) {
Logger.log(`Add listener registrations for annotations`);
const subscriptions: Disposable[] = [];
subscriptions.push(window.onDidChangeVisibleTextEditors(Functions.debounce(this._onVisibleTextEditorsChanged, 100), this));
subscriptions.push(window.onDidChangeTextEditorViewColumn(this._onTextEditorViewColumnChanged, this));
subscriptions.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this));
subscriptions.push(workspace.onDidCloseTextDocument(this._onTextDocumentClosed, this));
subscriptions.push(this.gitContextTracker.onDidChangeBlameability(this._onBlameabilityChanged, this));
this._annotationsDisposable = Disposable.from(...subscriptions);
}
this._annotationProviders.set(editor.viewColumn || -1, provider);
if (await provider.provideAnnotation(shaOrLine)) {
this._onDidToggleAnnotations.fire();
return true;
}
return false;
}
async toggleAnnotations(editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document || (type === FileAnnotationType.RecentChanges ? !this.git.isTrackable(editor.document.uri) : !this.git.isEditorBlameable(editor))) return false;
const provider = this._annotationProviders.get(editor.viewColumn || -1);
if (provider === undefined) return this.showAnnotations(editor, type, shaOrLine);
const reopen = provider.annotationType !== type;
await this.clear(provider.editor.viewColumn || -1);
if (!reopen) return false;
return this.showAnnotations(editor, type, shaOrLine);
}
private _onBlameabilityChanged(e: BlameabilityChangeEvent) {
if (e.blameable || !e.editor) return;
for (const [key, p] of this._annotationProviders) {
if (!TextDocumentComparer.equals(p.document, e.editor.document)) continue;
Logger.log('BlameabilityChanged:', `Clear annotations for column ${key}`);
this.clear(key);
}
}
private _onTextDocumentChanged(e: TextDocumentChangeEvent) {
for (const [key, p] of this._annotationProviders) {
if (!TextDocumentComparer.equals(p.document, e.document)) continue;
// TODO: Rework this once https://github.com/Microsoft/vscode/issues/27231 is released in v1.13
// We have to defer because isDirty is not reliable inside this event
setTimeout(() => {
// If the document is dirty all is fine, just kick out since the GitContextTracker will handle it
if (e.document.isDirty) return;
// If the document isn't dirty, it is very likely this event was triggered by an outside edit of this document
// Which means the document has been reloaded and the annotations have been removed, so we need to update (clear) our state tracking
Logger.log('TextDocumentChanged:', `Clear annotations for column ${key}`);
this.clear(key);
}, 1);
}
}
private _onTextDocumentClosed(e: TextDocument) {
for (const [key, p] of this._annotationProviders) {
if (!TextDocumentComparer.equals(p.document, e)) continue;
Logger.log('TextDocumentClosed:', `Clear annotations for column ${key}`);
this.clear(key);
}
}
private async _onTextEditorViewColumnChanged(e: TextEditorViewColumnChangeEvent) {
const viewColumn = e.viewColumn || -1;
Logger.log('TextEditorViewColumnChanged:', `Clear annotations for column ${viewColumn}`);
await this.clear(viewColumn);
for (const [key, p] of this._annotationProviders) {
if (!TextEditorComparer.equals(p.editor, e.textEditor)) continue;
Logger.log('TextEditorViewColumnChanged:', `Clear annotations for column ${key}`);
await this.clear(key);
}
}
private async _onVisibleTextEditorsChanged(e: TextEditor[]) {
if (e.every(_ => _.document.uri.scheme === 'inmemory')) return;
for (const [key, p] of this._annotationProviders) {
if (e.some(_ => TextEditorComparer.equals(p.editor, _))) continue;
Logger.log('VisibleTextEditorsChanged:', `Clear annotations for column ${key}`);
this.clear(key);
}
}
}

View File

@@ -0,0 +1,75 @@
'use strict';
// import { Functions } from '../system';
import { Disposable, ExtensionContext, TextDocument, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
import { FileAnnotationType } from '../annotations/annotationController';
import { TextDocumentComparer } from '../comparers';
import { ExtensionKey, IConfig } from '../configuration';
import { WhitespaceController } from './whitespaceController';
export abstract class AnnotationProviderBase extends Disposable {
public annotationType: FileAnnotationType;
public document: TextDocument;
protected _config: IConfig;
protected _disposable: Disposable;
constructor(context: ExtensionContext, public editor: TextEditor, protected decoration: TextEditorDecorationType | undefined, protected highlightDecoration: TextEditorDecorationType | undefined, protected whitespaceController: WhitespaceController | undefined) {
super(() => this.dispose());
this.document = this.editor.document;
this._config = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
const subscriptions: Disposable[] = [];
subscriptions.push(window.onDidChangeTextEditorSelection(this._onTextEditorSelectionChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
async dispose() {
await this.clear();
this._disposable && this._disposable.dispose();
}
private async _onTextEditorSelectionChanged(e: TextEditorSelectionChangeEvent) {
if (!TextDocumentComparer.equals(this.document, e.textEditor && e.textEditor.document)) return;
return this.selection(e.selections[0].active.line);
}
async clear() {
if (this.editor !== undefined) {
try {
if (this.highlightDecoration !== undefined) {
this.editor.setDecorations(this.highlightDecoration, []);
}
if (this.decoration !== undefined) {
this.editor.setDecorations(this.decoration, []);
}
}
catch (ex) { }
}
// HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- restore whitespace
this.whitespaceController && await this.whitespaceController.restore();
}
async reset(decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, whitespaceController?: WhitespaceController) {
await this.clear();
this._config = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
this.decoration = decoration;
this.highlightDecoration = highlightDecoration;
this.whitespaceController = whitespaceController;
await this.provideAnnotation(this.editor === undefined ? undefined : this.editor.selection.active.line);
}
abstract async provideAnnotation(shaOrLine?: string | number): Promise<boolean>;
abstract async selection(shaOrLine?: string | number): Promise<void>;
abstract async validate(): Promise<boolean>;
}

View File

@@ -0,0 +1,231 @@
import { Strings } from '../system';
import { DecorationInstanceRenderOptions, DecorationOptions, MarkdownString, ThemableDecorationRenderOptions } from 'vscode';
import { DiffWithCommand, ShowQuickCommitDetailsCommand } from '../commands';
import { IThemeConfig, themeDefaults } from '../configuration';
import { GlyphChars } from '../constants';
import { CommitFormatter, GitCommit, GitDiffChunkLine, GitService, GitUri, ICommitFormatOptions } from '../gitService';
import * as moment from 'moment';
interface IHeatmapConfig {
enabled: boolean;
location?: 'left' | 'right';
}
interface IRenderOptions {
uncommittedForegroundColor?: {
dark: string;
light: string;
};
before?: DecorationInstanceRenderOptions & ThemableDecorationRenderOptions & { height?: string };
dark?: DecorationInstanceRenderOptions;
light?: DecorationInstanceRenderOptions;
}
export const endOfLineIndex = 1000000;
const escapeMarkdownRegEx = /[`\>\#\*\_\-\+\.]/g;
// const sampleMarkdown = '## message `not code` *not important* _no underline_ \n> don\'t quote me \n- don\'t list me \n+ don\'t list me \n1. don\'t list me \nnot h1 \n=== \nnot h2 \n---\n***\n---\n___';
export class Annotations {
static applyHeatmap(decoration: DecorationOptions, date: Date, now: moment.Moment) {
const color = this._getHeatmapColor(now, date);
(decoration.renderOptions!.before! as any).borderColor = color;
}
private static _getHeatmapColor(now: moment.Moment, date: Date) {
const days = now.diff(moment(date), 'days');
if (days <= 2) return '#ffeca7';
if (days <= 7) return '#ffdd8c';
if (days <= 14) return '#ffdd7c';
if (days <= 30) return '#fba447';
if (days <= 60) return '#f68736';
if (days <= 90) return '#f37636';
if (days <= 180) return '#ca6632';
if (days <= 365) return '#c0513f';
if (days <= 730) return '#a2503a';
return '#793738';
}
static getHoverMessage(commit: GitCommit, dateFormat: string | null): MarkdownString {
if (dateFormat === null) {
dateFormat = 'MMMM Do, YYYY h:MMa';
}
let message = '';
if (!commit.isUncommitted) {
message = commit.message
// Escape markdown
.replace(escapeMarkdownRegEx, '\\$&')
// Escape markdown header (since the above regex won't match it)
.replace(/^===/gm, `${GlyphChars.ZeroWidthSpace}===`)
// Keep under the same block-quote
.replace(/\n/g, ' \n');
message = `\n\n> ${message}`;
}
const markdown = new MarkdownString(`[\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(commit.sha)}) &nbsp; __${commit.author}__, ${moment(commit.date).fromNow()} &nbsp; _(${moment(commit.date).format(dateFormat)})_${message}`);
markdown.isTrusted = true;
return markdown;
}
static getHoverDiffMessage(commit: GitCommit, chunkLine: GitDiffChunkLine | undefined): MarkdownString | undefined {
if (chunkLine === undefined) return undefined;
const codeDiff = this._getCodeDiff(chunkLine);
const markdown = new MarkdownString(commit.isUncommitted
? `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit)}) &nbsp; ${GlyphChars.Dash} &nbsp; _uncommitted_\n${codeDiff}`
: `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit)}) &nbsp; ${GlyphChars.Dash} &nbsp; [\`${commit.previousShortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(commit.previousSha!)}) ${GlyphChars.ArrowLeftRight} [\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(commit.sha)})\n${codeDiff}`);
markdown.isTrusted = true;
return markdown;
}
private static _getCodeDiff(chunkLine: GitDiffChunkLine): string {
const previous = chunkLine.previous === undefined ? undefined : chunkLine.previous[0];
return `\`\`\`
- ${previous === undefined || previous.line === undefined ? '' : previous.line.trim()}
+ ${chunkLine.line === undefined ? '' : chunkLine.line.trim()}
\`\`\``;
}
static async changesHover(commit: GitCommit, line: number, uri: GitUri, git: GitService): Promise<DecorationOptions> {
const chunkLine = await git.getDiffForLine(uri, line + uri.offset, commit.isUncommitted ? undefined : commit.previousSha);
const message = this.getHoverDiffMessage(commit, chunkLine);
return {
hoverMessage: message
} as DecorationOptions;
}
static detailsHover(commit: GitCommit, dateFormat: string | null): DecorationOptions {
const message = this.getHoverMessage(commit, dateFormat);
return {
hoverMessage: message
} as DecorationOptions;
}
static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions): DecorationOptions {
const content = Strings.pad(CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions), 1, 1);
return {
renderOptions: {
before: {
...renderOptions.before,
...{
contentText: content
}
},
dark: {
before: commit.isUncommitted
? { ...renderOptions.dark, ...{ color: renderOptions.uncommittedForegroundColor!.dark } }
: { ...renderOptions.dark }
},
light: {
before: commit.isUncommitted
? { ...renderOptions.light, ...{ color: renderOptions.uncommittedForegroundColor!.light } }
: { ...renderOptions.light }
}
} as DecorationInstanceRenderOptions
} as DecorationOptions;
}
static gutterRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions {
const cfgFileTheme = cfgTheme.annotations.file.gutter;
let borderStyle = undefined;
let borderWidth = undefined;
if (heatmap.enabled) {
borderStyle = 'solid';
borderWidth = heatmap.location === 'left' ? '0 0 0 2px' : '0 2px 0 0';
}
return {
uncommittedForegroundColor: {
dark: cfgFileTheme.dark.uncommittedForegroundColor || cfgFileTheme.dark.foregroundColor || themeDefaults.annotations.file.gutter.dark.foregroundColor,
light: cfgFileTheme.light.uncommittedForegroundColor || cfgFileTheme.light.foregroundColor || themeDefaults.annotations.file.gutter.light.foregroundColor
},
before: {
borderStyle: borderStyle,
borderWidth: borderWidth,
height: '100%',
margin: '0 26px -1px 0'
},
dark: {
backgroundColor: cfgFileTheme.dark.backgroundColor || undefined,
color: cfgFileTheme.dark.foregroundColor || themeDefaults.annotations.file.gutter.dark.foregroundColor,
textDecoration: cfgFileTheme.separateLines ? 'overline solid rgba(0, 0, 0, .2)' : 'none'
} as DecorationInstanceRenderOptions,
light: {
backgroundColor: cfgFileTheme.light.backgroundColor || undefined,
color: cfgFileTheme.light.foregroundColor || themeDefaults.annotations.file.gutter.light.foregroundColor,
textDecoration: cfgFileTheme.separateLines ? 'overline solid rgba(0, 0, 0, .05)' : 'none'
} as DecorationInstanceRenderOptions
} as IRenderOptions;
}
static hover(commit: GitCommit, renderOptions: IRenderOptions, heatmap: boolean, dateFormat: string | null): DecorationOptions {
return {
hoverMessage: this.getHoverMessage(commit, dateFormat),
renderOptions: heatmap ? { before: { ...renderOptions.before } } : undefined
} as DecorationOptions;
}
static hoverRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions {
if (!heatmap.enabled) return { before: undefined };
return {
before: {
borderStyle: 'solid',
borderWidth: '0 0 0 2px',
contentText: GlyphChars.ZeroWidthSpace,
height: '100%',
margin: '0 26px 0 0',
textDecoration: 'none'
}
} as IRenderOptions;
}
static trailing(commit: GitCommit, format: string, dateFormat: string | null, cfgTheme: IThemeConfig): DecorationOptions {
const message = CommitFormatter.fromTemplate(format, commit, {
truncateMessageAtNewLine: true,
dateFormat: dateFormat
} as ICommitFormatOptions);
return {
renderOptions: {
after: {
contentText: Strings.pad(message, 1, 1)
},
dark: {
after: {
backgroundColor: cfgTheme.annotations.line.trailing.dark.backgroundColor || undefined,
color: cfgTheme.annotations.line.trailing.dark.foregroundColor || themeDefaults.annotations.line.trailing.dark.foregroundColor
}
},
light: {
after: {
backgroundColor: cfgTheme.annotations.line.trailing.light.backgroundColor || undefined,
color: cfgTheme.annotations.line.trailing.light.foregroundColor || themeDefaults.annotations.line.trailing.light.foregroundColor
}
}
} as DecorationInstanceRenderOptions
} as DecorationOptions;
}
static withRange(decoration: DecorationOptions, start?: number, end?: number): DecorationOptions {
let range = decoration.range;
if (start !== undefined) {
range = range.with({
start: range.start.with({ character: start })
});
}
if (end !== undefined) {
range = range.with({
end: range.end.with({ character: end })
});
}
return { ...decoration, ...{ range: range } };
}
}

View File

@@ -0,0 +1,81 @@
'use strict';
import { Iterables } from '../system';
import { ExtensionContext, Range, TextEditor, TextEditorDecorationType } from 'vscode';
import { AnnotationProviderBase } from './annotationProvider';
import { GitBlame, GitService, GitUri } from '../gitService';
import { WhitespaceController } from './whitespaceController';
export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase {
protected _blame: Promise<GitBlame | undefined>;
constructor(context: ExtensionContext, editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, whitespaceController: WhitespaceController | undefined, protected git: GitService, protected uri: GitUri) {
super(context, editor, decoration, highlightDecoration, whitespaceController);
this._blame = this.git.getBlameForFile(this.uri);
}
async selection(shaOrLine?: string | number, blame?: GitBlame) {
if (!this.highlightDecoration) return;
if (blame === undefined) {
blame = await this._blame;
if (!blame || !blame.lines.length) return;
}
const offset = this.uri.offset;
let sha: string | undefined = undefined;
if (typeof shaOrLine === 'string') {
sha = shaOrLine;
}
else if (typeof shaOrLine === 'number') {
const line = shaOrLine - offset;
if (line >= 0) {
const commitLine = blame.lines[line];
sha = commitLine && commitLine.sha;
}
}
else {
sha = Iterables.first(blame.commits.values()).sha;
}
if (!sha) {
this.editor.setDecorations(this.highlightDecoration, []);
return;
}
const highlightDecorationRanges = blame.lines
.filter(l => l.sha === sha)
.map(l => this.editor.document.validateRange(new Range(l.line + offset, 0, l.line + offset, 1000000)));
this.editor.setDecorations(this.highlightDecoration, highlightDecorationRanges);
}
async validate(): Promise<boolean> {
const blame = await this._blame;
return blame !== undefined && blame.lines.length !== 0;
}
protected async getBlame(requiresWhitespaceHack: boolean): Promise<GitBlame | undefined> {
let whitespacePromise: Promise<void> | undefined;
// HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- override whitespace (turn off)
if (requiresWhitespaceHack) {
whitespacePromise = this.whitespaceController && this.whitespaceController.override();
}
let blame: GitBlame | undefined;
if (whitespacePromise) {
[blame] = await Promise.all([this._blame, whitespacePromise]);
}
else {
blame = await this._blame;
}
if (blame === undefined || !blame.lines.length) {
this.whitespaceController && await this.whitespaceController.restore();
return undefined;
}
return blame;
}
}

View File

@@ -0,0 +1,123 @@
'use strict';
import { Strings } from '../system';
import { DecorationOptions, Range } from 'vscode';
import { FileAnnotationType } from './annotationController';
import { Annotations, endOfLineIndex } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GlyphChars } from '../constants';
import { GitBlameCommit, ICommitFormatOptions } from '../gitService';
import * as moment from 'moment';
export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
async provideAnnotation(shaOrLine?: string | number, type?: FileAnnotationType): Promise<boolean> {
this.annotationType = FileAnnotationType.Gutter;
const blame = await this.getBlame(true);
if (blame === undefined) return false;
// console.time('Computing blame annotations...');
const cfg = this._config.annotations.file.gutter;
// Precalculate the formatting options so we don't need to do it on each iteration
const tokenOptions = Strings.getTokensFromTemplate(cfg.format)
.reduce((map, token) => {
map[token.key] = token.options as ICommitFormatOptions;
return map;
}, {} as { [token: string]: ICommitFormatOptions });
const options: ICommitFormatOptions = {
dateFormat: cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat,
tokenOptions: tokenOptions
};
const now = moment();
const offset = this.uri.offset;
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const separateLines = this._config.theme.annotations.file.gutter.separateLines;
const decorations: DecorationOptions[] = [];
const document = this.document;
let commit: GitBlameCommit | undefined;
let compacted = false;
let details: DecorationOptions | undefined;
let gutter: DecorationOptions | undefined;
let previousSha: string | undefined;
for (const l of blame.lines) {
commit = blame.commits.get(l.sha);
if (commit === undefined) continue;
const line = l.line + offset;
if (previousSha === l.sha) {
// Use a shallow copy of the previous decoration options
gutter = { ...gutter } as DecorationOptions;
if (cfg.compact && !compacted) {
// Since we are wiping out the contextText make sure to copy the objects
gutter.renderOptions = { ...gutter.renderOptions };
gutter.renderOptions.before = {
...gutter.renderOptions.before,
...{ contentText: GlyphChars.Space.repeat(Strings.getWidth(gutter.renderOptions!.before!.contentText!)) }
};
if (separateLines) {
gutter.renderOptions.dark = { ...gutter.renderOptions.dark };
gutter.renderOptions.dark.before = { ...gutter.renderOptions.dark.before, ...{ textDecoration: 'none' } };
gutter.renderOptions.light = { ...gutter.renderOptions.light };
gutter.renderOptions.light.before = { ...gutter.renderOptions.light.before, ...{ textDecoration: 'none' } };
}
compacted = true;
}
const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex;
gutter.range = new Range(line, 0, line, endIndex);
decorations.push(gutter);
if (details !== undefined) {
details = { ...details } as DecorationOptions;
details.range = cfg.hover.wholeLine
? document.validateRange(new Range(line, 0, line, endOfLineIndex))
: gutter.range;
decorations.push(details);
}
continue;
}
compacted = false;
previousSha = l.sha;
gutter = Annotations.gutter(commit, cfg.format, options, renderOptions);
if (cfg.heatmap.enabled) {
Annotations.applyHeatmap(gutter, commit.date, now);
}
const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex;
gutter.range = new Range(line, 0, line, endIndex);
decorations.push(gutter);
if (cfg.hover.details) {
details = Annotations.detailsHover(commit, dateFormat);
details.range = cfg.hover.wholeLine
? document.validateRange(new Range(line, 0, line, endOfLineIndex))
: gutter.range;
decorations.push(details);
}
}
if (decorations.length) {
this.editor.setDecorations(this.decoration!, decorations);
}
// console.timeEnd('Computing blame annotations...');
this.selection(shaOrLine, blame);
return true;
}
}

View File

@@ -0,0 +1,64 @@
'use strict';
import { DecorationOptions, Range } from 'vscode';
import { FileAnnotationType } from './annotationController';
import { Annotations, endOfLineIndex } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GitBlameCommit } from '../gitService';
import * as moment from 'moment';
export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
async provideAnnotation(shaOrLine?: string | number): Promise<boolean> {
this.annotationType = FileAnnotationType.Hover;
const blame = await this.getBlame(this._config.annotations.file.hover.heatmap.enabled);
if (blame === undefined) return false;
// console.time('Computing blame annotations...');
const cfg = this._config.annotations.file.hover;
const now = moment();
const offset = this.uri.offset;
const renderOptions = Annotations.hoverRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const decorations: DecorationOptions[] = [];
const document = this.document;
let commit: GitBlameCommit | undefined;
let hover: DecorationOptions | undefined;
for (const l of blame.lines) {
commit = blame.commits.get(l.sha);
if (commit === undefined) continue;
const line = l.line + offset;
hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled, dateFormat);
if (cfg.wholeLine) {
hover.range = document.validateRange(new Range(line, 0, line, endOfLineIndex));
}
else {
const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex;
hover.range = new Range(line, 0, line, endIndex);
}
if (cfg.heatmap.enabled) {
Annotations.applyHeatmap(hover, commit.date, now);
}
decorations.push(hover);
}
if (decorations.length) {
this.editor.setDecorations(this.decoration!, decorations);
}
// console.timeEnd('Computing blame annotations...');
this.selection(shaOrLine, blame);
return true;
}
}

View File

@@ -0,0 +1,74 @@
'use strict';
import { DecorationOptions, ExtensionContext, MarkdownString, Position, Range, TextEditor, TextEditorDecorationType } from 'vscode';
import { Annotations, endOfLineIndex } from './annotations';
import { FileAnnotationType } from './annotationController';
import { AnnotationProviderBase } from './annotationProvider';
import { GitService, GitUri } from '../gitService';
export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
constructor(context: ExtensionContext, editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, private git: GitService, private uri: GitUri) {
super(context, editor, decoration, highlightDecoration, undefined);
}
async provideAnnotation(shaOrLine?: string | number): Promise<boolean> {
this.annotationType = FileAnnotationType.RecentChanges;
const commit = await this.git.getLogCommit(this.uri.repoPath, this.uri.fsPath, { previous: true });
if (commit === undefined) return false;
const diff = await this.git.getDiffForFile(this.uri, commit.previousSha);
if (diff === undefined) return false;
const cfg = this._config.annotations.file.recentChanges;
const dateFormat = this._config.defaultDateFormat;
const decorators: DecorationOptions[] = [];
for (const chunk of diff.chunks) {
let count = chunk.currentPosition.start - 2;
for (const line of chunk.lines) {
if (line.line === undefined) continue;
count++;
if (line.state === 'unchanged') continue;
let endingIndex = 0;
if (cfg.hover.details || cfg.hover.changes) {
endingIndex = cfg.hover.wholeLine ? endOfLineIndex : this.editor.document.lineAt(count).firstNonWhitespaceCharacterIndex;
}
const range = this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endingIndex)));
if (cfg.hover.details) {
decorators.push({
hoverMessage: Annotations.getHoverMessage(commit, dateFormat),
range: range
} as DecorationOptions);
}
let message: MarkdownString | undefined = undefined;
if (cfg.hover.changes) {
message = Annotations.getHoverDiffMessage(commit, line);
}
decorators.push({
hoverMessage: message,
range: range
} as DecorationOptions);
}
}
this.editor.setDecorations(this.highlightDecoration!, decorators);
return true;
}
async selection(shaOrLine?: string | number): Promise<void> {
}
async validate(): Promise<boolean> {
return true;
}
}

View File

@@ -1,6 +1,6 @@
'use strict';
import { Disposable, workspace } from 'vscode';
import { Logger } from './logger';
import { Logger } from '../logger';
interface ConfigurationInspection {
key: string;
@@ -118,8 +118,6 @@ export class WhitespaceController extends Disposable {
if (this._count === 1 && this._configuration.overrideRequired) {
// Override whitespace (turn off)
await this._overrideWhitespace();
// Add a delay to give the editor time to turn off the whitespace
await new Promise((resolve, reject) => setTimeout(resolve, 250));
}
}

View File

@@ -1,390 +0,0 @@
'use strict';
import { Functions, Objects } from './system';
import { DecorationOptions, DecorationInstanceRenderOptions, DecorationRenderOptions, Disposable, ExtensionContext, Range, StatusBarAlignment, StatusBarItem, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
import { BlameAnnotationController } from './blameAnnotationController';
import { BlameAnnotationFormat, BlameAnnotationFormatter } from './blameAnnotationFormatter';
import { TextEditorComparer } from './comparers';
import { IBlameConfig, IConfig, StatusBarCommand } from './configuration';
import { DocumentSchemes, ExtensionKey } from './constants';
import { BlameabilityChangeEvent, GitCommit, GitContextTracker, GitService, GitUri, IGitCommitLine } from './gitService';
import * as moment from 'moment';
const activeLineDecoration: TextEditorDecorationType = window.createTextEditorDecorationType({
after: {
margin: '0 0 0 4em'
}
} as DecorationRenderOptions);
export class BlameActiveLineController extends Disposable {
private _activeEditorLineDisposable: Disposable | undefined;
private _blameable: boolean;
private _config: IConfig;
private _currentLine: number = -1;
private _disposable: Disposable;
private _editor: TextEditor | undefined;
private _statusBarItem: StatusBarItem | undefined;
private _updateBlameDebounced: (line: number, editor: TextEditor) => Promise<void>;
private _uri: GitUri;
constructor(context: ExtensionContext, private git: GitService, private gitContextTracker: GitContextTracker, private annotationController: BlameAnnotationController) {
super(() => this.dispose());
this._updateBlameDebounced = Functions.debounce(this._updateBlame, 250);
this._onConfigurationChanged();
const subscriptions: Disposable[] = [];
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
subscriptions.push(git.onDidChangeGitCache(this._onGitCacheChanged, this));
subscriptions.push(annotationController.onDidToggleBlameAnnotations(this._onBlameAnnotationToggled, this));
this._disposable = Disposable.from(...subscriptions);
}
dispose() {
this._editor && this._editor.setDecorations(activeLineDecoration, []);
this._activeEditorLineDisposable && this._activeEditorLineDisposable.dispose();
this._statusBarItem && this._statusBarItem.dispose();
this._disposable && this._disposable.dispose();
}
private _onConfigurationChanged() {
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
let changed: boolean = false;
if (!Objects.areEquivalent(cfg.statusBar, this._config && this._config.statusBar)) {
changed = true;
if (cfg.statusBar.enabled) {
const alignment = cfg.statusBar.alignment !== 'left' ? StatusBarAlignment.Right : StatusBarAlignment.Left;
if (this._statusBarItem !== undefined && this._statusBarItem.alignment !== alignment) {
this._statusBarItem.dispose();
this._statusBarItem = undefined;
}
this._statusBarItem = this._statusBarItem || window.createStatusBarItem(alignment, alignment === StatusBarAlignment.Right ? 1000 : 0);
this._statusBarItem.command = cfg.statusBar.command;
}
else if (!cfg.statusBar.enabled && this._statusBarItem) {
this._statusBarItem.dispose();
this._statusBarItem = undefined;
}
}
if (!Objects.areEquivalent(cfg.blame.annotation.activeLine, this._config && this._config.blame.annotation.activeLine)) {
changed = true;
if (cfg.blame.annotation.activeLine !== 'off' && this._editor) {
this._editor.setDecorations(activeLineDecoration, []);
}
}
if (!Objects.areEquivalent(cfg.blame.annotation.activeLineDarkColor, this._config && this._config.blame.annotation.activeLineDarkColor) ||
!Objects.areEquivalent(cfg.blame.annotation.activeLineLightColor, this._config && this._config.blame.annotation.activeLineLightColor)) {
changed = true;
}
this._config = cfg;
if (!changed) return;
let trackActiveLine = cfg.statusBar.enabled || cfg.blame.annotation.activeLine !== 'off';
if (trackActiveLine && !this._activeEditorLineDisposable) {
const subscriptions: Disposable[] = [];
subscriptions.push(window.onDidChangeActiveTextEditor(this._onActiveTextEditorChanged, this));
subscriptions.push(window.onDidChangeTextEditorSelection(this._onTextEditorSelectionChanged, this));
subscriptions.push(this.gitContextTracker.onDidBlameabilityChange(this._onBlameabilityChanged, this));
this._activeEditorLineDisposable = Disposable.from(...subscriptions);
}
else if (!trackActiveLine && this._activeEditorLineDisposable) {
this._activeEditorLineDisposable.dispose();
this._activeEditorLineDisposable = undefined;
}
this._onActiveTextEditorChanged(window.activeTextEditor);
}
private isEditorBlameable(editor: TextEditor | undefined): boolean {
if (editor === undefined || editor.document === undefined) return false;
if (!this.git.isTrackable(editor.document.uri)) return false;
if (editor.document.isUntitled && editor.document.uri.scheme === DocumentSchemes.File) return false;
return this.git.isEditorBlameable(editor);
}
private async _onActiveTextEditorChanged(editor: TextEditor | undefined) {
this._currentLine = -1;
const previousEditor = this._editor;
previousEditor && previousEditor.setDecorations(activeLineDecoration, []);
if (editor === undefined || !this.isEditorBlameable(editor)) {
this.clear(editor);
this._editor = undefined;
return;
}
this._blameable = editor !== undefined && editor.document !== undefined && !editor.document.isDirty;
this._editor = editor;
this._uri = await GitUri.fromUri(editor.document.uri, this.git);
const maxLines = this._config.advanced.caching.statusBar.maxLines;
// If caching is on and the file is small enough -- kick off a blame for the whole file
if (this._config.advanced.caching.enabled && (maxLines <= 0 || editor.document.lineCount <= maxLines)) {
this.git.getBlameForFile(this._uri);
}
this._updateBlame(editor.selection.active.line, editor);
}
private _onBlameabilityChanged(e: BlameabilityChangeEvent) {
this._blameable = e.blameable;
if (!e.blameable || !this._editor) {
this.clear(e.editor);
return;
}
// Make sure this is for the editor we are tracking
if (!TextEditorComparer.equals(this._editor, e.editor)) return;
this._updateBlame(this._editor.selection.active.line, this._editor);
}
private _onBlameAnnotationToggled() {
this._onActiveTextEditorChanged(window.activeTextEditor);
}
private _onGitCacheChanged() {
this._onActiveTextEditorChanged(window.activeTextEditor);
}
private async _onTextEditorSelectionChanged(e: TextEditorSelectionChangeEvent): Promise<void> {
// Make sure this is for the editor we are tracking
if (!this._blameable || !TextEditorComparer.equals(this._editor, e.textEditor)) return;
const line = e.selections[0].active.line;
if (line === this._currentLine) return;
this._currentLine = line;
if (!this._uri && e.textEditor) {
this._uri = await GitUri.fromUri(e.textEditor.document.uri, this.git);
}
this._updateBlameDebounced(line, e.textEditor);
}
private async _updateBlame(line: number, editor: TextEditor) {
line = line - this._uri.offset;
let commit: GitCommit | undefined = undefined;
let commitLine: IGitCommitLine | undefined = undefined;
// Since blame information isn't valid when there are unsaved changes -- don't show any status
if (this._blameable && line >= 0) {
const blameLine = await this.git.getBlameForLine(this._uri, line);
commitLine = blameLine === undefined ? undefined : blameLine.line;
commit = blameLine === undefined ? undefined : blameLine.commit;
}
if (commit !== undefined && commitLine !== undefined) {
this.show(commit, commitLine, editor);
}
else {
this.clear(editor);
}
}
clear(editor: TextEditor | undefined, previousEditor?: TextEditor) {
editor && editor.setDecorations(activeLineDecoration, []);
// I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay
if (editor) {
setTimeout(() => editor.setDecorations(activeLineDecoration, []), 1);
}
this._statusBarItem && this._statusBarItem.hide();
}
async show(commit: GitCommit, blameLine: IGitCommitLine, editor: TextEditor) {
// I have no idea why I need this protection -- but it happens
if (!editor.document) return;
if (this._config.statusBar.enabled && this._statusBarItem !== undefined) {
switch (this._config.statusBar.date) {
case 'off':
this._statusBarItem.text = `$(git-commit) ${commit.author}`;
break;
case 'absolute':
const dateFormat = this._config.statusBar.dateFormat || 'MMMM Do, YYYY h:MMa';
let date: string;
try {
date = moment(commit.date).format(dateFormat);
} catch (ex) {
date = moment(commit.date).format('MMMM Do, YYYY h:MMa');
}
this._statusBarItem.text = `$(git-commit) ${commit.author}, ${date}`;
break;
default:
this._statusBarItem.text = `$(git-commit) ${commit.author}, ${moment(commit.date).fromNow()}`;
break;
}
switch (this._config.statusBar.command) {
case StatusBarCommand.BlameAnnotate:
this._statusBarItem.tooltip = 'Toggle Blame Annotations';
break;
case StatusBarCommand.ShowBlameHistory:
this._statusBarItem.tooltip = 'Open Blame History Explorer';
break;
case StatusBarCommand.ShowFileHistory:
this._statusBarItem.tooltip = 'Open File History Explorer';
break;
case StatusBarCommand.DiffWithPrevious:
this._statusBarItem.tooltip = 'Compare with Previous Commit';
break;
case StatusBarCommand.ToggleCodeLens:
this._statusBarItem.tooltip = 'Toggle Git CodeLens';
break;
case StatusBarCommand.ShowQuickCommitDetails:
this._statusBarItem.tooltip = 'Show Commit Details';
break;
case StatusBarCommand.ShowQuickCommitFileDetails:
this._statusBarItem.tooltip = 'Show Line Commit Details';
break;
case StatusBarCommand.ShowQuickFileHistory:
this._statusBarItem.tooltip = 'Show File History';
break;
case StatusBarCommand.ShowQuickCurrentBranchHistory:
this._statusBarItem.tooltip = 'Show Branch History';
break;
}
this._statusBarItem.show();
}
if (this._config.blame.annotation.activeLine !== 'off') {
const activeLine = this._config.blame.annotation.activeLine;
const offset = this._uri.offset;
const cfg = {
annotation: {
sha: true,
author: this._config.statusBar.enabled ? false : this._config.blame.annotation.author,
date: this._config.statusBar.enabled ? 'off' : this._config.blame.annotation.date,
message: true
}
} as IBlameConfig;
const annotation = BlameAnnotationFormatter.getAnnotation(cfg, commit, BlameAnnotationFormat.Unconstrained);
// Get the full commit message -- since blame only returns the summary
let logCommit: GitCommit | undefined = undefined;
if (!commit.isUncommitted) {
logCommit = await this.git.getLogCommit(this._uri.repoPath, this._uri.fsPath, commit.sha);
}
// I have no idea why I need this protection -- but it happens
if (!editor.document) return;
let hoverMessage: string | string[] | undefined = undefined;
if (activeLine !== 'inline') {
// If the messages match (or we couldn't find the log), then this is a possible duplicate annotation
const possibleDuplicate = !logCommit || logCommit.message === commit.message;
// If we don't have a possible dupe or we aren't showing annotations get the hover message
if (!commit.isUncommitted && (!possibleDuplicate || !this.annotationController.isAnnotating(editor))) {
hoverMessage = BlameAnnotationFormatter.getAnnotationHover(cfg, blameLine, logCommit || commit);
// if (commit.previousSha !== undefined) {
// const changes = await this.git.getDiffForLine(this._uri.repoPath, this._uri.fsPath, blameLine.line + offset, commit.previousSha);
// if (changes !== undefined) {
// const previous = changes[0];
// if (previous !== undefined) {
// hoverMessage += `\n\n\`Before ${commit.shortSha}\`\n\`\`\`\n${previous.trim().replace(/\n/g, '\`\n>\n> \`')}\n\`\`\``;
// }
// else {
// hoverMessage += `\n\n\`Added in ${commit.shortSha}\``;
// }
// }
// }
}
else if (commit.isUncommitted) {
const changes = await this.git.getDiffForLine(this._uri.repoPath, this._uri.fsPath, blameLine.line + offset);
if (changes !== undefined) {
let original = changes[0];
if (original !== undefined) {
original = original.replace(/\n/g, '\`\n>\n> \`').trim();
hoverMessage = `\`${'0'.repeat(8)}\` &nbsp; __Uncommitted change__\n\n\---\n\`\`\`\n${original}\n\`\`\``;
}
// else {
// hoverMessage = `\`${'0'.repeat(8)}\` &nbsp; __Uncommitted change__\n\n\`Added\``;
// }
}
}
}
let decorationOptions: [DecorationOptions] | undefined = undefined;
switch (activeLine) {
case 'both':
case 'inline':
const range = editor.document.validateRange(new Range(blameLine.line + offset, 0, blameLine.line + offset, 1000000));
decorationOptions = [
{
range: range.with({
start: range.start.with({
character: range.end.character
})
}),
hoverMessage: hoverMessage,
renderOptions: {
after: {
contentText: annotation
},
dark: {
after: {
color: this._config.blame.annotation.activeLineDarkColor || 'rgba(153, 153, 153, 0.35)'
}
},
light: {
after: {
color: this._config.blame.annotation.activeLineLightColor || 'rgba(153, 153, 153, 0.35)'
}
}
} as DecorationInstanceRenderOptions
} as DecorationOptions
];
if (activeLine === 'both') {
// Add a hover decoration to the area between the start of the line and the first non-whitespace character
decorationOptions.push({
range: range.with({
end: range.end.with({
character: editor.document.lineAt(range.end.line).firstNonWhitespaceCharacterIndex
})
}),
hoverMessage: hoverMessage
} as DecorationOptions);
}
break;
case 'hover':
decorationOptions = [
{
range: editor.document.validateRange(new Range(blameLine.line + offset, 0, blameLine.line + offset, 1000000)),
hoverMessage: hoverMessage
} as DecorationOptions
];
break;
}
if (decorationOptions !== undefined) {
editor.setDecorations(activeLineDecoration, decorationOptions);
}
}
}
}

View File

@@ -1,253 +0,0 @@
'use strict';
import { Functions } from './system';
import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, TextDocument, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode';
import { BlameAnnotationProvider } from './blameAnnotationProvider';
import { TextDocumentComparer, TextEditorComparer } from './comparers';
import { IBlameConfig } from './configuration';
import { ExtensionKey } from './constants';
import { BlameabilityChangeEvent, GitService, GitUri, GitContextTracker } from './gitService';
import { Logger } from './logger';
import { WhitespaceController } from './whitespaceController';
export const BlameDecorations = {
annotation: window.createTextEditorDecorationType({
before: {
margin: '0 1.75em 0 0'
},
after: {
margin: '0 0 0 4em'
}
} as DecorationRenderOptions),
highlight: undefined as TextEditorDecorationType | undefined
};
export class BlameAnnotationController extends Disposable {
private _onDidToggleBlameAnnotations = new EventEmitter<void>();
get onDidToggleBlameAnnotations(): Event<void> {
return this._onDidToggleBlameAnnotations.event;
}
private _annotationProviders: Map<number, BlameAnnotationProvider> = new Map();
private _blameAnnotationsDisposable: Disposable | undefined;
private _config: IBlameConfig;
private _disposable: Disposable;
private _whitespaceController: WhitespaceController | undefined;
constructor(private context: ExtensionContext, private git: GitService, private gitContextTracker: GitContextTracker) {
super(() => this.dispose());
this._onConfigurationChanged();
const subscriptions: Disposable[] = [];
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
dispose() {
this._annotationProviders.forEach(async (p, i) => await this.clear(i));
BlameDecorations.annotation && BlameDecorations.annotation.dispose();
BlameDecorations.highlight && BlameDecorations.highlight.dispose();
this._blameAnnotationsDisposable && this._blameAnnotationsDisposable.dispose();
this._whitespaceController && this._whitespaceController.dispose();
this._disposable && this._disposable.dispose();
}
private _onConfigurationChanged() {
let toggleWhitespace = workspace.getConfiguration(`${ExtensionKey}.advanced.toggleWhitespace`).get<boolean>('enabled');
if (!toggleWhitespace) {
// Until https://github.com/Microsoft/vscode/issues/11485 is fixed we need to toggle whitespace for non-monospace fonts and ligatures
// TODO: detect monospace font
toggleWhitespace = workspace.getConfiguration('editor').get<boolean>('fontLigatures');
}
if (toggleWhitespace && !this._whitespaceController) {
this._whitespaceController = new WhitespaceController();
}
else if (!toggleWhitespace && this._whitespaceController) {
this._whitespaceController.dispose();
this._whitespaceController = undefined;
}
const cfg = workspace.getConfiguration(ExtensionKey).get<IBlameConfig>('blame')!;
if (cfg.annotation.highlight !== (this._config && this._config.annotation.highlight)) {
BlameDecorations.highlight && BlameDecorations.highlight.dispose();
switch (cfg.annotation.highlight) {
case 'gutter':
BlameDecorations.highlight = window.createTextEditorDecorationType({
dark: {
gutterIconPath: this.context.asAbsolutePath('images/blame-dark.svg'),
overviewRulerColor: 'rgba(255, 255, 255, 0.75)'
},
light: {
gutterIconPath: this.context.asAbsolutePath('images/blame-light.svg'),
overviewRulerColor: 'rgba(0, 0, 0, 0.75)'
},
gutterIconSize: 'contain',
overviewRulerLane: OverviewRulerLane.Right
});
break;
case 'line':
BlameDecorations.highlight = window.createTextEditorDecorationType({
dark: {
backgroundColor: 'rgba(255, 255, 255, 0.15)',
overviewRulerColor: 'rgba(255, 255, 255, 0.75)'
},
light: {
backgroundColor: 'rgba(0, 0, 0, 0.15)',
overviewRulerColor: 'rgba(0, 0, 0, 0.75)'
},
overviewRulerLane: OverviewRulerLane.Right,
isWholeLine: true
});
break;
case 'both':
BlameDecorations.highlight = window.createTextEditorDecorationType({
dark: {
backgroundColor: 'rgba(255, 255, 255, 0.15)',
gutterIconPath: this.context.asAbsolutePath('images/blame-dark.svg'),
overviewRulerColor: 'rgba(255, 255, 255, 0.75)'
},
light: {
backgroundColor: 'rgba(0, 0, 0, 0.15)',
gutterIconPath: this.context.asAbsolutePath('images/blame-light.svg'),
overviewRulerColor: 'rgba(0, 0, 0, 0.75)'
},
gutterIconSize: 'contain',
overviewRulerLane: OverviewRulerLane.Right,
isWholeLine: true
});
break;
default:
BlameDecorations.highlight = undefined;
break;
}
}
this._config = cfg;
}
async clear(column: number) {
const provider = this._annotationProviders.get(column);
if (!provider) return;
this._annotationProviders.delete(column);
await provider.dispose();
if (this._annotationProviders.size === 0) {
Logger.log(`Remove listener registrations for blame annotations`);
this._blameAnnotationsDisposable && this._blameAnnotationsDisposable.dispose();
this._blameAnnotationsDisposable = undefined;
}
this._onDidToggleBlameAnnotations.fire();
}
async showBlameAnnotation(editor: TextEditor, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;
const currentProvider = this._annotationProviders.get(editor.viewColumn || -1);
if (currentProvider && TextEditorComparer.equals(currentProvider.editor, editor)) {
await currentProvider.setSelection(shaOrLine);
return true;
}
const gitUri = await GitUri.fromUri(editor.document.uri, this.git);
const provider = new BlameAnnotationProvider(this.context, this.git, this._whitespaceController, editor, gitUri);
if (!await provider.supportsBlame()) return false;
if (currentProvider) {
await this.clear(currentProvider.editor.viewColumn || -1);
}
if (!this._blameAnnotationsDisposable && this._annotationProviders.size === 0) {
Logger.log(`Add listener registrations for blame annotations`);
const subscriptions: Disposable[] = [];
subscriptions.push(window.onDidChangeVisibleTextEditors(Functions.debounce(this._onVisibleTextEditorsChanged, 100), this));
subscriptions.push(window.onDidChangeTextEditorViewColumn(this._onTextEditorViewColumnChanged, this));
subscriptions.push(workspace.onDidCloseTextDocument(this._onTextDocumentClosed, this));
subscriptions.push(this.gitContextTracker.onDidBlameabilityChange(this._onBlameabilityChanged, this));
this._blameAnnotationsDisposable = Disposable.from(...subscriptions);
}
this._annotationProviders.set(editor.viewColumn || -1, provider);
if (await provider.provideBlameAnnotation(shaOrLine)) {
this._onDidToggleBlameAnnotations.fire();
return true;
}
return false;
}
isAnnotating(editor: TextEditor): boolean {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;
return !!this._annotationProviders.get(editor.viewColumn || -1);
}
async toggleBlameAnnotation(editor: TextEditor, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;
let provider = this._annotationProviders.get(editor.viewColumn || -1);
if (!provider) return this.showBlameAnnotation(editor, shaOrLine);
await this.clear(provider.editor.viewColumn || -1);
return false;
}
private _onBlameabilityChanged(e: BlameabilityChangeEvent) {
if (e.blameable || !e.editor) return;
for (const [key, p] of this._annotationProviders) {
if (!TextDocumentComparer.equals(p.document, e.editor.document)) continue;
Logger.log('BlameabilityChanged:', `Clear blame annotations for column ${key}`);
this.clear(key);
}
}
private _onTextDocumentClosed(e: TextDocument) {
for (const [key, p] of this._annotationProviders) {
if (!TextDocumentComparer.equals(p.document, e)) continue;
Logger.log('TextDocumentClosed:', `Clear blame annotations for column ${key}`);
this.clear(key);
}
}
private async _onTextEditorViewColumnChanged(e: TextEditorViewColumnChangeEvent) {
const viewColumn = e.viewColumn || -1;
Logger.log('TextEditorViewColumnChanged:', `Clear blame annotations for column ${viewColumn}`);
await this.clear(viewColumn);
for (const [key, p] of this._annotationProviders) {
if (!TextEditorComparer.equals(p.editor, e.textEditor)) continue;
Logger.log('TextEditorViewColumnChanged:', `Clear blame annotations for column ${key}`);
await this.clear(key);
}
}
private async _onVisibleTextEditorsChanged(e: TextEditor[]) {
if (e.every(_ => _.document.uri.scheme === 'inmemory')) return;
for (const [key, p] of this._annotationProviders) {
if (e.some(_ => TextEditorComparer.equals(p.editor, _))) continue;
Logger.log('VisibleTextEditorsChanged:', `Clear blame annotations for column ${key}`);
this.clear(key);
}
}
}

View File

@@ -1,113 +0,0 @@
'use strict';
import { IBlameConfig } from './configuration';
import { GitCommit, IGitCommitLine } from './gitService';
import * as moment from 'moment';
export const defaultAbsoluteDateLength = 10;
export const defaultRelativeDateLength = 13;
export const defaultAuthorLength = 16;
export const defaultMessageLength = 32;
export enum BlameAnnotationFormat {
Constrained,
Unconstrained
}
export class BlameAnnotationFormatter {
static getAnnotation(config: IBlameConfig, commit: GitCommit, format: BlameAnnotationFormat) {
const sha = commit.shortSha;
let message = this.getMessage(config, commit, format === BlameAnnotationFormat.Unconstrained ? 0 : defaultMessageLength);
if (format === BlameAnnotationFormat.Unconstrained) {
const authorAndDate = this.getAuthorAndDate(config, commit, config.annotation.dateFormat || 'MMMM Do, YYYY h:MMa');
if (config.annotation.sha) {
message = `${sha}${(authorAndDate ? `\u00a0\u2022\u00a0${authorAndDate}` : '')}${(message ? `\u00a0\u2022\u00a0${message}` : '')}`;
}
else if (config.annotation.author || config.annotation.date) {
message = `${authorAndDate}${(message ? `\u00a0\u2022\u00a0${message}` : '')}`;
}
return message;
}
const author = this.getAuthor(config, commit, defaultAuthorLength);
const date = this.getDate(config, commit, config.annotation.dateFormat || 'MM/DD/YYYY', true);
if (config.annotation.sha) {
message = `${sha}${(author ? `\u00a0\u2022\u00a0${author}` : '')}${(date ? `\u00a0\u2022\u00a0${date}` : '')}${(message ? `\u00a0\u2022\u00a0${message}` : '')}`;
}
else if (config.annotation.author) {
message = `${author}${(date ? `\u00a0\u2022\u00a0${date}` : '')}${(message ? `\u00a0\u2022\u00a0${message}` : '')}`;
}
else if (config.annotation.date) {
message = `${date}${(message ? `\u00a0\u2022\u00a0${message}` : '')}`;
}
return message;
}
static getAnnotationHover(config: IBlameConfig, line: IGitCommitLine, commit: GitCommit): string | Array<string> {
const message = `> \`${commit.message.replace(/\n/g, '\`\n>\n> \`')}\``;
if (commit.isUncommitted) {
return `\`${'0'.repeat(8)}\` &nbsp; __Uncommitted change__`;
}
return `\`${commit.shortSha}\` &nbsp; __${commit.author}__, ${moment(commit.date).fromNow()} _(${moment(commit.date).format(config.annotation.dateFormat || 'MMMM Do, YYYY h:MMa')})_ \n\n${message}`;
}
static getAuthorAndDate(config: IBlameConfig, commit: GitCommit, format: string, force: boolean = false) {
if (!force && !config.annotation.author && (!config.annotation.date || config.annotation.date === 'off')) return '';
if (!config.annotation.author) {
return this.getDate(config, commit, format);
}
if (!config.annotation.date || config.annotation.date === 'off') {
return this.getAuthor(config, commit);
}
return `${this.getAuthor(config, commit)}, ${this.getDate(config, commit, format)}`;
}
static getAuthor(config: IBlameConfig, commit: GitCommit, truncateTo: number = 0, force: boolean = false) {
if (!force && !config.annotation.author) return '';
const author = commit.isUncommitted ? 'Uncommitted' : commit.author;
if (!truncateTo) return author;
if (author.length > truncateTo) {
return `${author.substring(0, truncateTo - 1)}\u2026`;
}
if (force) return author; // Don't pad when just asking for the value
return author + '\u00a0'.repeat(truncateTo - author.length);
}
static getDate(config: IBlameConfig, commit: GitCommit, format: string, truncate: boolean = false, force: boolean = false) {
if (!force && (!config.annotation.date || config.annotation.date === 'off')) return '';
const date = config.annotation.date === 'relative'
? moment(commit.date).fromNow()
: moment(commit.date).format(format);
if (!truncate) return date;
const truncateTo = config.annotation.date === 'relative' ? defaultRelativeDateLength : defaultAbsoluteDateLength;
if (date.length > truncateTo) {
return `${date.substring(0, truncateTo - 1)}\u2026`;
}
if (force) return date; // Don't pad when just asking for the value
return date + '\u00a0'.repeat(truncateTo - date.length);
}
static getMessage(config: IBlameConfig, commit: GitCommit, truncateTo: number = 0, force: boolean = false) {
if (!force && !config.annotation.message) return '';
let message = commit.isUncommitted ? 'Uncommitted change' : commit.message;
if (truncateTo && message.length > truncateTo) {
return `${message.substring(0, truncateTo - 1)}\u2026`;
}
return message;
}
}

View File

@@ -1,302 +0,0 @@
'use strict';
import { Iterables } from './system';
import { DecorationInstanceRenderOptions, DecorationOptions, Disposable, ExtensionContext, Range, TextDocument, TextEditor, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
import { BlameAnnotationFormat, BlameAnnotationFormatter, defaultAuthorLength } from './blameAnnotationFormatter';
import { BlameDecorations } from './blameAnnotationController';
import { TextDocumentComparer } from './comparers';
import { BlameAnnotationStyle, IBlameConfig } from './configuration';
import { ExtensionKey } from './constants';
import { GitService, GitUri, IGitBlame } from './gitService';
import { WhitespaceController } from './whitespaceController';
export class BlameAnnotationProvider extends Disposable {
public document: TextDocument;
private _blame: Promise<IGitBlame>;
private _config: IBlameConfig;
private _disposable: Disposable;
constructor(context: ExtensionContext, private git: GitService, private whitespaceController: WhitespaceController | undefined, public editor: TextEditor, private uri: GitUri) {
super(() => this.dispose());
this.document = this.editor.document;
this._blame = this.git.getBlameForFile(this.uri);
this._config = workspace.getConfiguration(ExtensionKey).get<IBlameConfig>('blame')!;
const subscriptions: Disposable[] = [];
subscriptions.push(window.onDidChangeTextEditorSelection(this._onActiveSelectionChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
async dispose() {
if (this.editor) {
try {
this.editor.setDecorations(BlameDecorations.annotation, []);
BlameDecorations.highlight && this.editor.setDecorations(BlameDecorations.highlight, []);
// I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay
if (BlameDecorations.highlight !== undefined) {
setTimeout(() => {
if (BlameDecorations.highlight === undefined) return;
this.editor.setDecorations(BlameDecorations.highlight, []);
}, 1);
}
}
catch (ex) { }
}
// HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- restore whitespace
this.whitespaceController && await this.whitespaceController.restore();
this._disposable && this._disposable.dispose();
}
private async _onActiveSelectionChanged(e: TextEditorSelectionChangeEvent) {
if (!TextDocumentComparer.equals(this.document, e.textEditor && e.textEditor.document)) return;
return this.setSelection(e.selections[0].active.line);
}
async supportsBlame(): Promise<boolean> {
const blame = await this._blame;
return !!(blame && blame.lines.length);
}
async provideBlameAnnotation(shaOrLine?: string | number): Promise<boolean> {
let whitespacePromise: Promise<void> | undefined;
// HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- override whitespace (turn off)
if (this._config.annotation.style !== BlameAnnotationStyle.Trailing) {
whitespacePromise = this.whitespaceController && this.whitespaceController.override();
}
let blame: IGitBlame;
if (whitespacePromise) {
[blame] = await Promise.all([this._blame, whitespacePromise]);
}
else {
blame = await this._blame;
}
if (!blame || !blame.lines.length) {
this.whitespaceController && await this.whitespaceController.restore();
return false;
}
let blameDecorationOptions: DecorationOptions[] | undefined;
switch (this._config.annotation.style) {
case BlameAnnotationStyle.Compact:
blameDecorationOptions = this._getCompactGutterDecorations(blame);
break;
case BlameAnnotationStyle.Expanded:
blameDecorationOptions = this._getExpandedGutterDecorations(blame, false);
break;
case BlameAnnotationStyle.Trailing:
blameDecorationOptions = this._getExpandedGutterDecorations(blame, true);
break;
}
if (blameDecorationOptions) {
this.editor.setDecorations(BlameDecorations.annotation, blameDecorationOptions);
}
this._setSelection(blame, shaOrLine);
return true;
}
async setSelection(shaOrLine?: string | number) {
const blame = await this._blame;
if (!blame || !blame.lines.length) return;
return this._setSelection(blame, shaOrLine);
}
private _setSelection(blame: IGitBlame, shaOrLine?: string | number) {
if (!BlameDecorations.highlight) return;
const offset = this.uri.offset;
let sha: string | undefined = undefined;
if (typeof shaOrLine === 'string') {
sha = shaOrLine;
}
else if (typeof shaOrLine === 'number') {
const line = shaOrLine - offset;
if (line >= 0) {
const commitLine = blame.lines[line];
sha = commitLine && commitLine.sha;
}
}
else {
sha = Iterables.first(blame.commits.values()).sha;
}
if (!sha) {
this.editor.setDecorations(BlameDecorations.highlight, []);
return;
}
const highlightDecorationRanges = blame.lines
.filter(l => l.sha === sha)
.map(l => this.editor.document.validateRange(new Range(l.line + offset, 0, l.line + offset, 1000000)));
this.editor.setDecorations(BlameDecorations.highlight, highlightDecorationRanges);
}
private _getCompactGutterDecorations(blame: IGitBlame): DecorationOptions[] {
const offset = this.uri.offset;
let count = 0;
let lastSha: string;
return blame.lines.map(l => {
const commit = blame.commits.get(l.sha);
if (commit === undefined) throw new Error(`Cannot find sha ${l.sha}`);
let color: string;
if (commit.isUncommitted) {
color = 'rgba(0, 188, 242, 0.6)';
}
else {
color = l.previousSha ? '#999999' : '#6b6b6b';
}
let gutter = '';
if (lastSha !== l.sha) {
count = -1;
}
const isEmptyOrWhitespace = this.document.lineAt(l.line).isEmptyOrWhitespace;
if (!isEmptyOrWhitespace) {
switch (++count) {
case 0:
gutter = commit.shortSha;
break;
case 1:
gutter = `\u2759 ${BlameAnnotationFormatter.getAuthor(this._config, commit, defaultAuthorLength, true)}`;
break;
case 2:
gutter = `\u2759 ${BlameAnnotationFormatter.getDate(this._config, commit, this._config.annotation.dateFormat || 'MM/DD/YYYY', true, true)}`;
break;
default:
gutter = `\u2759`;
break;
}
}
const hoverMessage = BlameAnnotationFormatter.getAnnotationHover(this._config, l, commit);
lastSha = l.sha;
return {
range: this.editor.document.validateRange(new Range(l.line + offset, 0, l.line + offset, 1000000)),
hoverMessage: hoverMessage,
renderOptions: {
before: {
color: color,
contentText: gutter,
width: '11em'
}
}
} as DecorationOptions;
});
}
private _getExpandedGutterDecorations(blame: IGitBlame, trailing: boolean = false): DecorationOptions[] {
const offset = this.uri.offset;
let width = 0;
if (!trailing) {
if (this._config.annotation.sha) {
width += 5;
}
if (this._config.annotation.date && this._config.annotation.date !== 'off') {
if (width > 0) {
width += 7;
}
else {
width += 6;
}
if (this._config.annotation.date === 'relative') {
width += 2;
}
}
if (this._config.annotation.author) {
if (width > 5 + 6) {
width += 12;
}
else if (width > 0) {
width += 11;
}
else {
width += 10;
}
}
if (this._config.annotation.message) {
if (width > 5 + 6 + 10) {
width += 21;
}
else if (width > 5 + 6) {
width += 21;
}
else if (width > 0) {
width += 21;
}
else {
width += 19;
}
}
}
return blame.lines.map(l => {
const commit = blame.commits.get(l.sha);
if (commit === undefined) throw new Error(`Cannot find sha ${l.sha}`);
let color: string;
if (commit.isUncommitted) {
color = 'rgba(0, 188, 242, 0.6)';
}
else {
if (trailing) {
color = l.previousSha ? 'rgba(153, 153, 153, 0.5)' : 'rgba(107, 107, 107, 0.5)';
}
else {
color = l.previousSha ? 'rgb(153, 153, 153)' : 'rgb(107, 107, 107)';
}
}
const format = trailing ? BlameAnnotationFormat.Unconstrained : BlameAnnotationFormat.Constrained;
const gutter = BlameAnnotationFormatter.getAnnotation(this._config, commit, format);
const hoverMessage = BlameAnnotationFormatter.getAnnotationHover(this._config, l, commit);
let renderOptions: DecorationInstanceRenderOptions;
if (trailing) {
renderOptions = {
after: {
color: color,
contentText: gutter
}
} as DecorationInstanceRenderOptions;
}
else {
renderOptions = {
before: {
color: color,
contentText: gutter,
width: `${width}em`
}
} as DecorationInstanceRenderOptions;
}
return {
range: this.editor.document.validateRange(new Range(l.line + offset, 0, l.line + offset, 1000000)),
hoverMessage: hoverMessage,
renderOptions: renderOptions
} as DecorationOptions;
});
}
}

81
src/codeLensController.ts Normal file
View File

@@ -0,0 +1,81 @@
'use strict';
import { Objects } from './system';
import { Disposable, ExtensionContext, languages, TextEditor, workspace } from 'vscode';
import { IConfig } from './configuration';
import { CommandContext, ExtensionKey, setCommandContext } from './constants';
import { GitCodeLensProvider } from './gitCodeLensProvider';
import { GitService } from './gitService';
import { Logger } from './logger';
export class CodeLensController extends Disposable {
private _codeLensProvider: GitCodeLensProvider | undefined;
private _codeLensProviderDisposable: Disposable | undefined;
private _config: IConfig;
private _disposable: Disposable | undefined;
constructor(private context: ExtensionContext, private git: GitService) {
super(() => this.dispose());
this._onConfigurationChanged();
const subscriptions: Disposable[] = [];
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
subscriptions.push(git.onDidChangeGitCache(this._onGitCacheChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
dispose() {
this._disposable && this._disposable.dispose();
this._codeLensProviderDisposable && this._codeLensProviderDisposable.dispose();
this._codeLensProviderDisposable = undefined;
this._codeLensProvider = undefined;
}
private _onConfigurationChanged() {
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
if (!Objects.areEquivalent(cfg.codeLens, this._config && this._config.codeLens)) {
Logger.log('CodeLens config changed; resetting CodeLens provider');
if (cfg.codeLens.enabled && (cfg.codeLens.recentChange.enabled || cfg.codeLens.authors.enabled)) {
if (this._codeLensProvider) {
this._codeLensProvider.reset();
}
else {
this._codeLensProvider = new GitCodeLensProvider(this.context, this.git);
this._codeLensProviderDisposable = languages.registerCodeLensProvider(GitCodeLensProvider.selector, this._codeLensProvider);
}
}
else {
this._codeLensProviderDisposable && this._codeLensProviderDisposable.dispose();
this._codeLensProviderDisposable = undefined;
this._codeLensProvider = undefined;
}
setCommandContext(CommandContext.CanToggleCodeLens, cfg.codeLens.recentChange.enabled || cfg.codeLens.authors.enabled);
}
this._config = cfg;
}
private _onGitCacheChanged() {
Logger.log('Git cache changed; resetting CodeLens provider');
this._codeLensProvider && this._codeLensProvider.reset();
}
toggleCodeLens(editor: TextEditor) {
if (!this._config.codeLens.recentChange.enabled && !this._config.codeLens.authors.enabled) return;
Logger.log(`toggleCodeLens()`);
if (this._codeLensProviderDisposable) {
this._codeLensProviderDisposable.dispose();
this._codeLensProviderDisposable = undefined;
return;
}
this._codeLensProviderDisposable = languages.registerCodeLensProvider(GitCodeLensProvider.selector, new GitCodeLensProvider(this.context, this.git));
}
}

View File

@@ -1,38 +1,44 @@
'use strict';
export * from './commands/common';
export * from './commands/keyboard';
export * from './commands/clearFileAnnotations';
export * from './commands/closeUnchangedFiles';
export * from './commands/copyMessageToClipboard';
export * from './commands/copyShaToClipboard';
export * from './commands/diffDirectory';
export * from './commands/diffLineWithPrevious';
export * from './commands/diffLineWithWorking';
export * from './commands/diffWith';
export * from './commands/diffWithBranch';
export * from './commands/diffWithNext';
export * from './commands/diffWithPrevious';
export * from './commands/diffWithRevision';
export * from './commands/diffWithWorking';
export * from './commands/openChangedFiles';
export * from './commands/openBranchesInRemote';
export * from './commands/openBranchInRemote';
export * from './commands/openCommitInRemote';
export * from './commands/openFileInRemote';
export * from './commands/openInRemote';
export * from './commands/openRepoInRemote';
export * from './commands/showBlame';
export * from './commands/resetSuppressedWarnings';
export * from './commands/showBlameHistory';
export * from './commands/showCommitSearch';
export * from './commands/showFileBlame';
export * from './commands/showFileHistory';
export * from './commands/showLastQuickPick';
export * from './commands/showLineBlame';
export * from './commands/showQuickBranchHistory';
export * from './commands/showQuickCommitDetails';
export * from './commands/showQuickCommitFileDetails';
export * from './commands/showCommitSearch';
export * from './commands/showQuickFileHistory';
export * from './commands/showQuickBranchHistory';
export * from './commands/showQuickCurrentBranchHistory';
export * from './commands/showQuickFileHistory';
export * from './commands/showQuickRepoStatus';
export * from './commands/showQuickStashList';
export * from './commands/stashApply';
export * from './commands/stashDelete';
export * from './commands/stashSave';
export * from './commands/toggleBlame';
export * from './commands/toggleCodeLens';
export * from './commands/toggleCodeLens';
export * from './commands/toggleFileBlame';
export * from './commands/toggleFileRecentChanges';
export * from './commands/toggleLineBlame';

View File

@@ -0,0 +1,24 @@
'use strict';
import { TextEditor, TextEditorEdit, Uri, window } from 'vscode';
import { AnnotationController } from '../annotations/annotationController';
import { Commands, EditorCommand } from './common';
import { Logger } from '../logger';
export class ClearFileAnnotationsCommand extends EditorCommand {
constructor(private annotationController: AnnotationController) {
super(Commands.ClearFileAnnotations);
}
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri): Promise<any> {
if (editor === undefined || editor.document === undefined || editor.document.isDirty) return undefined;
try {
return this.annotationController.clear(editor.viewColumn || -1);
}
catch (ex) {
Logger.error(ex, 'ClearFileAnnotationsCommand');
return window.showErrorMessage(`Unable to clear file annotations. See output channel for more details`);
}
}
}

View File

@@ -1,71 +1,87 @@
'use strict';
import { TextEditor, Uri, window } from 'vscode';
import { ActiveEditorTracker } from '../activeEditorTracker';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { TextEditorComparer, UriComparer } from '../comparers';
import { GitService } from '../gitService';
import { Logger } from '../logger';
export interface CloseUnchangedFilesCommandArgs {
uris?: Uri[];
}
export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
constructor(private git: GitService) {
super(Commands.CloseUnchangedFiles);
}
async execute(editor: TextEditor, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) {
uri = getCommandUri(uri, editor);
try {
if (args.uris === undefined) {
const repoPath = await this.git.getRepoPathFromUri(uri);
if (!repoPath) return window.showWarningMessage(`Unable to close unchanged files`);
const status = await this.git.getStatusForRepo(repoPath);
if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`);
args.uris = status.files.map(_ => _.Uri);
}
const editorTracker = new ActiveEditorTracker();
let active = window.activeTextEditor;
let editor = active;
do {
if (editor !== undefined) {
if ((editor.document !== undefined && editor.document.isDirty) ||
args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri))) {
// If we didn't start with a valid editor, set one once we find it
if (active === undefined) {
active = editor;
}
editor = await editorTracker.awaitNext(500);
}
else {
if (active === editor) {
active = undefined;
}
editor = await editorTracker.awaitClose(500);
}
}
else {
if (active === editor) {
active = undefined;
}
editor = await editorTracker.awaitClose(500);
}
} while ((active === undefined && editor === undefined) || !TextEditorComparer.equals(active, editor, { useId: true, usePosition: true }));
editorTracker.dispose();
return undefined;
}
catch (ex) {
Logger.error(ex, 'CloseUnchangedFilesCommand');
return window.showErrorMessage(`Unable to close unchanged files. See output channel for more details`);
}
}
'use strict';
import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorTracker } from '../activeEditorTracker';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { TextEditorComparer, UriComparer } from '../comparers';
import { BuiltInCommands } from '../constants';
import { GitService } from '../gitService';
import { Logger } from '../logger';
import { Messages } from '../messages';
export interface CloseUnchangedFilesCommandArgs {
uris?: Uri[];
}
export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
constructor(private git: GitService) {
super(Commands.CloseUnchangedFiles);
}
async execute(editor?: TextEditor, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) {
uri = getCommandUri(uri, editor);
try {
if (args.uris === undefined) {
args = { ...args };
const repoPath = await this.git.getRepoPathFromUri(uri);
if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to close unchanged files`);
const status = await this.git.getStatusForRepo(repoPath);
if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`);
args.uris = status.files.map(_ => _.Uri);
}
if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors);
const editorTracker = new ActiveEditorTracker();
let count = 0;
let previous = undefined;
let editor = window.activeTextEditor;
while (true) {
if (editor !== undefined) {
if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) {
break;
}
if (editor.document !== undefined &&
(editor.document.isDirty || args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri)))) {
const lastPrevious = previous;
previous = editor;
editor = await editorTracker.awaitNext(500);
if (TextEditorComparer.equals(lastPrevious, editor, { useId: true, usePosition: true })) {
break;
}
continue;
}
}
previous = editor;
editor = await editorTracker.awaitClose(500);
if (previous === undefined && editor === undefined) {
count++;
// This is such a shitty hack, but I can't figure out any other reliable way to know that we've cycled through all the editors :(
if (count >= 4) {
break;
}
}
else {
count = 0;
}
}
editorTracker.dispose();
return undefined;
}
catch (ex) {
Logger.error(ex, 'CloseUnchangedFilesCommand');
return window.showErrorMessage(`Unable to close unchanged files. See output channel for more details`);
}
}
}

Some files were not shown because too many files have changed in this diff Show More