dr1p_pymux/pymux/entry_points/run_pymux.py

164 lines
4.9 KiB
Python

#!/usr/bin/env python
"""
pymux: Pure Python terminal multiplexer.
Usage:
pymux [(standalone|start-server|attach)] [-d]
[--truecolor] [--ansicolor] [(-S <socket>)] [(-f <file>)]
[(--log <logfile>)]
[--] [<command>]
pymux list-sessions
pymux -h | --help
pymux <command>
Options:
standalone : Run as a standalone process. (for debugging, detaching is
not possible.
start-server : Run a server daemon that can be attached later on.
attach : Attach to a running session.
-f : Path to configuration file. By default: '~/.pymux.conf'.
-S : Unix socket path.
-d : Detach all other clients, when attaching.
--log : Logfile.
--truecolor : Render true color (24 bit) instead of 256 colors.
(Each client can set this separately.)
"""
from __future__ import unicode_literals, absolute_import
from prompt_toolkit.output import ColorDepth
from pymux.main import Pymux
from pymux.client import create_client, list_clients
from pymux.utils import daemonize
import docopt
import getpass
import logging
import os
import sys
import tempfile
__all__ = (
'run',
)
def run():
a = docopt.docopt(__doc__)
socket_name = a['<socket>'] or os.environ.get('PYMUX')
socket_name_from_env = not a['<socket>'] and os.environ.get('PYMUX')
filename = a['<file>']
command = a['<command>']
true_color = a['--truecolor']
ansi_colors_only = a['--ansicolor'] or \
bool(os.environ.get('PROMPT_TOOLKIT_ANSI_COLORS_ONLY', False))
# Parse pane_id from socket_name. It looks like "socket_name,pane_id".
if socket_name and ',' in socket_name:
socket_name, pane_id = socket_name.rsplit(',', 1)
else:
pane_id = None
# Color depth.
if ansi_colors_only:
color_depth = ColorDepth.DEPTH_4_BIT
elif true_color:
color_depth = ColorDepth.DEPTH_24_BIT
else:
color_depth = ColorDepth.DEPTH_8_BIT
# Expand socket name. (Make it possible to just accept numbers.)
if socket_name and socket_name.isdigit():
socket_name = '%s/pymux.sock.%s.%s' % (
tempfile.gettempdir(), getpass.getuser(), socket_name)
# Configuration filename.
default_config = os.path.abspath(os.path.expanduser('~/.pymux.conf'))
if not filename and os.path.exists(default_config):
filename = default_config
if filename:
filename = os.path.abspath(os.path.expanduser(filename))
# Create 'Pymux'.
mux = Pymux(source_file=filename, startup_command=command)
# Setup logging.
if a['<logfile>']:
logging.basicConfig(filename=a['<logfile>'], level=logging.DEBUG)
if a['standalone']:
mux.run_standalone(color_depth=color_depth)
elif a['list-sessions'] or a['<command>'] in ('ls', 'list-sessions'):
for c in list_clients():
print(c.socket_name)
elif a['start-server']:
if socket_name_from_env:
_socket_from_env_warning()
sys.exit(1)
# Log to stdout.
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
# Run server.
socket_name = mux.listen_on_socket()
try:
mux.run_server()
except KeyboardInterrupt:
sys.exit(1)
elif a['attach']:
if socket_name_from_env:
_socket_from_env_warning()
sys.exit(1)
detach_other_clients = a['-d']
if socket_name:
create_client(socket_name).attach(
detach_other_clients=detach_other_clients,
color_depth=color_depth)
else:
# Connect to the first server.
for c in list_clients():
c.attach(detach_other_clients=detach_other_clients,
color_depth=color_depth)
break
else: # Nobreak.
print('No pymux instance found.')
sys.exit(1)
elif a['<command>'] and socket_name:
create_client(socket_name).run_command(a['<command>'], pane_id)
elif not socket_name:
# Run client/server combination.
socket_name = mux.listen_on_socket(socket_name)
pid = daemonize()
if pid > 0:
# Create window. It is important that this happens in the daemon,
# because the parent of the process running inside should be this
# daemon. (Otherwise the `waitpid` call won't work.)
mux.run_server()
else:
create_client(socket_name).attach(color_depth=color_depth)
else:
if socket_name_from_env:
_socket_from_env_warning()
sys.exit(1)
else:
print('Invalid command.')
sys.exit(1)
def _socket_from_env_warning():
print('Please be careful nesting pymux sessions.')
print('Unset PYMUX environment variable first.')
if __name__ == '__main__':
run()