1
1
import { inject , injectable } from 'inversify' ;
2
- import { Disposable , StatusBarAlignment , StatusBarItem , Uri } from 'vscode' ;
2
+ import { Disposable , LanguageStatusItem , LanguageStatusSeverity , StatusBarAlignment , StatusBarItem , Uri } from 'vscode' ;
3
+ import { IExtensionSingleActivationService } from '../../activation/types' ;
3
4
import { IApplicationShell , IWorkspaceService } from '../../common/application/types' ;
5
+ import { Commands , PYTHON_LANGUAGE } from '../../common/constants' ;
6
+ import { InterpreterStatusBarPosition } from '../../common/experiments/groups' ;
4
7
import '../../common/extensions' ;
5
- import { IDisposableRegistry , IPathUtils , Resource } from '../../common/types' ;
6
- import { Interpreters } from '../../common/utils/localize' ;
8
+ import { IDisposableRegistry , IExperimentService , IPathUtils , Resource } from '../../common/types' ;
9
+ import { InterpreterQuickPickList , Interpreters } from '../../common/utils/localize' ;
7
10
import { IServiceContainer } from '../../ioc/types' ;
8
11
import { traceLog } from '../../logging' ;
9
12
import { PythonEnvironment } from '../../pythonEnvironments/info' ;
@@ -14,9 +17,19 @@ import {
14
17
IInterpreterStatusbarVisibilityFilter ,
15
18
} from '../contracts' ;
16
19
20
+ /**
21
+ * Based on https://github.com/microsoft/vscode-python/issues/18040#issuecomment-992567670.
22
+ * This is to ensure the item appears right after the Python language status item.
23
+ */
24
+ const STATUS_BAR_ITEM_PRIORITY = 100.09999 ;
17
25
@injectable ( )
18
- export class InterpreterDisplay implements IInterpreterDisplay {
19
- private readonly statusBar : StatusBarItem ;
26
+ export class InterpreterDisplay implements IInterpreterDisplay , IExtensionSingleActivationService {
27
+ public supportedWorkspaceTypes : { untrustedWorkspace : boolean ; virtualWorkspace : boolean } = {
28
+ untrustedWorkspace : false ,
29
+ virtualWorkspace : true ,
30
+ } ;
31
+ private statusBar : StatusBarItem | undefined ;
32
+ private languageStatus : LanguageStatusItem | undefined ;
20
33
private readonly helper : IInterpreterHelper ;
21
34
private readonly workspaceService : IWorkspaceService ;
22
35
private readonly pathUtils : IPathUtils ;
@@ -26,26 +39,48 @@ export class InterpreterDisplay implements IInterpreterDisplay {
26
39
private interpreterPath : string | undefined ;
27
40
private statusBarCanBeDisplayed ?: boolean ;
28
41
private visibilityFilters : IInterpreterStatusbarVisibilityFilter [ ] = [ ] ;
42
+ private disposableRegistry : Disposable [ ] ;
43
+ private experiments : IExperimentService ;
29
44
30
45
constructor ( @inject ( IServiceContainer ) private readonly serviceContainer : IServiceContainer ) {
31
46
this . helper = serviceContainer . get < IInterpreterHelper > ( IInterpreterHelper ) ;
32
47
this . workspaceService = serviceContainer . get < IWorkspaceService > ( IWorkspaceService ) ;
33
48
this . pathUtils = serviceContainer . get < IPathUtils > ( IPathUtils ) ;
34
49
this . interpreterService = serviceContainer . get < IInterpreterService > ( IInterpreterService ) ;
35
50
36
- const application = serviceContainer . get < IApplicationShell > ( IApplicationShell ) ;
37
- const disposableRegistry = serviceContainer . get < Disposable [ ] > ( IDisposableRegistry ) ;
38
-
39
- this . statusBar = application . createStatusBarItem ( StatusBarAlignment . Left , 100 ) ;
40
- this . statusBar . command = 'python.setInterpreter' ;
41
- disposableRegistry . push ( this . statusBar ) ;
51
+ this . disposableRegistry = serviceContainer . get < Disposable [ ] > ( IDisposableRegistry ) ;
42
52
43
53
this . interpreterService . onDidChangeInterpreterInformation (
44
54
this . onDidChangeInterpreterInformation ,
45
55
this ,
46
- disposableRegistry ,
56
+ this . disposableRegistry ,
47
57
) ;
58
+ this . experiments = this . serviceContainer . get < IExperimentService > ( IExperimentService ) ;
48
59
}
60
+
61
+ public async activate ( ) : Promise < void > {
62
+ const application = this . serviceContainer . get < IApplicationShell > ( IApplicationShell ) ;
63
+ if ( this . experiments . inExperimentSync ( InterpreterStatusBarPosition . Unpinned ) ) {
64
+ this . languageStatus = application . createLanguageStatusItem ( 'python.selectedInterpreter' , {
65
+ language : PYTHON_LANGUAGE ,
66
+ } ) ;
67
+ this . languageStatus . severity = LanguageStatusSeverity . Information ;
68
+ this . languageStatus . command = {
69
+ title : InterpreterQuickPickList . browsePath . openButtonLabel ( ) ,
70
+ command : Commands . Set_Interpreter ,
71
+ } ;
72
+ this . disposableRegistry . push ( this . languageStatus ) ;
73
+ } else {
74
+ let [ alignment , priority ] = [ StatusBarAlignment . Left , 100 ] ;
75
+ if ( this . experiments . inExperimentSync ( InterpreterStatusBarPosition . Pinned ) ) {
76
+ [ alignment , priority ] = [ StatusBarAlignment . Right , STATUS_BAR_ITEM_PRIORITY ] ;
77
+ }
78
+ this . statusBar = application . createStatusBarItem ( alignment , priority ) ;
79
+ this . statusBar . command = Commands . Set_Interpreter ;
80
+ this . disposableRegistry . push ( this . statusBar ) ;
81
+ }
82
+ }
83
+
49
84
public async refresh ( resource ?: Uri ) {
50
85
// Use the workspace Uri if available
51
86
if ( resource && this . workspaceService . getWorkspaceFolder ( resource ) ) {
@@ -72,30 +107,56 @@ export class InterpreterDisplay implements IInterpreterDisplay {
72
107
private async updateDisplay ( workspaceFolder ?: Uri ) {
73
108
const interpreter = await this . interpreterService . getActiveInterpreter ( workspaceFolder ) ;
74
109
this . currentlySelectedWorkspaceFolder = workspaceFolder ;
75
- if ( interpreter ) {
76
- this . statusBar . color = '' ;
77
- this . statusBar . tooltip = this . pathUtils . getDisplayName ( interpreter . path , workspaceFolder ?. fsPath ) ;
78
- if ( this . interpreterPath !== interpreter . path ) {
79
- traceLog (
80
- Interpreters . pythonInterpreterPath ( ) . format (
81
- this . pathUtils . getDisplayName ( interpreter . path , workspaceFolder ?. fsPath ) ,
82
- ) ,
83
- ) ;
84
- this . interpreterPath = interpreter . path ;
110
+ if ( this . statusBar ) {
111
+ if ( interpreter ) {
112
+ this . statusBar . color = '' ;
113
+ this . statusBar . tooltip = this . pathUtils . getDisplayName ( interpreter . path , workspaceFolder ?. fsPath ) ;
114
+ if ( this . interpreterPath !== interpreter . path ) {
115
+ traceLog (
116
+ Interpreters . pythonInterpreterPath ( ) . format (
117
+ this . pathUtils . getDisplayName ( interpreter . path , workspaceFolder ?. fsPath ) ,
118
+ ) ,
119
+ ) ;
120
+ this . interpreterPath = interpreter . path ;
121
+ }
122
+ let text = interpreter . displayName ! ;
123
+ if ( this . experiments . inExperimentSync ( InterpreterStatusBarPosition . Pinned ) ) {
124
+ text = text . startsWith ( 'Python' ) ? text . substring ( 'Python' . length ) . trim ( ) : text ;
125
+ }
126
+ this . statusBar . text = text ;
127
+ this . currentlySelectedInterpreterPath = interpreter . path ;
128
+ } else {
129
+ this . statusBar . tooltip = '' ;
130
+ this . statusBar . color = '' ;
131
+ this . statusBar . text = '$(alert) Select Python Interpreter' ;
132
+ this . currentlySelectedInterpreterPath = undefined ;
133
+ }
134
+ } else if ( this . languageStatus ) {
135
+ if ( interpreter ) {
136
+ this . languageStatus . detail = this . pathUtils . getDisplayName ( interpreter . path , workspaceFolder ?. fsPath ) ;
137
+ if ( this . interpreterPath !== interpreter . path ) {
138
+ traceLog (
139
+ Interpreters . pythonInterpreterPath ( ) . format (
140
+ this . pathUtils . getDisplayName ( interpreter . path , workspaceFolder ?. fsPath ) ,
141
+ ) ,
142
+ ) ;
143
+ this . interpreterPath = interpreter . path ;
144
+ }
145
+ let text = interpreter . displayName ! ;
146
+ text = text . startsWith ( 'Python' ) ? text . substring ( 'Python' . length ) . trim ( ) : text ;
147
+ this . languageStatus . text = text ;
148
+ this . currentlySelectedInterpreterPath = interpreter . path ;
149
+ } else {
150
+ this . languageStatus . text = '$(alert) No Interpreter Selected' ;
151
+ this . languageStatus . detail = undefined ;
152
+ this . currentlySelectedInterpreterPath = undefined ;
85
153
}
86
- this . statusBar . text = interpreter . displayName ! ;
87
- this . currentlySelectedInterpreterPath = interpreter . path ;
88
- } else {
89
- this . statusBar . tooltip = '' ;
90
- this . statusBar . color = '' ;
91
- this . statusBar . text = '$(alert) Select Python Interpreter' ;
92
- this . currentlySelectedInterpreterPath = undefined ;
93
154
}
94
155
this . statusBarCanBeDisplayed = true ;
95
156
this . updateVisibility ( ) ;
96
157
}
97
158
private updateVisibility ( ) {
98
- if ( ! this . statusBarCanBeDisplayed ) {
159
+ if ( ! this . statusBar || ! this . statusBarCanBeDisplayed ) {
99
160
return ;
100
161
}
101
162
if ( this . visibilityFilters . length === 0 || this . visibilityFilters . every ( ( filter ) => ! filter . hidden ) ) {
0 commit comments