@@ -23,6 +23,7 @@ public partial class PSConsoleReadLine
2323 private int _tabCommandCount ;
2424 private CommandCompletion _tabCompletions ;
2525 private Runspace _runspace ;
26+ private string _directorySeparator ;
2627
2728 private static readonly Dictionary < CompletionResultType , PSKeyInfo [ ] > KeysEndingCompletion =
2829 new Dictionary < CompletionResultType , PSKeyInfo [ ] >
@@ -40,7 +41,7 @@ public partial class PSConsoleReadLine
4041 private static readonly char [ ] EolChars = { '\r ' , '\n ' } ;
4142
4243 // String helper for directory paths
43- private static readonly string DirectorySeparatorString = System . IO . Path . DirectorySeparatorChar . ToString ( ) ;
44+ private static readonly string DefaultDirectorySeparator = System . IO . Path . DirectorySeparatorChar . ToString ( ) ;
4445
4546 // Stub helper method so completion can be mocked
4647 [ ExcludeFromCodeCoverage ]
@@ -281,10 +282,26 @@ private CommandCompletion GetCompletions()
281282 System . Management . Automation . PowerShell ps ;
282283 if ( ! _mockableMethods . RunspaceIsRemote ( _runspace ) )
283284 {
285+ _directorySeparator ??= DefaultDirectorySeparator ;
284286 ps = System . Management . Automation . PowerShell . Create ( RunspaceMode . CurrentRunspace ) ;
285287 }
286288 else
287289 {
290+ if ( _directorySeparator is null )
291+ {
292+ // Use the default separator by default.
293+ _directorySeparator = DefaultDirectorySeparator ;
294+ PSPrimitiveDictionary dict = _runspace . GetApplicationPrivateData ( ) ;
295+
296+ if ( dict [ "PSVersionTable" ] is PSPrimitiveDictionary versionTable )
297+ {
298+ // If the 'Platform' key is available and its value is not 'Win*', then the server side is macOS or Linux.
299+ // In that case, we use the forward slash '/' as the directory separator.
300+ // Otherwise, the server side is Windows and we use the backward slash '\' instead.
301+ _directorySeparator = versionTable [ "Platform" ] is string platform && ! platform . StartsWith ( "Win" , StringComparison . Ordinal ) ? "/" : @"\" ;
302+ }
303+ }
304+
288305 ps = System . Management . Automation . PowerShell . Create ( ) ;
289306 ps . Runspace = _runspace ;
290307 }
@@ -375,25 +392,25 @@ private void DoReplacementForCompletion(CompletionResult completionResult, Comma
375392 completions . ReplacementLength = replacementText . Length ;
376393 }
377394
378- private static string GetReplacementTextForDirectory ( string replacementText , ref int cursorAdjustment )
395+ private string GetReplacementTextForDirectory ( string replacementText , ref int cursorAdjustment )
379396 {
380- if ( ! replacementText . EndsWith ( DirectorySeparatorString , StringComparison . Ordinal ) )
397+ if ( ! replacementText . EndsWith ( _directorySeparator , StringComparison . Ordinal ) )
381398 {
382- if ( replacementText . EndsWith ( String . Format ( "{0}\' " , DirectorySeparatorString ) , StringComparison . Ordinal ) ||
383- replacementText . EndsWith ( String . Format ( "{0}\" " , DirectorySeparatorString ) , StringComparison . Ordinal ) )
399+ if ( replacementText . EndsWith ( string . Format ( "{0}\' " , _directorySeparator ) , StringComparison . Ordinal ) ||
400+ replacementText . EndsWith ( string . Format ( "{0}\" " , _directorySeparator ) , StringComparison . Ordinal ) )
384401 {
385402 cursorAdjustment = - 1 ;
386403 }
387404 else if ( replacementText . EndsWith ( "'" , StringComparison . Ordinal ) ||
388405 replacementText . EndsWith ( "\" " , StringComparison . Ordinal ) )
389406 {
390407 var len = replacementText . Length ;
391- replacementText = replacementText . Substring ( 0 , len - 1 ) + System . IO . Path . DirectorySeparatorChar + replacementText [ len - 1 ] ;
408+ replacementText = replacementText . Substring ( 0 , len - 1 ) + _directorySeparator + replacementText [ len - 1 ] ;
392409 cursorAdjustment = - 1 ;
393410 }
394411 else
395412 {
396- replacementText = replacementText + System . IO . Path . DirectorySeparatorChar ;
413+ replacementText += _directorySeparator ;
397414 }
398415 }
399416 return replacementText ;
0 commit comments