@@ -103,8 +103,13 @@ 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+ {
108+ // on Linux, editorPath is a file, in a bin sub-directory
109+ var parent = Directory . GetParent ( manifestBase ) ;
110+ // but we can link to [vscode]/code or [vscode]/bin/code
111+ manifestBase = parent ? . Name == "bin" ? parent . Parent ? . FullName : parent ? . FullName ;
112+ }
108113
109114 if ( manifestBase == null )
110115 return false ;
@@ -156,18 +161,57 @@ public static IEnumerable<IVisualStudioInstallation> GetVisualStudioInstallation
156161 }
157162 else
158163 {
164+ // Well known locations
159165 candidates . Add ( "/usr/bin/code" ) ;
160166 candidates . Add ( "/bin/code" ) ;
161167 candidates . Add ( "/usr/local/bin/code" ) ;
168+
169+ // Preference ordered base directories relative to which desktop files should be searched
170+ candidates . AddRange ( GetXdgCandidates ( ) ) ;
162171 }
163172
164- foreach ( var candidate in candidates )
173+ foreach ( var candidate in candidates . Distinct ( ) )
165174 {
166175 if ( TryDiscoverInstallation ( candidate , out var installation ) )
167176 yield return installation ;
168177 }
169178 }
170179
180+ private static readonly Regex DesktopFileExecEntry = new Regex ( @"Exec=(\S+)" , RegexOptions . Singleline | RegexOptions . Compiled ) ;
181+
182+ private static IEnumerable < string > GetXdgCandidates ( )
183+ {
184+ var envdirs = Environment . GetEnvironmentVariable ( "XDG_DATA_DIRS" ) ;
185+ if ( string . IsNullOrEmpty ( envdirs ) )
186+ yield break ;
187+
188+ var dirs = envdirs . Split ( ':' ) ;
189+ foreach ( var dir in dirs )
190+ {
191+ Match match = null ;
192+
193+ try
194+ {
195+ var desktopFile = IOPath . Combine ( dir , "applications/code.desktop" ) ;
196+ if ( ! File . Exists ( desktopFile ) )
197+ continue ;
198+
199+ var content = File . ReadAllText ( desktopFile ) ;
200+ match = DesktopFileExecEntry . Match ( content ) ;
201+ }
202+ catch
203+ {
204+ // do not fail if we cannot read desktop file
205+ }
206+
207+ if ( match == null || ! match . Success )
208+ continue ;
209+
210+ yield return match . Groups [ 1 ] . Value ;
211+ break ;
212+ }
213+ }
214+
171215#if UNITY_EDITOR_LINUX
172216 [ System . Runtime . InteropServices . DllImport ( "libc" ) ]
173217 private static extern int readlink ( string path , byte [ ] buffer , int buflen ) ;
0 commit comments