@@ -103,8 +103,12 @@ public static bool TryDiscoverInstallation(string editorPath, out IVisualStudioI
103103 manifestBase = IOPath . GetDirectoryName ( manifestBase ) ;
104104 else if ( VisualStudioEditor . IsOSX ) // on Mac, editorPath is a directory
105105 manifestBase = IOPath . Combine ( manifestBase , "Contents" ) ;
106- else // on Linux, editorPath is a file, in a bin sub-directory
107- manifestBase = Directory . GetParent ( manifestBase ) ? . Parent ? . FullName ;
106+ else {
107+ // on Linux, editorPath is a file, in a bin sub-directory
108+ var parent = Directory . GetParent ( manifestBase ) ;
109+ // but we can link to [vscode]/code or [vscode]/bin/code
110+ manifestBase = parent ? . Name == "bin" ? parent . Parent ? . FullName : parent ? . FullName ;
111+ }
108112
109113 if ( manifestBase == null )
110114 return false ;
@@ -156,18 +160,53 @@ public static IEnumerable<IVisualStudioInstallation> GetVisualStudioInstallation
156160 }
157161 else
158162 {
163+ // Well known locations
159164 candidates . Add ( "/usr/bin/code" ) ;
160165 candidates . Add ( "/bin/code" ) ;
161166 candidates . Add ( "/usr/local/bin/code" ) ;
167+
168+ // Preference ordered base directories relative to which desktop files should be searched
169+ candidates . AddRange ( GetXdgCandidates ( ) ) ;
162170 }
163171
164- foreach ( var candidate in candidates )
172+ foreach ( var candidate in candidates . Distinct ( ) )
165173 {
166174 if ( TryDiscoverInstallation ( candidate , out var installation ) )
167175 yield return installation ;
168176 }
169177 }
170178
179+ private static readonly Regex DesktopFileExecEntry = new Regex ( @"Exec=(\S+)" , RegexOptions . Singleline | RegexOptions . Compiled ) ;
180+
181+ private static IEnumerable < string > GetXdgCandidates ( ) {
182+ var envdirs = Environment . GetEnvironmentVariable ( "XDG_DATA_DIRS" ) ;
183+ if ( string . IsNullOrEmpty ( envdirs ) )
184+ yield break ;
185+
186+ var dirs = envdirs . Split ( ':' ) ;
187+ foreach ( var dir in dirs )
188+ {
189+ Match match = null ;
190+
191+ try {
192+ var desktopFile = IOPath . Combine ( dir , "applications/code.desktop" ) ;
193+ if ( ! File . Exists ( desktopFile ) )
194+ continue ;
195+
196+ var content = File . ReadAllText ( desktopFile ) ;
197+ match = DesktopFileExecEntry . Match ( content ) ;
198+ } catch {
199+ // do not fail if we cannot read desktop file
200+ }
201+
202+ if ( match == null || ! match . Success )
203+ continue ;
204+
205+ yield return match . Groups . Last ( ) . Value ;
206+ break ;
207+ }
208+ }
209+
171210#if UNITY_EDITOR_LINUX
172211 [ System . Runtime . InteropServices . DllImport ( "libc" ) ]
173212 private static extern int readlink ( string path , byte [ ] buffer , int buflen ) ;
0 commit comments