4141except subprocess .CalledProcessError :
4242 pass
4343
44+ MOSH_PROGRAM = None
45+ try :
46+ MOSH_PROGRAM = subprocess .check_output ([WHICH_CMD , 'mosh' ]).strip () or None
47+ except subprocess .CalledProcessError :
48+ pass
49+
4450
4551parser = argparse .ArgumentParser (description = 'Geofront client utility' )
4652parser .add_argument (
@@ -287,6 +293,33 @@ def get_ssh_options(remote):
287293 return options
288294
289295
296+ def get_mosh_options (remote , ssh ):
297+ """Translate the given ``remote`` to a corresponding :program:`mosh`
298+ options. For example, it returns the following list for ``'user@host'``::
299+
300+ ['--', 'user@host']
301+
302+ The remote can contain the port number or omit the user login as well
303+ e.g. ``'host:22'``::
304+
305+ ['--ssh="/usr/bin/ssh -p 22"', '--', 'host']
306+
307+ """
308+ remote_match = REMOTE_PATTERN .match (remote )
309+ if not remote_match :
310+ raise ValueError ('invalid remote format: ' + str (remote ))
311+ options = []
312+ user = remote_match .group ('user' )
313+ host = remote_match .group ('host' )
314+ if user :
315+ host = user + '@' + host
316+ port = remote_match .group ('port' )
317+ if port :
318+ ssh += b' -p ' + port .encode ('utf-8' )
319+ options .extend ([b'--ssh' , ssh , b'--' , host ])
320+ return options
321+
322+
290323@subparser
291324def colonize (args ):
292325 """Make the given remote to allow the current master key.
@@ -395,6 +428,28 @@ def scp(args):
395428scp .add_argument ('destination' , help = 'the destination path' )
396429
397430
431+ @subparser
432+ def mosh (args , alias = None ):
433+ """Mosh to the remote through Geofront's temporary authorization."""
434+ if not args .mosh :
435+ mosh .error ('could not detect mosh client.' )
436+ remote = authorize .call (args , alias = alias )
437+ try :
438+ options = get_mosh_options (remote , ssh = args .ssh )
439+ except ValueError as e :
440+ mosh .error (str (e ))
441+ command = [args .mosh ] + options
442+ subprocess .call (command )
443+
444+
445+ mosh .add_argument ('remote' , help = 'the remote alias to mosh' )
446+ mosh .add_argument (
447+ '-M' , '--mosh' ,
448+ default = MOSH_PROGRAM ,
449+ required = False ,
450+ help = 'mosh client to use' + (' [%(default)s]' if MOSH_PROGRAM else '' )
451+ )
452+
398453@subparser
399454def go (args ):
400455 """Select a remote and SSH to it at once (in interactive way)."""
@@ -407,7 +462,7 @@ def go(args):
407462 ssh .call (args , alias = alias )
408463
409464
410- for p in authenticate , authorize , start , ssh , scp , go :
465+ for p in authenticate , authorize , start , ssh , scp , mosh , go :
411466 p .add_argument (
412467 '-O' , '--no-open-browser' ,
413468 dest = 'open_browser' ,
0 commit comments