Skip to content

Commit 2e80397

Browse files
authored
feat: support toggling 'whole file' annotations (#149)
Git blame toggle now cycles through three line decoration settings: 'none', 'line', and 'file'
1 parent c851038 commit 2e80397

4 files changed

Lines changed: 72 additions & 39 deletions

File tree

package.json

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://raw.githubusercontent.com/sourcegraph/sourcegraph/master/shared/src/schema/extension.schema.json",
2+
"$schema": "https://raw.githubusercontent.com/sourcegraph/sourcegraph/main/client/shared/src/schema/extension.schema.json",
33
"name": "git-extras",
44
"publisher": "sourcegraph",
55
"title": "Git extras",
@@ -25,18 +25,17 @@
2525
"command": "updateConfiguration",
2626
"commandArguments": [
2727
[
28-
"git.blame.lineDecorations"
28+
"git.blame.decorations"
2929
],
30-
"${!config.git.blame.lineDecorations}",
31-
null,
32-
"json"
30+
"${((!config.git.blame.decorations || config.git.blame.decorations === 'none') && 'line') || (config.git.blame.decorations === 'line' && 'file') || 'none'}",
31+
null
3332
],
3433
"category": "Git",
35-
"title": "${config.git.blame.lineDecorations && \"Hide\" || \"Show\"} blame",
34+
"title": "${((!config.git.blame.decorations || config.git.blame.decorations === 'none') && 'Show blame for selected lines') || (config.git.blame.decorations === 'line' && 'Show blame for the whole file') || 'Hide blame'}",
3635
"actionItem": {
3736
"label": "Blame",
38-
"description": "${config.git.blame.lineDecorations && \"Hide\" || \"Show\"} Git blame line annotations${!config.git.blame.decorateWholeFile && \" on selected lines\" || \"\"}",
39-
"pressed": "config.git.blame.lineDecorations",
37+
"description": "${((!config.git.blame.decorations || config.git.blame.decorations === 'none') && 'Show Git blame line annotations on selected lines') || (config.git.blame.decorations === 'line' && 'Show Git blame line annotations for the whole file') || 'Hide Git blame line annotations'}",
38+
"pressed": "(config.git.blame.decorations === 'line') || (config.git.blame.decorations === 'file')",
4039
"iconURL": "https://raw.githubusercontent.com/sourcegraph/sourcegraph-git-extras/63dd95962c43b95b3f3a9ea2aa0165d6b38a958c/icon/git_logo.svg?sanitize=true"
4140
}
4241
}
@@ -58,15 +57,11 @@
5857
"configuration": {
5958
"title": "Git extras",
6059
"properties": {
61-
"git.blame.lineDecorations": {
62-
"description": "Whether to show Git blame annotations at the end of each line.",
63-
"type": "boolean",
64-
"default": false
65-
},
66-
"git.blame.decorateWholeFile": {
67-
"description": "Whether to decorate all lines in a file, rather than just selected lines.",
68-
"type": "boolean",
69-
"default": false
60+
"git.blame.decorations": {
61+
"description": "Whether to decorate all lines in a file, only selected lines, or none at all.",
62+
"type": "string",
63+
"enum": ["none", "line", "file"],
64+
"default": "none"
7065
}
7166
}
7267
}

src/blame.test.ts

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -227,27 +227,12 @@ describe('getAllBlameDecorations()', () => {
227227
})
228228

229229
describe('getBlameDecorations()', () => {
230-
it('gets no decorations if git.blame.lineDecorations is false', async () => {
231-
expect(
232-
await getBlameDecorations({
233-
uri: 'a',
234-
settings: {
235-
'git.blame.lineDecorations': false,
236-
},
237-
now: NOW,
238-
selections: null,
239-
queryHunks: () => Promise.resolve([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3, FIXTURE_HUNK_4]),
240-
sourcegraph: SOURCEGRAPH as any,
241-
})
242-
).toEqual([])
243-
})
244-
245230
it('gets decorations for all hunks if no selections are passed', async () => {
246231
expect(
247232
await getBlameDecorations({
248233
uri: 'a',
249234
settings: {
250-
'git.blame.lineDecorations': true,
235+
'git.blame.decorations': 'line',
251236
},
252237
now: NOW,
253238
selections: null,
@@ -267,7 +252,7 @@ describe('getBlameDecorations()', () => {
267252
await getBlameDecorations({
268253
uri: 'a',
269254
settings: {
270-
'git.blame.lineDecorations': true,
255+
'git.blame.decorations': 'line',
271256
},
272257
now: NOW,
273258
selections: [
@@ -279,13 +264,27 @@ describe('getBlameDecorations()', () => {
279264
).toEqual([getDecorationFromHunk(FIXTURE_HUNK_4, NOW, 3, SOURCEGRAPH as any)])
280265
})
281266

282-
it('gets decorations for all hunks if git.blame.decorateWholeFile is true', async () => {
267+
it('gets no decorations if git.blame.decorations is "none"', async () => {
268+
expect(
269+
await getBlameDecorations({
270+
uri: 'a',
271+
settings: {
272+
'git.blame.decorations': 'none',
273+
},
274+
now: NOW,
275+
selections: null,
276+
queryHunks: () => Promise.resolve([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3, FIXTURE_HUNK_4]),
277+
sourcegraph: SOURCEGRAPH as any,
278+
})
279+
).toEqual([])
280+
})
281+
282+
it('gets decorations for all hunks if git.blame.decorations is "file"', async () => {
283283
expect(
284284
await getBlameDecorations({
285285
uri: 'a',
286286
settings: {
287-
'git.blame.lineDecorations': true,
288-
'git.blame.decorateWholeFile': true,
287+
'git.blame.decorations': 'file',
289288
},
290289
now: NOW,
291290
selections: [

src/blame.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,13 @@ export const getBlameDecorations = async ({
131131
queryHunks?: ({ uri, sourcegraph }: { uri: string; sourcegraph: typeof import('sourcegraph') }) => Promise<Hunk[]>
132132
sourcegraph: typeof import('sourcegraph')
133133
}): Promise<TextDocumentDecoration[]> => {
134-
if (!settings['git.blame.lineDecorations']) {
134+
const decorations = settings['git.blame.decorations'] || 'none'
135+
136+
if (decorations === 'none') {
135137
return []
136138
}
137139
const hunks = await queryHunks({ uri, sourcegraph })
138-
if (selections !== null && !settings['git.blame.decorateWholeFile']) {
140+
if (selections !== null && decorations === 'line') {
139141
return getBlameDecorationsForSelections(hunks, selections, now, sourcegraph)
140142
} else {
141143
return getAllBlameDecorations(hunks, now, sourcegraph)

src/extension.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import * as sourcegraph from 'sourcegraph'
44
import { getBlameDecorations } from './blame'
55

66
export interface Settings {
7+
['git.blame.decorations']?: 'none' | 'line' | 'file'
8+
// The following two settings are deprecated, but we will still look for them
9+
// to 'onboard' users to new setting
710
['git.blame.lineDecorations']?: boolean
811
['git.blame.decorateWholeFile']?: boolean
912
}
@@ -16,6 +19,40 @@ export function activate(context: sourcegraph.ExtensionContext): void {
1619
const configurationChanges = new BehaviorSubject<void>(undefined)
1720
context.subscriptions.add(sourcegraph.configuration.subscribe(() => configurationChanges.next(undefined)))
1821

22+
// Backcompat: Set 'git.blame.decorations' based on previous settings values
23+
;(async () => {
24+
try {
25+
const settings = sourcegraph.configuration.get<Settings>().value
26+
const initialDecorations = settings['git.blame.decorations']
27+
if (!initialDecorations) {
28+
if (settings['git.blame.lineDecorations'] === false) {
29+
await sourcegraph.commands.executeCommand('updateConfiguration', ['git.blame.decorations'], 'none')
30+
} else if (settings['git.blame.lineDecorations'] === true) {
31+
if (settings['git.blame.decorateWholeFile']) {
32+
await sourcegraph.commands.executeCommand(
33+
'updateConfiguration',
34+
['git.blame.decorations'],
35+
'file'
36+
)
37+
} else {
38+
await sourcegraph.commands.executeCommand(
39+
'updateConfiguration',
40+
['git.blame.decorations'],
41+
'line'
42+
)
43+
}
44+
} else {
45+
// Default to 'line'
46+
await sourcegraph.commands.executeCommand('updateConfiguration', ['git.blame.decorations'], 'line')
47+
}
48+
}
49+
} catch {
50+
// noop
51+
}
52+
})().catch(() => {
53+
// noop
54+
})
55+
1956
if (sourcegraph.app.activeWindowChanges) {
2057
const selectionChanges = from(sourcegraph.app.activeWindowChanges).pipe(
2158
filter((window): window is Exclude<typeof window, undefined> => window !== undefined),

0 commit comments

Comments
 (0)