@@ -139,26 +139,31 @@ var CliClientOpenCommand = cli.Command{
139139 Endpoint : endpoint ,
140140 RemoteDirectory : c .Args ().Get (1 ),
141141
142- RemoteEnv : c .StringSlice ("server-env" ),
143- LocalEditor : c .StringSlice ("local-editor" ),
144-
145- ShouldUsePorts : c .Bool ("use-ports" ),
146-
147- RemoteSocketPath : fmt .Sprintf ("/tmp/nvrh-socket-%s" , sessionId ),
148- LocalSocketPath : filepath .Join (os .TempDir (), fmt .Sprintf ("nvrh-socket-%s" , sessionId )),
149- AutomapPorts : c .Bool ("enable-automap-ports" ),
142+ AutomapPorts : c .Bool ("enable-automap-ports" ),
150143
151144 Debug : isDebug ,
152145
153146 TunneledPorts : make (map [string ]bool ),
154147
155148 NvimCmd : c .StringSlice ("nvim-cmd" ),
156-
157- SshArgs : c .StringSlice ("ssh-arg" ),
158149 }
159150
151+ remoteEnv := c .StringSlice ("server-env" )
152+ localEditor := c .StringSlice ("local-editor" )
153+ sshArgs := c .StringSlice ("ssh-arg" )
154+
155+ shouldUsePorts := c .Bool ("use-ports" )
156+ remoteSocketPath := fmt .Sprintf ("/tmp/nvrh-socket-%s" , sessionId )
157+ localSocketPath := filepath .Join (os .TempDir (), fmt .Sprintf ("nvrh-socket-%s" , sessionId ))
158+
159+ randomPort := getRandomPort ()
160+ localPortNumber := randomPort
161+ remotePortNumber := randomPort
162+
163+ var tunnelInfo * ssh_tunnel_info.SshTunnelInfo
164+
160165 // Setup SSH client
161- sshClient , sshClientErr := getSshClient (nvrhContext , endpoint , sshPath )
166+ sshClient , sshClientErr := getSshClient (nvrhContext , endpoint , sshPath , sshArgs )
162167 if sshClientErr != nil {
163168 return sshClientErr
164169 }
@@ -172,14 +177,13 @@ var CliClientOpenCommand = cli.Command{
172177 slog .Info ("Cleaning up" )
173178 closeNvimSocket (nv , didClientFail )
174179 killAllCmds (nvrhContext .CommandsToKill )
175- os .Remove (nvrhContext . LocalSocketPath )
180+ os .Remove (localSocketPath )
176181 if nvrhContext .SshClient != nil {
177182 nvrhContext .SshClient .Close ()
178183 }
179184 }()
180185
181186 siDone := make (chan error , 1 )
182- randomPort := getRandomPort ()
183187
184188 siTunnelInfo := & ssh_tunnel_info.SshTunnelInfo {
185189 Mode : "port" ,
@@ -191,8 +195,9 @@ var CliClientOpenCommand = cli.Command{
191195 // Start server info nvim instance.
192196 slog .Info ("Starting server info nvim instance" )
193197 go func () {
194- // Not quoting here because Powershell doesn't like it, and we don't know
195- // what shell we're using at this point.
198+ // Not quoting here because Powershell doesn't like it without the
199+ // preceding ampersand, and we don't know what shell we're using at this
200+ // point.
196201 nvimCmd := strings .Join (nvrhContext .NvimCmd , " " )
197202
198203 siDone <- nvrhContext .SshClient .Run (
@@ -201,7 +206,7 @@ var CliClientOpenCommand = cli.Command{
201206 )
202207 }()
203208
204- // Grab server info.
209+ // Grab server info and potentially prepare Windows .
205210 go func () {
206211 siNv , err := nvim_helpers .WaitForNvim (ctx , siTunnelInfo )
207212
@@ -217,6 +222,43 @@ var CliClientOpenCommand = cli.Command{
217222
218223 nvrhContext .ServerInfo = serverInfo
219224
225+ if nvrhContext .ServerInfo .Os == "windows" {
226+ shouldUsePorts = true
227+
228+ nvrhContext .WindowsLauncherPath = fmt .Sprintf (
229+ `%s\nvim-launcher-%s.bat` ,
230+ nvrhContext .ServerInfo .Tmpdir ,
231+ nvrhContext .SessionId ,
232+ )
233+
234+ tunnelInfo = & ssh_tunnel_info.SshTunnelInfo {
235+ Mode : "port" ,
236+ LocalSocket : fmt .Sprintf ("%d" , localPortNumber ),
237+ RemoteSocket : fmt .Sprintf ("%d" , remotePortNumber ),
238+ Public : false ,
239+ }
240+
241+ nvimCmd := nvim_helpers .BuildRemoteCommandString (
242+ nvrhContext .NvimCmd ,
243+ "bat" ,
244+ nvrhContext .RemoteDirectory ,
245+ remoteEnv ,
246+ tunnelInfo ,
247+ )
248+
249+ err := siNv .ExecLua (
250+ bridge_files .ReadFileWithoutError ("lua/setup_nvim_launcher.lua" ),
251+ nil ,
252+ nvimCmd ,
253+ nvrhContext .WindowsLauncherPath ,
254+ )
255+
256+ if err != nil {
257+ siDone <- err
258+ return
259+ }
260+ }
261+
220262 siNv .ExecLua ("vim.cmd('qall!')" , nil , nil )
221263 siNv .Close ()
222264
@@ -235,46 +277,40 @@ var CliClientOpenCommand = cli.Command{
235277 }
236278 }
237279
238- // Prep with new server info.
239- if nvrhContext .ServerInfo .Os == "windows" {
240- nvrhContext .ShouldUsePorts = true
241- }
242-
243- if nvrhContext .ShouldUsePorts {
244- randomPort := getRandomPort ()
245-
246- nvrhContext .LocalPortNumber = randomPort
247- nvrhContext .RemotePortNumber = randomPort
248- }
249-
250- tunnelInfo := & ssh_tunnel_info.SshTunnelInfo {
251- Mode : "unix" ,
252- LocalSocket : nvrhContext .LocalSocketPath ,
253- RemoteSocket : nvrhContext .RemoteSocketPath ,
254- Public : false ,
280+ // Even though this happens in the Windows Server path, we still need a
281+ // check here in case that path isn't hit.
282+ if tunnelInfo == nil {
283+ tunnelInfo = & ssh_tunnel_info.SshTunnelInfo {
284+ Mode : "unix" ,
285+ LocalSocket : localSocketPath ,
286+ RemoteSocket : remoteSocketPath ,
287+ Public : false ,
288+ }
255289 }
256290
257- if nvrhContext . ShouldUsePorts {
258- tunnelInfo .SwitchToPorts (nvrhContext . LocalPortNumber , nvrhContext . RemotePortNumber )
291+ if shouldUsePorts {
292+ tunnelInfo .SwitchToPorts (localPortNumber , remotePortNumber )
259293 }
260294
261295 // Start remote nvim
262296 go func () {
263- var cmdTemplate string
264- if nvrhContext .ServerInfo .ShellName == "powershell" {
265- cmdTemplate = `cd "%s"; %s`
266- } else if nvrhContext .ServerInfo .ShellName == "cmd" {
267- cmdTemplate = `cmd /c cd /d "%s" && %s`
297+ var nvimCommandString string
298+ if nvrhContext .ServerInfo .Os == "windows" {
299+ if nvrhContext .ServerInfo .ShellName == "bash" {
300+ nvimCommandString = fmt .Sprintf ("/tmp/nvim-launcher-%s.bat" , nvrhContext .SessionId )
301+ } else {
302+ nvimCommandString = nvrhContext .WindowsLauncherPath
303+ }
268304 } else {
269- cmdTemplate = `exec "$SHELL" -i -c 'cd "%s" && %s'`
305+ nvimCommandString = nvim_helpers .BuildRemoteCommandString (
306+ nvrhContext .NvimCmd ,
307+ nvrhContext .ServerInfo .ShellName ,
308+ nvrhContext .RemoteDirectory ,
309+ remoteEnv ,
310+ tunnelInfo ,
311+ )
270312 }
271313
272- nvimCommandString := fmt .Sprintf (
273- cmdTemplate ,
274- nvrhContext .RemoteDirectory ,
275- nvim_helpers .BuildRemoteCommandString (nvrhContext , tunnelInfo ),
276- )
277-
278314 slog .Info ("Starting remote nvim" , "nvimCommandString" , nvimCommandString )
279315 done <- nvrhContext .SshClient .Run (nvimCommandString , tunnelInfo )
280316 // Call stop so WaitForNvim can exit.
@@ -293,7 +329,7 @@ var CliClientOpenCommand = cli.Command{
293329 }
294330
295331 // Start local client
296- clientCmd := BuildClientNvimCmd (ctx , nvrhContext , tunnelInfo )
332+ clientCmd := BuildClientNvimCmd (ctx , localEditor , tunnelInfo )
297333 if nvrhContext .Debug {
298334 clientCmd .Stdout = os .Stdout
299335 clientCmd .Stderr = os .Stderr
@@ -402,35 +438,35 @@ var CliClientReconnectCommand = cli.Command{
402438 Endpoint : endpoint ,
403439 // RemoteDirectory: c.Args().Get(1),
404440
405- // RemoteEnv: c.StringSlice("server-env"),
406- LocalEditor : c .StringSlice ("local-editor" ),
407-
408- ShouldUsePorts : c .Bool ("use-ports" ),
409-
410- RemoteSocketPath : fmt .Sprintf ("/tmp/nvrh-socket-%s" , sessionId ),
411- LocalSocketPath : filepath .Join (os .TempDir (), fmt .Sprintf ("nvrh-socket-%s-%s" , sessionId , randomId )),
412441 // TODO Handle mapping ports better with multiple clients.
413- // AutomapPorts: c.Bool("enable-automap-ports"),
442+ // AutomapPorts: c.Bool("enable-automap-ports"),
414443
415444 Debug : isDebug ,
416445
417446 TunneledPorts : make (map [string ]bool ),
418447
419448 // NvimCmd: c.StringSlice("nvim-cmd"),
420-
421- SshArgs : c .StringSlice ("ssh-arg" ),
422449 }
423450
451+ localEditor := c .StringSlice ("local-editor" )
452+ sshArgs := c .StringSlice ("ssh-arg" )
453+
454+ shouldUsePorts := c .Bool ("use-ports" )
455+ remoteSocketPath := fmt .Sprintf ("/tmp/nvrh-socket-%s" , sessionId )
456+ localSocketPath := filepath .Join (os .TempDir (), fmt .Sprintf ("nvrh-socket-%s-%s" , sessionId , randomId ))
457+
458+ randomPort := getRandomPort ()
459+ localPortNumber := randomPort
460+ remotePortNumber := randomPort
461+
424462 // Setup SSH client
425- sshClient , sshClientErr := getSshClient (nvrhContext , endpoint , sshPath )
463+ sshClient , sshClientErr := getSshClient (nvrhContext , endpoint , sshPath , sshArgs )
426464 if sshClientErr != nil {
427465 return sshClientErr
428466 }
429467 nvrhContext .SshClient = sshClient
430468
431- if nvrhContext .ShouldUsePorts {
432- randomPort := getRandomPort ()
433-
469+ if shouldUsePorts {
434470 portNumberString := c .Args ().Get (2 )
435471 portNumber := 0
436472 if portNumberString != "" {
@@ -443,11 +479,8 @@ var CliClientReconnectCommand = cli.Command{
443479 portNumber = converted
444480 }
445481
446- nvrhContext .LocalPortNumber = randomPort
447482 if portNumber != 0 {
448- nvrhContext .RemotePortNumber = portNumber
449- } else {
450- nvrhContext .RemotePortNumber = randomPort
483+ remotePortNumber = portNumber
451484 }
452485 }
453486
@@ -458,7 +491,7 @@ var CliClientReconnectCommand = cli.Command{
458491 slog .Info ("Cleaning up" )
459492 closeNvimSocket (nv , false )
460493 killAllCmds (nvrhContext .CommandsToKill )
461- os .Remove (nvrhContext . LocalSocketPath )
494+ os .Remove (localSocketPath )
462495 if nvrhContext .SshClient != nil {
463496 nvrhContext .SshClient .Close ()
464497 }
@@ -467,13 +500,13 @@ var CliClientReconnectCommand = cli.Command{
467500 // Setup SSH tunnel
468501 tunnelInfo := & ssh_tunnel_info.SshTunnelInfo {
469502 Mode : "unix" ,
470- LocalSocket : nvrhContext . LocalSocketPath ,
471- RemoteSocket : nvrhContext . RemoteSocketPath ,
503+ LocalSocket : localSocketPath ,
504+ RemoteSocket : remoteSocketPath ,
472505 Public : false ,
473506 }
474507
475- if nvrhContext . ShouldUsePorts {
476- tunnelInfo .SwitchToPorts (nvrhContext . LocalPortNumber , nvrhContext . RemotePortNumber )
508+ if shouldUsePorts {
509+ tunnelInfo .SwitchToPorts (localPortNumber , remotePortNumber )
477510 }
478511
479512 go func () {
@@ -500,7 +533,7 @@ var CliClientReconnectCommand = cli.Command{
500533 }
501534
502535 // Start local client
503- clientCmd := BuildClientNvimCmd (ctx , nvrhContext , tunnelInfo )
536+ clientCmd := BuildClientNvimCmd (ctx , localEditor , tunnelInfo )
504537 if nvrhContext .Debug {
505538 clientCmd .Stdout = os .Stdout
506539 clientCmd .Stderr = os .Stderr
@@ -532,11 +565,11 @@ var CliClientReconnectCommand = cli.Command{
532565
533566func BuildClientNvimCmd (
534567 ctx context.Context ,
535- nvrhContext * nvrh_context. NvrhContext ,
568+ cmd [] string ,
536569 ti * ssh_tunnel_info.SshTunnelInfo ,
537570) * exec.Cmd {
538- replacedArgs := make ([]string , len (nvrhContext . LocalEditor ))
539- for i , arg := range nvrhContext . LocalEditor {
571+ replacedArgs := make ([]string , len (cmd ))
572+ for i , arg := range cmd {
540573 replacedArgs [i ] = strings .ReplaceAll (arg , "{{SOCKET_PATH}}" , ti .LocalBoundToIp ())
541574 }
542575
@@ -647,6 +680,7 @@ func prepareRemoteNvim(
647680 browserScriptPath ,
648681 nvrhContext .AutomapPorts ,
649682 string (marshalled ),
683+ nvrhContext .WindowsLauncherPath ,
650684 )
651685
652686 if err != nil {
@@ -742,6 +776,7 @@ func getSshClient(
742776 nvrhContext * nvrh_context.NvrhContext ,
743777 endpoint * ssh_endpoint.SshEndpoint ,
744778 sshPath string ,
779+ sshArgs []string ,
745780) (nvrh_base_ssh.BaseNvrhSshClient , error ) {
746781 if sshPath == "internal" {
747782 sshClient , err := go_ssh_ext .GetSshClientForEndpoint (endpoint )
@@ -758,6 +793,7 @@ func getSshClient(
758793 return nvrh_base_ssh .BaseNvrhSshClient (& nvrh_binary_ssh.NvrhBinarySshClient {
759794 Ctx : nvrhContext ,
760795 SshPath : sshPath ,
796+ SshArgs : sshArgs ,
761797 }), nil
762798}
763799
0 commit comments